diff --git a/AATool/AATool.csproj b/AATool/AATool.csproj index 809fe4bb..d59750d8 100644 --- a/AATool/AATool.csproj +++ b/AATool/AATool.csproj @@ -150,6 +150,8 @@ + + @@ -478,6 +480,27 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -685,6 +708,102 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -1966,6 +2085,78 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -2263,6 +2454,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -2497,6 +2694,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -6490,6 +6693,15 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -6511,6 +6723,12 @@ PreserveNewest + + PreserveNewest + + + PreserveNewest + PreserveNewest @@ -8876,9 +9094,7 @@ Designer - - - + diff --git a/AATool/Data/Objectives/Criterion.cs b/AATool/Data/Objectives/Criterion.cs index 0ee8d228..408b4f79 100644 --- a/AATool/Data/Objectives/Criterion.cs +++ b/AATool/Data/Objectives/Criterion.cs @@ -7,6 +7,8 @@ namespace AATool.Data.Objectives { public class Criterion : Objective { + public static string Key(string advancement, string criterion) => $"{advancement} {criterion}"; + public readonly Advancement Owner; public Uuid DesignatedPlayer => this.Owner.DesignatedPlayer; diff --git a/AATool/Data/Progress/Completion.cs b/AATool/Data/Progress/Completion.cs index 5bd3061b..58a8bca7 100644 --- a/AATool/Data/Progress/Completion.cs +++ b/AATool/Data/Progress/Completion.cs @@ -1,18 +1,16 @@ using System; using AATool.Net; -using Newtonsoft.Json; namespace AATool.Data.Progress { - [JsonObject] public struct Completion { public static readonly Completion Empty = new (Uuid.Empty, default); - [JsonProperty] public Uuid Player; - [JsonProperty] public DateTime Timestamp; + public Uuid Player; + public DateTime Timestamp; - [JsonIgnore] public bool IsEmpty => this.Player == Uuid.Empty; + public bool IsEmpty => this.Player == Uuid.Empty; public Completion(Uuid player, DateTime timestamp) { diff --git a/AATool/Data/Progress/Contribution.cs b/AATool/Data/Progress/Contribution.cs index 191ebecb..2919f3bb 100644 --- a/AATool/Data/Progress/Contribution.cs +++ b/AATool/Data/Progress/Contribution.cs @@ -1,38 +1,45 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using AATool.Data.Objectives; using AATool.Net; -using Newtonsoft.Json; namespace AATool.Data.Progress { - [TypeConverter(typeof(Contribution))] - [JsonObject] public class Contribution : ProgressState { - [JsonProperty] public readonly Uuid Player; - - [JsonConstructor] - public Contribution(Uuid Player, - Dictionary Advancements, - Dictionary<(string, string), Completion> Criteria, - Dictionary Recipes) - : base(Advancements, Criteria, Recipes) - { - this.Player = Player; - } + public readonly Uuid Player; public Contribution(Uuid Player) : base() { this.Player = Player; } - public static Contribution FromJsonString(string jsonString) => - JsonConvert.DeserializeObject(jsonString); + public Contribution(NetworkContribution network) : this(network.UUID) + { + this.Player = network.UUID; + this.InGameTime = network.InGameTime; + this.ObtainedGodApple = network.ObtainedGodApple; - public string ToJsonString() => - JsonConvert.SerializeObject(this); + //add advancements + foreach (KeyValuePair advancement in network.Advancements) + this.Advancements[advancement.Key] = new Completion(this.Player, advancement.Value); + //add criteria + foreach (string criterion in network.Criteria) + this.Criteria[criterion] = default; + //add stats + foreach (KeyValuePair stat in network.PickupCounts) + this.PickupCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in network.DropCounts) + this.DropCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in network.MineCounts) + this.MineCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in network.CraftCounts) + this.CraftCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in network.UseCounts) + this.UseCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in network.KillCounts) + this.KillCounts[stat.Key] = stat.Value; + } public override HashSet CompletionsOf(IObjective objective) { @@ -45,7 +52,7 @@ public override HashSet CompletionsOf(IObjective objective) } else if (objective is Criterion criterion) { - if (this.Criteria.TryGetValue((criterion.OwnerId, criterion.Id), out Completion completion)) + if (this.Criteria.TryGetValue(Criterion.Key(criterion.OwnerId, criterion.Id), out Completion completion)) completionists.Add(completion); } else if (objective is Block block) diff --git a/AATool/Data/Progress/NetworkContribution.cs b/AATool/Data/Progress/NetworkContribution.cs new file mode 100644 index 00000000..6efb58a5 --- /dev/null +++ b/AATool/Data/Progress/NetworkContribution.cs @@ -0,0 +1,68 @@ +using System; +using System.Collections.Generic; +using System.ComponentModel; +using AATool.Net; +using Newtonsoft.Json; + +namespace AATool.Data.Progress +{ + [JsonObject] + [TypeConverter(typeof(NetworkContribution))] + public class NetworkContribution + { + [JsonProperty] public Uuid UUID { get; set; } + [JsonProperty] public Dictionary Advancements { get; set; } + [JsonProperty] public HashSet Criteria { get; set; } + + [JsonProperty] public Dictionary PickupCounts { get; set; } + [JsonProperty] public Dictionary DropCounts { get; set; } + [JsonProperty] public Dictionary MineCounts { get; set; } + [JsonProperty] public Dictionary CraftCounts { get; set; } + [JsonProperty] public Dictionary UseCounts { get; set; } + [JsonProperty] public Dictionary KillCounts { get; set; } + + [JsonProperty] public TimeSpan InGameTime { get; set; } + [JsonProperty] public double KilometersFlown { get; set; } + [JsonProperty] public bool ObtainedGodApple { get; set; } + + public NetworkContribution() + { + this.Advancements = new(); + this.Criteria = new(); + this.PickupCounts = new(); + this.DropCounts = new(); + this.MineCounts = new(); + this.CraftCounts = new(); + this.UseCounts = new(); + this.KillCounts = new(); + } + + public NetworkContribution(Contribution contribution) : this() + { + this.UUID = contribution.Player; + this.InGameTime = contribution.InGameTime; + this.ObtainedGodApple = contribution.ObtainedGodApple; + + //add advancements + foreach (KeyValuePair advancement in contribution.Advancements) + this.Advancements[advancement.Key] = advancement.Value.Timestamp; + //add criteria + foreach (string criterion in contribution.Criteria.Keys) + this.Criteria.Add(criterion); + + //add stats + foreach (KeyValuePair stat in contribution.PickupCounts) + this.PickupCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in contribution.DropCounts) + this.DropCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in contribution.MineCounts) + this.MineCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in contribution.CraftCounts) + this.CraftCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in contribution.UseCounts) + this.UseCounts[stat.Key] = stat.Value; + foreach (KeyValuePair stat in contribution.KillCounts) + this.KillCounts[stat.Key] = stat.Value; + } + } +} diff --git a/AATool/Data/Progress/NetworkState.cs b/AATool/Data/Progress/NetworkState.cs new file mode 100644 index 00000000..881801c8 --- /dev/null +++ b/AATool/Data/Progress/NetworkState.cs @@ -0,0 +1,36 @@ +using System.Collections.Generic; +using Newtonsoft.Json; + +namespace AATool.Data.Progress +{ + [JsonObject] + public class NetworkState + { + [JsonProperty] public List Players { get; set; } + [JsonProperty] public string GameCategory { get; set; } + [JsonProperty] public string GameVersion { get; set; } + + [JsonConstructor] + public NetworkState() + { + this.Players = new (); + } + + public NetworkState(WorldState state) : this() + { + //copy world state + foreach (Contribution player in state.Players.Values) + this.Players.Add(new NetworkContribution(player)); + + //store current game category and version + this.GameCategory = Tracker.CurrentCategory; + this.GameVersion = Tracker.CurrentVersion; + } + + public static NetworkState FromJsonString(string jsonString) => + JsonConvert.DeserializeObject(jsonString); + + public string ToJsonString() => + JsonConvert.SerializeObject(this); + } +} diff --git a/AATool/Data/Progress/ProgressState.cs b/AATool/Data/Progress/ProgressState.cs index b350f900..4d10ebe6 100644 --- a/AATool/Data/Progress/ProgressState.cs +++ b/AATool/Data/Progress/ProgressState.cs @@ -1,50 +1,36 @@ using System; using System.Collections.Generic; -using System.ComponentModel; using AATool.Data.Objectives; -using Newtonsoft.Json; namespace AATool.Data.Progress { - [TypeConverter(typeof(ProgressState))] - [JsonObject] public abstract class ProgressState { - [JsonProperty] public Dictionary Advancements { get; set; } - [JsonProperty] public Dictionary Recipes { get; set; } - [JsonProperty] public Dictionary<(string adv, string crit), Completion> Criteria { get; set; } - [JsonProperty] public HashSet DeathMessages { get; set; } - - [JsonProperty] public Dictionary PickupCounts { get; set; } - [JsonProperty] public Dictionary DropCounts { get; set; } - [JsonProperty] public Dictionary MineCounts { get; set; } - [JsonProperty] public Dictionary CraftCounts { get; set; } - [JsonProperty] public Dictionary UseCounts { get; set; } - [JsonProperty] public Dictionary KillCounts { get; set; } - - [JsonProperty] public TimeSpan InGameTime { get; set; } - - [JsonProperty] public double KilometersFlown { get; set; } - - [JsonProperty] public bool ObtainedGodApple { get; set; } - - [JsonProperty] public int Deaths { get; set; } - [JsonProperty] public int DamageTaken { get; set; } - [JsonProperty] public int DamageDealt { get; set; } - [JsonProperty] public int Jumps { get; set; } - [JsonProperty] public int Sleeps { get; set; } - [JsonProperty] public int SaveAndQuits { get; set; } - [JsonProperty] public int ItemsEnchanted { get; set; } - - [JsonConstructor] - public ProgressState(Dictionary Advancements, - Dictionary<(string, string), Completion> Criteria, - Dictionary Recipes) - { - this.Advancements = Advancements; - this.Criteria = Criteria; - this.Recipes = Recipes; - } + public Dictionary Advancements { get; set; } + public Dictionary Criteria { get; set; } + public Dictionary Recipes { get; set; } + public HashSet DeathMessages { get; set; } + + public Dictionary PickupCounts { get; set; } + public Dictionary DropCounts { get; set; } + public Dictionary MineCounts { get; set; } + public Dictionary CraftCounts { get; set; } + public Dictionary UseCounts { get; set; } + public Dictionary KillCounts { get; set; } + + public TimeSpan InGameTime { get; set; } + + public double KilometersFlown { get; set; } + + public bool ObtainedGodApple { get; set; } + + public int Deaths { get; set; } + public int DamageTaken { get; set; } + public int DamageDealt { get; set; } + public int Jumps { get; set; } + public int Sleeps { get; set; } + public int SaveAndQuits { get; set; } + public int ItemsEnchanted { get; set; } public ProgressState() { @@ -59,13 +45,14 @@ public ProgressState() this.UseCounts = new (); this.KillCounts = new (); } + public abstract HashSet CompletionsOf(IObjective objective); public bool AdvancementCompleted(string id) => this.Advancements.ContainsKey(id); public bool CriterionCompleted(string advancement, string criterion) => - this.Criteria.ContainsKey((advancement, criterion)); + this.Criteria.ContainsKey(Criterion.Key(advancement, criterion)); public bool WasPickedUp(string name) => this.PickupCounts.ContainsKey(name); diff --git a/AATool/Data/Progress/WorldState.cs b/AATool/Data/Progress/WorldState.cs index a5d2a657..319158b8 100644 --- a/AATool/Data/Progress/WorldState.cs +++ b/AATool/Data/Progress/WorldState.cs @@ -1,68 +1,67 @@ -using System; -using System.Collections.Generic; -using System.ComponentModel; +using System.Collections.Generic; using AATool.Data.Objectives; using AATool.Net; using AATool.Utilities; -using Newtonsoft.Json; namespace AATool.Data.Progress { - [TypeConverter(typeof(WorldState))] - [JsonObject] public class WorldState : ProgressState { public static readonly WorldState Empty = new (); - [JsonProperty] public Dictionary Players { get; set; } + public Dictionary Players { get; set; } - [JsonProperty] public string GameCategory { get; set; } - [JsonProperty] public string GameVersion { get; set; } - - public WorldState() + public WorldState() : base() { - this.Advancements = new (); - this.Criteria = new (); - this.DeathMessages = new (); this.Players = new (); } - public string ToJsonString() - { - //store current category and version data then serialize - this.GameCategory = Tracker.CurrentCategory; - this.GameVersion = Tracker.CurrentVersion; - return JsonConvert.SerializeObject(this); - } - - public static WorldState FromJsonString(string jsonString) + public WorldState(NetworkState state) : this() { - try + //copy co-op state + foreach (NetworkContribution player in state.Players) { - //deserialize progress - dynamic json = JsonConvert.DeserializeObject(jsonString); - WorldState state = JsonConvert.DeserializeObject(jsonString); + //individual progress + var contribution = new Contribution(player); + this.Players[new Uuid(player.UUID.String)] = contribution; - //clone complex data structures - state.Advancements = json.CompletedAdvancements; - state.Criteria = json.CompletedCriteria; - state.Players = json.Players; - state.PickupCounts = json.PickedUp; - state.DropCounts = json.Dropped; - state.MineCounts = json.Mined; - state.CraftCounts = json.Crafted; - state.UseCounts = json.Used; - state.KillCounts = json.Killed; + //combined advancements + foreach (KeyValuePair advancement in contribution.Advancements) + { + if (!this.Advancements.TryGetValue(advancement.Key, out Completion first) || advancement.Value.Before(first.Timestamp)) + this.Advancements[advancement.Key] = advancement.Value; + } - //make sure everyone's names and avatars are loaded - foreach (KeyValuePair contribution in state.Players) - Player.FetchIdentityAsync(contribution.Key); - return state; + //combined criteria + foreach (KeyValuePair criterion in contribution.Criteria) + { + if (!this.Criteria.TryGetValue(criterion.Key, out Completion first) || criterion.Value.Before(first.Timestamp)) + this.Criteria[criterion.Key] = criterion.Value; + } + + //combined stats + this.CopyStats(player.PickupCounts, this.PickupCounts); + this.CopyStats(player.DropCounts, this.DropCounts); + this.CopyStats(player.MineCounts, this.MineCounts); + this.CopyStats(player.CraftCounts, this.CraftCounts); + this.CopyStats(player.UseCounts, this.UseCounts); + this.CopyStats(player.KillCounts, this.KillCounts); + + //enchanted golden apple + this.ObtainedGodApple |= contribution.ObtainedGodApple; + + //ingame time + if (contribution.InGameTime > this.InGameTime) + this.InGameTime = contribution.InGameTime; } - catch + } + + private void CopyStats(Dictionary source, Dictionary destination) + { + foreach (KeyValuePair statistic in source) { - //error deserializing world state - return new WorldState(); + _= destination.TryGetValue(statistic.Key, out int existing); + destination[statistic.Key] = existing + statistic.Value; } } @@ -82,7 +81,7 @@ public override HashSet CompletionsOf(IObjective objective) { foreach (KeyValuePair player in this.Players) { - if (player.Value.Criteria.TryGetValue((criterion.Owner.Id, criterion.Id), out Completion completion)) + if (player.Value.Criteria.TryGetValue(Criterion.Key(criterion.Owner.Id, criterion.Id), out Completion completion)) completionists.Add(completion); } } @@ -90,7 +89,7 @@ public override HashSet CompletionsOf(IObjective objective) { foreach (KeyValuePair player in this.Players) { - if (player.Value.UseCounts.ContainsKey(block.Id)) + if (player.Value.UseCounts.ContainsKey(block.Id) is true) completionists.Add(new Completion(player.Key, default)); } } @@ -104,18 +103,18 @@ public override HashSet CompletionsOf(IObjective objective) public void SyncDeathMessages() { - if (ActiveInstance.TryGetLog(out string log) && Player.TryGetName(Tracker.GetMainPlayer(), out string name)) + if (!ActiveInstance.TryGetLog(out string log) || !Player.TryGetName(Tracker.GetMainPlayer(), out string name)) + return; + + log = log.ToLower(); + foreach (Death death in Tracker.Deaths.All.Values) { - log = log.ToLower(); - foreach (Death death in Tracker.Deaths.All.Values) + foreach (string message in death.Messages) { - foreach (string message in death.Messages) + if (log.Contains($"[server thread/info]: {name.ToLower()} {message}")) { - if (log.Contains($"[server thread/info]: {name.ToLower()} {message}")) - { - this.DeathMessages.Add(death.Id); - break; - } + this.DeathMessages.Add(death.Id); + break; } } } diff --git a/AATool/Net/OpenTracker.cs b/AATool/Net/OpenTracker.cs index cec56040..47015b68 100644 --- a/AATool/Net/OpenTracker.cs +++ b/AATool/Net/OpenTracker.cs @@ -43,7 +43,7 @@ public static async void BroadcastProgress() try { string aaKey = AAKey.Strip(Config.Tracking.OpenTrackerKey); - var content = new StringContent(aaKey + Tracker.State.ToJsonString()); + var content = new StringContent(aaKey);// + Tracker.State.ToJsonString()); HttpResponseMessage response = await Client.PostAsync(Config.Tracking.OpenTrackerUrl, content); string message = await response.Content.ReadAsStringAsync(); WatchUrl = message; diff --git a/AATool/Net/Protocol.cs b/AATool/Net/Protocol.cs index 4dd2f046..728f2e56 100644 --- a/AATool/Net/Protocol.cs +++ b/AATool/Net/Protocol.cs @@ -4,9 +4,9 @@ namespace AATool.Net { public static class Protocol { - public static readonly Version Version = new ("7.0"); + public static readonly Version Version = new ("8.0"); - public const int BufferSize = 8192; + public const int BufferSize = 1024 * 1000; public const char CommandPrefix = '/'; public const char DataPrefix = '$'; public const char TokenDelimiter = '\n'; diff --git a/AATool/Net/Server.cs b/AATool/Net/Server.cs index 5dd9f220..a4073d50 100644 --- a/AATool/Net/Server.cs +++ b/AATool/Net/Server.cs @@ -5,6 +5,7 @@ using System.Net.Sockets; using AATool.Configuration; using AATool.Data.Categories; +using AATool.Data.Progress; using AATool.Net.Requests; using AATool.Saves; @@ -88,7 +89,7 @@ public void SendBlockHighlights(Socket client = null) public void SendProgress(Socket client = null) { - string jsonString = Tracker.State.ToJsonString(); + string jsonString = new NetworkState(Tracker.State).ToJsonString(); var message = Message.Progress(jsonString); //send lobby state to client(s) diff --git a/AATool/Net/Uuid.cs b/AATool/Net/Uuid.cs index 194f81f3..4157e977 100644 --- a/AATool/Net/Uuid.cs +++ b/AATool/Net/Uuid.cs @@ -6,8 +6,7 @@ namespace AATool.Net [JsonObject] public readonly struct Uuid { - [JsonIgnore] - public static readonly Uuid Empty = new (Guid.Empty); + [JsonIgnore] public static readonly Uuid Empty = new (Guid.Empty); [JsonProperty] public readonly string String; [JsonProperty] public readonly string ShortString; diff --git a/AATool/Properties/AssemblyInfo.cs b/AATool/Properties/AssemblyInfo.cs index eed88eeb..2ac4e1e1 100644 --- a/AATool/Properties/AssemblyInfo.cs +++ b/AATool/Properties/AssemblyInfo.cs @@ -33,6 +33,6 @@ // by using the '*' as shown below: // [assembly: AssemblyVersion("1.0.*")] -[assembly: AssemblyVersion("1.5.1.1")] -[assembly: AssemblyFileVersion("1.5.1.1")] +[assembly: AssemblyVersion("1.5.2.0")] +[assembly: AssemblyFileVersion("1.5.2.0")] [assembly: NeutralResourcesLanguage("en")] diff --git a/AATool/Saves/AchievementsFolder.cs b/AATool/Saves/AchievementsFolder.cs index a221e764..89c3d21d 100644 --- a/AATool/Saves/AchievementsFolder.cs +++ b/AATool/Saves/AchievementsFolder.cs @@ -20,9 +20,9 @@ private static bool IsCompleted(string achievement, JsonStream json) return false; } - private HashSet<(string adv, string crit)> GetCompletedCriteria(Advancement advancement, JsonStream json) + private HashSet GetCompletedCriteria(Advancement advancement, JsonStream json) { - HashSet<(string, string)> completed = new (); + HashSet completed = new (); dynamic criteriaList = json?[advancement.Id]?["progress"]; if (criteriaList is not null) { @@ -34,7 +34,7 @@ private static bool IsCompleted(string achievement, JsonStream json) { string criterion = tokens[1]; if (advancement.Criteria.Contains(criterion)) - completed.Add((advancement.Id, criterion)); + completed.Add(Criterion.Key(advancement.Id, criterion)); } } } @@ -79,10 +79,10 @@ protected override void Update(JsonStream json, WorldState state, Contribution c if (achievement.HasCriteria) { - foreach ((string adv, string crit) criterion in this.GetCompletedCriteria(achievement, json)) + foreach (string criterion in this.GetCompletedCriteria(achievement, json)) { state.Criteria.Add(criterion, new Completion(json.Player, default)); - contribution.Criteria.Add((criterion.adv, criterion.crit), + contribution.Criteria.Add(criterion, new Completion(json.Player, default)); } } diff --git a/AATool/Saves/AdvancementsFolder.cs b/AATool/Saves/AdvancementsFolder.cs index 74a704c3..d248618f 100644 --- a/AATool/Saves/AdvancementsFolder.cs +++ b/AATool/Saves/AdvancementsFolder.cs @@ -12,7 +12,7 @@ public class AdvancementsFolder : JsonFolder { private class AdvancementCompletion { - public readonly Dictionary<(string adv, string crit), DateTime> CriteriaTimestamps; + public readonly Dictionary CriteriaTimestamps; public readonly Uuid Player; public readonly string Id; public readonly bool AdvancementDone; @@ -24,13 +24,13 @@ public AdvancementCompletion(JsonStream json, dynamic token, string advancement) this.Id = advancement; this.Player = json.Player; this.Timestamp = DateTime.MinValue; - this.CriteriaTimestamps = new Dictionary<(string adv, string crit), DateTime>(); + this.CriteriaTimestamps = new Dictionary(); this.AdvancementDone = token?["done"] == true; } public void AddCriterion(string adv, string crit, DateTime completed) { - this.CriteriaTimestamps[(adv, crit)] = completed; + this.CriteriaTimestamps[Criterion.Key(adv, crit)] = completed; if (completed > this.Timestamp) this.Timestamp = completed; } @@ -111,7 +111,7 @@ private void UpdateAdvancements(AdvancementCompletion advancement, WorldState st private void UpdateCriteria(AdvancementCompletion advancement, WorldState state, Contribution contribution) { - foreach (KeyValuePair<(string adv, string crit), DateTime> criterion in advancement.CriteriaTimestamps) + foreach (KeyValuePair criterion in advancement.CriteriaTimestamps) { //update individual player progress var completion = new Completion(advancement.Player, criterion.Value); diff --git a/AATool/Tracker.cs b/AATool/Tracker.cs index ef2f5812..996c15b8 100644 --- a/AATool/Tracker.cs +++ b/AATool/Tracker.cs @@ -230,6 +230,9 @@ public static string GetStatusText() public static bool TrySetCategory(string category) { + if (string.IsNullOrEmpty(category)) + return false; + //check if category is the same if (Category is not null && category == Category.Name) return false; @@ -477,18 +480,19 @@ private static void UpdateCurrentWorld() private static void ParseCoOpProgress(Time time, Client client) { //update world from co-op server - if (client is null || !client.TryGetData(Protocol.Headers.Progress, out string jsonString)) + if (client is null || !client.TryGetData(Protocol.Headers.Progress, out string progress)) return; - if (LastServerMessage != jsonString) + if (LastServerMessage != progress) { CoOpStateChanged = true; - LastServerMessage = jsonString; - State = WorldState.FromJsonString(jsonString); + LastServerMessage = progress; + var networkState = NetworkState.FromJsonString(progress); + State = new WorldState(networkState); //sync category and version with host - TrySetCategory(State.GameCategory); - TrySetVersion(State.GameVersion); + TrySetCategory(networkState.GameCategory); + TrySetVersion(networkState.GameVersion); //reload objectives if game version has changed if (ObjectivesChanged) diff --git a/AATool/Winforms/Controls/CMainSettings.cs b/AATool/Winforms/Controls/CMainSettings.cs index 065f9c4c..7a635cc7 100644 --- a/AATool/Winforms/Controls/CMainSettings.cs +++ b/AATool/Winforms/Controls/CMainSettings.cs @@ -47,7 +47,7 @@ public void LoadSettings() this.startupPosition.Text = Config.Main.StartupArrangement.Value.ToString(); this.UpdateMonitorList(); - this.startupMonitor.SelectedIndex = MathHelper.Clamp(Config.Main.StartupDisplay - 1, 0, this.startupMonitor.Items.Count); + this.startupMonitor.SelectedIndex = MathHelper.Clamp(Config.Main.StartupDisplay - 1, 0, this.startupMonitor.Items.Count - 1); this.startupMonitor.Enabled = this.startupPosition.Text != "Remember"; //colors