diff --git a/Automation/bump_version.py b/Automation/bump_version.py
new file mode 100755
index 0000000..d3de051
--- /dev/null
+++ b/Automation/bump_version.py
@@ -0,0 +1,67 @@
+#!/usr/bin/python3
+
+import argparse
+import re
+# this assumes a mostly semver-complient version number
+
+if __name__ == "__main__":
+ parser = argparse.ArgumentParser(description="Increment GamecraftModdingAPI version")
+ parser.add_argument('version', metavar="VN", type=str, help="The version number to increment, or the index of the number (zero-indexed).")
+ args = parser.parse_args()
+
+ version_index = -1
+ try:
+ version_index = int(args.version)
+ except Exception:
+ if args.version.lower() == "major":
+ version_index = 0
+ elif args.version.lower() == "minor":
+ version_index = 1
+ elif args.version.lower() == "patch":
+ version_index = 2
+
+ if version_index < 0:
+ print("Could not parse version argument.")
+ exit(version_index)
+
+ print(version_index)
+ old_version = ""
+ new_version = ""
+
+ with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "r") as xmlFile:
+ print("Parsing GamecraftModdingAPI.csproj")
+ fileStr = xmlFile.read()
+ versionMatch = re.search(r"(.+)", fileStr)
+ if versionMatch is None:
+ print("Unable to find version number in GamecraftModdingAPI.csproj")
+ exit(1)
+ old_version = versionMatch.group(1)
+ versionList = old_version.split(".")
+ if len(versionList) <= version_index:
+ print("Invalid version string")
+ exit(1)
+ versionList[version_index] = str(int(versionList[version_index]) + 1)
+ for i in range(version_index + 1, len(versionList)):
+ try:
+ int(versionList[i])
+ versionList[i] = "0"
+ except Exception:
+ tmp = versionList[i].split("-")
+ tmp[0] = "0"
+ versionList[i] = "-".join(tmp)
+ new_version = ".".join(versionList)
+ print(new_version)
+ newFileContents = fileStr.replace(""+old_version+"", ""+new_version+"")
+
+ with open("../GamecraftModdingAPI/GamecraftModdingAPI.csproj", "w") as xmlFile:
+ print("Writing new version to project file")
+ xmlFile.write(newFileContents)
+
+ with open("../doxygen.conf", "r") as doxFile:
+ print("Parsing doxygen.conf")
+ doxStr = doxFile.read()
+ newFileContents = doxStr.replace("= \"v" + old_version + "\"", "= \"v" + new_version + "\"")
+
+ with open("../doxygen.conf", "w") as doxFile:
+ print("Writing new version to doxygen config")
+ doxFile.write(newFileContents)
diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs
index 2f9a901..0194bae 100644
--- a/GamecraftModdingAPI/Block.cs
+++ b/GamecraftModdingAPI/Block.cs
@@ -122,6 +122,7 @@ namespace GamecraftModdingAPI
new Dictionary
{
{typeof(ConsoleBlock), new[] {CommonExclusiveGroups.BUILD_CONSOLE_BLOCK_GROUP}},
+ {typeof(LogicGate), new [] {CommonExclusiveGroups.BUILD_LOGIC_BLOCK_GROUP}},
{typeof(Motor), new[] {CommonExclusiveGroups.BUILD_MOTOR_BLOCK_GROUP}},
{typeof(MusicBlock), new[] {CommonExclusiveGroups.BUILD_MUSIC_BLOCK_GROUP}},
{typeof(Piston), new[] {CommonExclusiveGroups.BUILD_PISTON_BLOCK_GROUP}},
@@ -420,6 +421,8 @@ namespace GamecraftModdingAPI
GameEngineManager.AddGameEngine(BlockEngine);
GameEngineManager.AddGameEngine(BlockEventsEngine);
GameEngineManager.AddGameEngine(ScalingEngine);
+ GameEngineManager.AddGameEngine(SignalEngine);
+ Wire.signalEngine = SignalEngine; // requires same functionality, no need to duplicate the engine
}
///
diff --git a/GamecraftModdingAPI/Blocks/BlockExceptions.cs b/GamecraftModdingAPI/Blocks/BlockExceptions.cs
index 47af014..9949424 100644
--- a/GamecraftModdingAPI/Blocks/BlockExceptions.cs
+++ b/GamecraftModdingAPI/Blocks/BlockExceptions.cs
@@ -40,4 +40,26 @@ namespace GamecraftModdingAPI.Blocks
{
}
}
+
+ public class WiringException : BlockException
+ {
+ public WiringException()
+ {
+ }
+
+ public WiringException(string message) : base(message)
+ {
+ }
+ }
+
+ public class WireInvalidException : WiringException
+ {
+ public WireInvalidException()
+ {
+ }
+
+ public WireInvalidException(string message) : base(message)
+ {
+ }
+ }
}
diff --git a/GamecraftModdingAPI/Blocks/BlockTests.cs b/GamecraftModdingAPI/Blocks/BlockTests.cs
index 6186a1d..9013b3d 100644
--- a/GamecraftModdingAPI/Blocks/BlockTests.cs
+++ b/GamecraftModdingAPI/Blocks/BlockTests.cs
@@ -4,6 +4,7 @@ using Gamecraft.Wires;
using GamecraftModdingAPI;
using GamecraftModdingAPI.Tests;
+using GamecraftModdingAPI.Utility;
namespace GamecraftModdingAPI.Blocks
{
@@ -96,10 +97,28 @@ namespace GamecraftModdingAPI.Blocks
if (!Assert.NotNull(b, "Block.Specialize() returned null, possibly because it failed silently.", "Specialized MusicBlock is not null.")) return;
b.IsPlaying = true; // play sfx
if (!Assert.Equal(b.IsPlaying, true, $"MusicBlock.IsPlaying {b.IsPlaying} does not equal true, possibly because it failed silently.", "MusicBlock.IsPlaying is set properly.")) return;
- if (!Assert.Equal(b.ChannelType, ChannelType.Character, $"MusicBlock.ChannelType {b.ChannelType} does not equal default value, possibly because it failed silently.", "MusicBlock.ChannelType is equal to default.")) return;
+ if (!Assert.Equal(b.ChannelType, ChannelType.None, $"MusicBlock.ChannelType {b.ChannelType} does not equal default value, possibly because it failed silently.", "MusicBlock.ChannelType is equal to default.")) return;
//Assert.Log(b.Track.ToString());
if (!Assert.Equal(b.Track.ToString(), new Guid("3237ff8f-f5f2-4f84-8144-496ca280f8c0").ToString(), $"MusicBlock.Track {b.Track} does not equal default value, possibly because it failed silently.", "MusicBlock.Track is equal to default.")) return;
}
- }
+
+ [APITestCase(TestType.EditMode)]
+ public static void TestLogicGate()
+ {
+ Block newBlock = Block.PlaceNew(BlockIDs.NOTLogicBlock, Unity.Mathematics.float3.zero + 1);
+ LogicGate b = null; // Note: the assignment operation is a lambda, which slightly confuses the compiler
+ Assert.Errorless(() => { b = newBlock.Specialise(); }, "Block.Specialize() raised an exception: ", "Block.Specialize() completed without issue.");
+ if (!Assert.NotNull(b, "Block.Specialize() returned null, possibly because it failed silently.", "Specialized LogicGate is not null.")) return;
+ if (!Assert.Equal(b.InputCount, 1u, $"LogicGate.InputCount {b.InputCount} does not equal default value, possibly because it failed silently.", "LogicGate.InputCount is default.")) return;
+ if (!Assert.Equal(b.OutputCount, 1u, $"LogicGate.OutputCount {b.OutputCount} does not equal default value, possibly because it failed silently.", "LogicGate.OutputCount is default.")) return;
+ if (!Assert.NotNull(b, "Block.Specialize() returned null, possibly because it failed silently.", "Specialized LogicGate is not null.")) return;
+ //if (!Assert.Equal(b.PortName(0, true), "Input", $"LogicGate.PortName(0, input:true) {b.PortName(0, true)} does not equal default value, possibly because it failed silently.", "LogicGate.PortName(0, input:true) is close enough to default.")) return;
+ LogicGate target = null;
+ if (!Assert.Errorless(() => { target = Block.PlaceNew(BlockIDs.ANDLogicBlock, Unity.Mathematics.float3.zero + 2); })) return;
+ Wire newWire = null;
+ if (!Assert.Errorless(() => { newWire = b.Connect(0, target, 0);})) return;
+ if (!Assert.NotNull(newWire, "SignalingBlock.Connect(...) returned null, possible because it failed silently.", "SignalingBlock.Connect(...) returned a non-null value.")) return;
+ }
+}
#endif
}
diff --git a/GamecraftModdingAPI/Blocks/LogicGate.cs b/GamecraftModdingAPI/Blocks/LogicGate.cs
new file mode 100644
index 0000000..124bc10
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/LogicGate.cs
@@ -0,0 +1,16 @@
+using RobocraftX.Common;
+using Svelto.ECS;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ public class LogicGate : SignalingBlock
+ {
+ public LogicGate(EGID id) : base(id)
+ {
+ }
+
+ public LogicGate(uint id) : base(new EGID(id, CommonExclusiveGroups.BUILD_LOGIC_BLOCK_GROUP))
+ {
+ }
+ }
+}
\ No newline at end of file
diff --git a/GamecraftModdingAPI/Blocks/SignalEngine.cs b/GamecraftModdingAPI/Blocks/SignalEngine.cs
index 13a0b3b..e961423 100644
--- a/GamecraftModdingAPI/Blocks/SignalEngine.cs
+++ b/GamecraftModdingAPI/Blocks/SignalEngine.cs
@@ -1,4 +1,5 @@
-using Svelto.ECS;
+using System;
+using Svelto.ECS;
using Svelto.DataStructures;
using Gamecraft.Wires;
@@ -9,7 +10,7 @@ namespace GamecraftModdingAPI.Blocks
///
/// Engine which executes signal actions
///
- public class SignalEngine : IApiEngine
+ public class SignalEngine : IApiEngine, IFactoryEngine
{
public const float POSITIVE_HIGH = 1.0f;
public const float NEGATIVE_HIGH = -1.0f;
@@ -20,6 +21,8 @@ namespace GamecraftModdingAPI.Blocks
public EntitiesDB entitiesDB { set; private get; }
+ public IEntityFactory Factory { get; set; }
+
public bool isRemovable => false;
public bool IsInGame = false;
@@ -34,7 +37,74 @@ namespace GamecraftModdingAPI.Blocks
IsInGame = true;
}
- // implementations for Signal static class
+ // implementations for block wiring
+
+ public WireEntityStruct CreateNewWire(EGID startBlock, byte startPort, EGID endBlock, byte endPort)
+ {
+ EGID wireEGID = new EGID(WiresExclusiveGroups.NewWireEntityId, NamedExclusiveGroup.Group);
+ EntityComponentInitializer wireInitializer = Factory.BuildEntity(wireEGID);
+ wireInitializer.Init(new WireEntityStruct
+ {
+ sourceBlockEGID = startBlock,
+ sourcePortUsage = startPort,
+ destinationBlockEGID = endBlock,
+ destinationPortUsage = endPort,
+ ID = wireEGID
+ });
+ return wireInitializer.Get();
+ }
+
+ public ref WireEntityStruct GetWire(EGID wire)
+ {
+ if (!entitiesDB.Exists(wire))
+ {
+ throw new WiringException($"Wire {wire} does not exist");
+ }
+ return ref entitiesDB.QueryEntity(wire);
+ }
+
+ public ref PortEntityStruct GetPort(EGID port)
+ {
+ if (!entitiesDB.Exists(port))
+ {
+ throw new WiringException($"Port {port} does not exist (yet?)");
+ }
+ return ref entitiesDB.QueryEntity(port);
+ }
+
+ public ref PortEntityStruct GetPortByOffset(BlockPortsStruct bps, byte portNumber, bool input)
+ {
+ ExclusiveGroup group = input
+ ? NamedExclusiveGroup.Group
+ : NamedExclusiveGroup.Group;
+ uint id = (input ? bps.firstInputID : bps.firstOutputID) + portNumber;
+ EGID egid = new EGID(id, group);
+ if (!entitiesDB.Exists(egid))
+ {
+ throw new WiringException("Port does not exist");
+ }
+ return ref entitiesDB.QueryEntity(egid);
+ }
+
+ public ref PortEntityStruct GetPortByOffset(Block block, byte portNumber, bool input)
+ {
+ BlockPortsStruct bps = GetFromDbOrInitData(block, block.Id, out bool exists);
+ if (!exists)
+ {
+ throw new BlockException("Block does not exist");
+ }
+ return ref GetPortByOffset(bps, portNumber, input);
+ }
+
+ public ref T GetComponent(EGID egid) where T : struct, IEntityComponent
+ {
+ return ref entitiesDB.QueryEntity(egid);
+ }
+
+ public bool Exists(EGID egid) where T : struct, IEntityComponent
+ {
+ return entitiesDB.Exists(egid);
+ }
public bool SetSignal(EGID blockID, float signal, out uint signalID, bool input = true)
{
@@ -123,7 +193,7 @@ namespace GamecraftModdingAPI.Blocks
return inputs;
}
- public EGID[] GetSignalOutputs(EGID blockID)
+ public EGID[] GetSignalOutputs(EGID blockID)
{
BlockPortsStruct ports = entitiesDB.QueryEntity(blockID);
EGID[] outputs = new EGID[ports.outputCount];
@@ -134,6 +204,42 @@ namespace GamecraftModdingAPI.Blocks
return outputs;
}
+ public EGID MatchBlockInputToPort(Block block, byte portUsage, out bool exists)
+ {
+ BlockPortsStruct ports = GetFromDbOrInitData(block, block.Id, out exists);
+ return new EGID(ports.firstInputID + portUsage, NamedExclusiveGroup.Group);
+ }
+
+ public EGID MatchBlockInputToPort(EGID block, byte portUsage, out bool exists)
+ {
+ if (!entitiesDB.Exists(block))
+ {
+ exists = false;
+ return default;
+ }
+ exists = true;
+ BlockPortsStruct ports = entitiesDB.QueryEntity(block);
+ return new EGID(ports.firstInputID + portUsage, NamedExclusiveGroup.Group);
+ }
+
+ public EGID MatchBlockOutputToPort(Block block, byte portUsage, out bool exists)
+ {
+ BlockPortsStruct ports = GetFromDbOrInitData(block, block.Id, out exists);
+ return new EGID(ports.firstOutputID + portUsage, NamedExclusiveGroup.Group);
+ }
+
+ public EGID MatchBlockOutputToPort(EGID block, byte portUsage, out bool exists)
+ {
+ if (!entitiesDB.Exists(block))
+ {
+ exists = false;
+ return default;
+ }
+ exists = true;
+ BlockPortsStruct ports = entitiesDB.QueryEntity(block);
+ return new EGID(ports.firstOutputID + portUsage, NamedExclusiveGroup.Group);
+ }
+
public ref WireEntityStruct MatchPortToWire(EGID portID, EGID blockID, out bool exists)
{
ref PortEntityStruct port = ref entitiesDB.QueryEntity(portID);
@@ -152,6 +258,57 @@ namespace GamecraftModdingAPI.Blocks
return ref defRef[0];
}
+ public ref WireEntityStruct MatchBlocksToWire(EGID startBlock, EGID endBlock, out bool exists, byte startPort = byte.MaxValue,
+ byte endPort = byte.MaxValue)
+ {
+ EGID[] startPorts;
+ if (startPort == byte.MaxValue)
+ {
+ // search all output ports on source block
+ startPorts = GetSignalOutputs(startBlock);
+ }
+ else
+ {
+ BlockPortsStruct ports = entitiesDB.QueryEntity(startBlock);
+ startPorts = new EGID[] {new EGID(ports.firstOutputID + startPort, NamedExclusiveGroup.Group) };
+ }
+
+ EGID[] endPorts;
+ if (startPort == byte.MaxValue)
+ {
+ // search all input ports on destination block
+ endPorts = GetSignalInputs(endBlock);
+ }
+ else
+ {
+ BlockPortsStruct ports = entitiesDB.QueryEntity(endBlock);
+ endPorts = new EGID[] {new EGID(ports.firstInputID + endPort, NamedExclusiveGroup.Group) };
+ }
+
+ EntityCollection wires = entitiesDB.QueryEntities(NamedExclusiveGroup.Group);
+ for (int endIndex = 0; endIndex < endPorts.Length; endIndex++)
+ {
+ PortEntityStruct endPES = entitiesDB.QueryEntity(endPorts[endIndex]);
+ for (int startIndex = 0; startIndex < startPorts.Length; startIndex++)
+ {
+ PortEntityStruct startPES = entitiesDB.QueryEntity(startPorts[startIndex]);
+ for (int w = 0; w < wires.count; w++)
+ {
+ if ((wires[w].destinationPortUsage == endPES.usage && wires[w].destinationBlockEGID == endBlock)
+ && (wires[w].sourcePortUsage == startPES.usage && wires[w].sourceBlockEGID == startBlock))
+ {
+ exists = true;
+ return ref wires[w];
+ }
+ }
+ }
+ }
+
+ 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);
@@ -175,6 +332,69 @@ namespace GamecraftModdingAPI.Blocks
return res.ToArray();
}
+ public EGID[] WiredToInput(EGID block, byte port)
+ {
+ WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup.Group,
+ (WireEntityStruct wes) => wes.destinationPortUsage == port && wes.destinationBlockEGID == block);
+ EGID[] result = new EGID[wireEntityStructs.Length];
+ for (uint i = 0; i < wireEntityStructs.Length; i++)
+ {
+ result[i] = wireEntityStructs[i].ID;
+ }
+
+ return result;
+ }
+
+ public EGID[] WiredToOutput(EGID block, byte port)
+ {
+ WireEntityStruct[] wireEntityStructs = Search(NamedExclusiveGroup.Group,
+ (WireEntityStruct wes) => wes.sourcePortUsage == port && wes.sourceBlockEGID == block);
+ EGID[] result = new EGID[wireEntityStructs.Length];
+ for (uint i = 0; i < wireEntityStructs.Length; i++)
+ {
+ result[i] = wireEntityStructs[i].ID;
+ }
+
+ return result;
+ }
+
+ private T[] Search(ExclusiveGroup group, Func isMatch) where T : struct, IEntityComponent
+ {
+ FasterList results = new FasterList();
+ EntityCollection components = entitiesDB.QueryEntities(group);
+ for (uint i = 0; i < components.count; i++)
+ {
+ if (isMatch(components[i]))
+ {
+ results.Add(components[i]);
+ }
+ }
+ return results.ToArray();
+ }
+
+ private ref T GetFromDbOrInitData(Block block, EGID id, out bool exists) where T : struct, IEntityComponent
+ {
+ T[] defRef = new T[1];
+ if (entitiesDB.Exists(id))
+ {
+ exists = true;
+ return ref entitiesDB.QueryEntity(id);
+ }
+ if (block == null || block.InitData.Group == null)
+ {
+ exists = false;
+ return ref defRef[0];
+ }
+ EntityComponentInitializer initializer = new EntityComponentInitializer(block.Id, block.InitData.Group);
+ if (initializer.Has())
+ {
+ exists = true;
+ return ref initializer.Get();
+ }
+ exists = false;
+ return ref defRef[0];
+ }
+
private EntityCollection GetSignalStruct(uint signalID, out uint index, bool input = true)
{
ExclusiveGroup group = input
diff --git a/GamecraftModdingAPI/Blocks/SignalingBlock.cs b/GamecraftModdingAPI/Blocks/SignalingBlock.cs
index 149e450..a137b98 100644
--- a/GamecraftModdingAPI/Blocks/SignalingBlock.cs
+++ b/GamecraftModdingAPI/Blocks/SignalingBlock.cs
@@ -16,18 +16,10 @@ namespace GamecraftModdingAPI.Blocks
{
public SignalingBlock(EGID id) : base(id)
{
- if (!BlockEngine.GetBlockInfoExists(this))
- {
- throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
- }
}
public SignalingBlock(uint id) : base(id)
{
- if (!BlockEngine.GetBlockInfoExists(this))
- {
- throw new BlockTypeException($"Block is not a {this.GetType().Name} block");
- }
}
///
@@ -85,5 +77,91 @@ namespace GamecraftModdingAPI.Blocks
{
get => BlockEngine.GetBlockInfo(this, (BlockPortsStruct st) => st.outputCount);
}
+
+ ///
+ /// Connect an output on this block to an input on another block.
+ ///
+ /// Output port number.
+ /// Input block.
+ /// Input port number.
+ /// The wire connection
+ /// The wire could not be created.
+ public Wire Connect(byte sourcePort, SignalingBlock destination, byte destinationPort)
+ {
+ if (sourcePort >= OutputCount)
+ {
+ throw new WiringException("Source port does not exist");
+ }
+
+ if (destinationPort >= destination.InputCount)
+ {
+ throw new WiringException("Destination port does not exist");
+ }
+ return Wire.Connect(this, sourcePort, destination, destinationPort);
+ }
+
+ ///
+ /// The port's name.
+ /// This is localized to the user's language, so this is not reliable for port identification.
+ ///
+ /// Port number.
+ /// Whether the port is an input (true) or an output (false).
+ /// The localized port name.
+ public string PortName(byte port, bool input)
+ {
+ BlockPortsStruct bps = BlockEngine.GetBlockInfo(this, (BlockPortsStruct a) => a);
+ PortEntityStruct pes = SignalEngine.GetPortByOffset(this, port, input);
+ return pes.portNameLocalised;
+ }
+
+ ///
+ /// The input port's name.
+ ///
+ /// Input port number.
+ /// The port name, localized to the user's language.
+ public string InputPortName(byte port) => PortName(port, true);
+
+ ///
+ /// The output port's name.
+ ///
+ /// Output port number.
+ /// The port name, localized to the user's language.
+ public string OutputPortName(byte port) => PortName(port, false);
+
+ ///
+ /// All wires connected to the input port.
+ /// These wires will always be wired output -> input.
+ ///
+ /// Port number.
+ /// Wires connected to the input port.
+ public Wire[] ConnectedToInput(byte port)
+ {
+ if (port >= InputCount) throw new WiringException($"Port input {port} does not exist");
+ EGID[] wireEgids = SignalEngine.WiredToInput(Id, port);
+ Wire[] wires = new Wire[wireEgids.Length];
+ for (uint i = 0; i < wireEgids.Length; i++)
+ {
+ wires[i] = new Wire(wireEgids[i]);
+ }
+ return wires;
+ }
+
+ ///
+ /// All wires connected to the output port.
+ /// These wires will always be wired output -> input.
+ ///
+ /// Port number.
+ /// Wires connected to the output port.
+ public Wire[] ConnectedToOutput(byte port)
+ {
+ if (port >= OutputCount) throw new WiringException($"Port output {port} does not exist");
+ EGID[] wireEgids = SignalEngine.WiredToOutput(Id, port);
+ Wire[] wires = new Wire[wireEgids.Length];
+ for (uint i = 0; i < wireEgids.Length; i++)
+ {
+ wires[i] = new Wire(wireEgids[i]);
+ }
+ return wires;
+ }
}
}
diff --git a/GamecraftModdingAPI/Blocks/Wire.cs b/GamecraftModdingAPI/Blocks/Wire.cs
new file mode 100644
index 0000000..c29795f
--- /dev/null
+++ b/GamecraftModdingAPI/Blocks/Wire.cs
@@ -0,0 +1,355 @@
+using System;
+
+using Gamecraft.Wires;
+using Svelto.ECS;
+using Svelto.ECS.Experimental;
+
+using GamecraftModdingAPI.Utility;
+
+namespace GamecraftModdingAPI.Blocks
+{
+ public class Wire
+ {
+ internal static SignalEngine signalEngine;
+
+ protected EGID startPortEGID;
+
+ protected EGID endPortEGID;
+
+ protected EGID startBlockEGID;
+
+ protected EGID endBlockEGID;
+
+ protected EGID wireEGID;
+
+ protected bool inputToOutput;
+
+ protected byte startPort;
+
+ protected byte endPort;
+
+ public static Wire Connect(SignalingBlock start, byte startPort, SignalingBlock end, byte endPort)
+ {
+ WireEntityStruct wire = signalEngine.CreateNewWire(start.Id, startPort, end.Id, endPort);
+ return new Wire(wire);
+ }
+
+ ///
+ /// An existing wire connection ending at the specified input.
+ /// If multiple exist, this will return the first one found.
+ ///
+ /// Destination block.
+ /// Port number.
+ /// The wire, where the end of the wire is the block port specified, or null if does not exist.
+ public static Wire ConnectedToInputPort(SignalingBlock end, byte endPort)
+ {
+ EGID port = signalEngine.MatchBlockInputToPort(end, endPort, out bool exists);
+ if (!exists) return null;
+ WireEntityStruct wire = signalEngine.MatchPortToWire(port, end.Id, out exists);
+ if (exists)
+ {
+ return new Wire(new Block(wire.sourceBlockEGID), end, wire.sourcePortUsage, endPort);
+ }
+ return null;
+ }
+
+ ///
+ /// An existing wire connection starting at the specified output.
+ /// If multiple exist, this will return the first one found.
+ ///
+ /// Source block entity ID.
+ /// Port number.
+ /// The wire, where the start of the wire is the block port specified, or null if does not exist.
+ public static Wire ConnectedToOutputPort(SignalingBlock start, byte startPort)
+ {
+ EGID port = signalEngine.MatchBlockOutputToPort(start, startPort, out bool exists);
+ if (!exists) return null;
+ WireEntityStruct wire = signalEngine.MatchPortToWire(port, start.Id, out exists);
+ if (exists)
+ {
+ return new Wire(start, new Block(wire.destinationBlockEGID), startPort, wire.destinationPortUsage);
+ }
+ return null;
+ }
+
+ ///
+ /// Construct a wire object from an existing connection.
+ ///
+ /// Starting block ID.
+ /// Ending block ID.
+ /// Starting port number, or guess if omitted.
+ /// Ending port number, or guess if omitted.
+ /// Guessing failed or wire does not exist.
+ public Wire(Block start, Block end, byte startPort = Byte.MaxValue, byte endPort = Byte.MaxValue)
+ {
+ startBlockEGID = start.Id;
+ endBlockEGID = end.Id;
+ // find block ports
+ WireEntityStruct wire = signalEngine.MatchBlocksToWire(start.Id, end.Id, out bool exists, startPort, endPort);
+ if (exists)
+ {
+ wireEGID = wire.ID;
+ endPortEGID = signalEngine.MatchBlockInputToPort(end, wire.destinationPortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockOutputToPort(start, wire.sourcePortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ inputToOutput = false;
+ endPort = wire.destinationPortUsage;
+ startPort = wire.sourcePortUsage;
+ }
+ else
+ {
+ // flip I/O around and try again
+ wire = signalEngine.MatchBlocksToWire(end.Id, start.Id, out exists, endPort, startPort);
+ if (exists)
+ {
+ wireEGID = wire.ID;
+ endPortEGID = signalEngine.MatchBlockOutputToPort(end, wire.sourcePortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockInputToPort(start, wire.destinationPortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ inputToOutput = true; // end is actually the source
+ // NB: start and end are handled exactly as they're received as params.
+ // This makes wire traversal easier, but makes logic in this class a bit more complex
+ endPort = wire.sourcePortUsage;
+ startPort = wire.destinationPortUsage;
+ }
+ else
+ {
+ throw new WireInvalidException("Wire not found");
+ }
+ }
+ }
+
+ ///
+ /// Construct a wire object from an existing wire connection.
+ ///
+ /// Starting block ID.
+ /// Ending block ID.
+ /// Starting port number.
+ /// Ending port number.
+ /// The wire ID.
+ /// Whether the wire direction goes input -> output (true) or output -> input (false, preferred).
+ public Wire(Block start, Block end, byte startPort, byte endPort, EGID wire, bool inputToOutput)
+ {
+ this.startBlockEGID = start.Id;
+ this.endBlockEGID = end.Id;
+ this.inputToOutput = inputToOutput;
+ this.wireEGID = wire;
+ if (inputToOutput)
+ {
+ endPortEGID = signalEngine.MatchBlockOutputToPort(start, startPort, out bool exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockInputToPort(end, endPort, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ }
+ else
+ {
+ endPortEGID = signalEngine.MatchBlockInputToPort(end, endPort, out bool exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockOutputToPort(start, startPort, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ }
+ this.startPort = startPort;
+ this.endPort = endPort;
+ }
+
+ ///
+ /// Construct a wire object from an existing wire connection.
+ ///
+ /// The wire ID.
+ public Wire(EGID wireEgid)
+ {
+ this.wireEGID = wireEgid;
+ WireEntityStruct wire = signalEngine.GetWire(wireEGID);
+ this.startBlockEGID = wire.sourceBlockEGID;
+ this.endBlockEGID = wire.destinationBlockEGID;
+ this.inputToOutput = false;
+ endPortEGID = signalEngine.MatchBlockInputToPort(wire.destinationBlockEGID, wire.destinationPortUsage, out bool exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockOutputToPort(wire.sourceBlockEGID, wire.sourcePortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ this.endPort = wire.destinationPortUsage;
+ this.startPort = wire.sourcePortUsage;
+ }
+
+ internal Wire(WireEntityStruct wire)
+ {
+ this.wireEGID = wire.ID;
+ this.startBlockEGID = wire.sourceBlockEGID;
+ this.endBlockEGID = wire.destinationBlockEGID;
+ inputToOutput = false;
+ endPortEGID = signalEngine.MatchBlockInputToPort(wire.destinationBlockEGID, wire.destinationPortUsage, out bool exists);
+ if (!exists) throw new WireInvalidException("Wire end port not found");
+ startPortEGID = signalEngine.MatchBlockOutputToPort(wire.sourceBlockEGID, wire.sourcePortUsage, out exists);
+ if (!exists) throw new WireInvalidException("Wire start port not found");
+ this.endPort = wire.destinationPortUsage;
+ this.startPort = wire.sourcePortUsage;
+ }
+
+ ///
+ /// The wire's in-game id.
+ ///
+ public EGID Id
+ {
+ get => wireEGID;
+ }
+
+ ///
+ /// The wire's signal value, as a float.
+ ///
+ public float Float
+ {
+ get
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return 0f;
+ return cds.valueAsFloat;
+ }
+
+ set
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return;
+ cds.valueAsFloat = value;
+ }
+ }
+
+ ///
+ /// The wire's string signal.
+ ///
+ public string String
+ {
+ get
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return "";
+ return cds.valueAsEcsString;
+ }
+
+ set
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return;
+ cds.valueAsEcsString.Set(value);
+ }
+ }
+
+ ///
+ /// The wire's raw string signal.
+ ///
+ public ECSString ECSString
+ {
+ get
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return default;
+ return cds.valueAsEcsString;
+ }
+
+ set
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return;
+ cds.valueAsEcsString = value;
+ }
+ }
+
+ ///
+ /// The wire's signal id.
+ /// I'm 50% sure this is useless.
+ ///
+ public uint SignalId
+ {
+ get
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return uint.MaxValue;
+ return cds.valueAsID;
+ }
+
+ set
+ {
+ ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists);
+ if (!exists) return;
+ cds.valueAsID = value;
+ }
+ }
+
+ ///
+ /// The block at the beginning of the wire.
+ ///
+ public SignalingBlock Start
+ {
+ get => new SignalingBlock(startBlockEGID);
+ }
+
+ ///
+ /// The port number that the beginning of the wire connects to.
+ ///
+ public byte StartPort
+ {
+ get => startPort;
+ }
+
+ ///
+ /// The block at the end of the wire.
+ ///
+ public SignalingBlock End
+ {
+ get => new SignalingBlock(endBlockEGID);
+ }
+
+ ///
+ /// The port number that the end of the wire connects to.
+ ///
+ public byte EndPort
+ {
+ get => endPort;
+ }
+
+ ///
+ /// Create a copy of the wire object where the direction of the wire is guaranteed to be from a block output to a block input.
+ /// This is simply a different memory configuration and does not affect the in-game wire (which is always output -> input).
+ ///
+ /// A copy of the wire object.
+ public Wire OutputToInputCopy()
+ {
+ return new Wire(wireEGID);
+ }
+
+ ///
+ /// Convert the wire object to the direction the signal flows.
+ /// Signals on wires always flow from a block output port to a block input port.
+ /// This is simply a different memory configuration and does not affect the in-game wire (which is always output -> input).
+ ///
+ public void OutputToInputInPlace()
+ {
+ if (inputToOutput)
+ {
+ inputToOutput = false;
+ // swap inputs and outputs
+ EGID temp = endBlockEGID;
+ endBlockEGID = startBlockEGID;
+ startBlockEGID = temp;
+ temp = endPortEGID;
+ endPortEGID = startPortEGID;
+ startPortEGID = temp;
+ byte tempPortNumber = endPort;
+ endPort = startPort;
+ startPort = tempPortNumber;
+ }
+ }
+
+ public override string ToString()
+ {
+ if (signalEngine.Exists(wireEGID))
+ {
+ return $"{nameof(Id)}: {Id}, Start{nameof(Start.Id)}: {Start.Id}, End{nameof(End.Id)}: {End.Id}, ({Start.Type}::{StartPort} aka {Start.PortName(StartPort, inputToOutput)}) -> ({End.Type}::{EndPort} aka {End.PortName(EndPort, !inputToOutput)})";
+ }
+ return $"{nameof(Id)}: {Id}, Start{nameof(Start.Id)}: {Start.Id}, End{nameof(End.Id)}: {End.Id}, ({Start.Type}::{StartPort} -> {End.Type}::{EndPort})";
+ }
+
+ internal static void Init() { }
+ }
+}
\ No newline at end of file
diff --git a/GamecraftModdingAPI/Events/DeterministicStepComposeEngineGroupsPatch.cs b/GamecraftModdingAPI/Events/DeterministicStepComposeEngineGroupsPatch.cs
index d6e58dc..9f16955 100644
--- a/GamecraftModdingAPI/Events/DeterministicStepComposeEngineGroupsPatch.cs
+++ b/GamecraftModdingAPI/Events/DeterministicStepComposeEngineGroupsPatch.cs
@@ -18,7 +18,8 @@ namespace GamecraftModdingAPI.Events
/// Patch of RobocraftX.StateSync.DeterministicStepCompositionRoot.ComposeEnginesGroups(...)
///
//[HarmonyPatch(typeof(DeterministicStepCompositionRoot), "DeterministicCompose")]
- [HarmonyPatch]
+ [Obsolete]
+ [HarmonyPatch]
class GameHostTransitionDeterministicGroupEnginePatch
{
diff --git a/GamecraftModdingAPI/Events/EmitterBuilder.cs b/GamecraftModdingAPI/Events/EmitterBuilder.cs
index 48a6cba..c6a6879 100644
--- a/GamecraftModdingAPI/Events/EmitterBuilder.cs
+++ b/GamecraftModdingAPI/Events/EmitterBuilder.cs
@@ -4,6 +4,7 @@ using Svelto.ECS;
namespace GamecraftModdingAPI.Events
{
+ [Obsolete]
public class EmitterBuilder
{
private string name;
diff --git a/GamecraftModdingAPI/Events/EventEngineFactory.cs b/GamecraftModdingAPI/Events/EventEngineFactory.cs
index f79dfca..7981303 100644
--- a/GamecraftModdingAPI/Events/EventEngineFactory.cs
+++ b/GamecraftModdingAPI/Events/EventEngineFactory.cs
@@ -11,6 +11,7 @@ namespace GamecraftModdingAPI.Events
///
/// Convenient factories for mod event engines
///
+ [Obsolete]
public static class EventEngineFactory
{
///
diff --git a/GamecraftModdingAPI/Events/EventManager.cs b/GamecraftModdingAPI/Events/EventManager.cs
index efbf377..f021e9f 100644
--- a/GamecraftModdingAPI/Events/EventManager.cs
+++ b/GamecraftModdingAPI/Events/EventManager.cs
@@ -14,6 +14,7 @@ namespace GamecraftModdingAPI.Events
/// Keeps track of event handlers and emitters.
/// This is used to add, remove and get API event handlers and emitters.
///
+ [Obsolete("This will be removed in an upcoming update. Use the new C# event architecture from GamecraftModdingAPI.App")]
public static class EventManager
{
private static Dictionary _eventEmitters = new Dictionary();
diff --git a/GamecraftModdingAPI/Events/GameActivatedComposePatch.cs b/GamecraftModdingAPI/Events/GameActivatedComposePatch.cs
index 4481f4b..4142fb3 100644
--- a/GamecraftModdingAPI/Events/GameActivatedComposePatch.cs
+++ b/GamecraftModdingAPI/Events/GameActivatedComposePatch.cs
@@ -17,6 +17,7 @@ namespace GamecraftModdingAPI.Events
///
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame()
///
+ [Obsolete]
[HarmonyPatch]
class GameActivatedComposePatch
{
diff --git a/GamecraftModdingAPI/Events/GameReloadedPatch.cs b/GamecraftModdingAPI/Events/GameReloadedPatch.cs
index 40f46e1..7228084 100644
--- a/GamecraftModdingAPI/Events/GameReloadedPatch.cs
+++ b/GamecraftModdingAPI/Events/GameReloadedPatch.cs
@@ -14,6 +14,7 @@ namespace GamecraftModdingAPI.Events
///
/// Patch of RobocraftX.FullGameCompositionRoot.ReloadGame()
///
+ [Obsolete]
[HarmonyPatch(typeof(FullGameCompositionRoot), "ReloadGame")]
class GameReloadedPatch
{
diff --git a/GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs b/GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs
index a12433a..725f544 100644
--- a/GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs
+++ b/GamecraftModdingAPI/Events/GameStateBuildEmitterEngine.cs
@@ -12,6 +12,7 @@ namespace GamecraftModdingAPI.Events
///
/// Event emitter engine for switching to to build mode.
///
+ [Obsolete]
public class GameStateBuildEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeStoppedModeEntered
{
public string Name { get; } = "GamecraftModdingAPIGameStateBuildEventEmitter" ;
diff --git a/GamecraftModdingAPI/Events/GameStateSimulationEmitterEngine.cs b/GamecraftModdingAPI/Events/GameStateSimulationEmitterEngine.cs
index 5689db9..6e6e2ce 100644
--- a/GamecraftModdingAPI/Events/GameStateSimulationEmitterEngine.cs
+++ b/GamecraftModdingAPI/Events/GameStateSimulationEmitterEngine.cs
@@ -12,6 +12,7 @@ namespace GamecraftModdingAPI.Events
///
/// Event emitter engine for switching to simulation mode.
///
+ [Obsolete]
public class GameStateSimulationEmitterEngine : IEventEmitterEngine, IUnorderedInitializeOnTimeRunningModeEntered
{
public string Name { get; } = "GamecraftModdingAPIGameStateSimulationEventEmitter" ;
diff --git a/GamecraftModdingAPI/Events/GameSwitchedToPatch.cs b/GamecraftModdingAPI/Events/GameSwitchedToPatch.cs
index 30bb0d5..dbd63c0 100644
--- a/GamecraftModdingAPI/Events/GameSwitchedToPatch.cs
+++ b/GamecraftModdingAPI/Events/GameSwitchedToPatch.cs
@@ -18,6 +18,7 @@ namespace GamecraftModdingAPI.Events
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateGame()
/// (scheduled for execution during RobocraftX.FullGameCompositionRoot.SwitchToGame())
///
+ [Obsolete]
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToGame")]
class GameSwitchedToPatch
{
diff --git a/GamecraftModdingAPI/Events/HandlerBuilder.cs b/GamecraftModdingAPI/Events/HandlerBuilder.cs
index d5d9879..10f3290 100644
--- a/GamecraftModdingAPI/Events/HandlerBuilder.cs
+++ b/GamecraftModdingAPI/Events/HandlerBuilder.cs
@@ -4,6 +4,7 @@ using Svelto.ECS;
namespace GamecraftModdingAPI.Events
{
+ [Obsolete]
public class HandlerBuilder
{
private string name;
diff --git a/GamecraftModdingAPI/Events/IEventEmitterEngine.cs b/GamecraftModdingAPI/Events/IEventEmitterEngine.cs
index f6fefc5..8917cef 100644
--- a/GamecraftModdingAPI/Events/IEventEmitterEngine.cs
+++ b/GamecraftModdingAPI/Events/IEventEmitterEngine.cs
@@ -13,6 +13,7 @@ namespace GamecraftModdingAPI.Events
///
/// Engine interface to create a ModEventEntityStruct in entitiesDB when a specific event occurs.
///
+ [Obsolete]
public interface IEventEmitterEngine : IFactoryEngine
{
///
diff --git a/GamecraftModdingAPI/Events/IEventHandlerEngine.cs b/GamecraftModdingAPI/Events/IEventHandlerEngine.cs
index 34a14af..228adb8 100644
--- a/GamecraftModdingAPI/Events/IEventHandlerEngine.cs
+++ b/GamecraftModdingAPI/Events/IEventHandlerEngine.cs
@@ -14,6 +14,7 @@ namespace GamecraftModdingAPI.Events
///
/// Engine interface to handle ModEventEntityStruct events emitted by IEventEmitterEngines.
///
+ [Obsolete]
public interface IEventHandlerEngine : IReactionaryEngine
{
}
diff --git a/GamecraftModdingAPI/Events/MenuActivatedPatch.cs b/GamecraftModdingAPI/Events/MenuActivatedPatch.cs
index 4237faa..382bac4 100644
--- a/GamecraftModdingAPI/Events/MenuActivatedPatch.cs
+++ b/GamecraftModdingAPI/Events/MenuActivatedPatch.cs
@@ -15,6 +15,7 @@ namespace GamecraftModdingAPI.Events
///
/// Patch of RobocraftX.FullGameCompositionRoot.ActivateMenu()
///
+ [Obsolete]
[HarmonyPatch(typeof(FullGameCompositionRoot), "ActivateMenu")]
class MenuActivatedPatch
{
diff --git a/GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs b/GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs
index 52a00b2..30b84da 100644
--- a/GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs
+++ b/GamecraftModdingAPI/Events/MenuSwitchedToPatch.cs
@@ -15,6 +15,7 @@ namespace GamecraftModdingAPI.Events
///
/// Patch of RobocraftX.FullGameCompositionRoot.SwitchToMenu()
///
+ [Obsolete]
[HarmonyPatch(typeof(FullGameCompositionRoot), "SwitchToMenu")]
class MenuSwitchedToPatch
{
diff --git a/GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs b/GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs
index 0e51823..0ea8170 100644
--- a/GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs
+++ b/GamecraftModdingAPI/Events/SimpleEventEmitterEngine.cs
@@ -12,6 +12,7 @@ namespace GamecraftModdingAPI.Events
///
/// A simple implementation of IEventEmitterEngine sufficient for most uses
///
+ [Obsolete]
public class SimpleEventEmitterEngine : IEventEmitterEngine
{
public string Name { get; set; }
diff --git a/GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs b/GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs
index 18314d9..ebce21d 100644
--- a/GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs
+++ b/GamecraftModdingAPI/Events/SimpleEventHandlerEngine.cs
@@ -13,6 +13,7 @@ namespace GamecraftModdingAPI.Events
///
/// A simple implementation of IEventHandlerEngine sufficient for most uses
///
+ [Obsolete]
public class SimpleEventHandlerEngine : IEventHandlerEngine
{
public int type { get; set; }
diff --git a/GamecraftModdingAPI/GamecraftModdingAPI.csproj b/GamecraftModdingAPI/GamecraftModdingAPI.csproj
index 46dffee..7337ebe 100644
--- a/GamecraftModdingAPI/GamecraftModdingAPI.csproj
+++ b/GamecraftModdingAPI/GamecraftModdingAPI.csproj
@@ -2,7 +2,7 @@
net472
true
- 1.4.0-preview
+ 1.5.0-preview
Exmods
GNU General Public Licence 3+
https://git.exmods.org/modtainers/GamecraftModdingAPI
diff --git a/GamecraftModdingAPI/Main.cs b/GamecraftModdingAPI/Main.cs
index aa80e2a..4a8cf24 100644
--- a/GamecraftModdingAPI/Main.cs
+++ b/GamecraftModdingAPI/Main.cs
@@ -4,7 +4,7 @@ using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Reflection;
-
+using GamecraftModdingAPI.Blocks;
using HarmonyLib;
using GamecraftModdingAPI.Utility;
@@ -49,6 +49,7 @@ namespace GamecraftModdingAPI
harmony.PatchAll(currentAssembly);
// init utility
Logging.MetaDebugLog($"Initializing Utility");
+#pragma warning disable 0612,0618
Utility.GameState.Init();
Utility.VersionTracking.Init();
// create default event emitters
@@ -61,6 +62,7 @@ namespace GamecraftModdingAPI
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.GameSwitchedTo, "GamecraftModdingAPIGameSwitchedToEventEmitter", false));
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.buildEngine);
EventManager.AddEventEmitter(GameHostTransitionDeterministicGroupEnginePatch.simEngine);
+#pragma warning restore 0612,0618
// init block implementors
Logging.MetaDebugLog($"Initializing Blocks");
// init inventory
@@ -70,6 +72,7 @@ namespace GamecraftModdingAPI
// init object-oriented classes
Player.Init();
Block.Init();
+ Wire.Init();
GameClient.Init();
AsyncUtils.Init();
GamecraftModdingAPI.App.Client.Init();
diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
index d8b50fa..e7bed82 100644
--- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
+++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
@@ -68,6 +68,7 @@ namespace GamecraftModdingAPI.Tests
//Utility.VersionTracking.Enable();//(very) unstable
// debug/test handlers
+#pragma warning disable 0612
HandlerBuilder.Builder()
.Name("appinit API debug")
.Handle(EventType.ApplicationInitialized)
@@ -115,7 +116,7 @@ namespace GamecraftModdingAPI.Tests
.Handle(EventType.Menu)
.OnActivation(() => { throw new Exception("Event Handler always throws an exception!"); })
.Build();
-
+#pragma warning restore 0612
/*HandlerBuilder.Builder("enter game from menu test")
.Handle(EventType.Menu)
.OnActivation(() =>
@@ -254,6 +255,19 @@ namespace GamecraftModdingAPI.Tests
})
.Build();
+ CommandBuilder.Builder()
+ .Name("WireTest")
+ .Description("Place two blocks and then wire them together")
+ .Action(() =>
+ {
+ LogicGate notBlock = Block.PlaceNew(BlockIDs.NOTLogicBlock, new float3(1, 2, 0));
+ LogicGate andBlock = Block.PlaceNew(BlockIDs.ANDLogicBlock, new float3(2, 2, 0));
+ // connect NOT Gate output to AND Gate input #2 (ports are zero-indexed, so 1 is 2nd position and 0 is 1st position)
+ Wire conn = notBlock.Connect(0, andBlock, 1);
+ Logging.CommandLog(conn.ToString());
+ })
+ .Build();
+
GameClient.SetDebugInfo("InstalledMods", InstalledMods);
Block.Placed += (sender, args) =>
Logging.MetaDebugLog("Placed block " + args.Type + " with ID " + args.ID);
diff --git a/GamecraftModdingAPI/Tests/TestRoot.cs b/GamecraftModdingAPI/Tests/TestRoot.cs
index f39169e..6acb51c 100644
--- a/GamecraftModdingAPI/Tests/TestRoot.cs
+++ b/GamecraftModdingAPI/Tests/TestRoot.cs
@@ -209,7 +209,7 @@ namespace GamecraftModdingAPI.Tests
{
Assert.Fail($"Build test '{m}' raised an exception: {e.ToString()}");
}
- yield return Yield.It;
+ yield return Yield.It;
}
}
}
diff --git a/GamecraftModdingAPI/Utility/VersionTracking.cs b/GamecraftModdingAPI/Utility/VersionTracking.cs
index 780ac38..32b86dc 100644
--- a/GamecraftModdingAPI/Utility/VersionTracking.cs
+++ b/GamecraftModdingAPI/Utility/VersionTracking.cs
@@ -14,6 +14,7 @@ namespace GamecraftModdingAPI.Utility
/// Tracks the API version the current game was built for.
/// For compatibility reasons, this must be enabled before it will work.
///
+ [Obsolete]
public static class VersionTracking
{
private static readonly VersionTrackingEngine versionEngine = new VersionTrackingEngine();
@@ -58,6 +59,7 @@ namespace GamecraftModdingAPI.Utility
}
+ [Obsolete]
internal class VersionTrackingEngine : IEventEmitterEngine
{
public string Name { get; } = "GamecraftModdingAPIVersionTrackingGameEngine";
@@ -94,11 +96,13 @@ namespace GamecraftModdingAPI.Utility
public void Emit() { }
}
+ [Obsolete]
public struct ModVersionStruct : IEntityComponent
{
public uint version;
}
+ [Obsolete]
public class ModVersionDescriptor: SerializableEntityDescriptor
{
[HashName("GamecraftModdingAPIVersionV0")]
diff --git a/doxygen.conf b/doxygen.conf
index d587ecd..bf447b4 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.3.0"
+PROJECT_NUMBER = "v1.5.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