Add game file persistence functionality
This commit is contained in:
parent
83427b806e
commit
07ba6f2dc4
10 changed files with 441 additions and 0 deletions
|
@ -48,6 +48,7 @@ namespace GamecraftModdingAPI
|
||||||
// init utility
|
// init utility
|
||||||
Logging.MetaDebugLog($"Initializing Utility");
|
Logging.MetaDebugLog($"Initializing Utility");
|
||||||
Utility.GameState.Init();
|
Utility.GameState.Init();
|
||||||
|
Utility.VersionTracking.Init();
|
||||||
// create default event emitters
|
// create default event emitters
|
||||||
Logging.MetaDebugLog($"Initializing Events");
|
Logging.MetaDebugLog($"Initializing Events");
|
||||||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false));
|
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false));
|
||||||
|
|
|
@ -0,0 +1,87 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using Harmony;
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
|
class DeserializeFromDiskEntitiesEnginePatch
|
||||||
|
{
|
||||||
|
internal static EntitiesDB entitiesDB = null;
|
||||||
|
|
||||||
|
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0");
|
||||||
|
|
||||||
|
public static void Prefix(ref ISerializationData ____serializationData, ref FasterList<byte> ____bytesStream, ref IEntitySerialization ____entitySerializer, bool ____spawnBlocksOnly)
|
||||||
|
{
|
||||||
|
if (____spawnBlocksOnly) return; // only run after second deserialization call (when all vanilla stuff is already deserialized)
|
||||||
|
uint originalPos = ____serializationData.dataPos;
|
||||||
|
Logging.MetaDebugLog($"dataPos: {originalPos}");
|
||||||
|
BinaryBufferReader bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out uint count), ____serializationData.dataPos);
|
||||||
|
byte[] frameBuffer = new byte[frameStart.Length];
|
||||||
|
Logging.MetaDebugLog($"serial data count: {____serializationData.data.count} capacity: {____serializationData.data.capacity}");
|
||||||
|
int i = 0;
|
||||||
|
// match frame start
|
||||||
|
while (frameBuffer != frameStart && bbr.Position < count-frameStart.Length)
|
||||||
|
{
|
||||||
|
i = 0;
|
||||||
|
frameBuffer[0] = bbr.ReadByte();
|
||||||
|
while (frameBuffer[i] == frameStart[i] && bbr.Position < count - frameStart.Length + i)
|
||||||
|
{
|
||||||
|
i++;
|
||||||
|
if (i == frameStart.Length) break;
|
||||||
|
frameBuffer[i] = bbr.ReadByte();
|
||||||
|
}
|
||||||
|
if (i == frameStart.Length) break;
|
||||||
|
}
|
||||||
|
// abort if at end of file
|
||||||
|
if (bbr.Position >= count - frameStart.Length)
|
||||||
|
{
|
||||||
|
Logging.MetaLog("Skipping deserialization (no frame found)");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
//____serializationData.dataPos = bbr.Position;
|
||||||
|
Logging.MetaDebugLog($"dataPos (after frame): {bbr.Position}");
|
||||||
|
uint customComponentsCount = bbr.ReadUint();
|
||||||
|
for (uint c = 0; c < customComponentsCount; c++)
|
||||||
|
{
|
||||||
|
// determine component from info
|
||||||
|
uint nameLength = bbr.ReadUint();
|
||||||
|
byte[] nameBytes = new byte[nameLength];
|
||||||
|
bbr.ReadBytes(nameBytes, nameLength);
|
||||||
|
string name = Encoding.UTF8.GetString(nameBytes);
|
||||||
|
Logging.MetaDebugLog($"Component name: {name} (len: {nameLength})");
|
||||||
|
uint componentEnd = bbr.ReadUint();
|
||||||
|
____serializationData.dataPos = bbr.Position;
|
||||||
|
if (SerializerManager.ExistsSerializer(name))
|
||||||
|
{
|
||||||
|
// deserialize component
|
||||||
|
IEntitySerializer serial = SerializerManager.GetSerializer(name);
|
||||||
|
if (!serial.Deserialize(ref ____serializationData, ____entitySerializer))
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog("Component deserialization failed!");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog("Skipping component deserialization: not found!");
|
||||||
|
}
|
||||||
|
bbr = new BinaryBufferReader(____bytesStream.ToArrayFast(out count), componentEnd);
|
||||||
|
}
|
||||||
|
____serializationData.dataPos = originalPos; // change back to original end point (just in case)
|
||||||
|
Logging.MetaDebugLog("Deserialization complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MethodBase TargetMethod()
|
||||||
|
{
|
||||||
|
return AccessTools.Method("RobocraftX.SaveAndLoad.DeserializeFromDiskEntitiesEngine:LoadingFinished");//AccessTools.TypeByName("RobocraftX.SaveAndLoad.DeserializeFromDiskEntities")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
18
GamecraftModdingAPI/Persistence/IEntitySerializer.cs
Normal file
18
GamecraftModdingAPI/Persistence/IEntitySerializer.cs
Normal file
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
public interface IEntitySerializer : IDeserializationFactory, IQueryingEntitiesEngine
|
||||||
|
{
|
||||||
|
IEntityFactory EntityFactory { set; }
|
||||||
|
|
||||||
|
bool Serialize(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer);
|
||||||
|
|
||||||
|
bool Deserialize(ref ISerializationData serializationData, IEntitySerialization entitySerializer);
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,18 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using RobocraftX.SaveAndLoad;
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
using Harmony;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
[HarmonyPatch(typeof(SaveAndLoadCompositionRoot), "Compose")]
|
||||||
|
class SaveAndLoadCompositionRootPatch
|
||||||
|
{
|
||||||
|
public static void Prefix(EnginesRoot enginesRoot)
|
||||||
|
{
|
||||||
|
SerializerManager.RegisterSerializers(enginesRoot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
GamecraftModdingAPI/Persistence/SaveGameEnginePatch.cs
Normal file
81
GamecraftModdingAPI/Persistence/SaveGameEnginePatch.cs
Normal file
|
@ -0,0 +1,81 @@
|
||||||
|
using System;
|
||||||
|
using System.Text;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using RobocraftX.SaveAndLoad;
|
||||||
|
using Svelto.DataStructures;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
using Harmony;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
[HarmonyPatch]
|
||||||
|
class SaveGameEnginePatch
|
||||||
|
{
|
||||||
|
private static readonly byte[] frameStart = Encoding.UTF8.GetBytes("\0\0\0GamecraftModdingAPI\0\0\0");
|
||||||
|
|
||||||
|
public static void Postfix(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog("Running Postfix on SerializeGameToBuffer: serializing custom components...");
|
||||||
|
if (SerializerManager.GetSerializersCount() == 0)
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog("Skipping component serialization: no serializers registered!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
serializationData.data.ExpandBy((uint)frameStart.Length);
|
||||||
|
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint buffLen), serializationData.dataPos);
|
||||||
|
uint originalPos = serializationData.dataPos;
|
||||||
|
Logging.MetaDebugLog($"dataPos: {originalPos}");
|
||||||
|
// Add frame start so it's easier to find GamecraftModdingAPI-serialized components
|
||||||
|
for (int i = 0; i < frameStart.Length; i++)
|
||||||
|
{
|
||||||
|
bbw.Write(frameStart[i]);
|
||||||
|
}
|
||||||
|
Logging.MetaDebugLog($"dataPos (after frame start): {bbw.Position}");
|
||||||
|
serializationData.data.ExpandBy(4u);
|
||||||
|
bbw.Write((uint)SerializerManager.GetSerializersCount());
|
||||||
|
string[] serializerKeys = SerializerManager.GetSerializerNames();
|
||||||
|
for (uint c = 0; c < serializerKeys.Length; c++)
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog($"dataPos (loop start): {bbw.Position}");
|
||||||
|
// write component info
|
||||||
|
serializationData.data.ExpandBy(4u + (uint)serializerKeys[c].Length);
|
||||||
|
bbw.Write((uint)serializerKeys[c].Length);
|
||||||
|
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||||
|
byte[] nameBytes = Encoding.UTF8.GetBytes(serializerKeys[c]);
|
||||||
|
for (int i = 0; i < nameBytes.Length; i++)
|
||||||
|
{
|
||||||
|
bbw.Write(nameBytes[i]);
|
||||||
|
}
|
||||||
|
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||||
|
serializationData.data.ExpandBy(4u);
|
||||||
|
serializationData.dataPos = bbw.Position + 4u;
|
||||||
|
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||||
|
Logging.MetaDebugLog($"dataPos (appears to be): {serializationData.dataPos}");
|
||||||
|
// serialize component
|
||||||
|
IEntitySerializer serializer = SerializerManager.GetSerializer(serializerKeys[c]);
|
||||||
|
if (!serializer.Serialize(ref serializationData, entitiesDB, entitySerializer))
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog("Component serialization failed!");
|
||||||
|
}
|
||||||
|
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||||
|
bbw.Write((uint)serializationData.dataPos);
|
||||||
|
Logging.MetaDebugLog($"dataPos (now): {bbw.Position}");
|
||||||
|
bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out buffLen), serializationData.dataPos);
|
||||||
|
Logging.MetaDebugLog($"dataPos (loop end): {bbw.Position}");
|
||||||
|
}
|
||||||
|
serializationData.data.Trim();
|
||||||
|
Logging.MetaDebugLog($"dataPos (end): {bbw.Position}");
|
||||||
|
Logging.MetaDebugLog("Serialization complete");
|
||||||
|
}
|
||||||
|
|
||||||
|
public static MethodBase TargetMethod()
|
||||||
|
{
|
||||||
|
return typeof(SaveGameEngine).GetMethod("SerializeGameToBuffer");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
72
GamecraftModdingAPI/Persistence/SerializerManager.cs
Normal file
72
GamecraftModdingAPI/Persistence/SerializerManager.cs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
public static class SerializerManager
|
||||||
|
{
|
||||||
|
private static Dictionary<string, IEntitySerializer> _serializers = new Dictionary<string, IEntitySerializer>();
|
||||||
|
|
||||||
|
private static Dictionary<string, Action<IEntitySerialization>> _registrations = new Dictionary<string, Action<IEntitySerialization>>();
|
||||||
|
|
||||||
|
private static EnginesRoot _lastEnginesRoot;
|
||||||
|
|
||||||
|
public static void AddSerializer<T>(IEntitySerializer serializer) where T : ISerializableEntityDescriptor, new()
|
||||||
|
{
|
||||||
|
string name = typeof(T).FullName;
|
||||||
|
_serializers[name] = serializer;
|
||||||
|
_registrations[name] = (IEntitySerialization ies) => { ies.RegisterSerializationFactory<T>(serializer); };
|
||||||
|
if (_lastEnginesRoot != null)
|
||||||
|
{
|
||||||
|
serializer.EntityFactory = _lastEnginesRoot.GenerateEntityFactory();
|
||||||
|
_registrations[name].Invoke(_lastEnginesRoot.GenerateEntitySerializer());
|
||||||
|
_lastEnginesRoot.AddEngine(serializer);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExistsSerializer(string name)
|
||||||
|
{
|
||||||
|
return _serializers.ContainsKey(name);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static bool ExistsSerializer<T>(IEntitySerializer serializer) where T : ISerializableEntityDescriptor, new()
|
||||||
|
{
|
||||||
|
return ExistsSerializer(typeof(T).FullName);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static IEntitySerializer GetSerializer(string name)
|
||||||
|
{
|
||||||
|
return _serializers[name];
|
||||||
|
}
|
||||||
|
|
||||||
|
public static string[] GetSerializerNames()
|
||||||
|
{
|
||||||
|
return _serializers.Keys.ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static int GetSerializersCount()
|
||||||
|
{
|
||||||
|
return _serializers.Count;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void RegisterSerializers(EnginesRoot enginesRoot)
|
||||||
|
{
|
||||||
|
_lastEnginesRoot = enginesRoot;
|
||||||
|
IEntityFactory factory = enginesRoot.GenerateEntityFactory();
|
||||||
|
IEntitySerialization ies = enginesRoot.GenerateEntitySerializer();
|
||||||
|
foreach (string key in _serializers.Keys)
|
||||||
|
{
|
||||||
|
Logging.MetaDebugLog($"Registering IEntitySerializer for {key}");
|
||||||
|
_serializers[key].EntityFactory = factory;
|
||||||
|
_registrations[key].Invoke(ies);
|
||||||
|
enginesRoot.AddEngine(_serializers[key]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
63
GamecraftModdingAPI/Persistence/SimpleEntitySerializer.cs
Normal file
63
GamecraftModdingAPI/Persistence/SimpleEntitySerializer.cs
Normal file
|
@ -0,0 +1,63 @@
|
||||||
|
using System;
|
||||||
|
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using RobocraftX.Common;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Persistence
|
||||||
|
{
|
||||||
|
public class SimpleEntitySerializer<Descriptor> : IEntitySerializer where Descriptor : ISerializableEntityDescriptor, new()
|
||||||
|
{
|
||||||
|
public delegate EGID[] GetEntitiesToSerialize(EntitiesDB entitiesDB);
|
||||||
|
|
||||||
|
private GetEntitiesToSerialize getEntitiesToSerialize;
|
||||||
|
|
||||||
|
protected int serializationType;
|
||||||
|
|
||||||
|
public IEntityFactory EntityFactory { set; protected get; }
|
||||||
|
|
||||||
|
public EntitiesDB entitiesDB { set; protected get; }
|
||||||
|
|
||||||
|
public EntityComponentInitializer BuildDeserializedEntity(EGID egid, ISerializationData serializationData, ISerializableEntityDescriptor entityDescriptor, int serializationType, IEntitySerialization entitySerialization)
|
||||||
|
{
|
||||||
|
EntityComponentInitializer esi = EntityFactory.BuildEntity<Descriptor>(egid);
|
||||||
|
entitySerialization.DeserializeEntityComponents(serializationData, entityDescriptor, ref esi, serializationType);
|
||||||
|
return esi;
|
||||||
|
}
|
||||||
|
|
||||||
|
public bool Deserialize(ref ISerializationData serializationData, IEntitySerialization entitySerializer)
|
||||||
|
{
|
||||||
|
BinaryBufferReader bbr = new BinaryBufferReader(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
|
||||||
|
uint entityCount = bbr.ReadUint();
|
||||||
|
serializationData.dataPos = bbr.Position;
|
||||||
|
for (uint i = 0; i < entityCount; i++)
|
||||||
|
{
|
||||||
|
entitySerializer.DeserializeEntity(serializationData, serializationType);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Ready() { }
|
||||||
|
|
||||||
|
public bool Serialize(ref ISerializationData serializationData, EntitiesDB entitiesDB, IEntitySerialization entitySerializer)
|
||||||
|
{
|
||||||
|
serializationData.data.ExpandBy(4u);
|
||||||
|
BinaryBufferWriter bbw = new BinaryBufferWriter(serializationData.data.ToArrayFast(out uint count), serializationData.dataPos);
|
||||||
|
EGID[] toSerialize = getEntitiesToSerialize(entitiesDB);
|
||||||
|
bbw.Write((uint)toSerialize.Length);
|
||||||
|
serializationData.dataPos = bbw.Position;
|
||||||
|
for (uint i = 0; i < toSerialize.Length; i++)
|
||||||
|
{
|
||||||
|
entitySerializer.SerializeEntity(toSerialize[i], serializationData, serializationType);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public SimpleEntitySerializer(GetEntitiesToSerialize getEntitiesToSerialize)
|
||||||
|
{
|
||||||
|
this.getEntitiesToSerialize = getEntitiesToSerialize;
|
||||||
|
serializationType = (int)SerializationType.Storage;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -44,6 +44,7 @@ namespace GamecraftModdingAPI.Tests
|
||||||
FileLog.Reset();
|
FileLog.Reset();
|
||||||
HarmonyInstance.DEBUG = true;
|
HarmonyInstance.DEBUG = true;
|
||||||
GamecraftModdingAPI.Main.Init();
|
GamecraftModdingAPI.Main.Init();
|
||||||
|
Logging.MetaDebugLog($"Version group id {(uint)ApiExclusiveGroups.versionGroup}");
|
||||||
// in case Steam is not installed/running
|
// in case Steam is not installed/running
|
||||||
// this will crash the game slightly later during startup
|
// this will crash the game slightly later during startup
|
||||||
//SteamInitPatch.ForcePassSteamCheck = true;
|
//SteamInitPatch.ForcePassSteamCheck = true;
|
||||||
|
@ -55,6 +56,8 @@ namespace GamecraftModdingAPI.Tests
|
||||||
Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers()));
|
Logging.MetaDebugLog("Audio Mixers: "+string.Join(",", AudioTools.GetMixers()));
|
||||||
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(
|
//AudioTools.SetVolume(0.0f, "Music"); // The game now sets this from settings again after this is called :(
|
||||||
|
|
||||||
|
Utility.VersionTracking.Enable();
|
||||||
|
|
||||||
// debug/test handlers
|
// debug/test handlers
|
||||||
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { },
|
EventManager.AddEventHandler(new SimpleEventHandlerEngine(() => { Logging.Log("App Inited event!"); }, () => { },
|
||||||
EventType.ApplicationInitialized, "appinit API debug"));
|
EventType.ApplicationInitialized, "appinit API debug"));
|
||||||
|
|
|
@ -13,5 +13,7 @@ namespace GamecraftModdingAPI.Utility
|
||||||
public static readonly ExclusiveGroup eventsExclusiveGroup = new ExclusiveGroup();
|
public static readonly ExclusiveGroup eventsExclusiveGroup = new ExclusiveGroup();
|
||||||
|
|
||||||
public static uint eventID;
|
public static uint eventID;
|
||||||
|
|
||||||
|
public static readonly ExclusiveGroup versionGroup = new ExclusiveGroup("GamecraftModdingAPIVersion");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
96
GamecraftModdingAPI/Utility/VersionTracking.cs
Normal file
96
GamecraftModdingAPI/Utility/VersionTracking.cs
Normal file
|
@ -0,0 +1,96 @@
|
||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using Svelto.ECS;
|
||||||
|
using Svelto.ECS.Serialization;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Persistence;
|
||||||
|
using GamecraftModdingAPI.Events;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Utility
|
||||||
|
{
|
||||||
|
public static class VersionTracking
|
||||||
|
{
|
||||||
|
private static readonly VersionTrackingEngine versionEngine = new VersionTrackingEngine();
|
||||||
|
|
||||||
|
private static bool isEnabled = false;
|
||||||
|
|
||||||
|
public static uint GetVersion()
|
||||||
|
{
|
||||||
|
if (!isEnabled) return 0u;
|
||||||
|
return versionEngine.GetGameVersion();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Enable()
|
||||||
|
{
|
||||||
|
EventManager.AddEventEmitter(versionEngine);
|
||||||
|
isEnabled = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Disable()
|
||||||
|
{
|
||||||
|
EventManager.AddEventEmitter(versionEngine);
|
||||||
|
isEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
SerializerManager.AddSerializer<ModVersionDescriptor>(new SimpleEntitySerializer<ModVersionDescriptor>(
|
||||||
|
(_) => { return new EGID[1] { new EGID(0u, ApiExclusiveGroups.versionGroup) }; }
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
internal class VersionTrackingEngine : IEventEmitterEngine
|
||||||
|
{
|
||||||
|
public string Name { get; } = "GamecraftModdingAPIVersionTrackingGameEngine";
|
||||||
|
|
||||||
|
public EntitiesDB entitiesDB { set; private get; }
|
||||||
|
|
||||||
|
public int type => -1;
|
||||||
|
|
||||||
|
public bool isRemovable => false;
|
||||||
|
|
||||||
|
public IEntityFactory Factory { set; private get; }
|
||||||
|
|
||||||
|
public void Dispose() { }
|
||||||
|
|
||||||
|
public void Ready()
|
||||||
|
{
|
||||||
|
EGID egid = new EGID(0u, ApiExclusiveGroups.versionGroup);
|
||||||
|
if (!entitiesDB.Exists<ModVersionStruct>(egid))
|
||||||
|
{
|
||||||
|
Version currentVersion = Assembly.GetExecutingAssembly().GetName().Version;
|
||||||
|
int v = (currentVersion.Major * 1000) + (currentVersion.Minor);
|
||||||
|
Factory.BuildEntity<ModVersionDescriptor>(egid).Init<ModVersionStruct>(new ModVersionStruct
|
||||||
|
{
|
||||||
|
version = (uint)v
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public uint GetGameVersion()
|
||||||
|
{
|
||||||
|
return entitiesDB.QueryUniqueEntity<ModVersionStruct>(ApiExclusiveGroups.versionGroup).version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void Emit() { }
|
||||||
|
}
|
||||||
|
|
||||||
|
public struct ModVersionStruct : IEntityComponent
|
||||||
|
{
|
||||||
|
public uint version;
|
||||||
|
}
|
||||||
|
|
||||||
|
public class ModVersionDescriptor: SerializableEntityDescriptor<ModVersionDescriptor._ModVersionDescriptor>
|
||||||
|
{
|
||||||
|
[HashName("GamecraftModdingAPIVersionV0")]
|
||||||
|
public class _ModVersionDescriptor : IEntityDescriptor
|
||||||
|
{
|
||||||
|
public IComponentBuilder[] componentsToBuild { get; } = new IComponentBuilder[]{
|
||||||
|
new SerializableComponentBuilder<SerializationType, ModVersionStruct>(((int)SerializationType.Network, new DefaultSerializer<ModVersionStruct>()), ((int)SerializationType.Storage, new DefaultSerializer<ModVersionStruct>())),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in a new issue