private async Task <AdventureState> RestoreAdventureState(Adventure adventure, Session session) { AdventureState state = null; // attempt to deserialize the player information if (session.New) { LogInfo("new session started"); } else if (!session.Attributes.TryGetValue(SESSION_STATE_KEY, out object playerStateValue) || !(playerStateValue is JObject playerState)) { LogWarn($"unable to find player state in session (type: {playerStateValue?.GetType().Name})\n" + JsonConvert.SerializeObject(session)); } else { state = playerState.ToObject <AdventureState>(); // validate the adventure still has a matching place for the player if (!adventure.Places.ContainsKey(state.CurrentPlaceId)) { LogWarn($"unable to find matching place for restored player in session (value: '{state.CurrentPlaceId}')\n" + JsonConvert.SerializeObject(session)); // reset player state.Reset(Adventure.StartPlaceId); } } // create new player if no player was restored if (state == null) { LogInfo("new player session started"); state = new AdventureState(Adventure.StartPlaceId); } return(state); }
private async Task <AdventureState> RestoreAdventureState(Adventure adventure, Session session) { var recordId = UserIdToSessionRecordKey(session.User.UserId); AdventureState state = null; if (session.New) { // check if the adventure state can be restored from the player table if (_adventurePlayerTable != null) { // check if a session can be restored from the database var record = await _dynamoClient.GetItemAsync(_adventurePlayerTable, new Dictionary <string, AttributeValue> { ["PlayerId"] = new AttributeValue { S = recordId } }); if (record.IsItemSet) { state = JsonConvert.DeserializeObject <AdventureState>(record.Item["State"].S); LogInfo($"restored state from player table\n{record.Item["State"].S}"); // check if the place the player was in still exists or if the player had reached an end state if (!adventure.Places.TryGetValue(state.CurrentPlaceId, out AdventurePlace place)) { LogWarn($"unable to find matching place for restored state from player table (value: '{state.CurrentPlaceId}')"); // reset player state.Reset(Adventure.StartPlaceId); } else if (place.Finished) { LogInfo("restored player had reached end place"); // reset player state.Reset(Adventure.StartPlaceId); } else if (state.CurrentPlaceId == Adventure.StartPlaceId) { // reset player state.Reset(Adventure.StartPlaceId); } } else { LogInfo("no previous state found in player table"); } } } else { // attempt to deserialize the player information if (!session.Attributes.TryGetValue(SESSION_STATE_KEY, out object playerStateValue) || !(playerStateValue is JObject playerState)) { LogWarn($"unable to find player state in session (type: {playerStateValue?.GetType().Name})\n" + JsonConvert.SerializeObject(session)); } else { state = playerState.ToObject <AdventureState>(); // validate the adventure still has a matching place for the player if (!adventure.Places.ContainsKey(state.CurrentPlaceId)) { LogWarn($"unable to find matching place for restored player in session (value: '{state.CurrentPlaceId}')\n" + JsonConvert.SerializeObject(session)); // reset player state.Reset(Adventure.StartPlaceId); } } } // create new player if no player was restored if (state == null) { LogInfo("new player session started"); state = new AdventureState(recordId, Adventure.StartPlaceId); } return(state); // local functions string UserIdToSessionRecordKey(string userId) { var md5 = System.Security.Cryptography.MD5.Create().ComputeHash(Encoding.UTF8.GetBytes(userId)); return($"resume-{new Guid(md5):N}"); } }