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 StoreAdventureState(AdventureState state) { if (_adventurePlayerTable != null) { var jsonState = JsonConvert.SerializeObject(state, Formatting.None); LogInfo($"storing state in player table\n{jsonState}"); await _dynamoClient.PutItemAsync(_adventurePlayerTable, new Dictionary <string, AttributeValue> { ["PlayerId"] = new AttributeValue { S = state.RecordId }, ["State"] = new AttributeValue { S = jsonState }, ["Expire"] = new AttributeValue { N = ToEpoch(DateTime.UtcNow.AddDays(30)).ToString() } }); } // local functions uint ToEpoch(DateTime date) { return((uint)date.ToUniversalTime().Subtract(new DateTime(1970, 1, 1, 0, 0, 0, DateTimeKind.Utc)).TotalSeconds); } }
//--- Class Methods --- public static void Main(string[] args) { var app = new CommandLineApplication { Name = "AdventureBot.Cli", FullName = "AdventureBot Command Line Interface", Description = "Choose-Your-Adventure CLI" }; app.HelpOption(); var filenameArg = app.Argument("<FILENAME>", "path to adventure file"); app.OnExecute(() => { if (filenameArg.Value == null) { Console.WriteLine(app.GetHelpText()); return; } if (!File.Exists(filenameArg.Value)) { app.ShowRootCommandFullNameAndVersion(); Console.WriteLine("ERROR: could not find file"); return; } // initialize the adventure from the adventure file Adventure adventure; try { adventure = Adventure.LoadFrom(filenameArg.Value); } catch (AdventureException e) { Console.WriteLine($"ERROR: {e.Message}"); return; } catch (Exception e) { Console.WriteLine($"ERROR: unable to load file"); Console.WriteLine(e); return; } // invoke adventure var state = new AdventureState("cli", Adventure.StartPlaceId); var engine = new AdventureEngine(adventure, state); AdventureLoop(engine); }); app.Execute(args); }
public Adventure() { AdventureState = AdventureState.CREATION; }
private async Task StoreAdventureState(AdventureState 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}"); } }