diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs
index 88932da..1a8673a 100644
--- a/GamecraftModdingAPI/Block.cs
+++ b/GamecraftModdingAPI/Block.cs
@@ -23,6 +23,7 @@ namespace GamecraftModdingAPI
protected static readonly RotationEngine RotationEngine = new RotationEngine();
protected static readonly RemovalEngine RemovalEngine = new RemovalEngine();
protected static readonly BlockEngine BlockEngine = new BlockEngine();
+ protected static readonly SignalEngine SignalEngine = new SignalEngine();
///
/// Place a new block at the given position. If scaled, position means the center of the block. The default block size is 0.2 in terms of position.
diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs
index 377fa5b..6275ca1 100644
--- a/GamecraftModdingAPI/Blocks/BlockEngine.cs
+++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs
@@ -74,8 +74,8 @@ namespace GamecraftModdingAPI.Blocks
if (exists)
return ref entitiesDB.QueryEntity(blockID);
T[] structHolder = new T[1];
- ref T structRef = ref structHolder[0];
- return ref structRef;
+ //ref T defRef = ref structHolder[0];
+ return ref structHolder[0];
}
public bool BlockExists(EGID id)
diff --git a/GamecraftModdingAPI/Blocks/Motor.cs b/GamecraftModdingAPI/Blocks/Motor.cs
new file mode 100644
index 0000000..13a246f
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/Motor.cs
@@ -0,0 +1,113 @@
+using System;
+
+using RobocraftX.Blocks;
+using Svelto.ECS;
+using Unity.Mathematics;
+
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ public class Motor : Block
+ {
+ ///
+ /// Places a new motor.
+ /// Any valid motor type is accepted.
+ /// This re-implements Block.PlaceNew(...)
+ ///
+ public static new Motor PlaceNew(BlockIDs block, float3 position,
+ float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
+ int uscale = 1, float3 scale = default, Player player = null)
+ {
+ if (!(block == BlockIDs.MotorS || block == BlockIDs.MotorM))
+ {
+ throw new BlockTypeException($"Block is not a {typeof(Motor).Name} block");
+ }
+ if (PlacementEngine.IsInGame && GameState.IsBuildMode())
+ {
+ try
+ {
+ EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
+ position, uscale, scale, player, rotation);
+ Sync();
+ return new Motor(id);
+ }
+ catch (Exception e)
+ {
+ Logging.MetaDebugLog(e);
+ }
+ }
+
+ return null;
+ }
+
+ public Motor(EGID id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ public Motor(uint id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ // custom motor properties
+
+ ///
+ /// The motor's maximum rotational velocity.
+ ///
+ public float TopSpeed
+ {
+ get
+ {
+ return BlockEngine.GetBlockInfo(Id).maxVelocity;
+ }
+
+ set
+ {
+ ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo(Id);
+ motor.maxVelocity = value;
+ }
+ }
+
+ ///
+ /// The motor's maximum rotational force.
+ ///
+ public float Torque
+ {
+ get
+ {
+ return BlockEngine.GetBlockInfo(Id).maxForce;
+ }
+
+ set
+ {
+ ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo(Id);
+ motor.maxForce = value;
+ }
+ }
+
+ ///
+ /// The motor's direction.
+ ///
+ public bool Reverse
+ {
+ get
+ {
+ return BlockEngine.GetBlockInfo(Id).reverse;
+ }
+
+ set
+ {
+ ref MotorReadOnlyStruct motor = ref BlockEngine.GetBlockInfo(Id);
+ motor.reverse = value;
+ }
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Blocks/Piston.cs b/GamecraftModdingAPI/Blocks/Piston.cs
new file mode 100644
index 0000000..1e69df6
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/Piston.cs
@@ -0,0 +1,90 @@
+using System;
+
+using RobocraftX.Blocks;
+using Svelto.ECS;
+using Unity.Mathematics;
+
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ public class Piston : Block
+ {
+ ///
+ /// Places a new piston.
+ /// Any valid piston type is accepted.
+ /// This re-implements Block.PlaceNew(...)
+ ///
+ public static new Piston PlaceNew(BlockIDs block, float3 position,
+ float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
+ int uscale = 1, float3 scale = default, Player player = null)
+ {
+ if (!(block == BlockIDs.ServoPiston || block == BlockIDs.StepperPiston || block == BlockIDs.PneumaticPiston))
+ {
+ throw new BlockTypeException($"Block is not a {typeof(Piston).Name} block");
+ }
+ if (PlacementEngine.IsInGame && GameState.IsBuildMode())
+ {
+ try
+ {
+ EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
+ position, uscale, scale, player, rotation);
+ Sync();
+ return new Piston(id);
+ }
+ catch (Exception e)
+ {
+ Logging.MetaDebugLog(e);
+ }
+ }
+
+ return null;
+ }
+
+ public Piston(EGID id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ public Piston(uint id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ // custom piston properties
+
+ ///
+ /// The piston's max extension distance.
+ ///
+ public float MaximumExtension
+ {
+ get => BlockEngine.GetBlockInfo(Id).maxDeviation;
+
+ set
+ {
+ ref PistonReadOnlyStruct piston = ref BlockEngine.GetBlockInfo(Id);
+ piston.maxDeviation = value;
+ }
+ }
+
+ ///
+ /// The piston's max extension force.
+ ///
+ public float MaximumForce
+ {
+ get => BlockEngine.GetBlockInfo(Id).maxForce;
+
+ set
+ {
+ ref PistonReadOnlyStruct piston = ref BlockEngine.GetBlockInfo(Id);
+ piston.maxForce = value;
+ }
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Blocks/Servo.cs b/GamecraftModdingAPI/Blocks/Servo.cs
new file mode 100644
index 0000000..1c22d0b
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/Servo.cs
@@ -0,0 +1,118 @@
+using System;
+
+using RobocraftX.Blocks;
+using Svelto.ECS;
+using Unity.Mathematics;
+
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ public class Servo : Block
+ {
+ ///
+ /// Places a new servo.
+ /// Any valid servo type is accepted.
+ /// This re-implements Block.PlaceNew(...)
+ ///
+ public static new Servo PlaceNew(BlockIDs block, float3 position,
+ float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
+ int uscale = 1, float3 scale = default, Player player = null)
+ {
+ if (!(block == BlockIDs.ServoAxle || block == BlockIDs.ServoHinge || block == BlockIDs.ServoPiston))
+ {
+ throw new BlockTypeException($"Block is not a {typeof(Servo).Name} block");
+ }
+ if (PlacementEngine.IsInGame && GameState.IsBuildMode())
+ {
+ try
+ {
+ EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
+ position, uscale, scale, player, rotation);
+ Sync();
+ return new Servo(id);
+ }
+ catch (Exception e)
+ {
+ Logging.MetaDebugLog(e);
+ }
+ }
+
+ return null;
+ }
+
+ public Servo(EGID id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ public Servo(uint id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ // custom servo properties
+
+ ///
+ /// The servo's minimum angle.
+ ///
+ public float MinimumAngle
+ {
+ get => BlockEngine.GetBlockInfo(Id).minDeviation;
+
+ set
+ {
+ ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo(Id);
+ servo.minDeviation = value;
+ }
+ }
+
+ ///
+ /// The servo's maximum angle.
+ ///
+ public float MaximumAngle
+ {
+ get => BlockEngine.GetBlockInfo(Id).maxDeviation;
+
+ set
+ {
+ ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo(Id);
+ servo.maxDeviation = value;
+ }
+ }
+
+ ///
+ /// The servo's maximum force.
+ ///
+ public float MaximumForce
+ {
+ get => BlockEngine.GetBlockInfo(Id).maxForce;
+
+ set
+ {
+ ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo(Id);
+ servo.maxForce = value;
+ }
+ }
+
+ ///
+ /// The servo's direction.
+ ///
+ public bool Reverse
+ {
+ get => BlockEngine.GetBlockInfo(Id).reverse;
+
+ set
+ {
+ ref ServoReadOnlyStruct servo = ref BlockEngine.GetBlockInfo(Id);
+ servo.reverse = value;
+ }
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Blocks/SignalEngine.cs b/GamecraftModdingAPI/Blocks/SignalEngine.cs
index 90343e2..36716af 100644
--- a/GamecraftModdingAPI/Blocks/SignalEngine.cs
+++ b/GamecraftModdingAPI/Blocks/SignalEngine.cs
@@ -10,6 +10,11 @@ namespace GamecraftModdingAPI.Blocks
///
public class SignalEngine : IApiEngine
{
+ public const float POSITIVE_HIGH = 1.0f;
+ public const float NEGATIVE_HIGH = -1.0f;
+ public const float HIGH = 1.0f;
+ public const float ZERO = 0.0f;
+
public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
public EntitiesDB entitiesDB { set; private get; }
@@ -58,13 +63,13 @@ namespace GamecraftModdingAPI.Blocks
channelData.valueAsFloat += signal;
if (clamp)
{
- if (channelData.valueAsFloat > Signals.POSITIVE_HIGH)
+ if (channelData.valueAsFloat > POSITIVE_HIGH)
{
- channelData.valueAsFloat = Signals.POSITIVE_HIGH;
+ channelData.valueAsFloat = POSITIVE_HIGH;
}
- else if (channelData.valueAsFloat < Signals.NEGATIVE_HIGH)
+ else if (channelData.valueAsFloat < NEGATIVE_HIGH)
{
- channelData.valueAsFloat = Signals.NEGATIVE_HIGH;
+ channelData.valueAsFloat = NEGATIVE_HIGH;
}
return channelData.valueAsFloat;
@@ -106,6 +111,60 @@ namespace GamecraftModdingAPI.Blocks
return signals;
}
+ public EGID[] GetSignalInputs(EGID blockID)
+ {
+ BlockPortsStruct ports = entitiesDB.QueryEntity(blockID);
+ EGID[] inputs = new EGID[ports.inputCount];
+ for (uint i = 0; i < ports.inputCount; i++)
+ {
+ inputs[i] = new EGID(i + ports.firstInputID, NamedExclusiveGroup.Group);
+ }
+ return inputs;
+ }
+
+ public EGID[] GetSignalOutputs(EGID blockID)
+ {
+ BlockPortsStruct ports = entitiesDB.QueryEntity(blockID);
+ EGID[] outputs = new EGID[ports.outputCount];
+ for (uint i = 0; i < ports.outputCount; i++)
+ {
+ outputs[i] = new EGID(i + ports.firstOutputID, NamedExclusiveGroup.Group);
+ }
+ return outputs;
+ }
+
+ public ref WireEntityStruct MatchPortToWire(EGID portID, EGID blockID, out bool exists)
+ {
+ ref PortEntityStruct port = ref entitiesDB.QueryEntity(portID);
+ WireEntityStruct[] wires = entitiesDB.QueryEntities(NamedExclusiveGroup.Group).ToFastAccess(out uint count);
+ for (uint i = 0; i < count; i++)
+ {
+ if ((wires[i].destinationPortUsage == port.usage && wires[i].destinationBlockEGID == blockID)
+ || (wires[i].sourcePortUsage == port.usage && wires[i].sourceBlockEGID == blockID))
+ {
+ exists = true;
+ return ref wires[i];
+ }
+ }
+ exists = false;
+ WireEntityStruct[] defRef = new WireEntityStruct[1];
+ return ref defRef[0];
+ }
+
+ public ref ChannelDataStruct GetChannelDataStruct(EGID portID, out bool exists)
+ {
+ ref PortEntityStruct port = ref entitiesDB.QueryEntity(portID);
+ ChannelDataStruct[] channels = entitiesDB.QueryEntities(NamedExclusiveGroup.Group).ToFastAccess(out uint count);
+ if (port.firstChannelIndexCachedInSim < count)
+ {
+ exists = true;
+ return ref channels[port.firstChannelIndexCachedInSim];
+ }
+ exists = false;
+ ChannelDataStruct[] defRef = new ChannelDataStruct[1];
+ return ref defRef[0];
+ }
+
public EGID[] GetElectricBlocks()
{
uint count = entitiesDB.Count(BlockIdentifiers.OWNED_BLOCKS) + entitiesDB.Count(BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
diff --git a/GamecraftModdingAPI/Blocks/SignalingBlock.cs b/GamecraftModdingAPI/Blocks/SignalingBlock.cs
new file mode 100644
index 0000000..d654ca9
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/SignalingBlock.cs
@@ -0,0 +1,131 @@
+using System;
+
+using Gamecraft.Wires;
+using Svelto.ECS;
+using Unity.Mathematics;
+
+using GamecraftModdingAPI;
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ ///
+ /// Common implementation for blocks that support wiring.
+ ///
+ public class SignalingBlock : Block
+ {
+ ///
+ /// Places a new signaling block.
+ /// Any valid functional block type with IO ports will work.
+ /// This re-implements Block.PlaceNew(...)
+ ///
+ public static new SignalingBlock PlaceNew(BlockIDs block, float3 position,
+ float3 rotation = default, BlockColors color = BlockColors.Default, byte darkness = 0,
+ int uscale = 1, float3 scale = default, Player player = null)
+ {
+ if (PlacementEngine.IsInGame && GameState.IsBuildMode())
+ {
+ try
+ {
+ EGID id = PlacementEngine.PlaceBlock(block, color, darkness,
+ position, uscale, scale, player, rotation);
+ Sync();
+ return new SignalingBlock(id);
+ }
+ catch (Exception e)
+ {
+ Logging.MetaDebugLog(e);
+ }
+ }
+
+ return null;
+ }
+
+ public SignalingBlock(EGID id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ public SignalingBlock(uint id) : base(id)
+ {
+ if (!BlockEngine.GetBlockInfoExists(this.Id))
+ {
+ throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
+ }
+ }
+
+ protected ref BlockPortsStruct GetBlockPortsStruct()
+ {
+ return ref BlockEngine.GetBlockInfo(Id);
+ }
+
+ ///
+ /// Generates the input port identifiers.
+ ///
+ /// The input identifiers.
+ protected EGID[] GetInputIds()
+ {
+ return SignalEngine.GetSignalInputs(Id);
+ }
+
+ ///
+ /// Generates the output port identifiers.
+ ///
+ /// The output identifiers.
+ protected EGID[] GetOutputIds()
+ {
+ return SignalEngine.GetSignalOutputs(Id);
+ }
+
+ ///
+ /// Gets the port struct.
+ ///
+ /// The port struct.
+ /// Port identifier.
+ protected ref PortEntityStruct GetPortStruct(EGID portId)
+ {
+ return ref BlockEngine.GetBlockInfo(portId);
+ }
+
+ ///
+ /// Gets the connected wire.
+ ///
+ /// The connected wire.
+ /// Port identifier.
+ /// Whether the port has a wire connected to it.
+ protected ref WireEntityStruct GetConnectedWire(EGID portId, out bool connected)
+ {
+ return ref SignalEngine.MatchPortToWire(portId, Id, out connected);
+ }
+
+ ///
+ /// [EXPERIMENTAL] Gets the channel data.
+ ///
+ /// The channel data.
+ /// Port identifier.
+ /// Whether the channel actually exists.
+ protected ref ChannelDataStruct GetChannelData(EGID portId, out bool exists)
+ {
+ return ref SignalEngine.GetChannelDataStruct(portId, out exists);
+ }
+
+ ///
+ /// The input port count.
+ ///
+ public uint InputCount
+ {
+ get => GetBlockPortsStruct().inputCount;
+ }
+
+ ///
+ /// The output port count.
+ ///
+ public uint OutputCount
+ {
+ get => GetBlockPortsStruct().outputCount;
+ }
+ }
+}
diff --git a/GamecraftModdingAPI/Blocks/Signals.cs b/GamecraftModdingAPI/Blocks/Signals.cs
deleted file mode 100644
index 6adf670..0000000
--- a/GamecraftModdingAPI/Blocks/Signals.cs
+++ /dev/null
@@ -1,177 +0,0 @@
-using Svelto.ECS;
-
-using GamecraftModdingAPI.Utility;
-
-namespace GamecraftModdingAPI.Blocks
-{
- ///
- /// [EXPERIMENTAL] Common block signal operations
- /// The functionality in this class only works when in a game.
- ///
- public static class Signals
- {
- // Signal constants
- public static readonly float HIGH = 1.0f;
- public static readonly float POSITIVE_HIGH = HIGH;
- public static readonly float NEGATIVE_HIGH = -1.0f;
- public static readonly float LOW = 0.0f;
-
- private static SignalEngine signalEngine = new SignalEngine();
-
- ///
- /// Set the electric block's (first) signal value.
- ///
- /// The block's id.
- /// The signal value (-1 to 1; not enforced).
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// Whether the block is in the owned group (true) or functional group (false)
- public static void SetSignalByBlock(uint blockID, float signal, bool input = true, bool owned = true)
- {
- EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
- if (signalEngine.IsInGame && GameState.IsSimulationMode())
- {
- signalEngine.SetSignal(egid, signal, out uint _, input);
- }
- }
-
- public static void SetSignalByBlock(EGID blockID, float signal, bool input = true)
- {
- if (signalEngine.IsInGame && GameState.IsSimulationMode())
- {
- signalEngine.SetSignal(blockID, signal, out uint _, input);
- }
- }
-
- ///
- /// Set the signal's value.
- ///
- /// The channel cluster's id.
- /// The signal value (-1 to 1; not enforced).
- /// Whether to retrieve input IDs (true) or output IDs (false).
- public static void SetSignalByID(uint signalID, float signal, bool input = true)
- {
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- signalEngine.SetSignal(signalID, signal, input);
- }
- }
-
- ///
- /// Add a value to an electric block's signal.
- ///
- /// The block's id.
- /// The signal value to add.
- /// Whether to clamp the resulting signal value between -1 and 1.
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// Whether the block is in the owned group (true) or functional group (false)
- /// The signal's new value.
- public static float AddSignalByBlock(uint blockID, float signal, bool clamp = true, bool input = true, bool owned = true)
- {
- EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.AddSignal(egid, signal, out uint _, clamp, input);
- }
- return 0f;
- }
-
- public static float AddSignalByBlock(EGID blockID, float signal, bool clamp = true, bool input = true)
- {
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.AddSignal(blockID, signal, out uint _, clamp, input);
- }
- return 0f;
- }
-
- ///
- /// Add a value to a conductive cluster channel.
- ///
- /// The channel cluster's id.
- /// The signal value to add.
- /// Whether to clamp the resulting signal value between -1 and 1.
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// The signal's new value.
- public static float AddSignalByID(uint signalID, float signal, bool clamp = true, bool input = true)
- {
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.AddSignal(signalID, signal, clamp, input);
- }
- return 0f;
- }
-
- ///
- /// Get a electric block's signal's (first) value.
- ///
- /// The block's id.
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// Whether the block is in the owned group (true) or functional group (false)
- /// The signal's value.
- public static float GetSignalByBlock(uint blockID, bool input = true, bool owned = true)
- {
- EGID egid = new EGID(blockID, owned? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.GetSignal(egid, out uint _, input);
- }
- return 0f;
- }
-
- public static float GetSignalByBlock(EGID blockID, bool input = true)
- {
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.GetSignal(blockID, out uint _, input);
- }
- return 0f;
- }
-
- ///
- /// Get a signal's value.
- ///
- /// The signal's id.
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// The signal's value.
- public static float GetSignalByID(uint signalID, bool input = true)
- {
- if (signalEngine.IsInGame && GamecraftModdingAPI.Utility.GameState.IsSimulationMode())
- {
- return signalEngine.GetSignal(signalID, input);
- }
- return 0f;
- }
-
- ///
- /// Get the ID of every electric block in the game world.
- ///
- /// The block IDs.
- public static EGID[] GetElectricBlocks()
- {
- return signalEngine.GetElectricBlocks();
- }
-
- ///
- /// Get the unique identifiers for the input wires connected to an electric block.
- ///
- /// The block's id.
- /// Whether to retrieve input IDs (true) or output IDs (false).
- /// Whether the block is in the owned group (true) or functional group (false)
- /// The unique IDs.
- public static uint[] GetSignalIDs(uint blockID, bool input = true, bool owned = true)
- {
- EGID egid = new EGID(blockID, owned ? BlockIdentifiers.OWNED_BLOCKS : BlockIdentifiers.FUNCTIONAL_BLOCK_PARTS);
- return signalEngine.GetSignalIDs(egid, input);
- }
-
- public static uint[] GetSignalIDs(EGID blockID, bool input = true, bool owned = true)
- {
- return signalEngine.GetSignalIDs(blockID, input);
- }
-
- public static void Init()
- {
- GameEngineManager.AddGameEngine(signalEngine);
- }
- }
-}
diff --git a/GamecraftModdingAPI/Blocks/Tweakable.cs b/GamecraftModdingAPI/Blocks/Tweakable.cs
deleted file mode 100644
index 6405ac3..0000000
--- a/GamecraftModdingAPI/Blocks/Tweakable.cs
+++ /dev/null
@@ -1,98 +0,0 @@
-namespace GamecraftModdingAPI.Blocks
-{
- ///
- /// Common tweakable stats operations.
- /// The functionality of this class works best in build mode.
- ///
- public static class Tweakable
- {
- private static TweakableEngine tweakableEngine = new TweakableEngine();
-
- ///
- /// Get the tweakable stat's value using a dynamic variable type.
- /// This is similar to GetStat but without strong type enforcement.
- /// This should be used in dynamically-typed languages like Python.
- ///
- /// The stat's value.
- /// The block's id.
- /// The stat's enumerated id.
- public static dynamic GetStatD(uint blockID, TweakableStat stat)
- {
- return tweakableEngine.GetStatDynamic(blockID, stat);
- }
-
- ///
- /// Get the tweakable stat's value.
- /// If T is not the same type as the stat, an InvalidCastException will be thrown.
- ///
- /// The stat's value.
- /// The block's id.
- /// The stat's enumerated id.
- /// The stat's type.
- public static T GetStat(uint blockID, TweakableStat stat)
- {
- return tweakableEngine.GetStatAny(blockID, stat);
- }
-
- ///
- /// Set the tweakable stat's value using dynamically-typed variables.
- /// This is similar to SetStat but without strong type enforcement.
- /// This should be used in dynamically-typed languages like Python.
- ///
- /// The stat's new value.
- /// The block's id.
- /// The stat's enumerated id.
- /// The stat's new value.
- public static dynamic SetStatD(uint blockID, TweakableStat stat, dynamic value)
- {
- return tweakableEngine.SetStatDynamic(blockID, stat, value);
- }
-
- ///
- /// Set the tweakable stat's value.
- /// If T is not the stat's actual type, an InvalidCastException will be thrown.
- ///
- /// The stat's new value.
- /// The block's id.
- /// The stat's enumerated id.
- /// The stat's new value.
- /// The stat's type.
- public static T SetStat(uint blockID, TweakableStat stat, T value)
- {
- return tweakableEngine.SetStatAny(blockID, stat, value);
- }
-
- ///
- /// Add another value to the tweakable stat's value using dynamically-typed variables.
- /// This is similar to AddStat but without strong type enforcement.
- /// This should be used in dynamically-typed languages like Python.
- ///
- /// The stat's new value.
- /// The block's id.
- /// The stat's enumerated id.
- /// The value to be added to the stat.
- public static dynamic AddStatD(uint blockID, TweakableStat stat, dynamic value)
- {
- return tweakableEngine.AddStatDynamic(blockID, stat, value);
- }
-
- ///
- /// Add another value to the tweakable stat's value.
- /// If T is not the stat's actual type, an InvalidCastException will be thrown.
- ///
- /// The stat's new value.
- /// The block's id.
- /// The stat's enumerated id.
- /// The value to be added to the stat.
- /// The stat's type.
- public static T AddStat(uint blockID, TweakableStat stat, T value)
- {
- return tweakableEngine.AddStatAny(blockID, stat, value);
- }
-
- public static void Init()
- {
- GamecraftModdingAPI.Utility.GameEngineManager.AddGameEngine(tweakableEngine);
- }
- }
-}
diff --git a/GamecraftModdingAPI/Blocks/TweakableEngine.cs b/GamecraftModdingAPI/Blocks/TweakableEngine.cs
deleted file mode 100644
index 36ace8a..0000000
--- a/GamecraftModdingAPI/Blocks/TweakableEngine.cs
+++ /dev/null
@@ -1,452 +0,0 @@
-using RobocraftX.Blocks;
-using Gamecraft.Wires;
-using Svelto.ECS;
-
-using GamecraftModdingAPI.Engines;
-
-
-namespace GamecraftModdingAPI.Blocks
-{
- public class TweakableEngine : IApiEngine
- {
- public string Name { get; } = "GamecraftModdingAPITweakableGameEngine";
-
- 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 Tweakable static class
-
- public T GetStatAny(EGID blockID, TweakableStat stat)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- return (T)(object)entitiesDB.QueryEntity(blockID).startValue;
- }
- break;
- }
- return default(T);
- }
-
- public T GetStatAny(uint blockID, TweakableStat stat)
- {
- return GetStatAny(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat);
- }
-
- public dynamic GetStatDynamic(EGID blockID, TweakableStat stat)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- return entitiesDB.QueryEntity(blockID).startValue;
- }
- break;
- }
- return null;
- }
-
- public dynamic GetStatDynamic(uint blockID, TweakableStat stat)
- {
- return GetStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat);
- }
-
- public T SetStatAny(EGID blockID, TweakableStat stat, T value)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxVelocity = (float)(object)value;
- return (T)(object)refStruct.maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxForce = (float)(object)value;
- return (T)(object)refStruct.maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation = (float)(object)value;
- return (T)(object)refStruct.maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.minDeviation = (float)(object)value;
- return (T)(object)refStruct.minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation = (float)(object)value;
- return (T)(object)refStruct.maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = (bool)(object)value;
- return (T)(object)refStruct.reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = (bool)(object)value;
- return (T)(object)refStruct.reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.startValue = (float)(object)value;
- return (T)(object)refStruct.startValue;
- }
- break;
- }
- return default(T);
- }
-
- public T SetStatAny(uint blockID, TweakableStat stat, T value)
- {
- return SetStatAny(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
- }
-
- public dynamic SetStatDynamic(EGID blockID, TweakableStat stat, dynamic value)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxVelocity = value;
- return refStruct.maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxForce = value;
- return refStruct.maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation = value;
- return refStruct.maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.minDeviation = value;
- return refStruct.minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation = value;
- return refStruct.maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = value;
- return refStruct.reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = value;
- return refStruct.reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.startValue = value;
- return refStruct.startValue;
- }
- break;
- }
- return null;
- }
-
- public dynamic SetStatDynamic(uint blockID, TweakableStat stat, dynamic value)
- {
- return SetStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
- }
-
- public T AddStatAny(EGID blockID, TweakableStat stat, T value)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxVelocity += (float)(object)value;
- return (T)(object)refStruct.maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxForce += (float)(object)value;
- return (T)(object)refStruct.maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation += (float)(object)value;
- return (T)(object)refStruct.maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.minDeviation += (float)(object)value;
- return (T)(object)refStruct.minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation += (float)(object)value;
- return (T)(object)refStruct.maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- // '+' is associated with logical OR in some fields, so it technically isn't invalid to "add" booleans
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = refStruct.reverse || (bool)(object)value;
- return (T)(object)refStruct.reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = refStruct.reverse || (bool)(object)value;
- return (T)(object)refStruct.reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.startValue += (float)(object)value;
- return (T)(object)refStruct.startValue;
- }
- break;
- }
- return default(T);
- }
-
- public T AddStatAny(uint blockID, TweakableStat stat, T value)
- {
- return AddStatAny(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
- }
-
- public dynamic AddStatDynamic(EGID blockID, TweakableStat stat, dynamic value)
- {
- switch (stat)
- {
- case TweakableStat.TopSpeed:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxVelocity += value;
- return refStruct.maxVelocity;
- }
- break;
- case TweakableStat.Torque:
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxForce += value;
- return refStruct.maxForce;
- }
- break;
- case TweakableStat.MaxExtension:
- if (entitiesDB.Exists(blockID))
- {
- ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation += value;
- return refStruct.maxDeviation;
- }
- break;
- case TweakableStat.MinAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.minDeviation += value;
- return refStruct.minDeviation;
- }
- break;
- case TweakableStat.MaxAngle:
- if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.maxDeviation += value;
- return refStruct.maxDeviation;
- }
- break;
- case TweakableStat.Reverse:
- // '+' is associated with logical OR in some fields, so it technically isn't invalid to "add" booleans
- if (entitiesDB.Exists(blockID))
- {
- ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = refStruct.reverse || value;
- return refStruct.reverse;
- }
- else if (entitiesDB.Exists(blockID))
- {
- ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.reverse = refStruct.reverse || value;
- return refStruct.reverse;
- }
- break;
- case TweakableStat.StartValue:
- if (entitiesDB.Exists(blockID))
- {
- ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity(blockID);
- refStruct.startValue += value;
- return refStruct.startValue;
- }
- break;
- }
- return null;
- }
-
- public dynamic AddStatDynamic(uint blockID, TweakableStat stat, dynamic value)
- {
- return AddStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
- }
- }
-}
diff --git a/GamecraftModdingAPI/Blocks/TweakableStat.cs b/GamecraftModdingAPI/Blocks/TweakableStat.cs
deleted file mode 100644
index 228c89d..0000000
--- a/GamecraftModdingAPI/Blocks/TweakableStat.cs
+++ /dev/null
@@ -1,13 +0,0 @@
-namespace GamecraftModdingAPI.Blocks
-{
- public enum TweakableStat
- {
- TopSpeed, // MotorReadOnlyStruct
- Torque, // MotorReadOnlyStruct
- MaxExtension, // PistonReadOnlyStruct
- MinAngle, // ServoReadOnlyStruct
- MaxAngle, // ServoReadOnlyStruct
- Reverse, // MotorReadOnlyStruct or ServoReadOnlyStruct
- StartValue, // SignalGeneratorEntityStruct
- }
-}
diff --git a/GamecraftModdingAPI/Main.cs b/GamecraftModdingAPI/Main.cs
index 5a65baf..56f481f 100644
--- a/GamecraftModdingAPI/Main.cs
+++ b/GamecraftModdingAPI/Main.cs
@@ -63,8 +63,6 @@ namespace GamecraftModdingAPI
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine);
// init block implementors
Logging.MetaDebugLog($"Initializing Blocks");
- Blocks.Signals.Init();
- Blocks.Tweakable.Init();
// init inventory
Inventory.Hotbar.Init();
// init input
diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
index 9d180ea..8576f97 100644
--- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
+++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
@@ -146,35 +146,6 @@ namespace GamecraftModdingAPI.Tests
.Action((float x, float y, float z) => { Block.PlaceNew(Blocks.BlockIDs.AluminiumCube, new Unity.Mathematics.float3(x, y, z)); })
.Build();
- System.Random random = new System.Random(); // for command below
- CommandBuilder.Builder()
- .Name("RandomizeSignalsInputs")
- .Description("Do the thing")
- .Action(() => {
- 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);
- }).Build();
-
CommandBuilder.Builder("getBlock")
.Action(() => uREPL.Log.Output(new Player(Players.PlayerType.Local).GetBlockLookedAt()+"")).Build();
diff --git a/doxygen.conf b/doxygen.conf
index 0535320..bdd0ed0 100644
--- a/doxygen.conf
+++ b/doxygen.conf
@@ -38,7 +38,7 @@ PROJECT_NAME = "GamecraftModdingAPI"
# could be handy for archiving the generated documentation or if some version
# control system is used.
-PROJECT_NUMBER = "v1.0.0"
+PROJECT_NUMBER = "v1.1.0"
# Using the PROJECT_BRIEF tag one can provide an optional one line description
# for a project that appears at the top of each page and should give viewer a