Integrating XBox Live SDK

Thanks for your reply. I searched the Microsoft Development forum for xboxlive development using the keyword mono game

I found one thread: https://social.msdn.microsoft.com/Forums/en-US/ee2f51b1-dbda-4c0a-9eaf-e8200d47ed2e/uwp-xbox-one-i-am-using-monogamevisual-studioc-how-do-i-integrate-xbox-live-into-it-properly?forum=xboxlivedev

With a useful link

So it appears something as follows:
1/ Use NuGet to add the SDK to the project
2/ Add the following statement: using Microsoft.Xbox.Services;
3/ Then write code as follows:
// Create Xbox Live user
Microsoft.Xbox.Services.System.XboxLiveUser user = new Microsoft.Xbox.Services.System.XboxLiveUser();

I am going to read through the link and adapt it for c#. I will then write a proper guide and post it here

Thanks for a nudge in the right direction. If anybody has any documentation for c# / monogame / visual studio please post here so I am not reinventing the wheel

Much appreciated

1 Like

Ok this is really really frustrating and there just doesn’t seem to be any documentation on this whatsoever

This is what I have tried so far

using Microsoft.Xbox.Services.System;

public class Game1 : Microsoft.Xna.Framework.Game
{

XboxLiveUser user;

protected override void Initialize()
{

user = new XboxLiveUser();

I get a system stack overflow error message on the line user = new XboxLiveUser(); and the game doesn’t progress any further

When Microsoft announced that Xbox Live supported monogame I thought it was a big announcement. Surely I cant be the only one trying this or who has tried this

Can we please get some documentation on this on the website

I’m absolutely stuck and at a dead end

Thanks for the link however it takes me to the step I am up to but not past it

I have a fully working monogame on my XboxOne. I can play it perfectly with a controller, it saves to the storage, and works as one would expect. I haven’t had any issues

However the final step is that an XboxOne game must have a signed in user and the gamer tag displayed. This is done by accessing the Xbox SDK. Unfortunately this is the part that I cant find documented anywhere on the web

It will be something like:
Step 1/ Import SDK
Step 2/ Initialise the user
Step 3/ Get the signed in user asynchronously
Step 4/ Handle sign outs, offline etc…

The Microsoft site has C++ and WinRT but not C#

The javascript version is http://www.nonostante.io/devblog/2017-08-30-how-to-integrate-xbox-live-api-in-uwp-games.html

However I do not know enough about what is going on to translate it. I also don’t know when to initialise the user and when to start the functions

I would very much appreciate if somebody who has a monogame in the Xbox store to post the code they used to handle the user sign in and obtain the user profile

Without this I’m stuck on 99%

1 Like

So this is a pretty low effort response and I apologize about that, but here is what my file for handling Xbox Live sign in looks like.

using System;
using Engine;
using System.Diagnostics;
using Microsoft.Xbox.Services.System;
using Microsoft.Xbox.Services;
using Microsoft.Xbox.Services.Statistics.Manager;
using Microsoft.Xna.Framework;

namespace MonoGameTiles
{
    public class XboxLiveObject : Entity
    {
        public XboxLiveUser CurrentUser { get; private set; }
        public XboxLiveContext CurrentContext { get; private set; }
        public StatisticManager StatsManager = null;
        public string UserId
        {
            get
            {
                if (CurrentUser.IsSignedIn)
                    return CurrentUser.XboxUserId;
                else
                    return null;
            }
        }
        private readonly GameTimeSpan _timer_time_since_last_presence_post = new GameTimeSpan();
        public XboxLivePresences CurrentPresence = XboxLivePresences.in_menus;
        private XboxLivePresences _old_presence = XboxLivePresences.in_menus;
        private bool _has_posted_initial_presence = false;
        private bool _currently_attempting_sign_in = false;

        public XboxLiveObject()
        {
            IsPersistent = true;
            SignIn();
            XboxLiveUser.SignOutCompleted += SignOutCompleted;
        }

        private void SignOutCompleted(object sender, SignOutCompletedEventArgs e)
        {
            if (StatsManager != null)
            {
                StatsManager.RequestFlushToService(e.User);
                StatsManager.DoWork();
                StatsManager.RemoveLocalUser(e.User);
                StatsManager.DoWork();
                StatsManager = null;
            }
            CurrentContext = null;
            Action upon_returning_to_menu = delegate
            {
                UserData.ResetUserData();
                SaveLoadSettings.Load();
            };
            Room_Main.ReturnToMainMenuAndShowMessage(new System.Collections.Generic.List<string>() { "User logged out of Xbox Live" }, 50, upon_returning_to_menu);
        }

        public async void SignIn(bool attempt_silent = true)
        {
            if (_currently_attempting_sign_in)
                return;

            _currently_attempting_sign_in = true;
            CurrentUser = new XboxLiveUser();

            if (!CurrentUser.IsSignedIn)
            {
                var coreDispatcher = Windows.ApplicationModel.Core.CoreApplication.GetCurrentView().CoreWindow.Dispatcher;
                if (attempt_silent)
                {
                    try
                    {
                        await CurrentUser.SignInSilentlyAsync(coreDispatcher);
                    }
                    catch
                    {
                        Debug.WriteLine("SignInSilentlyAsync Threw Exception");
                    }
                }
                if (!CurrentUser.IsSignedIn)
                {
                    Debug.WriteLine("Silent Sign-In failed, requesting sign in");
                    try
                    {
                        await CurrentUser.SignInAsync(coreDispatcher);
                    }
                    catch
                    {
                        Debug.WriteLine("SingInAsync Threw Exception");
                    }
                }
            }
            if (CurrentUser.IsSignedIn)
            {
                CurrentContext = new XboxLiveContext(CurrentUser);
                StatsManager = StatisticManager.SingletonInstance;
                StatsManager.AddLocalUser(CurrentUser);
                StatsManager.DoWork();
                UserData.ResetUserData();
                SaveLoadSettings.Load();
                if (!_has_posted_initial_presence)
                {
                    SetPresenceAsync(XboxLivePresences.in_menus);
                    _has_posted_initial_presence = true;
                }

                AchievementSystem.CheckEarnedFavoritesCount();
            }
            WriteInfo();
            _currently_attempting_sign_in = false;
        }

        private async void SetPresenceAsync(XboxLivePresences presence)
        {
            if (CurrentContext == null)
                return;

            try
            {
                string presence_string = presence.ToString();
                Microsoft.Xbox.Services.Presence.PresenceData presenceData = new Microsoft.Xbox.Services.Presence.PresenceData(CurrentContext.AppConfig.ServiceConfigurationId, presence_string);
                await CurrentContext.PresenceService.SetPresenceAsync(true, presenceData);
                Debug.WriteLine("Posted Presence: " + presence.ToString());
            }
            catch
            {
                Debug.WriteLine("Error Setting Presence");
            }
        }

        public bool HasPrivilege(GamingPrivilege privilege)
        {
            string privilege_string = ((int)privilege).ToString();
            var privileges = CurrentUser.Privileges.Split(' ');
            foreach (var item in privileges)
            {
                if (privilege_string == item.Trim())
                    return true;
            }

            return false;
        }

        public void RunExitCleanup()
        {
            if (CurrentUser.IsSignedIn)
            {
                StatsManager.RequestFlushToService(CurrentUser);
                StatsManager.DoWork();
                StatsManager.RemoveLocalUser(CurrentUser);
                StatsManager.DoWork();
            }
            CurrentContext = null;
            CurrentUser = null;
        }

        public override void onUpdate(GameTime gameTime)
        {
            base.onUpdate(gameTime);

            if (_old_presence != CurrentPresence && _timer_time_since_last_presence_post.TotalMilliseconds > 10000)
            {
                _timer_time_since_last_presence_post.Mark();
                _old_presence = CurrentPresence;
                SetPresenceAsync(CurrentPresence);
            }
        }

        public void WriteInfo()
        {
            Debug.WriteLine("############ Xbox Live Info ############");
            Debug.WriteLine(CurrentUser.XboxUserId);
            Debug.WriteLine(CurrentUser.WebAccountId);
            Debug.WriteLine("############ Xbox Live Info ############");
        }
    }
}

Note that this is a singleton entity (using my own entity system), but that’s really just so it can have it’s own update loop where I set the rich presence string if needed.

There’s a lot of stuff here that’s specific to my game, but I just figured I could give you some sort of idea of how a person might set it up. Also feel free to learn from my mistakes :wink: , Microsoft is very liberal with the way it throws exceptions which was really odd for me. Things such as failed sign in attempts or failed rich presence posts will throw exceptions (even if it failed for a standard reason).

Let me know if you need an example of achievements, I’ve got that working too. In fact, I’ve got everything working on the Xbox right now except for the fact that the game closes if a person signs out of their account… which was actually the reason I was browsing the forums and stumbled on your question in the first place lol.

1 Like

Thank you very very much

I will give it a good look over when I get a chance next and let you know if I have any questions :slight_smile:

1 Like

Hi !!! Your codes are very helpful !!!

I notice that you could set the rich presence strings successfully. And now I have a lot of difficulties setting these strings…

I just use the API SetPresenceAsync as the document says, but my title threw some bugs:

System.IO.FileNotFoundException: Failed todownload specify resource 。 (Exception from HRESULT: 0x800C0008)

at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(Task task)

at System.Runtime.CompilerServices.TaskAwaiter.GetResult()

at steamManager.d__16.MoveNext()


These are my codes:

    public void AddUser(XboxLiveUser user)
{       
        if (m_user == null)
        {
            m_user = user;
            m_context = new XboxLiveContext(user);        
        }
} 
     

    public void OnGUI()
{
    lock (m_logText)
    {
        DrawTextWithShadow(10, 300, 800, 900, m_logText);
    }

    ClearLog();

    if (GUI.Button(new Rect(10, 150, 150, 30), "Cycle Presence"))
    {
        CyclePresence();
    }
 
} 

  private async void CyclePresence()
{  
     if (XboxLiveIntegration.AchievementManager.GetInstance().IsSignedIn)
    {
        AddUser(XboxLiveIntegration.AchievementManager.GetInstance().XboxLiveUser);                       
       
        try
        {
            PresenceData data = new PresenceData(m_context.AppConfig.ServiceConfigurationId, m_presenceIds[m_currentPresenceId]);
           
            await m_context.PresenceService.SetPresenceAsync(false, data);            
          
            LogLine("CyclePresence succeed. ");
        }
        catch (Exception ex)
        {
            LogLine("CyclePresence failed: " + ex.ToString());                
        }
    }

Actually, I even don’t know how to link the settings( for Rich Presence Strings) in XDP with the API. Could you please give me some suggestions?

Thanks a lot !!!

Hey there, so I’ve got a couple questions. You mentioned XDP, XDP is not where you set up your game if you are using UWP (which is what my example is for). I actually set up my game in XDP the first time out if confusion and learned the hard way that for UWP games you have to set it up in the Windows Dev Center. Though in my defense they didn’t even have an option for Xbox games in the Dev Center at the time :stuck_out_tongue: .

Secondly, how often are you attempting to set the rich presence string? There’s a reason my code checks to see how long it’s been since the last set. If I remember right, setting it more than 3 times within 15 seconds will get you throttled by the server, if you get throttled the game will throw a failure to post exception. Personally I don’t agree with the idea of throwing an exception for something not working server side, but Microsoft seems to love exceptions.

Thanks for your reply!!! :blush:
Firstly, I did set up my game in the Windows Dev Center , but I created Sandbox and made service configurations in XDP. Then I associated UDC product with the XDP title. Since the rich presence string is a part of service configurations, I set that in XDP.

Secondly, I did set the rich presence strings very frequently… However , when I first set that , this exception has appeared.
I want to know if I use this API incorrectly? Or if I need to make other configurations and get data from the server ?

I’m not sure of your exact problem yet, but I would start with setting up your service configuration in Windows Dev Center, if your game is a UWP game you won’t use XDP at all. Again, I was confused on this too. Also, when you set up your game in Windows Dev Center you have to create it as a sandbox project if I remember right (I just know I had to delete and recreate mine).

I would reach out to IDDS, they are the ones in charge of making sure you’re set up properly in Dev Center. Once that’s done you can see where you stand.

Also, in your code when AddUser(XboxLiveUser user) gets called is that user already logged in? It’s apparently VERY IMPORTANT (for what reason I don’t know) that when you create the XboxLiveContext the user is already signed in. If not, parts of Xbox Live will work and other parts won’t, I struggled with this for days before figuring it out.
https://forums.xboxlive.com/questions/65290/rich-presence-setpresenceasync-throws-bad-request.html

1 Like

Thanks!!! This link is helpful.And I 'm trying to fix this problem.When I get some solutions, I’ll share that here:grin:

I just found this about Xbox Live - https://docs.microsoft.com/en-us/windows/uwp/xbox-live/using-xbox-live/error-handling/error-handling-winrt

It’s something good to know up front, basically you have to wrap EVERY call to Xbox Live in a try/catch block. I’m really not used to programming in that mindset whatsoever, in practice I rarely use try/catch.

I have set the Rich Presence Strings successfully ! The real reason why my game threw that exception is I did not enable Internet (Client) capability in VS.(As this picture shows)

Since I could set up achievements successfully without this configuration , I ignored that.
I was inspired by an answer in the Xbox Developer Forum and I’m so grateful for your help !!!:blush:

1 Like

Hi could you show how to do a leaderboard ?
i’am looking for an answer for a few days now and can’t find any.

Thanks

Unfortunately that’s the one thing I haven’t messed with in Xbox Live.

Does anybody knows if (and how) a second player can be logged in into the second controller?

In PS4 when you connect a second controller you’re asked to log in the new controller with another PS4 account (or guest), so when playing N-player games it’s great because it can display your gamertag.

I’m porting a 2 player game and I’d like to add this feature, but I’m unable to find out how.
(I don’t know if it’s even possible as I’ve just had the X1 for a month and haven’t played a 2p game with it yet)

I have a very preliminar support of leaderboards in one of my games.

You first have to query the leaderboard. In example:

StatisticManager statsManager;

var query=new LeaderboardQuery();
query.MaxItems=numScores;
statsManager.GetLeaderboard (user,leaderboardId,query);

afterwards you have to manually query statsManager with DoWork (in example, in every Update cycle, or through a Thread) which returns you different events.

Try/catch it, as DoWork can throw exceptions.

    var eventList=live.statsManager.DoWork();
    foreach (var ev in eventList)
    {
        if (ev.EventType==StatisticEventType.GetLeaderboardComplete)
        {
            var args=ev.EventArgs as LeaderboardResultEventArgs;
            if (args!=null && args.Result!=null)
            {
                processLeaderboardResults (args.Result);
                leaderboardAltered=true;
            }
        }
    }

Inside processLeaderboardResults, you do a

foreach (var row in result.Rows)

and you have each leaderboard entry in those rows. row.GamerTag, row.Rank , …

What you do with those (i.e. put them in a list to display them ) it’s all up to you.

p.s. why the h… I can’t format the code? :slight_smile:

Thanks, this was what i needed.

DoWork() can throw exceptions too!? Dang, everything needs try/catch.

Also @KakCAT , I believe games can be set up in “multi-user mode” but I’ve never messed with it myself. Essentially your game needs to be structured that way from the start as it will affect how you handle Xbox Live (to my understanding).

Thanks, the link was what I was searching for.

It is indeed complicating a lot the sign in process and specially the savegames, I have to think wether using or not. After all, you can also control several gamepads without loging in.