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<PropertyName>(); ``` _Lists and Sets_ ```cs public void AddTo<PropertyName>(V value); public void RemoveFrom<PropertyName>(V value); ``` _Lists_ ```cs public void InsertInto<PropertyName>(int index, V value); public void RemoveFrom<PropertyName>At(int index); ``` _Dictionaries_ ```cs public void AddTo<PropertyName>(T key, V value); public void RemoveFrom<PropertyName>(T key); public void ReplaceIn<PropertyName>(T key, V value); ``` Over time, they will be cleaned up and more variants added such as `bool RemoveFrom<PropertyName>(T key, out V value)`
This commit is contained in:
parent
3a0d4b171b
commit
b7882df136
25 changed files with 64 additions and 77 deletions
|
|
@ -3,7 +3,7 @@
|
|||
"isRoot": true,
|
||||
"tools": {
|
||||
"modernuoschemagenerator": {
|
||||
"version": "2.9.0",
|
||||
"version": "2.10.8",
|
||||
"commands": [
|
||||
"ModernUOSchemaGenerator"
|
||||
]
|
||||
|
|
|
|||
|
|
@ -38,7 +38,7 @@
|
|||
<PackageReference Include="Zlib.Bindings" Version="1.11.0" />
|
||||
|
||||
<PackageReference Include="ModernUO.Serialization.Annotations" Version="2.9.1" />
|
||||
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.9.2" />
|
||||
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.10.8" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Migrations/*.v*.json" />
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -922,7 +922,7 @@ namespace Server.Engines.ConPVP
|
|||
ac.Delete();
|
||||
}
|
||||
|
||||
this.Clear(Components);
|
||||
ClearComponents();
|
||||
|
||||
// stairs
|
||||
AddComponent(new AddonComponent(0x74D), -1, +1, -5);
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -34,13 +34,6 @@ namespace Server.Items
|
|||
[SerializableField(2, setter: "private")]
|
||||
private List<Mobile> _no;
|
||||
|
||||
public void ClearTopic()
|
||||
{
|
||||
Topic = Array.Empty<string>();
|
||||
|
||||
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.
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -138,7 +138,7 @@ namespace Server.Items
|
|||
return;
|
||||
}
|
||||
|
||||
this.Add(Components, c);
|
||||
AddToComponents(c);
|
||||
|
||||
c.Addon = this;
|
||||
c.Offset = new Point3D(x, y, z);
|
||||
|
|
|
|||
|
|
@ -227,7 +227,7 @@ namespace Server.Items
|
|||
return;
|
||||
}
|
||||
|
||||
this.Add(Components, c);
|
||||
AddToComponents(c);
|
||||
|
||||
c.Addon = this;
|
||||
c.Offset = new Point3D(x, y, z);
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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));
|
||||
|
|
|
|||
|
|
@ -151,7 +151,7 @@ public partial class Runebook : Item, ISecurable, ICraftable
|
|||
DefaultIndex = -1;
|
||||
}
|
||||
|
||||
this.RemoveAt(_entries, index);
|
||||
RemoveFromEntriesAt(index);
|
||||
|
||||
var rune = new RecallRune
|
||||
{
|
||||
|
|
|
|||
|
|
@ -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.");
|
||||
}
|
||||
|
|
|
|||
|
|
@ -37,7 +37,7 @@ public partial class MiniHouseAddon : BaseAddon
|
|||
c.Delete();
|
||||
}
|
||||
|
||||
this.Clear(Components);
|
||||
ClearComponents();
|
||||
|
||||
var info = MiniHouseInfo.GetInfo(_type);
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -40,7 +40,7 @@
|
|||
<PackageReference Include="Zstd.Binaries" Version="1.6.0" />
|
||||
|
||||
<PackageReference Include="ModernUO.Serialization.Annotations" Version="2.9.1" />
|
||||
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.9.2" />
|
||||
<PackageReference Include="ModernUO.Serialization.Generator" Version="2.10.8" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<AdditionalFiles Include="Migrations/*.v*.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"
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue