From b7882df1369b6427c9682f92902a379cec3a75f0 Mon Sep 17 00:00:00 2001 From: Kamron Batman <3953314+kamronbatman@users.noreply.github.com> Date: Sun, 3 Dec 2023 18:55:31 -0500 Subject: [PATCH] fix: Fixes serialization and dirty tracking conveniences (#1627) ### Summary - Fixes issues with non-_ISerializable_ objects having bad serialization (Skill/Stat. Mods) - Fixes issues with MarkDirty and namespaces: https://github.com/modernuo/SerializationGenerator/issues/29 - Fixes missing dirty tracking for some data structures. - Fixes cascading MarkDirty for non-serializable types that have owners that are also non-serializable types. ### New Codegenned API When a data structure (Array, List, Dictionary, HashSet, etc) is source generated for serialization, new methods are added which will handle dirty tracking. Use these instead of the built in methods for that data structure. _All Data Structures_ ```cs public void Clear(); ``` _Lists and Sets_ ```cs public void AddTo(V value); public void RemoveFrom(V value); ``` _Lists_ ```cs public void InsertInto(int index, V value); public void RemoveFromAt(int index); ``` _Dictionaries_ ```cs public void AddTo(T key, V value); public void RemoveFrom(T key); public void ReplaceIn(T key, V value); ``` Over time, they will be cleaned up and more variants added such as `bool RemoveFrom(T key, out V value)` --- .config/dotnet-tools.json | 2 +- Projects/Server/Server.csproj | 2 +- .../Bulk Orders/Books/BulkOrderBook.cs | 4 ++-- .../Engines/CannedEvil/ChampionSpawn.cs | 12 ++++++------ .../Engines/ConPVP/Games/BombingRun.cs | 2 +- .../UOContent/Engines/Doom/GauntletSpawner.cs | 12 ++++++------ Projects/UOContent/Items/Addons/BallotBox.cs | 19 +++++-------------- Projects/UOContent/Items/Addons/BaseAddon.cs | 2 +- .../Items/Addons/BaseAddonContainer.cs | 2 +- .../UOContent/Items/Addons/SolenAntHole.cs | 4 ++-- Projects/UOContent/Items/Aquarium/Aquarium.cs | 16 ++++++++-------- Projects/UOContent/Items/Guilds/Guildstone.cs | 4 ++-- Projects/UOContent/Items/Maps/MapItem.cs | 5 ----- .../Items/Misc/CommunicationCrystals.cs | 4 ++-- .../UOContent/Items/Misc/Corpses/Corpse.cs | 4 ++-- .../Items/Misc/FlippableAddonAttribute.cs | 4 ++-- Projects/UOContent/Items/Misc/KeyRing.cs | 8 ++++---- .../Items/Misc/PlayerBulletinBoards.cs | 6 +++--- .../Items/Skill Items/Magical/Runebook.cs | 2 +- .../Special/House Raffle/HouseRaffleStone.cs | 4 ++-- .../UOContent/Items/Special/MiniHouses.cs | 2 +- .../Mutation Core/PlagueBeastInnard.cs | 4 ++-- .../Mutation Core/PlagueBeastOrgans.cs | 13 +++++++------ Projects/UOContent/UOContent.csproj | 2 +- version.json | 2 +- 25 files changed, 64 insertions(+), 77 deletions(-) diff --git a/.config/dotnet-tools.json b/.config/dotnet-tools.json index 1895d3624..82f6f558f 100644 --- a/.config/dotnet-tools.json +++ b/.config/dotnet-tools.json @@ -3,7 +3,7 @@ "isRoot": true, "tools": { "modernuoschemagenerator": { - "version": "2.9.0", + "version": "2.10.8", "commands": [ "ModernUOSchemaGenerator" ] diff --git a/Projects/Server/Server.csproj b/Projects/Server/Server.csproj index db151f7b0..684d01082 100755 --- a/Projects/Server/Server.csproj +++ b/Projects/Server/Server.csproj @@ -38,7 +38,7 @@ - + diff --git a/Projects/UOContent/Engines/Bulk Orders/Books/BulkOrderBook.cs b/Projects/UOContent/Engines/Bulk Orders/Books/BulkOrderBook.cs index c80621d47..23f6587c5 100644 --- a/Projects/UOContent/Engines/Bulk Orders/Books/BulkOrderBook.cs +++ b/Projects/UOContent/Engines/Bulk Orders/Books/BulkOrderBook.cs @@ -149,13 +149,13 @@ public partial class BulkOrderBook : Item, ISecurable public void AddEntry(IBOBEntry entry) { - this.Add(Entries, entry); + AddToEntries(entry); InvalidateProperties(); } public void RemoveEntry(IBOBEntry entry) { - this.Remove(Entries, entry); + RemoveFromEntries(entry); InvalidateProperties(); } diff --git a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs index e519adfb0..35e2de7f8 100755 --- a/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs +++ b/Projects/UOContent/Engines/CannedEvil/ChampionSpawn.cs @@ -534,7 +534,7 @@ public partial class ChampionSpawn : Item AwardArtifact((Champion as BaseChampion)?.GetArtifact()); } - this.Clear(_damageEntries); + ClearDamageEntries(); if (_platform != null) { @@ -570,7 +570,7 @@ public partial class ChampionSpawn : Item ((Corpse)m.Corpse).BeginDecay(TimeSpan.FromMinutes(1)); } - this.RemoveAt(_creatures, i); + RemoveFromCreaturesAt(i); --i; ++_kills; @@ -776,7 +776,7 @@ public partial class ChampionSpawn : Item // Allow creatures to turn into Paragons at Ilshenar champions. m.OnBeforeSpawn(loc, Map); - this.Add(_creatures, m); + AddToCreatures(m); m.MoveToWorld(loc, Map); if (m is BaseCreature bc) @@ -1114,7 +1114,7 @@ public partial class ChampionSpawn : Item _redSkulls[i].Delete(); } - this.Clear(_redSkulls); + ClearRedSkulls(); } if (_whiteSkulls != null) @@ -1124,7 +1124,7 @@ public partial class ChampionSpawn : Item _whiteSkulls[i].Delete(); } - this.Clear(_whiteSkulls); + ClearWhiteSkulls(); } DeleteCreatures(); @@ -1161,7 +1161,7 @@ public partial class ChampionSpawn : Item } } - this.Clear(_creatures); + ClearCreatures(); } } diff --git a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs index 6c511a8ba..5b4a22e93 100644 --- a/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs +++ b/Projects/UOContent/Engines/ConPVP/Games/BombingRun.cs @@ -922,7 +922,7 @@ namespace Server.Engines.ConPVP ac.Delete(); } - this.Clear(Components); + ClearComponents(); // stairs AddComponent(new AddonComponent(0x74D), -1, +1, -5); diff --git a/Projects/UOContent/Engines/Doom/GauntletSpawner.cs b/Projects/UOContent/Engines/Doom/GauntletSpawner.cs index 32f9e134b..77655cc2e 100644 --- a/Projects/UOContent/Engines/Doom/GauntletSpawner.cs +++ b/Projects/UOContent/Engines/Doom/GauntletSpawner.cs @@ -216,14 +216,14 @@ public partial class GauntletSpawner : Item return area / 100; } - public virtual void ClearTraps() + public virtual void RemoveAllTraps() { for (var i = 0; i < Traps.Count; ++i) { Traps[i].Delete(); } - Traps.Clear(); + ClearTraps(); } public virtual void SpawnTrap() @@ -303,19 +303,19 @@ public partial class GauntletSpawner : Item return Math.Max((playerCount + PlayersPerSpawn - 1) / PlayersPerSpawn, 1); } - public virtual void ClearCreatures() + public virtual void RemoveAllCreatures() { for (var i = 0; i < Creatures.Count; ++i) { Creatures[i].Delete(); } - Creatures.Clear(); + ClearCreatures(); } public virtual void FullSpawn() { - ClearCreatures(); + RemoveAllCreatures(); var count = ComputeSpawnCount(); @@ -324,7 +324,7 @@ public partial class GauntletSpawner : Item Spawn(); } - ClearTraps(); + RemoveAllTraps(); count = ComputeTrapCount(); diff --git a/Projects/UOContent/Items/Addons/BallotBox.cs b/Projects/UOContent/Items/Addons/BallotBox.cs index 0e9f4cddd..13c2b744f 100644 --- a/Projects/UOContent/Items/Addons/BallotBox.cs +++ b/Projects/UOContent/Items/Addons/BallotBox.cs @@ -34,13 +34,6 @@ namespace Server.Items [SerializableField(2, setter: "private")] private List _no; - public void ClearTopic() - { - Topic = Array.Empty(); - - ClearVotes(); - } - public void AddLineToTopic(string line) { if (Topic.Length >= MaxTopicLines) @@ -59,11 +52,8 @@ namespace Server.Items public void ClearVotes() { - if (Yes.Count > 0 || No.Count > 0) - { - this.Clear(_yes); - this.Clear(_no); - } + ClearYes(); + ClearNo(); } public bool IsOwner(Mobile from) @@ -197,6 +187,7 @@ namespace Server.Items if (isOwner) { m_Box.ClearTopic(); + m_Box.ClearVotes(); from.SendLocalizedMessage( 500370, @@ -228,7 +219,7 @@ namespace Server.Items } else { - m_Box.Add(m_Box._yes, from); + m_Box.AddToYes(from); from.SendLocalizedMessage(500373); // Your vote has been registered. } } @@ -245,7 +236,7 @@ namespace Server.Items } else { - m_Box.Add(m_Box._no, from); + m_Box.AddToNo(from); from.SendLocalizedMessage(500373); // Your vote has been registered. } } diff --git a/Projects/UOContent/Items/Addons/BaseAddon.cs b/Projects/UOContent/Items/Addons/BaseAddon.cs index f771e4315..340a93065 100644 --- a/Projects/UOContent/Items/Addons/BaseAddon.cs +++ b/Projects/UOContent/Items/Addons/BaseAddon.cs @@ -138,7 +138,7 @@ namespace Server.Items return; } - this.Add(Components, c); + AddToComponents(c); c.Addon = this; c.Offset = new Point3D(x, y, z); diff --git a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs index 71c69c05c..ad655c24e 100644 --- a/Projects/UOContent/Items/Addons/BaseAddonContainer.cs +++ b/Projects/UOContent/Items/Addons/BaseAddonContainer.cs @@ -227,7 +227,7 @@ namespace Server.Items return; } - this.Add(Components, c); + AddToComponents(c); c.Addon = this; c.Offset = new Point3D(x, y, z); diff --git a/Projects/UOContent/Items/Addons/SolenAntHole.cs b/Projects/UOContent/Items/Addons/SolenAntHole.cs index 3b234a6ed..1b2010fdd 100644 --- a/Projects/UOContent/Items/Addons/SolenAntHole.cs +++ b/Projects/UOContent/Items/Addons/SolenAntHole.cs @@ -119,7 +119,7 @@ namespace Server.Items public void SpawnAnt(BaseCreature ant) { - this.Add(_spawned, ant); + AddToSpawned(ant); var map = Map; var p = Location; @@ -143,7 +143,7 @@ namespace Server.Items { if (!_spawned[i].Alive || _spawned[i].Deleted) { - this.RemoveAt(_spawned, i); + RemoveFromSpawnedAt(i); } } diff --git a/Projects/UOContent/Items/Aquarium/Aquarium.cs b/Projects/UOContent/Items/Aquarium/Aquarium.cs index 4b6351897..f4a5d78ce 100644 --- a/Projects/UOContent/Items/Aquarium/Aquarium.cs +++ b/Projects/UOContent/Items/Aquarium/Aquarium.cs @@ -550,7 +550,7 @@ namespace Server.Items LiveCreatures = Math.Max(LiveCreatures - 1, 0); // An unfortunate accident has left a creature floating upside-down. It is starting to smell. - this.Add(_events, 1074366); + AddToEvents(1074366); } } @@ -563,7 +563,7 @@ namespace Server.Items else if (m_EvaluateDay) { // reset events - this.Clear(_events); + ClearEvents(); // food events if ( @@ -571,7 +571,7 @@ namespace Server.Items _food.State != (int)FoodState.Dead || _food.Added >= _food.Improve && _food.State == (int)FoodState.Full) { - this.Add(_events, 1074368); // The tank looks worse than it did yesterday. + AddToEvents(1074368); // The tank looks worse than it did yesterday. } if ( @@ -579,18 +579,18 @@ namespace Server.Items _food.State != (int)FoodState.Overfed || _food.Added < _food.Maintain && _food.State == (int)FoodState.Overfed) { - this.Add(_events, 1074367); // The tank looks healthier today. + AddToEvents(1074367); // The tank looks healthier today. } // water events if (_water.Added < _water.Maintain && _water.State != (int)WaterState.Dead) { - this.Add(_events, 1074370); // This tank can use more water. + AddToEvents(1074370); // This tank can use more water. } if (_water.Added >= _water.Improve && _water.State != (int)WaterState.Strong) { - this.Add(_events, 1074369); // The water looks clearer today. + AddToEvents(1074369); // The water looks clearer today. } UpdateFoodState(); @@ -663,7 +663,7 @@ namespace Server.Items if (AddFish(fish)) { - this.Add(_events, message); + AddToEvents(message); } else { @@ -1017,7 +1017,7 @@ namespace Server.Items Owner.From.PlaySound(0x5A2); } - m_Aquarium.RemoveAt(m_Aquarium._events, 0); + m_Aquarium.RemoveFromEventsAt(0); m_Aquarium.InvalidateProperties(); } } diff --git a/Projects/UOContent/Items/Guilds/Guildstone.cs b/Projects/UOContent/Items/Guilds/Guildstone.cs index d808e4066..467b99f85 100644 --- a/Projects/UOContent/Items/Guilds/Guildstone.cs +++ b/Projects/UOContent/Items/Guilds/Guildstone.cs @@ -184,7 +184,7 @@ public partial class Guildstone : Item, IAddon, IChoppable targetState.Leaving = guildState.Leaving; } - _guild.Remove(_guild.Accepted, from); + _guild.Accepted.Remove(from); _guild.AddMember(from); GuildGump.EnsureClosed(from); @@ -305,7 +305,7 @@ public partial class GuildstoneDeed : Item addon.MoveToWorld(loc, from.Map); - house.Add(house.Addons, addon); + house.Addons.Add(addon); Delete(); } else diff --git a/Projects/UOContent/Items/Maps/MapItem.cs b/Projects/UOContent/Items/Maps/MapItem.cs index 8aba38219..b9ee21e53 100644 --- a/Projects/UOContent/Items/Maps/MapItem.cs +++ b/Projects/UOContent/Items/Maps/MapItem.cs @@ -275,11 +275,6 @@ public partial class MapItem : Item, ICraftable } } - public virtual void ClearPins() - { - Pins.Clear(); - } - private void Deserialize(IGenericReader reader, int version) { // Version 0 doesn't serialize Facet/Editable, and count is not encoded diff --git a/Projects/UOContent/Items/Misc/CommunicationCrystals.cs b/Projects/UOContent/Items/Misc/CommunicationCrystals.cs index 165de0160..a52b1a12d 100644 --- a/Projects/UOContent/Items/Misc/CommunicationCrystals.cs +++ b/Projects/UOContent/Items/Misc/CommunicationCrystals.cs @@ -146,13 +146,13 @@ public partial class BroadcastCrystal : Item public void AddReceiver(ReceiverCrystal receiver) { - this.Add(Receivers, receiver); + AddToReceivers(receiver); InvalidateProperties(); } public void RemoveReceiver(ReceiverCrystal receiver) { - this.Remove(Receivers, receiver); + RemoveFromReceivers(receiver); InvalidateProperties(); } diff --git a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs index 641413096..af8315126 100644 --- a/Projects/UOContent/Items/Misc/Corpses/Corpse.cs +++ b/Projects/UOContent/Items/Misc/Corpses/Corpse.cs @@ -675,7 +675,7 @@ public partial class Corpse : Container, ICarvable from.CriminalAction(true); } - this.Add(_looters, from); + AddToLooters(from); _instancedItems?.Remove(item); @@ -695,7 +695,7 @@ public partial class Corpse : Container, ICarvable from.CriminalAction(true); } - this.Add(_looters, from); + AddToLooters(from); _instancedItems?.Remove(item); } diff --git a/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs b/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs index f5c659e01..2a76571ea 100644 --- a/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs +++ b/Projects/UOContent/Items/Misc/FlippableAddonAttribute.cs @@ -124,7 +124,7 @@ public class FlippableAddonAttribute : Attribute c.Delete(); } - addon.Clear(addon.Components); + addon.ClearComponents(); } else if (item is BaseAddonContainer addonContainer) { @@ -134,7 +134,7 @@ public class FlippableAddonAttribute : Attribute c.Delete(); } - addonContainer.Clear(addonContainer.Components); + addonContainer.ClearComponents(); } } } diff --git a/Projects/UOContent/Items/Misc/KeyRing.cs b/Projects/UOContent/Items/Misc/KeyRing.cs index dd2745b68..2a3c39759 100644 --- a/Projects/UOContent/Items/Misc/KeyRing.cs +++ b/Projects/UOContent/Items/Misc/KeyRing.cs @@ -66,13 +66,13 @@ public partial class KeyRing : Item key.Delete(); } - this.Clear(_keys); + ClearKeys(); } public void Add(Key key) { key.Internalize(); - this.Add(_keys, key); + AddToKeys(key); UpdateItemID(); } @@ -93,7 +93,7 @@ public partial class KeyRing : Item break; } - this.RemoveAt(_keys, i); + RemoveFromKeysAt(i); } UpdateItemID(); @@ -108,7 +108,7 @@ public partial class KeyRing : Item if (key.KeyValue == keyValue) { key.Delete(); - this.RemoveAt(_keys, i); + RemoveFromKeysAt(i); } } diff --git a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs index cb45f246a..b3cc04172 100644 --- a/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs +++ b/Projects/UOContent/Items/Misc/PlayerBulletinBoards.cs @@ -153,11 +153,11 @@ public abstract partial class BasePlayerBB : Item, ISecurable } else { - board.Add(board.Messages, message); + board.AddToMessages(message); if (board.Messages.Count > 50) { - board.RemoveAt(board.Messages, 0); + board.RemoveFromMessagesAt(0); if (page > 0) { @@ -491,7 +491,7 @@ public class PlayerBBGump : Gump { if (page >= 1 && page <= board.Messages.Count) { - board.RemoveAt(board.Messages, page - 1); + board.RemoveFromMessagesAt(page - 1); } from.SendGump(new PlayerBBGump(from, house, board, 0)); diff --git a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs index 2fb09549c..1443e41b3 100644 --- a/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs +++ b/Projects/UOContent/Items/Skill Items/Magical/Runebook.cs @@ -151,7 +151,7 @@ public partial class Runebook : Item, ISecurable, ICraftable DefaultIndex = -1; } - this.RemoveAt(_entries, index); + RemoveFromEntriesAt(index); var rune = new RecallRune { diff --git a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs index a0d7552ca..9b6d38755 100644 --- a/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs +++ b/Projects/UOContent/Items/Special/House Raffle/HouseRaffleStone.cs @@ -127,7 +127,7 @@ public partial class HouseRaffleStone : Item { if (value == HouseRaffleState.Active) { - this.Clear(_entries); + ClearEntries(); Winner = null; Deed = null; Started = Core.Now; @@ -465,7 +465,7 @@ public partial class HouseRaffleStone : Item if (_ticketPrice == 0 || from.Backpack?.ConsumeTotal(typeof(Gold), _ticketPrice) == true || Banker.Withdraw(from, _ticketPrice)) { - this.Add(Entries, new RaffleEntry(from)); + AddToEntries(new RaffleEntry(from)); from.SendMessage(MessageHue, "You have successfully entered the plot's raffle."); } diff --git a/Projects/UOContent/Items/Special/MiniHouses.cs b/Projects/UOContent/Items/Special/MiniHouses.cs index f42ca5565..5366094bb 100644 --- a/Projects/UOContent/Items/Special/MiniHouses.cs +++ b/Projects/UOContent/Items/Special/MiniHouses.cs @@ -37,7 +37,7 @@ public partial class MiniHouseAddon : BaseAddon c.Delete(); } - this.Clear(Components); + ClearComponents(); var info = MiniHouseInfo.GetInfo(_type); diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs index cae0e86f2..bead7bdd0 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastInnard.cs @@ -94,7 +94,7 @@ public partial class PlagueBeastComponent : PlagueBeastInnard { if (_organ?.OnDropped(from, dropped, this) == true && dropped is PlagueBeastComponent component) { - _organ.Add(_organ.Components, component); + _organ.AddToComponents(component); } return true; @@ -109,7 +109,7 @@ public partial class PlagueBeastComponent : PlagueBeastInnard // * You rip the organ out of the plague beast's flesh * from.SendLocalizedMessage(IsGland ? 1071895 : 1071914, null); - _organ.Remove(_organ.Components, this); + _organ.RemoveFromComponents(this); Organ = null; from.PlaySound(0x1CA); diff --git a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs index 424f5b0cc..cb7053d84 100644 --- a/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs +++ b/Projects/UOContent/Items/Special/Mutation Core/PlagueBeastOrgans.cs @@ -45,7 +45,7 @@ public partial class PlagueBeastOrgan : PlagueBeastInnard c.Location = new Point3D(X + x, Y + y, Z); c.Map = Map; - this.Add(Components, c); + AddToComponents(c); } public override bool Scissor(Mobile from, Scissors scissors) @@ -55,6 +55,12 @@ public partial class PlagueBeastOrgan : PlagueBeastInnard if (!Opened && !_opening) { _opening = true; + + Timer.StartTimer(TimeSpan.FromSeconds(3), Open); + + scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071897); // You carefully cut into the organ. + return true; + void Open() { _opening = false; @@ -63,11 +69,6 @@ public partial class PlagueBeastOrgan : PlagueBeastInnard FinishOpening(from); } } - - Timer.StartTimer(TimeSpan.FromSeconds(3), Open); - - scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071897); // You carefully cut into the organ. - return true; } scissors.PublicOverheadMessage(MessageType.Regular, 0x3B2, 1071898); // You have already cut this organ open. diff --git a/Projects/UOContent/UOContent.csproj b/Projects/UOContent/UOContent.csproj index 398d6f2de..b022fada9 100644 --- a/Projects/UOContent/UOContent.csproj +++ b/Projects/UOContent/UOContent.csproj @@ -40,7 +40,7 @@ - + diff --git a/version.json b/version.json index ce75bdf47..4ed56ec73 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { "$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json", - "version": "0.11.1" + "version": "0.11.2" }