@@ -1,218 +0,0 @@ | |||
using System; | |||
using System.Collections; | |||
using System.Collections.Generic; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Reflection; | |||
using HarmonyLib; | |||
using DataLoader; | |||
using RobocraftX.Common; | |||
using RobocraftX.Rendering; | |||
using RobocraftX.Schedulers; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Experimental; | |||
using Svelto.Tasks; | |||
using Svelto.Tasks.ExtraLean; | |||
using UnityEngine; | |||
using UnityEngine.AddressableAssets; | |||
using Material = UnityEngine.Material; | |||
using ServiceLayer; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Blocks | |||
{ | |||
/// <summary> | |||
/// Experimental support for adding custom blocks to the game. | |||
/// </summary> | |||
public class CustomBlock : Block | |||
{ | |||
private static ushort nextID = 500; | |||
/// <summary> | |||
/// Key: Prefab path | |||
/// </summary> | |||
private static readonly Dictionary<string, Type> CustomBlocks = new Dictionary<string, Type>(); | |||
//private static readonly CustomBlockEngine Engine = new CustomBlockEngine(); | |||
private static readonly List<(ushort id, Action<CubeListData> action)> BlockChangeActions = | |||
new List<(ushort, Action<CubeListData>)>(); | |||
private static bool _canRegister = true; | |||
/// <summary> | |||
/// Register a custom block type. Call it as soon as possible (in OnApplicationStart()).<br /> | |||
/// You need a Unity project with Addressables and Havok installed and need a prefab added as an addressable asset. | |||
/// Build the addressables and the project and copy the catalog.json from StreamingAssets, you'll need to reference this file. | |||
/// Also copy the asset files from the subfolder to the same path in the game. | |||
/// </summary> | |||
/// <typeparam name="T">The custom block type</typeparam> | |||
public static void RegisterCustomBlock<T>() where T : CustomBlock | |||
{ | |||
if (!_canRegister) | |||
throw new InvalidOperationException( | |||
"It's too late to register custom blocks. Register it before the game starts loading."); | |||
var type = typeof(T); | |||
var attr = type.GetCustomAttribute<CustomBlockAttribute>(); | |||
if (attr == null) | |||
throw new ArgumentException("The custom block type is missing the CustomBlock annotation"); | |||
string typeName = type.FullName ?? | |||
throw new ArgumentException("The given block type doesn't have a concrete full name."); | |||
if (!File.Exists(attr.Catalog)) | |||
throw new FileNotFoundException("The specified catalog cannot be found for " + typeName); | |||
CustomBlocks.Add(attr.AssetPath, type); | |||
Logging.MetaDebugLog("Registered custom block type " + typeName); | |||
} | |||
/// <summary> | |||
/// A low-level method for changing any property of an existing block. Use with caution. | |||
/// </summary> | |||
/// <param name="id">The block ID</param> | |||
/// <param name="modifier">An action that modifies a property of the block</param> | |||
public static void ChangeExistingBlock(ushort id, Action<CubeListData> modifier) | |||
{ | |||
BlockChangeActions.Add((id, modifier)); | |||
} | |||
public CustomBlock(EGID id) : base(id) | |||
{ | |||
/*if (id.groupID != Group) | |||
throw new BlockTypeException("The block is not a custom block! It has a group of " + id.groupID);*/ | |||
} | |||
public CustomBlock(uint id) : base(id) | |||
{ | |||
} | |||
//public static ExclusiveGroup Group { get; } = new ExclusiveGroup("Custom block"); | |||
//[HarmonyPatch] - TODO | |||
public static class MaterialCopyPatch | |||
{ | |||
private static Material[] materials; | |||
public static void Prefix(List<PrefabData> prefabData, IList<GameObject> prefabs) | |||
{ | |||
for (var index = 0; index < prefabs.Count; index++) | |||
{ | |||
if (prefabData[index].prefabName == "ConsoleBlock") | |||
materials = prefabs[index].GetComponentsInChildren<MeshRenderer>()[0].sharedMaterials; | |||
} | |||
for (var index = 0; index < prefabs.Count; index++) | |||
{ | |||
if (CustomBlocks.ContainsKey(prefabData[index].prefabName)) //This is a custom block | |||
prefabs[index].GetComponentsInChildren<MeshRenderer>()[0].sharedMaterials = materials; | |||
} | |||
} | |||
public static MethodBase TargetMethod() | |||
{ //General block registration | |||
return AccessTools.Method("RobocraftX.Rendering.ECSGPUIResourceManager:InitPreRegisteredPrefabs"); | |||
} | |||
} | |||
[HarmonyPatch] | |||
public static class CubeRegistrationPatch | |||
{ | |||
public static void Prefix(IDataDB dataDB) | |||
{ | |||
//var abd = dataDB.GetValue<CubeListData>((int) BlockIDs.Cube); | |||
foreach (var (key, type) in CustomBlocks) | |||
{ | |||
var attr = type.GetCustomAttribute<CustomBlockAttribute>(); | |||
var cld = new CubeListData | |||
{ //"Assets/Prefabs/Cube.prefab" - "CTR_CommandBlock" - "strConsoleBlock" | |||
cubeType = attr.Type, | |||
//cubeCategory = (CubeCategory) 1000, | |||
cubeCategory = attr.Category, | |||
inventoryCategory = attr.InventoryCategory, | |||
ID = nextID++, | |||
Path = attr.AssetPath, //Index out of range exception: Asset failed to load (wrong path) | |||
SpriteName = attr.SpriteName, | |||
CubeNameKey = attr.NameKey, | |||
CubeDescriptionKey = attr.DescKey, | |||
SelectableFaces = new[] {0, 1, 2, 3, 4, 5}, | |||
GridScale = new[] {5f, 5, 5}, | |||
DefaultMaterialID = 0, //TODO: Material API | |||
scalingPermission = attr.ScalingPermission, | |||
SortIndex = attr.SortIndex, | |||
DefaultColour = attr.DefaultColor.Index, | |||
Volume = attr.Volume, | |||
EdgeConnectingFaces = new[] {0, 1, 2, 3, 4, 5}, | |||
PointDataVolumeMultiplier = 1f | |||
}; | |||
dataDB.GetValues<CubeListData>().Add(cld.ID.ToString(), cld); //The registration needs to happen after the ID has been set | |||
dataDB.GetFasterValues<CubeListData>().Add(cld.ID, cld); //So can't use the builtin method to create a CubeListData | |||
//Engine.RegisterBlock((ushort) cld.ID, key); - TODO | |||
} | |||
foreach (var (id, action) in BlockChangeActions) | |||
action(dataDB.GetValue<CubeListData>(id)); | |||
/*ushort lastKey = ushort.MaxValue; | |||
foreach (var (key, value) in dataDB.GetValues<CubeListData>() | |||
.OrderBy(kv=>ushort.Parse(kv.Key))) | |||
{ | |||
var data = (CubeListData) value; | |||
ushort currentKey = ushort.Parse(key); | |||
Console.WriteLine($"{LocalizationService.Localize(data.CubeNameKey)}{(currentKey != lastKey + 1 ? $" = {key}" : "")},"); | |||
lastKey = currentKey; | |||
}*/ | |||
_canRegister = false; | |||
} | |||
public static MethodBase TargetMethod() | |||
{ | |||
return AccessTools.Method("RobocraftX.CR.MainGame.MainGameCompositionRoot:Init"); | |||
} | |||
} | |||
/*[HarmonyPatch] - The block has no collision even in simulation if using a custom category | |||
private static class FactorySetupPatch | |||
{ | |||
public static void Prefix(BlockEntityFactory __instance) | |||
{ | |||
var builders = (Dictionary<CubeCategory, IBlockBuilder>) | |||
AccessTools.Field(__instance.GetType(), "_blockBuilders").GetValue(__instance); | |||
builders.Add((CubeCategory) 1000, new BlockBuilder<StandardBlockEntityDescriptor>(Group)); | |||
} | |||
public static MethodBase TargetMethod() | |||
{ | |||
return AccessTools.Method(typeof(BlockEntityFactory), "ParseDataDB"); | |||
} | |||
}*/ | |||
private static IEnumerator Prepare() | |||
{ //Should be pretty quick | |||
foreach (var type in CustomBlocks.Values) | |||
{ | |||
var attr = type.GetCustomAttribute<CustomBlockAttribute>(); | |||
Logging.Log("Loading custom block catalog " + attr.Catalog); | |||
var res = Addressables.LoadContentCatalogAsync(attr.Catalog); | |||
while (!res.IsDone) yield return Yield.It; | |||
Logging.Log("Loaded custom block catalog: " + res.Result.LocatorId); | |||
Addressables.AddResourceLocator(res.Result); | |||
} | |||
} | |||
internal new static void Init() | |||
{ | |||
Prepare().RunOn(ExtraLean.UIScheduler); | |||
//GameEngineManager.AddGameEngine(Engine); - TODO: Fix serialization and implement block ID update | |||
} | |||
/*internal static void OnBlockFactoryObtained(BlockEntityFactory factory) | |||
{ | |||
var builders = (Dictionary<CubeCategory, IBlockBuilder>) | |||
AccessTools.Field(factory.GetType(), "_blockBuilders").GetValue(factory); | |||
builders.Add((CubeCategory) 1000, new BlockBuilder<StandardBlockEntityDescriptor>(Group)); | |||
}*/ | |||
internal struct DataStruct : IEntityComponent | |||
{ | |||
public ECSString Name; | |||
public ushort ID; | |||
} | |||
} | |||
} |
@@ -1,85 +0,0 @@ | |||
using System; | |||
using DataLoader; | |||
namespace TechbloxModdingAPI.Blocks | |||
{ | |||
[AttributeUsage(AttributeTargets.Class)] | |||
public class CustomBlockAttribute : Attribute | |||
{ | |||
/// <summary> | |||
/// Custom block attribute necessary for configuration. | |||
/// </summary> | |||
/// <param name="catalog">File path to the catalog.json that holds asset references for the custom block</param> | |||
/// <param name="assetPath">The path/address to the block's prefab specified in Unity</param> | |||
/// <param name="nameKey">The translation key for the block's name</param> | |||
/// <param name="spriteName">The path to the inventory sprite for the block, console block by default</param> | |||
/// <param name="descKey">The translation key for the block's description</param> | |||
public CustomBlockAttribute(string catalog, string assetPath, string nameKey, | |||
string spriteName = "CTR_CommandBlock", string descKey = "") | |||
{ | |||
Catalog = catalog; | |||
AssetPath = assetPath; | |||
SpriteName = spriteName; | |||
NameKey = nameKey; | |||
DescKey = descKey; | |||
} | |||
/// <summary> | |||
/// The location of the catalog.json file used to find assets for this block. | |||
/// </summary> | |||
public string Catalog { get; } | |||
/// <summary> | |||
/// The asset path/address for the block's prefab. | |||
/// </summary> | |||
public string AssetPath { get; } | |||
/// <summary> | |||
/// The name of the sprite used in the inventory. | |||
/// </summary> | |||
public string SpriteName { get; } | |||
/// <summary> | |||
/// The translation key for the block's name. | |||
/// </summary> | |||
public string NameKey { get; } | |||
/// <summary> | |||
/// The translation key for the block's description. | |||
/// </summary> | |||
public string DescKey { get; } | |||
/// <summary> | |||
/// The block's type - block, joint, light. | |||
/// </summary> | |||
public CubeType Type { get; set; } = CubeType.Block; | |||
/// <summary> | |||
/// The block's category, so it's treated as a pre-existing functional block. | |||
/// </summary> | |||
public CubeCategory Category { get; set; } = CubeCategory.General; | |||
/// <summary> | |||
/// The block's inventory category. | |||
/// </summary> | |||
public InventoryCategory InventoryCategory { get; set; } = InventoryCategory.Shapes; | |||
/// <summary> | |||
/// The block's mass. | |||
/// </summary> | |||
public float Mass { get; set; } = 1f; | |||
/// <summary> | |||
/// The key of the material properties this block should use. | |||
/// </summary> | |||
public string Material { get; set; } = "Aluminium"; | |||
/// <summary> | |||
/// The scaling permission determining what scaling is allowed on this block. | |||
/// </summary> | |||
public ScalingPermission ScalingPermission { get; set; } | |||
/// <summary> | |||
/// The sort index in the inventory. | |||
/// </summary> | |||
public int SortIndex { get; set; } | |||
/// <summary> | |||
/// The default color of the block when placed. | |||
/// </summary> | |||
public BlockColor DefaultColor { get; set; } | |||
/// <summary> | |||
/// The volume of the block. | |||
/// </summary> | |||
public float Volume { get; set; } = 1f; | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
namespace TechbloxModdingAPI.Blocks.Engines | |||
{ | |||
/*public class CustomBlockEngine : IFactoryEngine | |||
{ | |||
public class CustomBlockEntityDescriptor : SerializableEntityDescriptor<CustomBlockEntityDescriptor._CustomBlockDescriptor> | |||
{ | |||
[HashName("TechbloxModdingAPICustomBlockV0")] | |||
public class _CustomBlockDescriptor : IEntityDescriptor | |||
{ | |||
public IComponentBuilder[] componentsToBuild { get; } = | |||
{ | |||
new SerializableComponentBuilder<SerializationType, CustomBlock.DataStruct>( | |||
((int) SerializationType.Network, new DefaultSerializer<CustomBlock.DataStruct>()), | |||
((int) SerializationType.Storage, new DefaultSerializer<CustomBlock.DataStruct>())) | |||
}; | |||
} | |||
} | |||
public void Ready() | |||
{ | |||
SerializerManager.AddSerializer<CustomBlockEntityDescriptor>( | |||
new SimpleEntitySerializer<CustomBlockEntityDescriptor>(db => | |||
{ | |||
var (coll, c) = db.QueryEntities<CustomBlock.DataStruct>(ApiExclusiveGroups.customBlockGroup); | |||
var egids = new EGID[c]; | |||
for (int i = 0; i < c; i++) | |||
egids[i] = new EGID(coll[i].ID, ApiExclusiveGroups.customBlockGroup); | |||
return egids; | |||
})); | |||
foreach (var (id, name) in _registeredBlocks) | |||
{ | |||
Factory.BuildEntity<CustomBlockEntityDescriptor>(id, ApiExclusiveGroups.customBlockGroup) | |||
.Init(new CustomBlock.DataStruct {Name = new ECSString(name), ID = id}); | |||
} | |||
} | |||
public EntitiesDB entitiesDB { get; set; } | |||
private List<(ushort id, string name)> _registeredBlocks = new List<(ushort, string)>(); | |||
public void Dispose() | |||
{ | |||
} | |||
public void RegisterBlock(ushort id, string name) | |||
{ | |||
_registeredBlocks.Add((id, name)); | |||
} | |||
public string Name { get; } = "TechbloxModdingAPICustomBlockEngine"; | |||
public bool isRemovable { get; } = false; | |||
public IEntityFactory Factory { get; set; } | |||
}*/ | |||
} |
@@ -1,47 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using HarmonyLib; | |||
using Svelto.ECS; | |||
using RobocraftX.Common; | |||
using RobocraftX.StateSync; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.StateSync.DeterministicStepCompositionRoot.ComposeEnginesGroups(...) | |||
/// </summary> | |||
//[HarmonyPatch(typeof(DeterministicStepCompositionRoot), "DeterministicCompose")] | |||
[Obsolete] | |||
[HarmonyPatch] | |||
class GameHostTransitionDeterministicGroupEnginePatch | |||
{ | |||
public static readonly GameStateBuildEmitterEngine buildEngine = new GameStateBuildEmitterEngine(); | |||
public static readonly GameStateSimulationEmitterEngine simEngine = new GameStateSimulationEmitterEngine(); | |||
public static void Postfix() | |||
{ | |||
//stateSyncReg.buildModeInitializationEngines.Add(buildEngine); | |||
//stateSyncReg.simulationModeInitializationEngines.Add(simEngine); | |||
//enginesRoot.AddEngine(buildEngine); | |||
//enginesRoot.AddEngine(simEngine); | |||
buildEngine.EmitIfBuildMode(); | |||
simEngine.EmitIfSimMode(); | |||
} | |||
[HarmonyTargetMethod] | |||
public static MethodBase TargetMethod(Harmony harmonyInstance) | |||
{ | |||
return AccessTools.Method(AccessTools.TypeByName("RobocraftX.StateSync.GameHostTransitionDeterministicGroupEngine"), "EndTransition"); | |||
//.MakeGenericMethod(typeof(CosmeticEnginesSequenceBuildOrder), typeof(CosmeticEnginesSequenceSimOrder), typeof(DeterministicToCosmeticSyncBuildOrder), typeof(DeterministicToCosmeticSyncSimOrder)); | |||
} | |||
} | |||
} |
@@ -1,106 +0,0 @@ | |||
using System; | |||
using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
[Obsolete] | |||
public class EmitterBuilder | |||
{ | |||
private string name; | |||
private int? type; | |||
/// <summary> | |||
/// Create a new event emitter builder. | |||
/// </summary> | |||
public EmitterBuilder() | |||
{ | |||
} | |||
/// <summary> | |||
/// Create a new event emitter builder. | |||
/// This is equivalent to new <code>EmitterBuilder().Name(name)</code> | |||
/// </summary> | |||
/// <param name="name">The emitter name.</param> | |||
public EmitterBuilder(string name) | |||
{ | |||
this.name = name; | |||
} | |||
/// <summary> | |||
/// Create and return an event emitter builder. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
public static EmitterBuilder Builder() | |||
{ | |||
return new EmitterBuilder(); | |||
} | |||
/// <summary> | |||
/// Create and return an event emitter builder. | |||
/// This is equivalent to <code>Builder().Name(name)</code> | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="name">The emitter name.</param> | |||
public static EmitterBuilder Builder(string name) | |||
{ | |||
return new EmitterBuilder(name); | |||
} | |||
/// <summary> | |||
/// Name the event emitter. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="name">The event emitter name.</param> | |||
public EmitterBuilder Name(string name) | |||
{ | |||
this.name = name; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Set the type of event to handle. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="eventType">The event type.</param> | |||
public EmitterBuilder Handle(EventType eventType) | |||
{ | |||
return Handle((int)eventType); | |||
} | |||
/// <summary> | |||
/// Set the type of event to handle. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="eventType">The event type.</param> | |||
public EmitterBuilder Handle(int eventType) | |||
{ | |||
this.type = eventType; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Build the event emitter. | |||
/// </summary> | |||
/// <returns>The event emitter.</returns> | |||
/// <param name="register">Automatically register the event emitter with EventManager.AddEventemitter().</param> | |||
public IEventEmitterEngine Build(bool register = true) | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new EventParameterMissingException("Event emitter name must be defined before Build() is called"); | |||
} | |||
if (!type.HasValue) | |||
{ | |||
throw new EventParameterMissingException("Event emitter event type must be defined before Build() is called"); | |||
} | |||
SimpleEventEmitterEngine result = new SimpleEventEmitterEngine(type.Value, name); | |||
if (register) | |||
{ | |||
EventManager.AddEventEmitter(result); | |||
} | |||
return result; | |||
} | |||
} | |||
} |
@@ -1,61 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Convenient factories for mod event engines | |||
/// </summary> | |||
[Obsolete] | |||
public static class EventEngineFactory | |||
{ | |||
/// <summary> | |||
/// Factory method which automatically adds the SimpleEventHandlerEngine to the Manager | |||
/// </summary> | |||
/// <param name="name">The name of the engine</param> | |||
/// <param name="type">The type of event to handle</param> | |||
/// <param name="onActivated">The operation to do when the event is created</param> | |||
/// <param name="onDestroyed">The operation to do when the event is destroyed (if applicable)</param> | |||
/// <returns>The created object</returns> | |||
public static SimpleEventHandlerEngine CreateAddSimpleHandler(string name, int type, Action onActivated, Action onDestroyed) | |||
{ | |||
var engine = new SimpleEventHandlerEngine(onActivated, onDestroyed, type, name); | |||
EventManager.AddEventHandler(engine); | |||
return engine; | |||
} | |||
/// <summary> | |||
/// Factory method which automatically adds the SimpleEventHandlerEngine to the Manager | |||
/// </summary> | |||
/// <param name="name">The name of the engine</param> | |||
/// <param name="type">The type of event to handle</param> | |||
/// <param name="onActivated">The operation to do when the event is created</param> | |||
/// <param name="onDestroyed">The operation to do when the event is destroyed (if applicable)</param> | |||
/// <returns>The created object</returns> | |||
public static SimpleEventHandlerEngine CreateAddSimpleHandler(string name, int type, Action<EntitiesDB> onActivated, Action<EntitiesDB> onDestroyed) | |||
{ | |||
var engine = new SimpleEventHandlerEngine(onActivated, onDestroyed, type, name); | |||
EventManager.AddEventHandler(engine); | |||
return engine; | |||
} | |||
/// <summary> | |||
/// Factory method which automatically adds the SimpleEventEmitterEngine to the Manager | |||
/// </summary> | |||
/// <param name="name">The name of the engine</param> | |||
/// <param name="type">The type of event to emit</param> | |||
/// <param name="isRemovable">Will removing this engine not break your code?</param> | |||
/// <returns>The created object</returns> | |||
public static SimpleEventEmitterEngine CreateAddSimpleEmitter(string name, int type, bool isRemovable = true) | |||
{ | |||
var engine = new SimpleEventEmitterEngine(type, name, isRemovable); | |||
EventManager.AddEventEmitter(engine); | |||
return engine; | |||
} | |||
} | |||
} |
@@ -16,28 +16,6 @@ namespace TechbloxModdingAPI.Events | |||
} | |||
} | |||
public class EventNotFoundException : EventException | |||
{ | |||
public EventNotFoundException() | |||
{ | |||
} | |||
public EventNotFoundException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
public class EventAlreadyExistsException : EventException | |||
{ | |||
public EventAlreadyExistsException() | |||
{ | |||
} | |||
public EventAlreadyExistsException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
public class EventRuntimeException : EventException | |||
{ | |||
public EventRuntimeException() | |||
@@ -52,15 +30,4 @@ namespace TechbloxModdingAPI.Events | |||
{ | |||
} | |||
} | |||
public class EventParameterMissingException : EventException | |||
{ | |||
public EventParameterMissingException() | |||
{ | |||
} | |||
public EventParameterMissingException(string message) : base(message) | |||
{ | |||
} | |||
} | |||
} |
@@ -1,128 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Keeps track of event handlers and emitters. | |||
/// This is used to add, remove and get API event handlers and emitters. | |||
/// </summary> | |||
[Obsolete("This will be removed in an upcoming update. Use the new C# event architecture from TechbloxModdingAPI.App")] | |||
public static class EventManager | |||
{ | |||
private static Dictionary<string, IEventEmitterEngine> _eventEmitters = new Dictionary<string, IEventEmitterEngine>(); | |||
private static Dictionary<string, IEventHandlerEngine> _eventHandlers = new Dictionary<string, IEventHandlerEngine>(); | |||
private static EnginesRoot _lastEngineRoot; | |||
// event handler management | |||
public static void AddEventHandler(IEventHandlerEngine engine) | |||
{ | |||
if (ExistsEventHandler(engine)) | |||
{ | |||
throw new EventAlreadyExistsException($"IEventHandlerEngine {engine.Name} already exists"); | |||
} | |||
_eventHandlers[engine.Name] = engine; | |||
if (_lastEngineRoot != null) | |||
{ | |||
Logging.MetaDebugLog($"Registering IEventHandlerEngine {engine.Name}"); | |||
_lastEngineRoot.AddEngine(engine); | |||
} | |||
} | |||
public static bool ExistsEventHandler(string name) | |||
{ | |||
return _eventHandlers.ContainsKey(name); | |||
} | |||
public static bool ExistsEventHandler(IEventHandlerEngine engine) | |||
{ | |||
return ExistsEventHandler(engine.Name); | |||
} | |||
public static IEventHandlerEngine GetEventHandler(string name) | |||
{ | |||
return _eventHandlers[name]; | |||
} | |||
public static string[] GetEventHandlerNames() | |||
{ | |||
return _eventHandlers.Keys.ToArray(); | |||
} | |||
public static void RemoveEventHandler(string name) | |||
{ | |||
_eventHandlers.Remove(name); | |||
} | |||
// event emitter management | |||
public static void AddEventEmitter(IEventEmitterEngine engine) | |||
{ | |||
if (ExistsEventEmitter(engine)) | |||
{ | |||
throw new EventAlreadyExistsException($"IEventEmitterEngine {engine.Name} already exists"); | |||
} | |||
_eventEmitters[engine.Name] = engine; | |||
if (_lastEngineRoot != null) | |||
{ | |||
Logging.MetaDebugLog($"Registering IEventEmitterEngine {engine.Name}"); | |||
_lastEngineRoot.AddEngine(engine); | |||
} | |||
} | |||
public static bool ExistsEventEmitter(string name) | |||
{ | |||
return _eventEmitters.ContainsKey(name); | |||
} | |||
public static bool ExistsEventEmitter(IEventEmitterEngine engine) | |||
{ | |||
return ExistsEventEmitter(engine.Name); | |||
} | |||
public static IEventEmitterEngine GetEventEmitter(string name) | |||
{ | |||
return _eventEmitters[name]; | |||
} | |||
public static string[] GetEventEmitterNames() | |||
{ | |||
return _eventEmitters.Keys.ToArray(); | |||
} | |||
public static void RemoveEventEmitter(string name) | |||
{ | |||
if (_eventEmitters[name].isRemovable) | |||
{ | |||
_eventEmitters.Remove(name); | |||
} | |||
} | |||
public static void RegisterEngines(EnginesRoot enginesRoot) | |||
{ | |||
_lastEngineRoot = enginesRoot; | |||
// Register handlers before emitters so no events are missed | |||
var entityFactory = enginesRoot.GenerateEntityFactory(); | |||
foreach (var key in _eventHandlers.Keys) | |||
{ | |||
Logging.MetaDebugLog($"Registering IEventHandlerEngine {_eventHandlers[key].Name}"); | |||
enginesRoot.AddEngine(_eventHandlers[key]); | |||
} | |||
foreach (var key in _eventEmitters.Keys) | |||
{ | |||
Logging.MetaDebugLog($"Registering IEventEmitterEngine {_eventEmitters[key].Name}"); | |||
_eventEmitters[key].Factory = entityFactory; | |||
enginesRoot.AddEngine(_eventEmitters[key]); | |||
} | |||
} | |||
} | |||
} |
@@ -1,24 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Built-in event types. | |||
/// These are configured to fire when the API is initialized. | |||
/// </summary> | |||
public enum EventType | |||
{ | |||
ApplicationInitialized, | |||
Menu, | |||
MenuSwitchedTo, | |||
Game, | |||
GameReloaded, | |||
GameSwitchedTo, | |||
SimulationSwitchedTo, | |||
BuildSwitchedTo | |||
} | |||
} |
@@ -1,56 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using HarmonyLib; | |||
using RobocraftX.CR.MainGame; | |||
using Svelto.ECS; | |||
using Unity.Entities; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame() | |||
/// </summary> | |||
[Obsolete] | |||
[HarmonyPatch] | |||
class GameActivatedComposePatch | |||
{ | |||
public static bool IsGameSwitching = false; | |||
public static bool IsGameReloading = false; | |||
public static void Postfix(ref object contextHolder, ref EnginesRoot enginesRoot, World physicsWorld) | |||
{ | |||
// register custom game engines | |||
GameEngineManager.RegisterEngines(enginesRoot); | |||
// A new EnginesRoot is always created when ActivateGame is called | |||
// so all event emitters and handlers must be re-registered. | |||
EventManager.RegisterEngines(enginesRoot); | |||
Logging.Log("Dispatching Game Activated event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIGameActivatedEventEmitter").Emit(); | |||
if (IsGameSwitching) | |||
{ | |||
IsGameSwitching = false; | |||
Logging.Log("Dispatching Game Switched To event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIGameSwitchedToEventEmitter").Emit(); | |||
} | |||
if (IsGameReloading) | |||
{ | |||
IsGameReloading = false; | |||
Logging.Log("Dispatching Game Reloaded event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIGameReloadedEventEmitter").Emit(); | |||
} | |||
} | |||
public static MethodBase TargetMethod() | |||
{ | |||
return typeof(MainGameCompositionRoot).GetMethods().First(m => m.Name == "Compose") | |||
.MakeGenericMethod(typeof(object)); | |||
} | |||
} | |||
} |
@@ -1,26 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using HarmonyLib; | |||
using RobocraftX; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.FullGameCompositionRoot.ReloadGame() | |||
/// </summary> | |||
[Obsolete] | |||
[HarmonyPatch(typeof(FullGameCompositionRoot), "ReloadGame")] | |||
class GameReloadedPatch | |||
{ | |||
public static void Postfix() | |||
{ | |||
GameActivatedComposePatch.IsGameReloading = true; | |||
} | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
using System; | |||
using Unity.Jobs; | |||
using RobocraftX.SimulationModeState; | |||
using RobocraftX.StateSync; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Event emitter engine for switching to to build mode. | |||
/// </summary> | |||
[Obsolete] | |||
public class GameStateBuildEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeStoppedModeEntered | |||
{ | |||
public string Name { get; } = "TechbloxModdingAPIGameStateBuildEventEmitter" ; | |||
public EntitiesDB entitiesDB { set; private get; } | |||
public int type { get; } = (int)EventType.BuildSwitchedTo; | |||
public bool isRemovable { get; } = false; | |||
public IEntityFactory Factory { set; private get; } | |||
public void Dispose() { } | |||
public void Emit() | |||
{ | |||
Logging.Log("Dispatching Build Switched To event"); | |||
if (Factory == null) { return; } | |||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup) | |||
.Init(new ModEventEntityStruct { type = type }); | |||
} | |||
public void EmitIfBuildMode() | |||
{ | |||
//Logging.MetaDebugLog($"nextSimulationMode: {entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode}"); | |||
if (entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode == SimulationMode.TimeStopped) | |||
{ | |||
Emit(); | |||
} | |||
} | |||
public JobHandle OnInitializeTimeStoppedMode(JobHandle inputDeps) | |||
{ | |||
Emit(); | |||
return inputDeps; | |||
} | |||
public void Ready() { } | |||
} | |||
} |
@@ -1,53 +0,0 @@ | |||
using System; | |||
using Unity.Jobs; | |||
using RobocraftX.SimulationModeState; | |||
using RobocraftX.StateSync; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Event emitter engine for switching to simulation mode. | |||
/// </summary> | |||
[Obsolete] | |||
public class GameStateSimulationEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeRunningModeEntered | |||
{ | |||
public string Name { get; } = "TechbloxModdingAPIGameStateSimulationEventEmitter" ; | |||
public EntitiesDB entitiesDB { set; private get; } | |||
public int type { get; } = (int)EventType.SimulationSwitchedTo; | |||
public bool isRemovable { get; } = false; | |||
public IEntityFactory Factory { set; private get; } | |||
public void Dispose() { } | |||
public void Emit() | |||
{ | |||
Logging.Log("Dispatching Simulation Switched To event"); | |||
if (Factory == null) { return; } | |||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup) | |||
.Init(new ModEventEntityStruct { type = type }); | |||
} | |||
public void EmitIfSimMode() | |||
{ | |||
if (entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).nextSimulationMode == SimulationMode.TimeRunning) | |||
{ | |||
Emit(); | |||
} | |||
} | |||
public JobHandle OnInitializeTimeRunningMode(JobHandle inputDeps) | |||
{ | |||
Emit(); | |||
return inputDeps; | |||
} | |||
public void Ready() { } | |||
} | |||
} |
@@ -1,30 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using System.Reflection; | |||
using HarmonyLib; | |||
using RobocraftX; | |||
using RobocraftX.CR.MainGame; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame() | |||
/// (scheduled for execution during RobocraftX.FullGameCompositionRoot.SwitchToGame()) | |||
/// </summary> | |||
[Obsolete] | |||
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToGame")] | |||
class GameSwitchedToPatch | |||
{ | |||
public static void Prefix() | |||
{ | |||
GameActivatedComposePatch.IsGameSwitching = true; | |||
} | |||
} | |||
} |
@@ -1,166 +0,0 @@ | |||
using System; | |||
using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
[Obsolete] | |||
public class HandlerBuilder | |||
{ | |||
private string name; | |||
private int? type; | |||
private Action<EntitiesDB> activated; | |||
private Action<EntitiesDB> destroyed; | |||
/// <summary> | |||
/// Create a new event handler builder. | |||
/// </summary> | |||
public HandlerBuilder() | |||
{ | |||
} | |||
/// <summary> | |||
/// Create a new event handler builder. | |||
/// This is equivalent to new <code>HandlerBuilder().Name(name)</code> | |||
/// </summary> | |||
/// <param name="name">The handler name.</param> | |||
public HandlerBuilder(string name) | |||
{ | |||
this.name = name; | |||
} | |||
/// <summary> | |||
/// Create and return an event handler builder. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
public static HandlerBuilder Builder() | |||
{ | |||
return new HandlerBuilder(); | |||
} | |||
/// <summary> | |||
/// Create and return an event handler builder. | |||
/// This is equivalent to <code>Builder().Name(name)</code> | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="name">The handler name.</param> | |||
public static HandlerBuilder Builder(string name) | |||
{ | |||
return new HandlerBuilder(name); | |||
} | |||
/// <summary> | |||
/// Name the event handler. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="name">The event handler name.</param> | |||
public HandlerBuilder Name(string name) | |||
{ | |||
this.name = name; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Set the action to perform on when the activated event occurs. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="action">The activated event action.</param> | |||
public HandlerBuilder OnActivation(Action action) | |||
{ | |||
return OnActivation((_) => { action(); }); | |||
} | |||
/// <summary> | |||
/// Set the action to perform on when the activated event occurs. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="action">The activated event action.</param> | |||
public HandlerBuilder OnActivation(Action<EntitiesDB> action) | |||
{ | |||
this.activated = action; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Set the action to perform when the destroyed event occurs. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="action">The destroyed event action.</param> | |||
public HandlerBuilder OnDestruction(Action action) | |||
{ | |||
return OnDestruction((_) => { action(); }); | |||
} | |||
/// <summary> | |||
/// Set the action to perform when the destroyed event occurs. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="action">The destroyed event action.</param> | |||
public HandlerBuilder OnDestruction(Action<EntitiesDB> action) | |||
{ | |||
this.destroyed = action; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Set the type of event to handle. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="eventType">The event type.</param> | |||
public HandlerBuilder Handle(EventType eventType) | |||
{ | |||
return Handle((int)eventType); | |||
} | |||
/// <summary> | |||
/// Set the type of event to handle. | |||
/// </summary> | |||
/// <returns>The builder.</returns> | |||
/// <param name="eventType">The event type.</param> | |||
public HandlerBuilder Handle(int eventType) | |||
{ | |||
this.type = eventType; | |||
return this; | |||
} | |||
/// <summary> | |||
/// Build the event handler. | |||
/// </summary> | |||
/// <returns>The event handler.</returns> | |||
/// <param name="register">Automatically register the event handler with EventManager.AddEventHandler().</param> | |||
public IEventHandlerEngine Build(bool register = true) | |||
{ | |||
if (string.IsNullOrWhiteSpace(name)) | |||
{ | |||
throw new EventParameterMissingException("Event handler name must be defined before Build() is called"); | |||
} | |||
if (activated == null && destroyed == null) | |||
{ | |||
throw new EventParameterMissingException("Event handler destruction or activated event action must be defined before Build() is called"); | |||
} | |||
if (!type.HasValue) | |||
{ | |||
throw new EventParameterMissingException("Event handler event type must be defined before Build() is called"); | |||
} | |||
Action<EntitiesDB> validActivated = activated; | |||
if (validActivated == null) | |||
{ | |||
validActivated = (_) => { }; | |||
} | |||
Action<EntitiesDB> validDestroyed = destroyed; | |||
if (validDestroyed == null) | |||
{ | |||
validDestroyed = (_) => { }; | |||
} | |||
SimpleEventHandlerEngine result = new SimpleEventHandlerEngine(validActivated, validDestroyed, type.Value, name); | |||
if (register) | |||
{ | |||
EventManager.AddEventHandler(result); | |||
} | |||
return result; | |||
} | |||
} | |||
} |
@@ -1,23 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Engines; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Engine interface to create a ModEventEntityStruct in entitiesDB when a specific event occurs. | |||
/// </summary> | |||
[Obsolete] | |||
public interface IEventEmitterEngine : IFactoryEngine | |||
{ | |||
/// <summary> | |||
/// Emit the event. (Optional) | |||
/// </summary> | |||
void Emit(); | |||
} | |||
} |
@@ -1,20 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Internal; | |||
using TechbloxModdingAPI.Engines; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Engine interface to handle ModEventEntityStruct events emitted by IEventEmitterEngines. | |||
/// </summary> | |||
[Obsolete] | |||
public interface IEventHandlerEngine : IReactionaryEngine<ModEventEntityStruct> | |||
{ | |||
} | |||
} |
@@ -1,42 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using HarmonyLib; | |||
using RobocraftX; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateMenu() | |||
/// </summary> | |||
[Obsolete] | |||
[HarmonyPatch(typeof(FullGameCompositionRoot), "ActivateMenu")] | |||
class MenuActivatedPatch | |||
{ | |||
private static bool firstLoad = true; | |||
public static void Postfix(ref EnginesRoot ____frontEndEnginesRoot, FullGameCompositionRoot __instance) | |||
{ | |||
// register custom menu engines | |||
MenuEngineManager.RegisterEngines(____frontEndEnginesRoot); | |||
// A new EnginesRoot is always created when ActivateMenu is called | |||
// so all event emitters and handlers must be re-registered. | |||
EventManager.RegisterEngines(____frontEndEnginesRoot); | |||
if (firstLoad) | |||
{ | |||
firstLoad = false; | |||
FullGameFields.Init(__instance); | |||
//Application.Application.SetFullGameCompositionRoot(__instance); | |||
Logging.Log("Dispatching App Init event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIApplicationInitializedEventEmitter").Emit(); | |||
} | |||
Logging.Log("Dispatching Menu Activated event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIMenuActivatedEventEmitter").Emit(); | |||
} | |||
} | |||
} |
@@ -1,28 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using HarmonyLib; | |||
using RobocraftX; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// Patch of RobocraftX.FullGameCompositionRoot.SwitchToMenu() | |||
/// </summary> | |||
[Obsolete] | |||
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToMenu")] | |||
class MenuSwitchedToPatch | |||
{ | |||
public static void Postfix() | |||
{ | |||
// Event emitters and handlers should already be registered by MenuActivated event | |||
Logging.Log("Dispatching Menu Switched To event"); | |||
EventManager.GetEventEmitter("TechbloxModdingAPIMenuSwitchedToEventEmitter").Emit(); | |||
} | |||
} | |||
} |
@@ -1,17 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// EntityDescriptor for creating ModEventEntityStructs | |||
/// </summary> | |||
public class ModEventEntityDescriptor : GenericEntityDescriptor<ModEventEntityStruct> | |||
{ | |||
} | |||
} |
@@ -1,23 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// The event entity struct | |||
/// </summary> | |||
public struct ModEventEntityStruct : IEntityComponent, INeedEGID | |||
{ | |||
/// <summary> | |||
/// The type of event that has been emitted | |||
/// </summary> | |||
public int type; | |||
public EGID ID { get; set; } | |||
} | |||
} |
@@ -1,66 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// A simple implementation of IEventEmitterEngine sufficient for most uses | |||
/// </summary> | |||
[Obsolete] | |||
public class SimpleEventEmitterEngine : IEventEmitterEngine | |||
{ | |||
public string Name { get; set; } | |||
public int type { get; set; } | |||
public bool isRemovable { get; } | |||
public IEntityFactory Factory { private get; set; } | |||
public EntitiesDB entitiesDB { set; private get; } | |||
public void Ready() { } | |||
/// <summary> | |||
/// Emit the event | |||
/// </summary> | |||
public void Emit() | |||
{ | |||
Factory.BuildEntity<ModEventEntityDescriptor>(ApiExclusiveGroups.eventID++, ApiExclusiveGroups.eventsExclusiveGroup) | |||
.Init(new ModEventEntityStruct { type = type }); | |||
} | |||
public void Dispose() { } | |||
/// <summary> | |||
/// Construct the engine | |||
/// </summary> | |||
/// <param name="type">The EventType to use for ModEventEntityStruct.type</param> | |||
/// <param name="name">The name of this engine</param> | |||
/// <param name="isRemovable">Will removing this engine not break your code?</param> | |||
public SimpleEventEmitterEngine(EventType type, string name, bool isRemovable = true) | |||
{ | |||
this.type = (int)type; | |||
this.Name = name; | |||
this.isRemovable = isRemovable; | |||
} | |||
/// <summary> | |||
/// Construct the engine | |||
/// </summary> | |||
/// <param name="type">The object to use for ModEventEntityStruct.type</param> | |||
/// <param name="name">The name of this engine</param> | |||
/// <param name="isRemovable">Will removing this engine not break your code?</param> | |||
public SimpleEventEmitterEngine(int type, string name, bool isRemovable = true) | |||
{ | |||
this.type = type; | |||
this.Name = name; | |||
this.isRemovable = isRemovable; | |||
} | |||
} | |||
} |
@@ -1,145 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using Svelto.ECS; | |||
using TechbloxModdingAPI.Utility; | |||
namespace TechbloxModdingAPI.Events | |||
{ | |||
/// <summary> | |||
/// A simple implementation of IEventHandlerEngine sufficient for most uses | |||
/// </summary> | |||
[Obsolete] | |||
public class SimpleEventHandlerEngine : IEventHandlerEngine | |||
{ | |||
public int type { get; set; } | |||
public string Name { get; set; } | |||
private bool isActivated = false; | |||
private bool jankActivateFix = false; | |||
private bool jankDestroyFix = false; | |||
private readonly Action<EntitiesDB> onActivated; | |||
private readonly Action<EntitiesDB> onDestroyed; | |||
public EntitiesDB entitiesDB { set; private get; } | |||
public bool isRemovable => true; | |||
public void Add(ref ModEventEntityStruct entityView, EGID egid) | |||
{ | |||
if (entityView.type.Equals(this.type)) | |||
{ | |||
jankActivateFix = !jankActivateFix; | |||
if (jankActivateFix) return; | |||
isActivated = true; | |||
onActivatedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
/// <summary> | |||
/// Manually activate the EventHandler. | |||
/// Once activated, the next remove event will not be ignored. | |||
/// </summary> | |||
/// <param name="handle">Whether to invoke the activated action</param> | |||
public void Activate(bool handle = false) | |||
{ | |||
isActivated = true; | |||
if (handle && entitiesDB != null) | |||
{ | |||
onActivatedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
public void Deactivate() | |||
{ | |||
isActivated = false; | |||
} | |||
public void Ready() { } | |||
public void Remove(ref ModEventEntityStruct entityView, EGID egid) | |||
{ | |||
if (entityView.type.Equals(this.type) && isActivated) | |||
{ | |||
jankDestroyFix = !jankDestroyFix; | |||
if (jankDestroyFix) return; | |||
isActivated = false; | |||
onDestroyedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
public void Dispose() | |||
{ | |||
if (isActivated) | |||
{ | |||
isActivated = false; | |||
onDestroyedInvokeCatchError(entitiesDB); | |||
} | |||
} | |||
/// <summary> | |||
/// Construct the engine | |||
/// </summary> | |||
/// <param name="activated">The operation to do when the event is created</param> | |||
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param> | |||
/// <param name="type">The type of event to handle</param> | |||
/// <param name="name">The name of the engine</param> | |||
/// <param name="simple">A useless parameter to use to avoid Python overload resolution errors</param> | |||
public SimpleEventHandlerEngine(Action activated, Action removed, int type, string name, bool simple = true) | |||
: this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, type, name) { } | |||
/// <summary> | |||
/// Construct the engine | |||
/// </summary> | |||
/// <param name="activated">The operation to do when the event is created</param> | |||
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param> | |||
/// <param name="type">The type of event to handler</param> | |||
/// <param name="name">The name of the engine</param> | |||
public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, int type, string name) | |||
{ | |||
this.type = type; | |||
this.Name = name; | |||
this.onActivated = activated; | |||
this.onDestroyed = removed; | |||
} | |||
private void onActivatedInvokeCatchError(EntitiesDB _entitiesDB) | |||
{ | |||
try | |||
{ | |||
onActivated.Invoke(_entitiesDB); | |||
} | |||
catch (Exception e) | |||
{ | |||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when activated", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
} | |||
} | |||
private void onDestroyedInvokeCatchError(EntitiesDB _entitiesDB) | |||
{ | |||
try | |||
{ | |||
onDestroyed.Invoke(_entitiesDB); | |||
} | |||
catch (Exception e) | |||
{ | |||
EventRuntimeException wrappedException = new EventRuntimeException($"EventHandler {Name} threw an exception when destroyed", e); | |||
Logging.LogWarning(wrappedException.ToString()); | |||
} | |||
} | |||
public SimpleEventHandlerEngine(Action activated, Action removed, EventType type, string name, bool simple = true) | |||
: this((EntitiesDB _) => { activated.Invoke(); }, (EntitiesDB _) => { removed.Invoke(); }, (int)type, name) { } | |||
public SimpleEventHandlerEngine(Action<EntitiesDB> activated, Action<EntitiesDB> removed, EventType type, string name, bool simple = true) | |||
: this(activated, removed, (int)type, name) { } | |||
} | |||
} |
@@ -62,20 +62,7 @@ namespace TechbloxModdingAPI | |||
// init utility | |||
Logging.MetaDebugLog($"Initializing Utility"); | |||
#pragma warning disable 0612,0618 | |||
Utility.GameState.Init(); | |||
Utility.VersionTracking.Init(); | |||
// create default event emitters | |||
Logging.MetaDebugLog($"Initializing Events"); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "TechbloxModdingAPIApplicationInitializedEventEmitter", false)); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Menu, "TechbloxModdingAPIMenuActivatedEventEmitter", false)); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.MenuSwitchedTo, "TechbloxModdingAPIMenuSwitchedToEventEmitter", false)); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.Game, "TechbloxModdingAPIGameActivatedEventEmitter", false)); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameReloaded, "TechbloxModdingAPIGameReloadedEventEmitter", false)); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameSwitchedTo, "TechbloxModdingAPIGameSwitchedToEventEmitter", false)); | |||
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.buildEngine); | |||
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine); | |||
#pragma warning restore 0612,0618 | |||
// init block implementors | |||
Logging.MetaDebugLog($"Initializing Blocks"); | |||
// init inventory | |||
@@ -1,51 +1,20 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Diagnostics; | |||
using System.IO; | |||
using System.Linq; | |||
using System.Reflection; | |||
using System.Reflection.Emit; | |||
using System.Text; | |||
using TechbloxModdingAPI.App; | |||
using HarmonyLib; | |||
using IllusionInjector; | |||
// test | |||
using GPUInstancer; | |||
using Svelto.ECS; | |||
using RobocraftX.Blocks; | |||
using RobocraftX.Common; | |||
using RobocraftX.SimulationModeState; | |||
using RobocraftX.FrontEnd; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
using RobocraftX.Schedulers; | |||
using Svelto.Tasks.ExtraLean; | |||
using uREPL; | |||
using TechbloxModdingAPI.Interface.IMGUI; | |||
using TechbloxModdingAPI.Tasks; | |||
using RobocraftX.Common.Input; | |||
using RobocraftX.CR.MainGame; | |||
using RobocraftX.GUI.CommandLine; | |||
using RobocraftX.Multiplayer; | |||
using RobocraftX.StateSync; | |||
using Svelto.Context; | |||
using Svelto.DataStructures; | |||
using Svelto.Services; | |||
using TechbloxModdingAPI.Blocks; | |||
using TechbloxModdingAPI.Commands; | |||
using TechbloxModdingAPI.Events; | |||
using TechbloxModdingAPI.Input; | |||
using TechbloxModdingAPI.Players; | |||
using TechbloxModdingAPI.Utility; | |||
using UnityEngine.AddressableAssets; | |||
using UnityEngine.AddressableAssets.ResourceLocators; | |||
using UnityEngine.ResourceManagement.AsyncOperations; | |||
using UnityEngine.ResourceManagement.ResourceLocations; | |||
using UnityEngine.ResourceManagement.ResourceProviders; | |||
using Debug = FMOD.Debug; | |||
using EventType = TechbloxModdingAPI.Events.EventType; | |||
using Label = TechbloxModdingAPI.Interface.IMGUI.Label; | |||
using ScalingPermission = DataLoader.ScalingPermission; | |||
namespace TechbloxModdingAPI.Tests | |||
{ | |||
@@ -77,13 +46,6 @@ namespace TechbloxModdingAPI.Tests | |||
Harmony.DEBUG = true; | |||
Main.Init(); | |||
Logging.MetaDebugLog($"Version group id {(uint)ApiExclusiveGroups.versionGroup}"); | |||
// in case Steam is not installed/running | |||
// this will crash the game slightly later during startup | |||
//SteamInitPatch.ForcePassSteamCheck = true; | |||
// in case running in a VM | |||
//MinimumSpecsCheckPatch.ForcePassMinimumSpecCheck = true; | |||
// disable some Techblox analytics | |||
//AnalyticsDisablerPatch.DisableAnalytics = true; | |||
// disable background music | |||
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 :( | |||
@@ -91,62 +53,7 @@ namespace TechbloxModdingAPI.Tests | |||
//Utility.VersionTracking.Enable();//(very) unstable | |||
// debug/test handlers | |||
#pragma warning disable 0612 | |||
HandlerBuilder.Builder() | |||
.Name("appinit API debug") | |||
.Handle(EventType.ApplicationInitialized) | |||
.OnActivation(() => { Logging.Log("App Inited event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("menuact API debug") | |||
.Handle(EventType.Menu) | |||
.OnActivation(() => { Logging.Log("Menu Activated event!"); }) | |||
.OnDestruction(() => { Logging.Log("Menu Destroyed event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("menuswitch API debug") | |||
.Handle(EventType.MenuSwitchedTo) | |||
.OnActivation(() => { Logging.Log("Menu Switched To event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("gameact API debug") | |||
.Handle(EventType.Menu) | |||
.OnActivation(() => { Logging.Log("Game Activated event!"); }) | |||
.OnDestruction(() => { Logging.Log("Game Destroyed event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("gamerel API debug") | |||
.Handle(EventType.GameReloaded) | |||
.OnActivation(() => { Logging.Log("Game Reloaded event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("gameswitch API debug") | |||
.Handle(EventType.GameSwitchedTo) | |||
.OnActivation(() => { Logging.Log("Game Switched To event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("simulationswitch API debug") | |||
.Handle(EventType.SimulationSwitchedTo) | |||
.OnActivation(() => { Logging.Log("Game Mode Simulation Switched To event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("buildswitch API debug") | |||
.Handle(EventType.BuildSwitchedTo) | |||
.OnActivation(() => { Logging.Log("Game Mode Build Switched To event!"); }) | |||
.Build(); | |||
HandlerBuilder.Builder("menu activated API error thrower test") | |||
.Handle(EventType.Menu) | |||
.OnActivation(() => { throw new Exception("Event Handler always throws an exception!"); }) | |||
.Build(); | |||
#pragma warning restore 0612 | |||
/*HandlerBuilder.Builder("enter game from menu test") | |||
.Handle(EventType.Menu) | |||
.OnActivation(() => | |||
{ | |||
Tasks.Scheduler.Schedule(new Tasks.Repeatable(enterGame, shouldRetry, 0.2f)); | |||
}) | |||
.Build();*/ | |||
Client.EnterMenu += (sender, args) => throw new Exception("Test handler always throws an exception!"); | |||
// debug/test commands | |||
if (Dependency.Hell("ExtraCommands")) | |||
@@ -195,7 +102,6 @@ namespace TechbloxModdingAPI.Tests | |||
for (int i = 0; i < 100; i++) | |||
for (int j = 0; j < 100; j++) | |||
Block.PlaceNew(BlockIDs.Cube, new float3(x + i, y, z + j)); | |||
//Block.Sync(); | |||
sw.Stop(); | |||
Logging.CommandLog("Finished in " + sw.ElapsedMilliseconds + "ms"); | |||
}) | |||
@@ -236,7 +142,7 @@ namespace TechbloxModdingAPI.Tests | |||
}).Build(); | |||
CommandBuilder.Builder("GetBlockByID", "Gets a block based on its object identifier and teleports it up.") | |||
CommandBuilder.Builder("MoveBlockByID", "Gets a block based on its object identifier and teleports it up.") | |||
.Action<char>(ch => | |||
{ | |||
foreach (var body in SimBody.GetFromObjectID(ch)) | |||
@@ -251,41 +157,6 @@ namespace TechbloxModdingAPI.Tests | |||
} | |||
}).Build(); | |||
/*CommandBuilder.Builder() | |||
.Name("PlaceConsole") | |||
.Description("Place a bunch of console block with a given text - entering simulation with them crashes the game as the cmd doesn't exist") | |||
.Action((float x, float y, float z) => | |||
{ | |||
Stopwatch sw = new Stopwatch(); | |||
sw.Start(); | |||
for (int i = 0; i < 100; i++) | |||
{ | |||
for (int j = 0; j < 100; j++) | |||
{ | |||
var block = Block.PlaceNew<ConsoleBlock>(BlockIDs.ConsoleBlock, | |||
new float3(x + i, y, z + j)); | |||
block.Command = "test_command"; | |||
} | |||
} | |||
sw.Stop(); | |||
Logging.CommandLog($"Blocks placed in {sw.ElapsedMilliseconds} ms"); | |||
}) | |||
.Build();*/ | |||
/*CommandBuilder.Builder() | |||
.Name("WireTest") | |||
.Description("Place two blocks and then wire them together") | |||
.Action(() => | |||
{ | |||
LogicGate notBlock = Block.PlaceNew<LogicGate>(BlockIDs.NOTLogicBlock, new float3(1, 2, 0)); | |||
LogicGate andBlock = Block.PlaceNew<LogicGate>(BlockIDs.ANDLogicBlock, new float3(2, 2, 0)); | |||
// connect NOT Gate output to AND Gate input #2 (ports are zero-indexed, so 1 is 2nd position and 0 is 1st position) | |||
Wire conn = notBlock.Connect(0, andBlock, 1); | |||
Logging.CommandLog(conn.ToString()); | |||
}) | |||
.Build();*/ | |||
CommandBuilder.Builder("TestChunkHealth", "Sets the chunk looked at to the given health.") | |||
.Action((float val, float max) => | |||
{ | |||
@@ -327,49 +198,6 @@ namespace TechbloxModdingAPI.Tests | |||
Logging.MetaDebugLog("Placed block " + args.Block); | |||
Block.Removed += (sender, args) => | |||
Logging.MetaDebugLog("Removed block " + args.Block); | |||
/* | |||
CommandManager.AddCommand(new SimpleCustomCommandEngine<float>((float d) => { UnityEngine.Camera.main.fieldOfView = d; }, | |||
"SetFOV", "Set the player camera's field of view")); | |||
CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>( | |||
(x, y, z) => { | |||
bool success = TechbloxModdingAPI.Blocks.Movement.MoveConnectedBlocks( | |||
TechbloxModdingAPI.Blocks.BlockIdentifiers.LatestBlockID, | |||
new Unity.Mathematics.float3(x, y, z)); | |||
if (!success) | |||
{ | |||
TechbloxModdingAPI.Utility.Logging.CommandLogError("Blocks can only be moved in Build mode!"); | |||
} | |||
}, "MoveLastBlock", "Move the most-recently-placed block, and any connected blocks by the given offset")); | |||
CommandManager.AddCommand(new SimpleCustomCommandEngine<float, float, float>( | |||
(x, y, z) => { Blocks.Placement.PlaceBlock(Blocks.BlockIDs.Cube, new Unity.Mathematics.float3(x, y, z)); }, | |||
"PlaceAluminium", "Place a block of aluminium at the given coordinates")); | |||
System.Random random = new System.Random(); // for command below | |||
CommandManager.AddCommand(new SimpleCustomCommandEngine( | |||
() => { | |||
if (!GameState.IsSimulationMode()) | |||
{ | |||
Logging.CommandLogError("You must be in simulation mode for this to work!"); | |||
return; | |||
} | |||
Tasks.Repeatable task = new Tasks.Repeatable(() => { | |||
uint count = 0; | |||
EGID[] eBlocks = Blocks.Signals.GetElectricBlocks(); | |||
for (uint i = 0u; i < eBlocks.Length; i++) | |||
{ | |||
uint[] ids = Blocks.Signals.GetSignalIDs(eBlocks[i]); | |||
for (uint j = 0u; j < ids.Length; j++) | |||
{ | |||
Blocks.Signals.SetSignalByID(ids[j], (float)random.NextDouble()); | |||
count++; | |||
} | |||
} | |||
Logging.MetaDebugLog($"Did the thing on {count} inputs"); | |||
}, | |||
() => { return GameState.IsSimulationMode(); }); | |||
Tasks.Scheduler.Schedule(task); | |||
}, "RandomizeSignalsInputs", "Do the thing")); | |||
*/ | |||
} | |||
// dependency test | |||
@@ -406,30 +234,6 @@ namespace TechbloxModdingAPI.Tests | |||
uiImg.Enabled = true; | |||
Logging.MetaDebugLog($"Got blue bg asset {handle.Result}"); | |||
};*/ | |||
CommandBuilder.Builder("enableCompletions") | |||
.Action(() => | |||
{ | |||
var p = Window.selected.main.parameters; | |||
p.useCommandCompletion = true; | |||
p.useMonoCompletion = true; | |||
p.useGlobalClassCompletion = true; | |||
Log.Output("Submitted: " + Window.selected.submittedCode); | |||
}) | |||
.Build(); | |||
try | |||
{ | |||
CustomBlock.RegisterCustomBlock<TestBlock>(); | |||
Logging.MetaDebugLog("Registered test custom block"); | |||
} | |||
catch (FileNotFoundException) | |||
{ | |||
Logging.MetaDebugLog("Test custom block catalog not found"); | |||
} | |||
CustomBlock.ChangeExistingBlock((ushort) BlockIDs.CarWheel, | |||
cld => cld.scalingPermission = ScalingPermission.NonUniform); | |||
/*((FasterList<GuiInputMap.GuiInputMapElement>)AccessTools.Property(typeof(GuiInputMap), "GuiInputsButtonDown").GetValue(null)) | |||
.Add(new GuiInputMap.GuiInputMapElement(RewiredConsts.Action.ToggleCommandLine, GuiIn))*/ | |||
@@ -448,40 +252,6 @@ namespace TechbloxModdingAPI.Tests | |||
return modsString = sb.ToString(); | |||
} | |||
private bool retry = true; | |||
private bool shouldRetry() | |||
{ | |||
return retry; | |||
} | |||
private void enterGame() | |||
{ | |||
App.Client app = new App.Client(); | |||
App.Game[] myGames = app.MyGames; | |||
Logging.MetaDebugLog($"MyGames count {myGames.Length}"); | |||
if (myGames.Length != 0) | |||
{ | |||
Logging.MetaDebugLog($"MyGames[0] EGID {myGames[0].EGID}"); | |||
retry = false; | |||
try | |||
{ | |||
//myGames[0].Description = "test msg pls ignore"; // make sure game exists first | |||
Logging.MetaDebugLog($"Entering game {myGames[0].Name}"); | |||
myGames[0].EnterGame(); | |||
} | |||
catch (Exception e) | |||
{ | |||
Logging.MetaDebugLog($"Failed to enter game; exception: {e}"); | |||
retry = true; | |||
} | |||
} | |||
else | |||
{ | |||
Logging.MetaDebugLog("MyGames not populated yet :("); | |||
} | |||
} | |||
public override void OnUpdate() | |||
{ | |||
if (UnityEngine.Input.GetKeyDown(KeyCode.End)) | |||
@@ -504,18 +274,6 @@ namespace TechbloxModdingAPI.Tests | |||
return ((Action) MinimumSpecsCheck.CheckRequirementsMet).Method; | |||
} | |||
} | |||
[CustomBlock("customCatalog.json", "Assets/Prefabs/Cube.prefab", "strAluminiumCube", SortIndex = 12)] | |||
public class TestBlock : CustomBlock | |||
{ | |||
public TestBlock(EGID id) : base(id) | |||
{ | |||
} | |||
public TestBlock(uint id) : base(id) | |||
{ | |||
} | |||
} | |||
} | |||
#endif | |||
} |
@@ -123,24 +123,6 @@ namespace TechbloxModdingAPI.Utility | |||
Svelto.Console.LogWarning(obj.ToString()); | |||
} | |||
[Obsolete("SystemLog was removed from Svelto.Common")] | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public static void SystemLog(string msg) | |||
{ | |||
Svelto.Console.Log(msg); | |||
} | |||
/// <summary> | |||
/// Write a message to stdout (ie the terminal, like Command Prompt or PowerShell) | |||
/// </summary> | |||
/// <param name="obj">The object to log</param> | |||
[Obsolete("SystemLog was removed from Svelto.Common")] | |||
[MethodImpl(MethodImplOptions.AggressiveInlining)] | |||
public static void SystemLog(object obj) | |||
{ | |||
Svelto.Console.Log(obj.ToString()); | |||
} | |||
// descriptive logging | |||
/// <summary> | |||
@@ -1,115 +0,0 @@ | |||
using System; | |||
using System.Reflection; | |||
using RobocraftX.Common; | |||
using Svelto.ECS; | |||
using Svelto.ECS.Serialization; | |||
using TechbloxModdingAPI.Events; | |||
using TechbloxModdingAPI.Persistence; | |||
namespace TechbloxModdingAPI.Utility | |||
{ | |||
/// <summary> | |||
/// Tracks the API version the current game was built for. | |||
/// For compatibility reasons, this must be enabled before it will work. | |||
/// </summary> | |||
[Obsolete] | |||
public static class VersionTracking | |||
{ | |||
private static readonly VersionTrackingEngine versionEngine = new VersionTrackingEngine(); | |||
private static bool isEnabled = false; | |||
/// <summary> | |||
/// Gets the API version saved in the current game. | |||
/// </summary> | |||
/// <returns>The version.</returns> | |||
public static uint GetVersion() | |||
{ | |||
if (!isEnabled) return 0u; | |||
return versionEngine.GetGameVersion(); | |||
} | |||
/// <summary> | |||
/// Enable API version tracking. | |||
/// </summary> | |||
public static void Enable() | |||
{ | |||
if (!SerializerManager.ExistsSerializer(typeof(ModVersionStruct).FullName)) | |||
{ | |||
SerializerManager.AddSerializer<ModVersionDescriptor>(new SimpleEntitySerializer<ModVersionDescriptor>( | |||
(_) => { return new EGID[1] { new EGID(0u, ApiExclusiveGroups.versionGroup) }; } | |||
)); | |||
} | |||
EventManager.AddEventEmitter(versionEngine); | |||
isEnabled = true; | |||
} | |||
/// <summary> | |||
/// Disable API version tracking. | |||
/// </summary> | |||
public static void Disable() | |||
{ | |||
EventManager.AddEventEmitter(versionEngine); | |||
isEnabled = false; | |||
} | |||
public static void Init() { } | |||
} | |||
[Obsolete] | |||
internal class VersionTrackingEngine : IEventEmitterEngine | |||
{ | |||
public string Name { get; } = "TechbloxModdingAPIVersionTrackingGameEngine"; | |||
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() { } | |||
} | |||
[Obsolete] | |||
public struct ModVersionStruct : IEntityComponent | |||
{ | |||
public uint version; | |||
} | |||
[Obsolete] | |||
public class ModVersionDescriptor: SerializableEntityDescriptor<ModVersionDescriptor._ModVersionDescriptor> | |||
{ | |||
[HashName("TechbloxModdingAPIVersionV0")] | |||
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>())), | |||
}; | |||
} | |||
} | |||
} |