### 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)`
158 lines
4.6 KiB
C#
158 lines
4.6 KiB
C#
using System.Collections.Generic;
|
|
using ModernUO.Serialization;
|
|
using Server.Mobiles;
|
|
using Server.Spells;
|
|
|
|
namespace Server.Items
|
|
{
|
|
[SerializationGenerator(0)]
|
|
public partial class SolenAntHoleComponent : AddonComponent
|
|
{
|
|
public SolenAntHoleComponent(int itemID) : base(itemID)
|
|
{
|
|
}
|
|
|
|
public override void OnDoubleClick(Mobile from)
|
|
{
|
|
if (from.InRange(this, 2))
|
|
{
|
|
var map = Map;
|
|
|
|
if (map == Map.Trammel || map == Map.Felucca)
|
|
{
|
|
from.MoveToWorld(new Point3D(5922, 2024, 0), map);
|
|
// * ~1_NAME~ dives into the mysterious hole! *
|
|
PublicOverheadMessage(MessageType.Regular, 0x3B2, 1114446, from.Name);
|
|
}
|
|
}
|
|
else
|
|
{
|
|
from.LocalOverheadMessage(MessageType.Regular, 0x3B2, 1019045); // I can't reach that.
|
|
}
|
|
}
|
|
}
|
|
|
|
[SerializationGenerator(1)]
|
|
public partial class SolenAntHole : BaseAddon
|
|
{
|
|
[SerializableField(0, getter: "private", setter: "private")]
|
|
private List<Mobile> _spawned;
|
|
|
|
[Constructible]
|
|
public SolenAntHole()
|
|
{
|
|
_spawned = new List<Mobile>();
|
|
|
|
AddComponent(new AddonComponent(0x914), "dirt", 0, 0, 0, 0);
|
|
AddComponent(new SolenAntHoleComponent(0x122A), "a hole", 0x1, 0, 0, 0);
|
|
AddComponent(new AddonComponent(0x1B23), "dirt", 0x970, 1, 1, 0);
|
|
AddComponent(new AddonComponent(0xEE0), "dirt", 0, 1, 0, 0);
|
|
AddComponent(new AddonComponent(0x1B24), "dirt", 0x970, 1, -1, 0);
|
|
AddComponent(new AddonComponent(0xEE1), "dirt", 0, 0, -1, 0);
|
|
AddComponent(new AddonComponent(0x1B25), "dirt", 0x970, -1, -1, 0);
|
|
AddComponent(new AddonComponent(0xEE2), "dirt", 0, -1, 0, 0);
|
|
AddComponent(new AddonComponent(0x1B26), "dirt", 0x970, -1, 1, 0);
|
|
AddComponent(new AddonComponent(0xED3), "dirt", 0, 0, 1, 0);
|
|
}
|
|
|
|
public override bool ShareHue => false;
|
|
public override bool HandlesOnMovement => true;
|
|
|
|
public override void OnMovement(Mobile m, Point3D oldLocation)
|
|
{
|
|
if (!m.Player || !m.Alive || m.Hidden || !SpawnKilled())
|
|
{
|
|
return;
|
|
}
|
|
|
|
if (Utility.InRange(Location, m.Location, 3) && !Utility.InRange(Location, oldLocation, 3))
|
|
{
|
|
var count = 1 + Utility.Random(4);
|
|
|
|
for (var i = 0; i < count; i++)
|
|
{
|
|
SpawnAnt();
|
|
}
|
|
|
|
if (Utility.RandomDouble() < 0.05)
|
|
{
|
|
SpawnAnt(new Beetle());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void AddComponent(AddonComponent c, string name, int hue, int x, int y, int z)
|
|
{
|
|
c.Hue = hue;
|
|
c.Name = name;
|
|
AddComponent(c, x, y, z);
|
|
}
|
|
|
|
public void SpawnAnt()
|
|
{
|
|
var random = Utility.Random(3);
|
|
var map = Map;
|
|
|
|
if (map == Map.Trammel)
|
|
{
|
|
if (random < 2)
|
|
{
|
|
SpawnAnt(new RedSolenWorker());
|
|
}
|
|
else
|
|
{
|
|
SpawnAnt(new RedSolenWarrior());
|
|
}
|
|
}
|
|
else if (map == Map.Felucca)
|
|
{
|
|
if (random < 2)
|
|
{
|
|
SpawnAnt(new BlackSolenWorker());
|
|
}
|
|
else
|
|
{
|
|
SpawnAnt(new BlackSolenWarrior());
|
|
}
|
|
}
|
|
}
|
|
|
|
public void SpawnAnt(BaseCreature ant)
|
|
{
|
|
AddToSpawned(ant);
|
|
|
|
var map = Map;
|
|
var p = Location;
|
|
|
|
for (var i = 0; i < 5; i++)
|
|
{
|
|
if (SpellHelper.FindValidSpawnLocation(map, ref p, false))
|
|
{
|
|
break;
|
|
}
|
|
}
|
|
|
|
ant.MoveToWorld(p, map);
|
|
ant.Home = Location;
|
|
ant.RangeHome = 10;
|
|
}
|
|
|
|
public bool SpawnKilled()
|
|
{
|
|
for (var i = _spawned.Count - 1; i >= 0; i--)
|
|
{
|
|
if (!_spawned[i].Alive || _spawned[i].Deleted)
|
|
{
|
|
RemoveFromSpawnedAt(i);
|
|
}
|
|
}
|
|
|
|
return _spawned.Count < 2;
|
|
}
|
|
|
|
private void Deserialize(IGenericReader reader, int version)
|
|
{
|
|
_spawned = reader.ReadEntityList<Mobile>();
|
|
}
|
|
}
|
|
}
|