|
- using System;
- using System.Collections.Generic;
- using HarmonyLib;
- using RobocraftX.Schedulers;
- using Svelto.ECS;
- using Svelto.ECS.Hybrid;
- using Svelto.Tasks;
- using Svelto.Tasks.Lean;
- using TechbloxModdingAPI.Blocks.Engines;
- using TechbloxModdingAPI.Common.Engines;
- using TechbloxModdingAPI.Utility;
- using TechbloxModdingAPI.Utility.ECS;
-
- namespace TechbloxModdingAPI.Common;
-
- public class EcsObjectBaseEngine : IFactoryEngine, IFunEngine
- {
- public void Ready()
- {
- }
-
- public EntitiesDB entitiesDB { get; set; }
-
- public void Dispose()
- {
- }
-
- public EntityReference GetEntityReference(EGID egid)
- {
- return entitiesDB is not null && egid != default ? egid.ToEntityReference(entitiesDB) : EntityReference.Invalid;
- }
-
- public EGID GetEgid(EntityReference reference)
- {
- return entitiesDB is not null && reference.ToEGID(entitiesDB, out var egid) ? egid : default;
- }
-
- public OptionalRef<T> GetComponentOptional<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent
- {
- return entitiesDB.QueryEntityOptional<T>(obj);
- }
-
- public ref T GetComponent<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent
- {
- #if DEBUG
- if (entitiesDB.Exists<T>(obj.Id) && obj.InitData.Valid)
- throw new ArgumentException("The block exists but the init data has not been removed!");
- #endif
- return ref entitiesDB.QueryEntityOrDefault<T>(obj);
- }
-
- public ref T GetViewComponent<T>(EcsObjectBase obj) where T : struct, IEntityViewComponent
- {
- return ref entitiesDB.QueryEntityOrDefault<T>(obj);
- }
-
- public object GetComponent(EcsObjectBase obj, Type type, string name)
- {
- var opt = AccessTools.Method(typeof(NativeApiExtensions), "QueryEntityOptional",
- new[] { typeof(EntitiesDB), typeof(EcsObjectBase), typeof(ExclusiveGroupStruct) }, new[] { type })
- .Invoke(null, new object[] { entitiesDB, obj, null });
- var str = AccessTools.Property(opt.GetType(), "Value").GetValue(opt);
- return AccessTools.Field(str.GetType(), name).GetValue(str);
- }
-
- public void SetComponent(EcsObjectBase obj, Type type, string name, object value)
- {
- var opt = AccessTools.Method(typeof(BlockEngine), "GetBlockInfoOptional", generics: new[] { type })
- .Invoke(this, new object[] { obj });
- var prop = AccessTools.Property(opt.GetType(), "Value");
- var str = prop.GetValue(opt);
- AccessTools.Field(str.GetType(), name).SetValue(str, value);
- prop.SetValue(opt, str);
- }
-
- private readonly Dictionary<EcsObjectBase, Action<EcsObjectBase>> _waitingForSubmission = new();
-
- public void TrackNewEntity(EcsObjectBase obj, Action<EcsObjectBase> done)
- {
- if (_waitingForSubmission.ContainsKey(obj))
- throw new InvalidOperationException("Something has gone horribly wrong here");
- _waitingForSubmission.Add(obj, done);
- WaitUntilEntitySubmission().RunOn(ClientLean.UIScheduler); // TODO: Pick the right scheduler
- }
-
- private IEnumerator<TaskContract> WaitUntilEntitySubmission()
- {
- // TODO: Get the scheduler instance based on the engine (inject in engine manager)
- yield return new WaitForSubmissionEnumerator(FullGameFields._mainGameEnginesRoot.scheduler).Continue();
- foreach (var (obj, done) in _waitingForSubmission) done(obj);
- }
-
- public IEntityFactory Factory { get; set; }
- public IEntityFunctions Functions { get; set; }
- }
|