question

Travis Lange avatar image
Travis Lange asked

Using GameServerSDK in newest release of Docker results in error

This is the error message we get when attempting to call GameserverSDK.Start(true).

(Filename: C:\buildslave\unity\build\Runtime/Export/Debug.bindings.h Line: 45)

Got Exception: Microsoft.Playfab.Gaming.GSDK.CSharp.GSDKInitializationException: Cannot read configuration file C:\Config\gsdkConfig.json ---> System.PlatformNotSupportedException: Operation is not supported on this platform.
  at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDynamicMethod (System.String name, System.Type returnType, System.Type[] parameterTypes, System.Type owner) [0x00018] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Utilities.DynamicReflectionDelegateFactory.CreateDefaultConstructor[T] (System.Type type) [0x00010] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.DefaultContractResolver.GetDefaultCreator (System.Type createdType) [0x00005] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.DefaultContractResolver.InitializeContract (Newtonsoft.Json.Serialization.JsonContract contract) [0x00093] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateObjectContract (System.Type objectType) [0x00007] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.DefaultContractResolver.CreateContract (System.Type objectType) [0x0010f] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at System.Collections.Concurrent.ConcurrentDictionary`2[TKey,TValue].GetOrAdd (TKey key, System.Func`2[T,TResult] valueFactory) [0x00034] in <c6bd535f6ab848b4a13f34d01b756eef>:0 
  at Newtonsoft.Json.Utilities.ThreadSafeStore`2[TKey,TValue].Get (TKey key) [0x00000] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.DefaultContractResolver.ResolveContract (System.Type type) [0x0000b] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.GetContractSafe (System.Type type) [0x0000b] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.Serialization.JsonSerializerInternalReader.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType, System.Boolean checkAdditionalContent) [0x0000e] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.JsonSerializer.DeserializeInternal (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00054] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.JsonSerializer.Deserialize (Newtonsoft.Json.JsonReader reader, System.Type objectType) [0x00000] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject (System.String value, System.Type type, Newtonsoft.Json.JsonSerializerSettings settings) [0x0002d] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value, Newtonsoft.Json.JsonSerializerSettings settings) [0x00000] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Newtonsoft.Json.JsonConvert.DeserializeObject[T] (System.String value) [0x00000] in <d47de75a7e3f422ca4ca64a654c80495>:0 
  at Microsoft.Playfab.Gaming.GSDK.CSharp.InternalSdk.GetConfiguration () [0x00037] in <5dc70375649a4ecc9e94d9e4921c86a5>:0 
   --- End of inner exception stack trace ---
  at Microsoft.Playfab.Gaming.GSDK.CSharp.InternalSdk.GetConfiguration () [0x00051] in <5dc70375649a4ecc9e94d9e4921c86a5>:0 
  at Microsoft.Playfab.Gaming.GSDK.CSharp.InternalSdk.StartAsync (System.Boolean debugLogs) [0x00024] in <5dc70375649a4ecc9e94d9e4921c86a5>:0 
  at Microsoft.Playfab.Gaming.GSDK.CSharp.GameserverSDK.Start (System.Boolean debugLogs) [0x00000] in <5dc70375649a4ecc9e94d9e4921c86a5>:0 
  at LangeStudios.PlayFab.PlayFabGameServerManager.Start () [0x0001c] in <ec7d7cb911ac4aca94c09ec6c7de2bd1>:0 

Everything used to work just fine. The only thing I can think of is we updated Docker. We are using Docker Desktop Community 2.1.0.1, Newtonsoft.Json 12.0.2, com.playfab.csharpsdk 0.9.190516, and Unity 2018.3.11f1.

Edit:

An older build of our project that I found works. This makes me think its not Docker. Maybe the newest versions of the GSDK or Newtonsoft have breaking changes.

Edit 2:

I tried using an older version of newtonsoft: 11.0.1. That did not fix things :(.

unity3d
3 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Travis Lange avatar image Travis Lange commented ·

I ended up finding an older build and things seem to work in that older build. I'll see if I can figure out what may have changed to cause this error.

0 Likes 0 ·
Travis Lange avatar image Travis Lange Travis Lange commented ·

Maybe the newest version of Newtonsoft doesn't work with the newest version of the gsdk? That or the newest version of the gsdk has breaking things? I'll try some older versions and see what I can find.

0 Likes 0 ·
Travis Lange avatar image Travis Lange commented ·

Ok so I tried using an older version of the gsdk: 0.5.190104 and I still get the same error. Now maybe I will try using the unity GSDK. This is very strange tho.

0 Likes 0 ·

1 Answer

·
brandon@uprootstudios.com avatar image
brandon@uprootstudios.com answered

We're using Unity 2019 and the latest version of Docker and aren't having issues, although we recently updated to the Unity GSDK from the C# one, maybe that would fix your issues?

13 comments
10 |1200

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.

Travis Lange avatar image Travis Lange commented ·

Hey Brandon. Thanks for the response. I'll try it out! :)

0 Likes 0 ·
brandon@uprootstudios.com avatar image brandon@uprootstudios.com Travis Lange commented ·

Sure thing! There aren't really many instructions for the Unity GSDK, but it's basically the same as the C# one. You just import the 'PlayFabMultiplayerSDK.unitypackage' and use the PlayFabMultiplayerAgentAPI static methods instead of GameserverSDK, although there are some minor differences (like ReadyForPlayers() being a void method instead of a boolean and there is now an OnServerActive callback)

0 Likes 0 ·
Travis Lange avatar image Travis Lange brandon@uprootstudios.com commented ·

Thanks for the heads up! :) How do you handle registering client connections with Thunderhead? I see a "ReceiveAuthenticateMessage" class. Do I have to send this myself, or is Thunderhead configured to already send this to me when a player connects in order to register connected players? (That would be super cool, but I would also be surpised if this was the case. I'm guessing I have to call it myself. I just don't see any examples as to how they do this).

0 Likes 0 ·
Travis Lange avatar image Travis Lange Travis Lange commented ·

Yes I most definitely agree that it is vague. I think we should create a separate question for this as it is a very good question.

1 Like 1 ·
brandon@uprootstudios.com avatar image brandon@uprootstudios.com Travis Lange commented ·

@TCROC Hmm... I'm not entirely sure what you mean (which means I'm probably doing something wrong...).

If you're talking about just telling Thunderhead how many players are connected, we've done the following:

public override void OnServerAddPlayer(NetworkConnection conn, AddPlayerMessage message) {
    players.Add(new ConnectedPlayer(conn.connectionId.ToString()));
    
    if (isReady) {
        PlayFabMultiplayerAgentAPI.UpdateConnectedPlayers(players);
    }
    
    scoreController.RegisterPlayer(conn, "", serverDebugMode);
    base.OnServerAddPlayer(conn, message);
}

Also if you're using UNET/Mirror, you'll probably need to override ConnectedPlayers:

using ConnectedPlayer = PlayFab.MultiplayerAgent.Model.ConnectedPlayer;

If you mean validating that connected players should actually be in the game (which is probably not what you mean), then you can use

PlayFabMultiplayerAgentAPI.GetInitialPlayers();
0 Likes 0 ·
Show more comments
Travis Lange avatar image Travis Lange Travis Lange commented ·

Hey @Brandon Phillips ya that's exactly what I was looking for! Thanks! To take it one step further for the list of connected players, the player could send his playFabId as a custom message to the GameServer when he joins and replace that conn.connectionId with his playFabId when that message is recieved. I have no idea if that is necessary, but in the examples that I have seen from playFab, they register the playFabId of the player. Idk if their APIs use this to see what games the player's friends are in or not. If PlayFab could provide some clarity as to what the string value of the "ConnectedPlayer" should be / if it is used anywhere else besides just keeping a player count that would be great! :)

0 Likes 0 ·
Travis Lange avatar image Travis Lange Travis Lange commented ·

And yes we are using Mirror

0 Likes 0 ·
Travis Lange avatar image Travis Lange Travis Lange commented ·

@Brandon Phillips I agree that a concrete answer would be nice. I look forward to hearing back from PlayFab on the question you just posted. Based on what I'm reading in the docs, I think doing a Linq query on the list to replace the "connecitonId" with the "playFabId" in the list and calling "updateConnectedPlayers" should work. But again a concrete answer would be nice.

0 Likes 0 ·
Sarah Zhang avatar image Sarah Zhang Travis Lange commented ·

From our point of view, we think the string value of the "ConnectedPlayer" should be PlayFabId because it can identify a player and would be convenient to interact with PlayFab later on. We see you got the same answer from another post. It's great.

About the original question you posted, it’s truly strange for this to happen, we need to do some tests with our test project, any updates will let you know.

0 Likes 0 ·
Travis Lange avatar image Travis Lange Sarah Zhang commented ·

@Sarah Zhang Thanks! Let me know what you find! :)

0 Likes 0 ·
Travis Lange avatar image Travis Lange commented ·

I can confirm that we have been able to do local debugging with Docker and the Unity GSDK. There was only one thing that we needed to do and that was make sure we set the "PlayFabAgentView" GameObject to "DontDestroyOnLoad" so that it can continue to communicate with ThunderHead when scenes change like this:

PlayFabMultiplayerAgentAPI.Start();
DontDestroyOnLoad(GameObject.Find("PlayFabAgentView"));

The "PlayFabMultiplayerAgentView" script should probably do this itself and maybe there is a reason it doesn't. It would be cool if PlayFab could comment on this and maybe I will ask it as a separate question, but for now this works. Thanks for the help @Brandon Phillips!

0 Likes 0 ·

Write an Answer

Hint: Notify or tag a user in this post by typing @username.

Up to 2 attachments (including images) can be used with a maximum of 512.0 KiB each and 1.0 MiB total.