Generalized component access
And other refactorings
This commit is contained in:
parent
bf08b61788
commit
1c6d2bda89
12 changed files with 178 additions and 254 deletions
|
@ -16,8 +16,11 @@ using TechbloxModdingAPI.Blocks.Engines;
|
|||
using TechbloxModdingAPI.Client.App;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Common.Traits;
|
||||
using TechbloxModdingAPI.Tests;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using Unity.Transforms;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TechbloxModdingAPI
|
||||
{
|
||||
|
@ -25,11 +28,9 @@ namespace TechbloxModdingAPI
|
|||
/// A single (perhaps scaled) block. Properties may return default values if the block is removed and then setting them is ignored.
|
||||
/// For specific block type operations, use the specialised block classes in the TechbloxModdingAPI.Blocks namespace.
|
||||
/// </summary>
|
||||
public class Block : EcsObjectBase, IEquatable<Block>, IEquatable<EGID>
|
||||
public class Block : EcsObjectBase, IHasPhysics, IEquatable<Block>, IEquatable<EGID>
|
||||
{
|
||||
protected static readonly PlacementEngine PlacementEngine = new();
|
||||
protected static readonly MovementEngine MovementEngine = new();
|
||||
protected static readonly RotationEngine RotationEngine = new();
|
||||
protected static readonly RemovalEngine RemovalEngine = new();
|
||||
protected static readonly SignalEngine SignalEngine = new();
|
||||
protected static readonly BlockEventsEngine BlockEventsEngine = new();
|
||||
|
@ -163,13 +164,21 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Position
|
||||
{
|
||||
get => MovementEngine.GetPosition(this);
|
||||
get => GetComponent<PositionEntityStruct>().position;
|
||||
set
|
||||
{
|
||||
MovementEngine.MoveBlock(this, value);
|
||||
// main (persistent) position
|
||||
GetComponent<PositionEntityStruct>().position = value;
|
||||
// placement grid position
|
||||
GetComponent<GridRotationStruct>().position = value;
|
||||
// rendered position
|
||||
GetComponent<LocalTransformEntityStruct>().position = value;
|
||||
this.UpdatePhysicsUECSComponent(new Translation { Value = value });
|
||||
|
||||
GetComponent<GridConnectionsEntityStruct>().areConnectionsAssigned = false;
|
||||
if (blockGroup != null)
|
||||
blockGroup.PosAndRotCalculated = false;
|
||||
BlockEngine.UpdateDisplayedBlock(Id);
|
||||
BlockEngine.UpdateDisplayData(Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -178,13 +187,24 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Rotation
|
||||
{
|
||||
get => RotationEngine.GetRotation(this);
|
||||
get => ((Quaternion)GetComponent<RotationEntityStruct>().rotation).eulerAngles;
|
||||
set
|
||||
{
|
||||
RotationEngine.RotateBlock(this, value);
|
||||
// main (persistent) rotation
|
||||
Quaternion newRotation = GetComponent<RotationEntityStruct>().rotation;
|
||||
newRotation.eulerAngles = value;
|
||||
GetComponent<RotationEntityStruct>().rotation = newRotation;
|
||||
// placement grid rotation
|
||||
GetComponent<GridRotationStruct>().rotation = newRotation;
|
||||
// rendered rotation
|
||||
GetComponent<LocalTransformEntityStruct>().rotation = newRotation;
|
||||
this.UpdatePhysicsUECSComponent(new Rotation { Value = newRotation });
|
||||
|
||||
// They are assigned during machine processing anyway
|
||||
GetComponent<GridConnectionsEntityStruct>().areConnectionsAssigned = false;
|
||||
if (blockGroup != null)
|
||||
blockGroup.PosAndRotCalculated = false;
|
||||
BlockEngine.UpdateDisplayedBlock(Id);
|
||||
BlockEngine.UpdateDisplayData(Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -194,18 +214,19 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float3 Scale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale;
|
||||
get => GetComponent<ScalingEntityStruct>().scale;
|
||||
set
|
||||
{
|
||||
int uscale = UniformScale;
|
||||
if (value.x < 4e-5) value.x = uscale;
|
||||
if (value.y < 4e-5) value.y = uscale;
|
||||
if (value.z < 4e-5) value.z = uscale;
|
||||
BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale = value;
|
||||
GetComponent<ScalingEntityStruct>().scale = value;
|
||||
GetComponent<GridConnectionsEntityStruct>().areConnectionsAssigned = false;
|
||||
//BlockEngine.GetBlockInfo<GridScaleStruct>(this).gridScale = value - (int3) value + 1;
|
||||
if (!Exists) return; //UpdateCollision needs the block to exist
|
||||
ScalingEngine.UpdateCollision(Id);
|
||||
BlockEngine.UpdateDisplayedBlock(Id);
|
||||
BlockEngine.UpdateDisplayData(Id);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -215,11 +236,12 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public int UniformScale
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor;
|
||||
get => GetComponent<UniformBlockScaleEntityStruct>().scaleFactor;
|
||||
set
|
||||
{
|
||||
//It appears that only the non-uniform scale has any visible effect so we'll set that as well
|
||||
if (value < 1) value = 1;
|
||||
BlockEngine.GetBlockInfo<UniformBlockScaleEntityStruct>(this).scaleFactor = value;
|
||||
GetComponent<UniformBlockScaleEntityStruct>().scaleFactor = value;
|
||||
Scale = new float3(value, value, value);
|
||||
}
|
||||
}
|
||||
|
@ -229,12 +251,12 @@ namespace TechbloxModdingAPI
|
|||
*/
|
||||
public bool Flipped
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ScalingEntityStruct>(this).scale.x < 0;
|
||||
get => GetComponent<ScalingEntityStruct>().scale.x < 0;
|
||||
set
|
||||
{
|
||||
ref var st = ref BlockEngine.GetBlockInfo<ScalingEntityStruct>(this);
|
||||
ref var st = ref GetComponent<ScalingEntityStruct>();
|
||||
st.scale.x = math.abs(st.scale.x) * (value ? -1 : 1);
|
||||
BlockEngine.UpdatePrefab(this, (byte) Material, value);
|
||||
BlockEngine.UpdateDisplayedPrefab(this, (byte) Material, value);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -245,7 +267,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
get
|
||||
{
|
||||
var opt = BlockEngine.GetBlockInfoOptional<DBEntityStruct>(this);
|
||||
var opt = GetComponentOptional<DBEntityStruct>();
|
||||
return opt ? (BlockIDs) opt.Get().DBID : BlockIDs.Invalid;
|
||||
}
|
||||
}
|
||||
|
@ -257,16 +279,17 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
get
|
||||
{
|
||||
var opt = BlockEngine.GetBlockInfoOptional<ColourParameterEntityStruct>(this);
|
||||
var opt = GetComponentOptional<ColourParameterEntityStruct>();
|
||||
return new BlockColor(opt ? opt.Get().indexInPalette : byte.MaxValue);
|
||||
}
|
||||
set
|
||||
{
|
||||
// TODO: Expose CubeListData in the API
|
||||
if (value.Color == BlockColors.Default)
|
||||
value = new BlockColor(FullGameFields._dataDb.TryGetValue((int) Type, out CubeListData cld)
|
||||
? cld.DefaultColour
|
||||
: throw new BlockTypeException("Unknown block type! Could not set default color."));
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this);
|
||||
ref var color = ref GetComponent<ColourParameterEntityStruct>();
|
||||
color.indexInPalette = value.Index;
|
||||
color.hasNetworkChange = true;
|
||||
color.paletteColour = BlockEngine.ConvertBlockColor(color.indexInPalette); //Setting to 255 results in black
|
||||
|
@ -279,10 +302,10 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float4 CustomColor
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this).paletteColour;
|
||||
get => GetComponent<ColourParameterEntityStruct>().paletteColour;
|
||||
set
|
||||
{
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(this);
|
||||
ref var color = ref GetComponent<ColourParameterEntityStruct>();
|
||||
color.paletteColour = value;
|
||||
color.hasNetworkChange = true;
|
||||
}
|
||||
|
@ -295,7 +318,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
get
|
||||
{
|
||||
var opt = BlockEngine.GetBlockInfoOptional<CubeMaterialStruct>(this);
|
||||
var opt = GetComponentOptional<CubeMaterialStruct>();
|
||||
return opt ? (BlockMaterial) opt.Get().materialId : BlockMaterial.Default;
|
||||
}
|
||||
set
|
||||
|
@ -307,11 +330,11 @@ namespace TechbloxModdingAPI
|
|||
: throw new BlockTypeException("Unknown block type! Could not set default material.");
|
||||
if (!FullGameFields._dataDb.ContainsKey<MaterialPropertiesData>(val))
|
||||
throw new BlockException($"Block material {value} does not exist!");
|
||||
ref var comp = ref BlockEngine.GetBlockInfo<CubeMaterialStruct>(this);
|
||||
ref var comp = ref GetComponent<CubeMaterialStruct>();
|
||||
if (comp.materialId == val)
|
||||
return;
|
||||
comp.materialId = val;
|
||||
BlockEngine.UpdatePrefab(this, val, Flipped); //The default causes the screen to go black
|
||||
BlockEngine.UpdateDisplayedPrefab(this, val, Flipped); //The default causes the screen to go black
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -324,12 +347,12 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
get
|
||||
{
|
||||
var opt = BlockEngine.GetBlockInfoOptional<LabelResourceIDComponent>(this);
|
||||
var opt = GetComponentOptional<LabelResourceIDComponent>();
|
||||
return opt ? FullGameFields._managers.blockLabelResourceManager.GetText(opt.Get().instanceID) : null;
|
||||
}
|
||||
set
|
||||
{
|
||||
var opt = BlockEngine.GetBlockInfoOptional<LabelResourceIDComponent>(this);
|
||||
var opt = GetComponentOptional<LabelResourceIDComponent>();
|
||||
if (opt) FullGameFields._managers.blockLabelResourceManager.SetText(opt.Get().instanceID, value);
|
||||
}
|
||||
}
|
||||
|
@ -349,7 +372,7 @@ namespace TechbloxModdingAPI
|
|||
{
|
||||
if (blockGroup != null) return blockGroup;
|
||||
if (!GameClient.IsBuildMode) return null; // Breaks in simulation
|
||||
var bgec = BlockEngine.GetBlockInfo<BlockGroupEntityComponent>(this);
|
||||
var bgec = GetComponent<BlockGroupEntityComponent>();
|
||||
return blockGroup = bgec.currentBlockGroup == -1
|
||||
? null
|
||||
: GetInstance(new EGID((uint)bgec.currentBlockGroup, BlockGroupExclusiveGroups.BlockGroupEntityGroup),
|
||||
|
@ -366,7 +389,7 @@ namespace TechbloxModdingAPI
|
|||
blockGroup?.RemoveInternal(this);
|
||||
if (!InitData.Valid)
|
||||
return;
|
||||
BlockEngine.GetBlockInfo<BlockGroupEntityComponent>(this).currentBlockGroup = (int?) value?.Id.entityID ?? -1;
|
||||
GetComponent<BlockGroupEntityComponent>().currentBlockGroup = (int?) value?.Id.entityID ?? -1;
|
||||
value?.AddInternal(this);
|
||||
blockGroup = value;
|
||||
}
|
||||
|
@ -377,8 +400,8 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public bool Static
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<BlockStaticComponent>(this).isStatic;
|
||||
set => BlockEngine.GetBlockInfo<BlockStaticComponent>(this).isStatic = value;
|
||||
get => GetComponent<BlockStaticComponent>().isStatic;
|
||||
set => GetComponent<BlockStaticComponent>().isStatic = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -386,7 +409,7 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public float Mass
|
||||
{
|
||||
get => BlockEngine.GetBlockInfo<MassStruct>(this).mass;
|
||||
get => GetComponent<MassStruct>().mass;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -394,16 +417,10 @@ namespace TechbloxModdingAPI
|
|||
/// </summary>
|
||||
public BlockComplexity Complexity
|
||||
{
|
||||
get => new(BlockEngine.GetBlockInfo<BlockComplexityComponent>(this));
|
||||
set => BlockEngine.GetBlockInfo<BlockComplexityComponent>(this) = value;
|
||||
get => new(GetComponent<BlockComplexityComponent>());
|
||||
set => GetComponent<BlockComplexityComponent>() = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Whether the block exists. The other properties will return a default value if the block doesn't exist.
|
||||
/// If the block was just placed, then this will also return false but the properties will work correctly.
|
||||
/// </summary>
|
||||
public bool Exists => BlockEngine.BlockExists(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of blocks that are connected to this one. Returns an empty array if the block doesn't exist.
|
||||
/// </summary>
|
||||
|
@ -422,7 +439,7 @@ namespace TechbloxModdingAPI
|
|||
/// <returns>The SimBody of the chunk or null if the block doesn't exist or not in simulation mode.</returns>
|
||||
public SimBody GetSimBody()
|
||||
{
|
||||
var st = BlockEngine.GetBlockInfo<GridConnectionsEntityStruct>(this);
|
||||
var st = GetComponent<GridConnectionsEntityStruct>();
|
||||
/*return st.machineRigidBodyId != uint.MaxValue
|
||||
? new SimBody(st.machineRigidBodyId, st.clusterId) - TODO:
|
||||
: null;*/
|
||||
|
@ -487,8 +504,6 @@ namespace TechbloxModdingAPI
|
|||
public static void Init()
|
||||
{
|
||||
EngineManager.AddEngine(PlacementEngine, ApiEngineType.Build);
|
||||
EngineManager.AddEngine(MovementEngine, ApiEngineType.Build);
|
||||
EngineManager.AddEngine(RotationEngine, ApiEngineType.Build);
|
||||
EngineManager.AddEngine(RemovalEngine, ApiEngineType.Build);
|
||||
EngineManager.AddEngine(BlockEngine, ApiEngineType.Build, ApiEngineType.PlayServer, ApiEngineType.PlayClient);
|
||||
EngineManager.AddEngine(BlockEventsEngine, ApiEngineType.Build);
|
||||
|
|
|
@ -2,7 +2,7 @@ using RobocraftX.Blocks;
|
|||
|
||||
namespace TechbloxModdingAPI.Blocks
|
||||
{
|
||||
public record BlockComplexity(int Cpu, int Power)
|
||||
public readonly record struct BlockComplexity(int Cpu, int Power)
|
||||
{
|
||||
public BlockComplexity(BlockComplexityComponent component) : this(component.cpu, component.power)
|
||||
{
|
||||
|
|
|
@ -97,8 +97,5 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
};
|
||||
}
|
||||
}
|
||||
|
||||
public string Name { get; } = "TechbloxModdingAPIBlockCloneGameEngine";
|
||||
public bool isRemovable { get; } = false;
|
||||
}
|
||||
}
|
|
@ -1,8 +1,6 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using HarmonyLib;
|
||||
|
||||
using Gamecraft.ColourPalette;
|
||||
using Gamecraft.Wires;
|
||||
using RobocraftX.Blocks;
|
||||
|
@ -14,13 +12,9 @@ using Svelto.DataStructures;
|
|||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using Svelto.ECS.Experimental;
|
||||
using Svelto.ECS.Hybrid;
|
||||
using Techblox.BuildingDrone;
|
||||
using Techblox.ObjectIDBlockServer;
|
||||
using TechbloxModdingAPI.Common;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
using PrefabsID = RobocraftX.Common.PrefabsID;
|
||||
|
||||
|
@ -74,50 +68,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
: entitiesDB.QueryEntity<PaletteEntryEntityStruct>(index,
|
||||
ColourPaletteExclusiveGroups.COLOUR_PALETTE_GROUP).Colour;
|
||||
|
||||
public OptionalRef<T> GetBlockInfoOptional<T>(Block block) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
return entitiesDB.QueryEntityOptional<T>(block);
|
||||
}
|
||||
|
||||
public ref T GetBlockInfo<T>(Block block) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
#if DEBUG
|
||||
if (!typeof(BlockTagEntityStruct).IsAssignableFrom(typeof(T)) && block.Exists && block.InitData.Valid)
|
||||
throw new ArgumentException("The block exists but the init data has not been removed!");
|
||||
#endif
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(block);
|
||||
}
|
||||
|
||||
internal ref T GetBlockInfo<T>(EcsObjectBase obj) where T : unmanaged, IEntityComponent
|
||||
{
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(obj);
|
||||
}
|
||||
|
||||
public ref T GetBlockInfoViewComponent<T>(Block block) where T : struct, IEntityViewComponent
|
||||
{
|
||||
return ref entitiesDB.QueryEntityOrDefault<T>(block);
|
||||
}
|
||||
|
||||
internal object GetBlockInfo(Block block, 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, block, null });
|
||||
var str = AccessTools.Property(opt.GetType(), "Value").GetValue(opt);
|
||||
return AccessTools.Field(str.GetType(), name).GetValue(str);
|
||||
}
|
||||
|
||||
internal void SetBlockInfo(Block block, Type type, string name, object value)
|
||||
{
|
||||
var opt = AccessTools.Method(typeof(BlockEngine), "GetBlockInfoOptional", generics: new[] { type })
|
||||
.Invoke(this, new object[] { block });
|
||||
var prop = AccessTools.Property(opt.GetType(), "Value");
|
||||
var str = prop.GetValue(opt);
|
||||
AccessTools.Field(str.GetType(), name).SetValue(str, value);
|
||||
prop.SetValue(opt, str);
|
||||
}
|
||||
|
||||
public void UpdateDisplayedBlock(EGID id)
|
||||
public void UpdateDisplayData(EGID id)
|
||||
{
|
||||
if (!BlockExists(id)) return;
|
||||
var pos = entitiesDB.QueryEntity<PositionEntityStruct>(id);
|
||||
|
@ -129,7 +80,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
entitiesDB.PublishEntityChangeDelayed<GFXPrefabEntityStructGPUI>(id); // Signal a prefab change so it updates the render buffers
|
||||
}
|
||||
|
||||
internal void UpdatePrefab(Block block, byte material, bool flipped)
|
||||
internal void UpdateDisplayedPrefab(Block block, byte material, bool flipped)
|
||||
{
|
||||
var prefabAssetIDOpt = entitiesDB.QueryEntityOptional<PrefabAssetIDComponent>(block);
|
||||
uint prefabAssetID = prefabAssetIDOpt
|
||||
|
@ -150,12 +101,12 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
entitiesDB.PublishEntityChangeDelayed<CubeMaterialStruct>(block.Id);
|
||||
entitiesDB.PublishEntityChangeDelayed<GFXPrefabEntityStructGPUI>(block.Id);
|
||||
|
||||
ref BuildingActionComponent local =
|
||||
/*ref BuildingActionComponent local =
|
||||
ref entitiesDB.QueryEntity<BuildingActionComponent>(BuildingDroneUtility
|
||||
.GetLocalBuildingDrone(entitiesDB).ToEGID(entitiesDB));
|
||||
local.buildAction = BuildAction.ChangeMaterial;
|
||||
local.targetPosition = block.Position;
|
||||
this.entitiesDB.PublishEntityChangeDelayed<BuildingActionComponent>(local.ID);
|
||||
local.targetPosition = block.Position; - TODO: This probably only plays the audio
|
||||
this.entitiesDB.PublishEntityChangeDelayed<BuildingActionComponent>(local.ID);*/
|
||||
}
|
||||
//Phyiscs prefab: prefabAssetID, set on block creation from the CubeListData
|
||||
}
|
||||
|
|
|
@ -1,68 +0,0 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using Unity.Transforms;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes block movement actions
|
||||
/// </summary>
|
||||
public class MovementEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "TechbloxModdingAPIMovementGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsInGame = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
// implementations for Movement static class
|
||||
|
||||
internal float3 MoveBlock(Block block, float3 vector)
|
||||
{
|
||||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
var phyStruct = this.entitiesDB.QueryEntityOptional<DOTSPhysicsEntityStruct>(block);
|
||||
// main (persistent) position
|
||||
posStruct.position = vector;
|
||||
// placement grid position
|
||||
gridStruct.position = vector;
|
||||
// rendered position
|
||||
transStruct.position = vector;
|
||||
// collision position
|
||||
if (phyStruct)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.Get().dotsEntity, new Translation
|
||||
{
|
||||
Value = posStruct.position
|
||||
});
|
||||
}
|
||||
|
||||
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).areConnectionsAssigned = false;
|
||||
return posStruct.position;
|
||||
}
|
||||
|
||||
internal float3 GetPosition(Block block)
|
||||
{
|
||||
return entitiesDB.QueryEntityOrDefault<PositionEntityStruct>(block).position;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -1,75 +0,0 @@
|
|||
using RobocraftX.Common;
|
||||
using RobocraftX.DOTS;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.EntityStructs;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using Unity.Mathematics;
|
||||
using UnityEngine;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
|
||||
namespace TechbloxModdingAPI.Blocks.Engines
|
||||
{
|
||||
/// <summary>
|
||||
/// Engine which executes block movement actions
|
||||
/// </summary>
|
||||
public class RotationEngine : IApiEngine
|
||||
{
|
||||
public string Name { get; } = "TechbloxModdingAPIRotationGameEngine";
|
||||
|
||||
public EntitiesDB entitiesDB { set; private get; }
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
public bool IsInGame = false;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
IsInGame = false;
|
||||
}
|
||||
|
||||
public void Ready()
|
||||
{
|
||||
IsInGame = true;
|
||||
}
|
||||
|
||||
// implementations for Rotation static class
|
||||
|
||||
internal float3 RotateBlock(Block block, Vector3 vector)
|
||||
{
|
||||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
|
||||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntityOrDefault<GridRotationStruct>(block);
|
||||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntityOrDefault<LocalTransformEntityStruct>(block);
|
||||
var phyStruct = this.entitiesDB.QueryEntityOptional<DOTSPhysicsEntityStruct>(block);
|
||||
// main (persistent) rotation
|
||||
Quaternion newRotation = rotStruct.rotation;
|
||||
newRotation.eulerAngles = vector;
|
||||
rotStruct.rotation = newRotation;
|
||||
// placement grid rotation
|
||||
gridStruct.rotation = newRotation;
|
||||
// rendered rotation
|
||||
transStruct.rotation = newRotation;
|
||||
// collision rotation
|
||||
if (phyStruct)
|
||||
{ //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.Get().dotsEntity,
|
||||
new Unity.Transforms.Rotation
|
||||
{
|
||||
Value = rotStruct.rotation
|
||||
});
|
||||
}
|
||||
|
||||
// TODO: Connections probably need to be assigned (maybe)
|
||||
// They are assigned during machine processing anyway
|
||||
entitiesDB.QueryEntityOrDefault<GridConnectionsEntityStruct>(block).areConnectionsAssigned = false;
|
||||
return ((Quaternion)rotStruct.rotation).eulerAngles;
|
||||
|
||||
}
|
||||
|
||||
internal float3 GetRotation(Block block)
|
||||
{
|
||||
ref RotationEntityStruct rotStruct = ref entitiesDB.QueryEntityOrDefault<RotationEntityStruct>(block);
|
||||
return ((Quaternion) rotStruct.rotation).eulerAngles;
|
||||
}
|
||||
}
|
||||
}
|
|
@ -29,7 +29,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
private EntityManager _entityManager; //Unity entity manager
|
||||
|
||||
public void UpdateCollision(EGID egid)
|
||||
{
|
||||
{ // TODO: Move to BlockEngine/IHasPhysics
|
||||
if (_entityManager == default)
|
||||
_entityManager = FullGameFields._physicsWorld.EntityManager;
|
||||
//Assuming the block exists
|
||||
|
|
|
@ -41,7 +41,7 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
private static IEntityFactory _entityFactory;
|
||||
|
||||
public EntityInitializer PlaceBlock(BlockIDs block, float3 position, Player player, bool autoWire)
|
||||
{ //It appears that only the non-uniform scale has any visible effect, but if that's not given here it will be set to the uniform one
|
||||
{
|
||||
return BuildBlock((ushort) block, position, autoWire, (player ?? Player.LocalPlayer).Id);
|
||||
}
|
||||
|
||||
|
@ -52,15 +52,19 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
if(!FullGameFields._dataDb.ContainsKey<CubeListData>(block))
|
||||
throw new BlockException("Block with ID " + block + " not found!");
|
||||
//RobocraftX.CR.MachineEditing.PlaceSingleBlockEngine
|
||||
DBEntityStruct dbEntity = new DBEntityStruct {DBID = block};
|
||||
|
||||
EntityInitializer structInitializer = _blockEntityFactory.Build(CommonExclusiveGroups.blockIDGeneratorClient.Next(), block); //The ghost block index is only used for triggers
|
||||
var structInitializer = _blockEntityFactory.Build(CommonExclusiveGroups.blockIDGeneratorClient.Next(), block); //The ghost block index is only used for triggers
|
||||
|
||||
// Use the default steel material for the block until it's changed and set up the graphics for it
|
||||
uint prefabAssetID = structInitializer.Has<PrefabAssetIDComponent>()
|
||||
? structInitializer.Get<PrefabAssetIDComponent>().prefabAssetID
|
||||
: throw new BlockException("Prefab asset ID not found!"); //Set by the game
|
||||
uint prefabId = PrefabsID.GetOrAddPrefabID((ushort) prefabAssetID, (byte) BlockMaterial.SteelBodywork, 1, false);
|
||||
structInitializer.Init(new GFXPrefabEntityStructGPUI(prefabId));
|
||||
structInitializer.Init(dbEntity);
|
||||
structInitializer.Get<CubeMaterialStruct>().materialId = (byte) BlockMaterial.SteelBodywork;
|
||||
|
||||
// The DBID is the block's type (cube, servo, seat etc.)
|
||||
structInitializer.Init(new DBEntityStruct {DBID = block});
|
||||
structInitializer.Init(new PositionEntityStruct {position = position});
|
||||
structInitializer.Init(new RotationEntityStruct {rotation = quaternion.identity});
|
||||
structInitializer.Init(new ScalingEntityStruct {scale = new float3(1, 1, 1)});
|
||||
|
@ -70,7 +74,6 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
rotation = quaternion.identity
|
||||
});
|
||||
structInitializer.Init(new UniformBlockScaleEntityStruct {scaleFactor = 1});
|
||||
structInitializer.Get<CubeMaterialStruct>().materialId = (byte) BlockMaterial.SteelBodywork;
|
||||
var bssesopt = entitiesDB.QueryEntityOptional<BoxSelectStateEntityStruct>(new EGID(playerId,
|
||||
BoxSelectExclusiveGroups.BoxSelectVolumeExclusiveGroup));
|
||||
if (!bssesopt)
|
||||
|
@ -107,10 +110,6 @@ namespace TechbloxModdingAPI.Blocks.Engines
|
|||
return structInitializer;
|
||||
}
|
||||
|
||||
public string Name => "TechbloxModdingAPIPlacementGameEngine";
|
||||
|
||||
public bool isRemovable => false;
|
||||
|
||||
[HarmonyPatch]
|
||||
class FactoryObtainerPatch
|
||||
{
|
|
@ -2,6 +2,7 @@ using System;
|
|||
using System.Collections.Generic;
|
||||
using Svelto.DataStructures;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Hybrid;
|
||||
using Svelto.ECS.Internal;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Common.Utils;
|
||||
|
@ -18,6 +19,11 @@ public abstract class EcsObjectBase
|
|||
/// </summary>
|
||||
public EntityReference Reference { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Whether the entity reference is still valid. Returns false if this object no longer exists.
|
||||
/// </summary>
|
||||
public bool Exists => Id != default; // TODO: Might need extra code to support IDs during init
|
||||
|
||||
private static readonly Dictionary<Type, WeakDictionary<EntityReference, EcsObjectBase>> _instances = new();
|
||||
private static readonly EcsObjectBaseEngine _engine = new();
|
||||
|
||||
|
@ -58,6 +64,38 @@ public abstract class EcsObjectBase
|
|||
Reference = reference;
|
||||
}
|
||||
|
||||
|
||||
|
||||
protected internal OptionalRef<T> GetComponentOptional<T>() where T : unmanaged, IEntityComponent
|
||||
{
|
||||
return _engine.GetComponentOptional<T>(this);
|
||||
}
|
||||
|
||||
protected internal ref T GetComponent<T>() where T : unmanaged, IEntityComponent
|
||||
{
|
||||
return ref _engine.GetComponent<T>(this);
|
||||
}
|
||||
|
||||
protected internal ref T GetViewComponent<T>() where T : struct, IEntityViewComponent
|
||||
{
|
||||
return ref _engine.GetViewComponent<T>(this);
|
||||
}
|
||||
|
||||
protected internal object GetComponent(Type type, string name)
|
||||
{
|
||||
return _engine.GetComponent(this, type, name);
|
||||
}
|
||||
|
||||
protected internal void SetComponent(Type type, string name, object value)
|
||||
{
|
||||
_engine.SetComponent(this, type, name, value);
|
||||
}
|
||||
|
||||
protected bool RemoveEntity()
|
||||
{
|
||||
// TODO: _entityFunctions.Remove...()
|
||||
}
|
||||
|
||||
#region ECS initializer stuff
|
||||
|
||||
protected internal EcsInitData InitData;
|
||||
|
|
|
@ -1,5 +1,11 @@
|
|||
using System;
|
||||
using HarmonyLib;
|
||||
using Svelto.ECS;
|
||||
using Svelto.ECS.Hybrid;
|
||||
using TechbloxModdingAPI.Blocks.Engines;
|
||||
using TechbloxModdingAPI.Common.Engines;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using TechbloxModdingAPI.Utility.ECS;
|
||||
|
||||
namespace TechbloxModdingAPI.Common;
|
||||
|
||||
|
@ -10,6 +16,7 @@ public class EcsObjectBaseEngine : IApiEngine
|
|||
}
|
||||
|
||||
public EntitiesDB entitiesDB { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
@ -23,4 +30,42 @@ public class EcsObjectBaseEngine : IApiEngine
|
|||
{
|
||||
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);
|
||||
}
|
||||
}
|
20
TechbloxModdingAPI/Common/Traits/HasPhysics.cs
Normal file
20
TechbloxModdingAPI/Common/Traits/HasPhysics.cs
Normal file
|
@ -0,0 +1,20 @@
|
|||
using RobocraftX.DOTS;
|
||||
using TechbloxModdingAPI.Utility;
|
||||
using Unity.Entities;
|
||||
using Unity.Transforms;
|
||||
|
||||
namespace TechbloxModdingAPI.Common.Traits;
|
||||
|
||||
public interface IHasPhysics
|
||||
{
|
||||
}
|
||||
|
||||
public static class HasPhysicsExtensions
|
||||
{
|
||||
internal static void UpdatePhysicsUECSComponent<T, O>(this O obj, T componentData) where O : EcsObjectBase, IHasPhysics where T : struct, IComponentData
|
||||
{
|
||||
var phyStruct = obj.GetComponentOptional<DOTSPhysicsEntityStruct>();
|
||||
if (phyStruct) //It exists
|
||||
FullGameFields._physicsWorld.EntityManager.SetComponentData(phyStruct.Get().dotsEntity, componentData);
|
||||
}
|
||||
}
|
|
@ -11,6 +11,8 @@
|
|||
<NeutralLanguage>en-CA</NeutralLanguage>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>latest</LangVersion>
|
||||
<Configurations>Debug;Release;Test</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
|
Loading…
Reference in a new issue