Async Turnbased. Error Converting State to type 'Photon.Hive.Plugin.SerializableGameState
Hello,
I am using Pun 2 - Free & PlayFab CloudScript to make an async turn-based game.
Everything has worked smoothly so far except for loading a room with the serialized (JSON.stringified) state.
When loading a new room with the return
I am also able to successfully save the room state on /PathClose to my web server after the EmptyRoomTTL of 12 seconds has passed. I also have set the PlayerTTL = -1 according to the documentation.
The errors occurs when a Player attempts to ReJoin a room with the return
I receive this error in the OnJoinRoomFailed callback.
I can't quite figure out where to go from here!
Does anybody have any advice or tips to push me in the right direction? Thanks for your time:)
I am using Pun 2 - Free & PlayFab CloudScript to make an async turn-based game.
Everything has worked smoothly so far except for loading a room with the serialized (JSON.stringified) state.
When loading a new room with the return
{"State":"", "ResultCode":0}
, the game starts fine and transitions from my Main Menu into the Main Scene. Perfect!I am also able to successfully save the room state on /PathClose to my web server after the EmptyRoomTTL of 12 seconds has passed. I also have set the PlayerTTL = -1 according to the documentation.
The errors occurs when a Player attempts to ReJoin a room with the return
{"State":data.State, "ResultCode":0}
where data.State
is the serialized state fetched from a web server. I receive this error in the OnJoinRoomFailed callback.
Error converting value data.State to type 'Photon.Hive.Plugin.SerializableGameState'
. I am stripping out the DebugInfo property that is passed into the /PathClose webhook before posting to my web server but the error occurs even if I just save the whole State. I can't quite figure out where to go from here!
Does anybody have any advice or tips to push me in the right direction? Thanks for your time:)
0
Best Answers
-
Hi @WickedWorlok,
Let's stop altering the state for now, so no more stripping of debug info and let's save it as is after stringifing it.
Where or how do you save this in AWS?
Can you compare the state string before saving it in RoomClosed handler with the state string loaded from AWS in RoomCreated handler? maybe the data was changed somehow.
I suggest you try to reproduce with minimal steps (create, leave, rejoin) and minimal data possible (less or no room properties, no cached events, no expected users, a single actor).
Send us the two strings (the state that Photon sends you in PathClose and the state you return to Photon in PathCreate) in two different files by email along with your AppId and a link to this forum discussion.5 -
Hello @JohnTube
I was able to successfully get the previous room state to load without any errors by replacingreturn {"State":data.state, "ResultCode":0};
withreturn {"State":JSON.parse(data.state), "ResultCode":0};
.
The state was being stored in the DB as a string. I assumed in the return object that it needed to return this string however parsing it back into an object did the trick.
I now have more questions of course but will try to solve through them using the documentation and forums. You might hear from me again😅. Thanks for your time and help!
0
Answers
-
The colleague who can answer this for sure, is currently on vacation.
Back next week. Please bear with us until he's back.0 -
Everyone needs a vacation! Thanks for the quick reply Tobias and looking forward to hearing from your colleague.0
-
hi @WickedWorlok,
Thank you for choosing Photon!
The error is probably due to your CloudScript code.
It looks like you are returning"data.State"
as string to Photon instead of its actual value.
So Photon receives"State": "data.State"
.
Feel free to copy paste the code snippet here for PathCreate and PathClose handlers if you can't fix this.0 -
Hello @JohnTube,
NOTE: The stringified object returned from my AWS Gateway has a lowercase s (state). I'm aware in the question I used an uppercase (State). Sorry for any confusion! But this is not the problem to be clear. In the code examples you will see data.state which is correct in my case.
Since data.state is such a huge object I did not want to paste it here. data.state in this case is actually the serialized room state. I am sure of this because I am logging the values to Slack within the handlers. I also made a simple CloudScript function that simulates getting a rooms state from my AWS API. I am attaching a link to a picture of what the response looks like after running that CloudScript function.
Link: https://drive.google.com/file/d/1SeT6a0SnvObPrjZtrIcoRstvJPhunkH-/view?usp=sharing
Here is my /RoomCreated (PathCreate) handler:// Triggered automatically when a Photon room is first created handlers.RoomCreated = function (args) { log.debug("Room Created - Game: " + args.GameId + " MaxPlayers: " + args.CreateOptions.MaxPlayers); logToMyAPI(args, "Room Created"); switch (args.Type) { // Player loads room state from AWS API Gateway case 'Load': try { const url = `${AWS_BASE_URL}/${args.GameId}`; // justCreated is true if the GameId could not be found in the DB const {data, justCreated} = JSON.parse(http.request(url, 'GET', null, contentType, null)); // logToMyAPI({res, justCreated:res.justCreated, type:typeof res.justCreated, resType:typeof res}, 'Room Created Response Log') logToMyAPI({data, justCreated}, 'Room Created Response Log'); if (justCreated && args.CreateIfNotExists) { logToMyAPI('Creating new game with empty state'); return {"State":"", "ResultCode":0}; } else { const msg = 'Loading game from previous state' logToMyAPI({state:data.state}, 'Loaded State') return {"State":data.state, "ResultCode":0}; } } catch (err) { logToMyAPI(err, 'Room Created Error') return { "Message" : "Failed to create room", "ResultCode" : 1 } } break; default: logToMyAPI('Room Created Type was different than Load') return { ResultCode : 0, Message: 'Room Created Type was different than load' }; } };
Here is my RoomClosed (PathClose) handler:// Triggered automatically when a Photon room closes // Note: currentPlayerId is undefined in this function handlers.RoomClosed = function (args) { log.debug("Room Closed - Game: " + args.GameId); var {State} = args; var {DebugInfo, ...TheState} = State; // I am stripping out DebugInfo before posting to my AWS API var {DebugInfo, Binary, ...logState} = State; switch (args.Type) { case 'Save': try { var url = `${AWS_BASE_URL}/${args.GameId}`; var response = http.request(url, 'POST', JSON.stringify(TheState), "application/json", null); var Message = 'Room Closed and Saved!'; logToMyAPI({response, logState, Message}, 'Room Closed') return { ResultCode : 0, Message }; } catch (err) { logToMyAPI({err, msg:'Error in Room Close. Failed to update group data'}, 'Room Closed'); return {ResultCode:1, Message:'Error in Room Close'}; } break; default: logToMyAPI('Room Closed but not Saved:(') return { ResultCode : 0, Message: 'Room Closed but not Saved:(' }; } };
0 -
To give more context, this is the error I receive within Unity in the OnJoinRoomFailed callback
To shorten the message, I cut out some of the Binary.OnJoinRoomFailed with code: 32752 and message: Failed to load state from https://6B5F9.playfablogic.com/webhook/1/prod/TIY67MX4IBBTCAXZ7HFGXKH4F913T7ESE4NQH9A5PSXC8BJ638/RoomCreated? : Error converting value "{"ActorCounter":1,"ActorList":[{"ActorNr":1,"UserId":"B91D87C244B9C062","Nickname":"Wicked Worlok","Binary":"RGIAAAEBRAAAAAFi/3MADVdpY2tlZCBXb3Jsb2s=","DeactivationTime":"2019-04-17T01:32:22.8579333+00:00","DEBUG_BINARY":{"1":{"255":"Wicked Worlok"}}}],"Binary":{"18":"RAAAAAhi+nkAAHNzAAZjdXJTY25zAAYzX0dhbWVzAA9UVVJOX0lOREVYX1BST1BpAAAAAHMAEFRVUk5fU1RSSU5HX1BST1BzAAUxMDAxO3MACkxFVkVMX1BST1BpAAAAAXMAD0dST1VQX0ZPT0RfUFJPUGkAAABhcwAOSU5WRU5UT1JZX1BST1B5ABRzAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAHMAE05VTV9QTEFZRVJTX0FUX0VYSVRpAAAAAA==","19":"RGl6AAEAAAAAAHl6AANpAAAAAWLKaAAEYgZpo7vJoGIHaQAAA+liAWNWAAxAoAAAQOAAAAAAjjYgdpAAAEFWIBY1YADD+AAABAQAAAAAAAAGIAcwAIQ2hlcnJpZXM="},"CheckUserOnJoin":true,"CustomProperties":{},"DeleteCacheOnLeave":false,"EmptyRoomTTL":12000,"IsOpen":true,"IsVisible":true,"LobbyId":"","LobbyType":0,"LobbyProperties":[],"MaxPlayers":4,"PlayerTTL":-1,"SuppressRoomEvents":false,"Slice":0,"ExcludedActors":[],"PublishUserId":true,"ExpectedUsers":[],"RoomFlags":41}" to type 'Photon.Hive.Plugin.SerializableGameState'. Path 'State', line 1, position 10513. UnityEngine.Debug:LogFormat(String, Object[]) MainMenu:OnJoinRoomFailed(Int16, String) (at Assets/scripts/MainMenu.cs:91) Photon.Realtime.MatchMakingCallbacksContainer:OnJoinRoomFailed(Int16, String) (at Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:3377) Photon.Realtime.LoadBalancingClient:CallbackRoomEnterFailed(OperationResponse) (at Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:1858) Photon.Realtime.LoadBalancingClient:OnOperationResponse(OperationResponse) (at Assets/Photon/PhotonRealtime/Code/LoadBalancingClient.cs:1992) ExitGames.Client.Photon.PeerBase:DeserializeMessageAndCallback(StreamBuffer) (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/PeerBase.cs:616) ExitGames.Client.Photon.EnetPeer:DispatchIncomingCommands() (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/EnetPeer.cs:545) ExitGames.Client.Photon.PhotonPeer:DispatchIncomingCommands() (at C:/Dev/photon-sdk-dotnet/PhotonDotnet/PhotonPeer.cs:1473) Photon.Pun.PhotonHandler:FixedUpdate() (at Assets/Photon/PhotonUnityNetworking/Code/PhotonHandler.cs:130)
0 -
Hi @WickedWorlok,
Let's stop altering the state for now, so no more stripping of debug info and let's save it as is after stringifing it.
Where or how do you save this in AWS?
Can you compare the state string before saving it in RoomClosed handler with the state string loaded from AWS in RoomCreated handler? maybe the data was changed somehow.
I suggest you try to reproduce with minimal steps (create, leave, rejoin) and minimal data possible (less or no room properties, no cached events, no expected users, a single actor).
Send us the two strings (the state that Photon sends you in PathClose and the state you return to Photon in PathCreate) in two different files by email along with your AppId and a link to this forum discussion.5 -
Hello @JohnTube
I was able to successfully get the previous room state to load without any errors by replacingreturn {"State":data.state, "ResultCode":0};
withreturn {"State":JSON.parse(data.state), "ResultCode":0};
.
The state was being stored in the DB as a string. I assumed in the return object that it needed to return this string however parsing it back into an object did the trick.
I now have more questions of course but will try to solve through them using the documentation and forums. You might hear from me again😅. Thanks for your time and help!
0