Fix an issue with the new generator, switch to using entity references
This commit is contained in:
parent
27218aeb8d
commit
bf08b61788
33 changed files with 133 additions and 101 deletions
|
@ -8,7 +8,7 @@
|
|||
<PackageProjectUrl>https://git.exmods.org/modtainers/GamecraftModdingAPI</PackageProjectUrl>
|
||||
<NeutralLanguage>en-CA</NeutralLanguage>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>9</LangVersion>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<OutputType>Exe</OutputType>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||
|
|
|
@ -5,21 +5,23 @@ using System.Linq;
|
|||
using System.Linq.Expressions;
|
||||
using System.Reflection;
|
||||
using Gamecraft.Tweaks;
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace CodeGenerator
|
||||
{
|
||||
public class ECSAnalyzer
|
||||
public static class ECSAnalyzer
|
||||
{
|
||||
public static ECSClassInfo AnalyzeEntityDescriptor(Type entityDescriptorType)
|
||||
{
|
||||
// TODO: Add support for creating/deleting entities (getting an up to date server/client engines root)
|
||||
var templateType = typeof(EntityDescriptorTemplate<>).MakeGenericType(entityDescriptorType);
|
||||
var getTemplateClass = Expression.Constant(templateType);
|
||||
var getDescriptorExpr = Expression.PropertyOrField(getTemplateClass, "descriptor");
|
||||
var templateDescriptor = AccessTools.Property(templateType, "descriptor");
|
||||
var getDescriptorExpr = Expression.MakeMemberAccess(null, templateDescriptor ?? throw new InvalidOperationException());
|
||||
var getTemplateDescriptorExpr =
|
||||
Expression.Lambda<Func<IEntityDescriptor>>(getDescriptorExpr);
|
||||
var getTemplateDescriptor = getTemplateDescriptorExpr.Compile();
|
||||
// TODO: Crashes on constructing the descriptor type. Maybe move the analysis part to a mod.
|
||||
var builders = getTemplateDescriptor().componentsToBuild;
|
||||
return new ECSClassInfo
|
||||
{
|
||||
|
|
|
@ -15,7 +15,8 @@ namespace CodeGenerator
|
|||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
GenerateBlockClasses();
|
||||
//GenerateBlockClasses();
|
||||
ECSClassGenerator.Generate(typeof(EngineBlockEntityDescriptor));
|
||||
}
|
||||
|
||||
private static void GenerateBlockClasses()
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using RobocraftX.StateSync;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Jobs;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
|
|
|
@ -8,13 +8,13 @@ using Svelto.ECS.EntityStructs;
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.Blocks;
|
||||
using Unity.Mathematics;
|
||||
using HarmonyLib;
|
||||
using RobocraftX.PilotSeat;
|
||||
using RobocraftX.Rendering;
|
||||
using Techblox.BlockLabelsServer;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Blocks.Engines;
|
||||
using TechbloxModdingAPI.Client.App;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Tests;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
|
|
@ -9,8 +9,8 @@ using UnityEngine;
|
|||
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Blocks.Engines;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
{
|
||||
|
|
|
@ -5,11 +5,9 @@ using Gamecraft.Wires;
|
|||
using HarmonyLib;
|
||||
using RobocraftX.Blocks;
|
||||
using RobocraftX.Character;
|
||||
using RobocraftX.Common;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
{
|
||||
|
|
|
@ -18,9 +18,8 @@ using Svelto.ECS.Hybrid;
|
|||
using Techblox.BuildingDrone;
|
||||
using Techblox.ObjectIDBlockServer;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
using PrefabsID = RobocraftX.Common.PrefabsID;
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
|
|
@ -12,7 +12,7 @@ using RobocraftX.Rendering;
|
|||
using RobocraftX.Rendering.GPUI;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
|
|
|
@ -9,12 +9,10 @@ using RobocraftX.StateSync;
|
|||
using Svelto.ECS;
|
||||
using Svelto.ECS.Native;
|
||||
using Techblox.Blocks.Connections;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Collections;
|
||||
using Unity.Jobs;
|
||||
using Allocator = Unity.Collections.Allocator;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
|
|
|
@ -2,11 +2,9 @@
|
|||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
|
||||
|
|
|
@ -4,10 +4,8 @@ using HarmonyLib;
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Entities;
|
||||
|
||||
using TechbloxModdingAPI.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
|
|
|
@ -1,11 +1,7 @@
|
|||
using System;
|
||||
|
||||
using Gamecraft.Wires;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Experimental;
|
||||
|
||||
using TechbloxModdingAPI.Blocks.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks
|
||||
{
|
||||
|
|
|
@ -3,7 +3,7 @@ using RobocraftX.Multiplayer;
|
|||
using Svelto.ECS;
|
||||
using Techblox.GameSelection;
|
||||
using TechbloxModdingAPI.Client.Game;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI.Client.App;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using System;
|
||||
using RobocraftX.GUI.MyGamesScreen;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI.Client.Game;
|
||||
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using Svelto.ECS;
|
||||
using Techblox.Destruction;
|
||||
using Techblox.TimeRunning.Clusters;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
{
|
||||
|
|
|
@ -1,4 +1,4 @@
|
|||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Commands
|
||||
{
|
||||
|
|
|
@ -1,81 +1,95 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq.Expressions;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Internal;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Common.Utils;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
namespace TechbloxModdingAPI.Common;
|
||||
|
||||
public abstract class EcsObjectBase
|
||||
{
|
||||
public abstract class EcsObjectBase
|
||||
{
|
||||
public EGID Id { get; }
|
||||
public EGID Id => _engine.GetEgid(Reference);
|
||||
/// <summary>
|
||||
/// A reference to a specific entity that persists through group swaps and such.
|
||||
/// May be an invalid reference, in that case operations do not have any effect.
|
||||
/// </summary>
|
||||
public EntityReference Reference { get; }
|
||||
|
||||
private static readonly Dictionary<Type, WeakDictionary<EGID, EcsObjectBase>> _instances = new();
|
||||
private static readonly Dictionary<Type, WeakDictionary<EntityReference, EcsObjectBase>> _instances = new();
|
||||
private static readonly EcsObjectBaseEngine _engine = new();
|
||||
|
||||
internal static WeakDictionary<EGID, EcsObjectBase> GetInstances(Type type)
|
||||
private static WeakDictionary<EntityReference, EcsObjectBase> GetInstances(Type type)
|
||||
{
|
||||
return _instances.TryGetValue(type, out var dict) ? dict : null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a cached instance if there's an actively used instance of the object already.
|
||||
/// Objects still get garbage collected and then they will be removed from the cache.
|
||||
/// </summary>
|
||||
/// <param name="egid">The EGID of the entity</param>
|
||||
/// <param name="constructor">The constructor to construct the object</param>
|
||||
/// <typeparam name="T">The object type</typeparam>
|
||||
/// <returns></returns>
|
||||
internal static T GetInstance<T>(EGID egid, Func<EGID, T> constructor, Type type = null) where T : EcsObjectBase
|
||||
{
|
||||
var instances = GetInstances(type ?? typeof(T));
|
||||
if (instances == null || !instances.TryGetValue(_engine.GetEntityReference(egid), out var instance))
|
||||
return constructor(egid); // It will be added by the constructor
|
||||
return (T)instance;
|
||||
}
|
||||
|
||||
protected EcsObjectBase(EGID id, Type entityDescriptorType) : this(_engine.GetEntityReference(id), entityDescriptorType)
|
||||
{
|
||||
}
|
||||
|
||||
protected EcsObjectBase(EntityReference reference, Type entityDescriptorType)
|
||||
{
|
||||
if (!_instances.TryGetValue(GetType(), out var dict))
|
||||
{
|
||||
return _instances.TryGetValue(type, out var dict) ? dict : null;
|
||||
dict = new();
|
||||
_instances.Add(GetType(), dict);
|
||||
}
|
||||
if (!dict.ContainsKey(reference)) // Multiple instances may be created
|
||||
dict.Add(reference, this);
|
||||
Reference = reference;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Returns a cached instance if there's an actively used instance of the object already.
|
||||
/// Objects still get garbage collected and then they will be removed from the cache.
|
||||
/// </summary>
|
||||
/// <param name="egid">The EGID of the entity</param>
|
||||
/// <param name="constructor">The constructor to construct the object</param>
|
||||
/// <typeparam name="T">The object type</typeparam>
|
||||
/// <returns></returns>
|
||||
internal static T GetInstance<T>(EGID egid, Func<EGID, T> constructor, Type type = null) where T : EcsObjectBase
|
||||
{
|
||||
var instances = GetInstances(type ?? typeof(T));
|
||||
if (instances == null || !instances.TryGetValue(egid, out var instance))
|
||||
return constructor(egid); // It will be added by the constructor
|
||||
return (T)instance;
|
||||
}
|
||||
#region ECS initializer stuff
|
||||
|
||||
protected EcsObjectBase(EGID id, Type entityDescriptorType)
|
||||
{
|
||||
if (!_instances.TryGetValue(GetType(), out var dict))
|
||||
{
|
||||
dict = new WeakDictionary<EGID, EcsObjectBase>();
|
||||
_instances.Add(GetType(), dict);
|
||||
}
|
||||
if (!dict.ContainsKey(id)) // Multiple instances may be created
|
||||
dict.Add(id, this);
|
||||
Id = id;
|
||||
}
|
||||
protected internal EcsInitData InitData;
|
||||
|
||||
#region ECS initializer stuff
|
||||
/// <summary>
|
||||
/// Holds information needed to construct a component initializer.
|
||||
/// Necessary because the initializer is a ref struct which cannot be assigned to a field.
|
||||
/// </summary>
|
||||
protected internal struct EcsInitData
|
||||
{
|
||||
private FasterDictionary<RefWrapperType, ITypeSafeDictionary> group;
|
||||
private EntityReference reference;
|
||||
|
||||
protected internal EcsInitData InitData;
|
||||
public static implicit operator EcsInitData(EntityInitializer initializer) => new()
|
||||
{ group = GetInitGroup(initializer), reference = initializer.reference };
|
||||
|
||||
/// <summary>
|
||||
/// Holds information needed to construct a component initializer.
|
||||
/// Necessary because the initializer is a ref struct which cannot be assigned to a field.
|
||||
/// </summary>
|
||||
protected internal struct EcsInitData
|
||||
{
|
||||
private FasterDictionary<RefWrapperType, ITypeSafeDictionary> group;
|
||||
private EntityReference reference;
|
||||
public EntityInitializer Initializer(EGID id) => new(id, group, reference);
|
||||
public bool Valid => group != null;
|
||||
}
|
||||
|
||||
public static implicit operator EcsInitData(EntityInitializer initializer) => new()
|
||||
{ group = GetInitGroup(initializer), reference = initializer.reference };
|
||||
private delegate FasterDictionary<RefWrapperType, ITypeSafeDictionary> GetInitGroupFunc(
|
||||
EntityInitializer initializer);
|
||||
|
||||
public EntityInitializer Initializer(EGID id) => new(id, group, reference);
|
||||
public bool Valid => group != null;
|
||||
}
|
||||
/// <summary>
|
||||
/// Accesses the group field of the initializer
|
||||
/// </summary>
|
||||
private static readonly GetInitGroupFunc GetInitGroup = Reflections.CreateAccessor<GetInitGroupFunc>("_group");
|
||||
|
||||
private delegate FasterDictionary<RefWrapperType, ITypeSafeDictionary> GetInitGroupFunc(
|
||||
EntityInitializer initializer);
|
||||
#endregion
|
||||
|
||||
/// <summary>
|
||||
/// Accesses the group field of the initializer
|
||||
/// </summary>
|
||||
private static readonly GetInitGroupFunc GetInitGroup = Reflections.CreateAccessor<GetInitGroupFunc>("_group");
|
||||
|
||||
#endregion
|
||||
public static void Init()
|
||||
{
|
||||
EngineManager.AddEngine(_engine, ApiEngineType.Build, ApiEngineType.Menu, ApiEngineType.PlayClient, ApiEngineType.PlayServer);
|
||||
}
|
||||
}
|
26
TechbloxModdingAPI/Common/EcsObjectBaseEngine.cs
Normal file
26
TechbloxModdingAPI/Common/EcsObjectBaseEngine.cs
Normal file
|
@ -0,0 +1,26 @@
|
|||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Common;
|
||||
|
||||
public class EcsObjectBaseEngine : IApiEngine
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
|
@ -1,7 +1,7 @@
|
|||
using System;
|
||||
using Svelto.ECS;
|
||||
|
||||
namespace TechbloxModdingAPI.Common;
|
||||
namespace TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
/// <summary>
|
||||
/// Base engine interface used by all TechbloxModdingAPI engines
|
|
@ -1,4 +1,4 @@
|
|||
namespace TechbloxModdingAPI.Common;
|
||||
namespace TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
public interface INamedApiEngine : IApiEngine
|
||||
{
|
|
@ -1,5 +1,5 @@
|
|||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Engines
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System.Collections;
|
||||
using System.Threading.Tasks;
|
||||
using RobocraftX.Schedulers;
|
||||
using Svelto.ECS;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.ExtraLean;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Common.Utils;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
using RobocraftX.Common.Input;
|
||||
using RobocraftX.Players;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Input
|
||||
{
|
||||
|
|
|
@ -13,9 +13,9 @@ using Techblox.Camera;
|
|||
using Techblox.Character;
|
||||
using TechbloxModdingAPI.Blocks;
|
||||
using TechbloxModdingAPI.Client.App;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Players;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
|
|
|
@ -2,7 +2,7 @@ using RobocraftX.Character;
|
|||
using RobocraftX.Character.Movement;
|
||||
using RobocraftX.Common.Input;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Players
|
||||
{
|
||||
|
|
|
@ -2,11 +2,10 @@
|
|||
using Svelto.ECS;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
|
||||
using Gamecraft.Damage;
|
||||
using RobocraftX.Common;
|
||||
using RobocraftX.Physics;
|
||||
using Techblox.TimeRunning.Clusters;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
{
|
||||
|
|
|
@ -5,7 +5,7 @@ using System.Reflection.Emit;
|
|||
using System.Text;
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Utility
|
||||
{
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
using Svelto.ECS;
|
||||
using Svelto.ECS.Hybrid;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI.Utility.ECS
|
||||
{
|
||||
|
|
|
@ -1,9 +1,9 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.Tasks;
|
||||
using Svelto.Tasks.Lean;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Tasks;
|
||||
|
||||
namespace TechbloxModdingAPI.Utility.ECS
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
using Svelto.ECS;
|
||||
using RobocraftX.SimulationModeState;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
|
||||
namespace TechbloxModdingAPI.Utility
|
||||
{
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
using System;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using TechbloxModdingAPI.Common;
|
||||
|
||||
namespace TechbloxModdingAPI.Utility
|
||||
{
|
||||
|
|
Loading…
Reference in a new issue