fix(core): Updates to serialization (#590)

- [X] Adds `AdhocPersistence` which replaces RunUO `Persistence`
- [X] Fixes a few minor bugs with EntityPersistence deserialization
- [X] Reverts/updates some serialization changes
This commit is contained in:
Kamron Batman 2021-05-09 00:10:39 -07:00 • committed by GitHub
parent f0969223f7
commit 6e9477ea13
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
18 changed files with 370 additions and 248 deletions

View file

@ -126,14 +126,12 @@ namespace Server
continue;
}
T t;
ConstructorInfo ctor = objs.Item1;
I indexer = indexInfo.CreateIndex(number);
ctorArgs[0] = indexer;
t = ctor.Invoke(ctorArgs) as T;
if (t != null)
if (ctor.Invoke(ctorArgs) is T t)
{
entities.Add(new EntityIndex<T>(t, typeID, pos, length));
map[indexer] = t;
@ -162,19 +160,18 @@ namespace Server
}
using FileStream bin = new FileStream(dataPath, FileMode.Open, FileAccess.Read, FileShare.Read);
BufferReader br = null;
foreach (var entry in entities)
{
T t = entry.Entity;
var position = bin.Position;
var position = entry.Position;
bin.Seek(position, SeekOrigin.Begin);
// Skip this entry
if (t == null)
{
bin.Seek(entry.Length, SeekOrigin.Current);
continue;
}
@ -185,7 +182,7 @@ namespace Server
}
else
{
br.SwapBuffers(buffer, out _);
br.Reset(buffer, out _);
}
bin.Read(buffer.AsSpan());
@ -221,8 +218,6 @@ namespace Server
}
t.Delete();
// Skip this entry
bin.Seek(position + entry.Length, SeekOrigin.Begin);
}
}
}

View file

@ -153,6 +153,7 @@ namespace Server
m_DiskWriteHandle.WaitOne();
}
[MethodImpl(MethodImplOptions.AggressiveInlining)]
private static void EnqueueForDecay(Item item)
{
if (WorldState != WorldState.Saving)
@ -468,8 +469,6 @@ namespace Server
Broadcast(0x35, true, "The world is saving, please wait.");
var now = DateTime.UtcNow;
logger.Information("Saving world");
var watch = Stopwatch.StartNew();
@ -645,5 +644,85 @@ namespace Server
[MethodImpl(MethodImplOptions.AggressiveInlining)]
public static void RemoveGuild(BaseGuild guild) => Guilds.Remove(guild.Serial);
private struct TypeOf<T> { }
public static T ReadEntity<T>(this IGenericReader reader) where T : class, ISerializable
{
Serial serial = reader.ReadUInt();
return default(TypeOf<T>) switch
{
TypeOf<BaseGuild> => FindGuild(serial) as T,
TypeOf<IEntity> => FindEntity<IEntity>(serial) as T,
_ => default
};
}
public static List<T> ReadEntityList<T>(this IGenericReader reader) where T : class, ISerializable
{
var count = reader.ReadInt();
var list = new List<T>(count);
for (var i = 0; i < count; ++i)
{
var entity = reader.ReadEntity<T>();
if (entity != null)
{
list.Add(entity);
}
}
return list;
}
public static HashSet<T> ReadEntitySet<T>(this IGenericReader reader) where T : class, ISerializable
{
var count = reader.ReadInt();
var set = new HashSet<T>(count);
for (var i = 0; i < count; ++i)
{
var entity = reader.ReadEntity<T>();
if (entity != null)
{
set.Add(entity);
}
}
return set;
}
public static void Write(this IGenericWriter writer, ISerializable value)
{
writer.Write(value?.Deleted != false ? Serial.MinusOne : value.Serial);
}
public static void Write<T>(this IGenericWriter writer, ICollection<T> coll) where T : class, ISerializable
{
writer.Write(coll.Count);
foreach (var entry in coll)
{
writer.Write(entry);
}
}
public static void Write<T>(
this IGenericWriter writer, ICollection<T> coll, Action<IGenericWriter, T> action
) where T : class, ISerializable
{
if (coll == null)
{
writer.Write(0);
return;
}
writer.Write(coll.Count);
foreach (var entry in coll)
{
action(writer, entry);
}
}
}
}