mirror of
https://github.com/space-wizards/RobustToolbox.git
synced 2026-02-15 03:30:53 +01:00
Have RobustSerializer use a shared string dictionary (#1117)
* implements shared string dictionary and handshake from net-code-2 * fix unit test switch to szr sawmill * try to silence some warnings around ZipEntry * rebase and use system zip instead of icsharplib fix rebase artifacts * Update Robust.Shared/Interfaces/GameObjects/IComponentFactory.cs * Update Robust.Shared/Serialization/RobustSerializer.MappedStringSerializer.cs * Update Robust.Shared/Serialization/RobustSerializer.MappedStringSerializer.cs * Apply suggestions from code review * Apply suggestions from code review * Update Robust.Shared/Serialization/RobustSerializer.cs * since no longer gathering from paths, make string splitting more robust * make string gathering ignore strings under 4 chars long make string gathering yet more robust * add limit to size of mapped strings * add more string data to feed into shared string dictionary from YAML files add JSON importer but don't parse RSI metadata yet fix typo that breaks nulls in MappedStringSerializer minor refactoring make string splitting more robust add WriteUnsignedInt / ReadUnsignedInt for validating WriteCompressedUnsignedInt / ReadCompressedUnsignedInt aren't bogus * comment out some log statements * minor refactor, reorder logging add null check due to smart typing NRT checks * Add doc comments, readability improvements to MappedStringSerializer The protocol, handshake, and internal logic are now more documented. The main area that could still be improved is the documentation of how the cache system works, but the code is readable enough for now that it isn't immediately necessary. * add documentation, organization * update some more doc comments * add flows to doc comment for NetworkInitialize * more documentation and organization * more docs * instead of retrieving INetManager by IoC, assign when NetworkInitialize is invoked * "document" the regex * Update Robust.Shared/Network/NetManager.cs * add missing check for LockMappedStrings * Update Robust.Shared/Serialization/RobustSerializer.MappedStringSerializer.cs Co-authored-by: ComicIronic <comicironic@gmail.com> * change to warning instead of throw for unlocked string mapping Co-authored-by: ComicIronic <comicironic@gmail.com>
This commit is contained in:
@@ -6,20 +6,27 @@ using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Runtime.Loader;
|
||||
using Robust.Shared.Interfaces.Network;
|
||||
|
||||
namespace Robust.Shared.Serialization
|
||||
{
|
||||
|
||||
public class RobustSerializer : IRobustSerializer
|
||||
public partial class RobustSerializer : IRobustSerializer
|
||||
{
|
||||
|
||||
[Dependency] private readonly IReflectionManager reflectionManager = default!;
|
||||
private Serializer Serializer = default!;
|
||||
[Dependency] private readonly IReflectionManager _reflectionManager = default!;
|
||||
[Dependency] private readonly INetManager _netManager = default!;
|
||||
|
||||
private HashSet<Type> SerializableTypes = default!;
|
||||
|
||||
#region Statistics
|
||||
private Serializer _serializer = default!;
|
||||
|
||||
private HashSet<Type> _serializableTypes = default!;
|
||||
|
||||
#region Statistics
|
||||
|
||||
public static long LargestObjectSerializedBytes { get; private set; }
|
||||
|
||||
public static Type? LargestObjectSerializedType { get; private set; }
|
||||
|
||||
public static long BytesSerialized { get; private set; }
|
||||
@@ -27,74 +34,119 @@ namespace Robust.Shared.Serialization
|
||||
public static long ObjectsSerialized { get; private set; }
|
||||
|
||||
public static long LargestObjectDeserializedBytes { get; private set; }
|
||||
|
||||
public static Type? LargestObjectDeserializedType { get; private set; }
|
||||
|
||||
public static long BytesDeserialized { get; private set; }
|
||||
|
||||
public static long ObjectsDeserialized { get; private set; }
|
||||
#endregion
|
||||
|
||||
#endregion
|
||||
|
||||
public void Initialize()
|
||||
{
|
||||
var types = reflectionManager.FindTypesWithAttribute<NetSerializableAttribute>().ToList();
|
||||
#if DEBUG
|
||||
var mappedStringSerializer = new MappedStringSerializer();
|
||||
var types = _reflectionManager.FindTypesWithAttribute<NetSerializableAttribute>().ToList();
|
||||
#if !FULL_RELEASE
|
||||
// confirm only shared types are marked for serialization, no client & server only types
|
||||
foreach (var type in types)
|
||||
{
|
||||
if (type.Assembly.FullName!.Contains("Server") || type.Assembly.FullName.Contains("Client"))
|
||||
if (type.Assembly.FullName!.Contains("Server"))
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type} is server/client specific but has a NetSerializableAttribute!");
|
||||
throw new InvalidOperationException($"Type {type} is server specific but has a NetSerializableAttribute!");
|
||||
}
|
||||
|
||||
if (type.Assembly.FullName.Contains("Client"))
|
||||
{
|
||||
throw new InvalidOperationException($"Type {type} is client specific but has a NetSerializableAttribute!");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
var settings = new Settings();
|
||||
Serializer = new Serializer(types, settings);
|
||||
SerializableTypes = new HashSet<Type>(Serializer.GetTypeMap().Keys);
|
||||
var settings = new Settings
|
||||
{
|
||||
CustomTypeSerializers = new ITypeSerializer[] {mappedStringSerializer}
|
||||
};
|
||||
_serializer = new Serializer(types, settings);
|
||||
_serializableTypes = new HashSet<Type>(_serializer.GetTypeMap().Keys);
|
||||
|
||||
if (_netManager.IsClient)
|
||||
{
|
||||
MappedStringSerializer.LockMappedStrings = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
var defaultAssemblies = AssemblyLoadContext.Default.Assemblies;
|
||||
var gameAssemblies = _reflectionManager.Assemblies;
|
||||
var robustShared = defaultAssemblies
|
||||
.First(a => a.GetName().Name == "Robust.Shared");
|
||||
MappedStringSerializer.AddStrings(robustShared);
|
||||
|
||||
// TODO: Need to add a GetSharedAssemblies method to the reflection manager
|
||||
|
||||
var contentShared = gameAssemblies
|
||||
.FirstOrDefault(a => a.GetName().Name == "Content.Shared");
|
||||
if (contentShared != null)
|
||||
{
|
||||
MappedStringSerializer.AddStrings(contentShared);
|
||||
}
|
||||
|
||||
// TODO: Need to add a GetServerAssemblies method to the reflection manager
|
||||
|
||||
var contentServer = gameAssemblies
|
||||
.FirstOrDefault(a => a.GetName().Name == "Content.Server");
|
||||
if (contentServer != null)
|
||||
{
|
||||
MappedStringSerializer.AddStrings(contentServer);
|
||||
}
|
||||
}
|
||||
|
||||
MappedStringSerializer.NetworkInitialize(_netManager);
|
||||
}
|
||||
|
||||
public void Serialize(Stream stream, object toSerialize)
|
||||
{
|
||||
var start = stream.Position;
|
||||
Serializer.Serialize(stream, toSerialize);
|
||||
_serializer.Serialize(stream, toSerialize);
|
||||
var end = stream.Position;
|
||||
var byteCount = end - start;
|
||||
BytesSerialized += byteCount;
|
||||
++ObjectsSerialized;
|
||||
|
||||
if (byteCount > LargestObjectSerializedBytes)
|
||||
if (byteCount <= LargestObjectSerializedBytes)
|
||||
{
|
||||
LargestObjectSerializedBytes = byteCount;
|
||||
LargestObjectSerializedType = toSerialize.GetType();
|
||||
return;
|
||||
}
|
||||
|
||||
LargestObjectSerializedBytes = byteCount;
|
||||
LargestObjectSerializedType = toSerialize.GetType();
|
||||
}
|
||||
|
||||
public T Deserialize<T>(Stream stream)
|
||||
{
|
||||
return (T) Deserialize(stream);
|
||||
}
|
||||
=> (T) Deserialize(stream);
|
||||
|
||||
public object Deserialize(Stream stream)
|
||||
{
|
||||
var start = stream.Position;
|
||||
var result = Serializer.Deserialize(stream);
|
||||
var result = _serializer.Deserialize(stream);
|
||||
var end = stream.Position;
|
||||
var byteCount = end - start;
|
||||
BytesDeserialized += byteCount;
|
||||
++ObjectsDeserialized;
|
||||
|
||||
if (byteCount > LargestObjectDeserializedBytes)
|
||||
if (byteCount <= LargestObjectDeserializedBytes)
|
||||
{
|
||||
LargestObjectDeserializedBytes = byteCount;
|
||||
LargestObjectDeserializedType = result.GetType();
|
||||
return result;
|
||||
}
|
||||
|
||||
LargestObjectDeserializedBytes = byteCount;
|
||||
LargestObjectDeserializedType = result.GetType();
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool CanSerialize(Type type)
|
||||
{
|
||||
return SerializableTypes.Contains(type);
|
||||
}
|
||||
=> _serializableTypes.Contains(type);
|
||||
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user