|
|
@@ -43,14 +43,12 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
/// <returns>The wire, where the end of the wire is the block port specified, or null if does not exist.</returns> |
|
|
|
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(Block.New(wire.sourceBlockEGID), end, wire.sourcePortUsage, endPort); |
|
|
|
} |
|
|
|
return null; |
|
|
|
var port = signalEngine.MatchBlockIOToPort(end, endPort, false); |
|
|
|
if (!port) return null; |
|
|
|
WireEntityStruct wire = signalEngine.MatchPortToWire(port, end.Id, out var exists); |
|
|
|
return exists |
|
|
|
? new Wire(wire.sourceBlockEGID, end.Id, wire.sourcePortUsage, endPort, wire.ID, false) |
|
|
|
: null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
@@ -62,18 +60,16 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
/// <returns>The wire, where the start of the wire is the block port specified, or null if does not exist.</returns> |
|
|
|
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, Block.New(wire.destinationBlockEGID), startPort, wire.destinationPortUsage); |
|
|
|
} |
|
|
|
return null; |
|
|
|
var port = signalEngine.MatchBlockIOToPort(start, startPort, true); |
|
|
|
if (!port) return null; |
|
|
|
WireEntityStruct wire = signalEngine.MatchPortToWire(port, start.Id, out var exists); |
|
|
|
return exists |
|
|
|
? new Wire(start.Id, wire.destinationBlockEGID, startPort, wire.destinationPortUsage, wire.ID, false) |
|
|
|
: null; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// Construct a wire object from an existing connection. |
|
|
|
/// Construct a wire object froam n existing connection. |
|
|
|
/// </summary> |
|
|
|
/// <param name="start">Starting block ID.</param> |
|
|
|
/// <param name="end">Ending block ID.</param> |
|
|
@@ -84,40 +80,25 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
startBlockEGID = start.Id; |
|
|
|
endBlockEGID = end.Id; |
|
|
|
bool flipped = false; |
|
|
|
// find block ports |
|
|
|
WireEntityStruct wire = signalEngine.MatchBlocksToWire(start.Id, end.Id, out bool exists, startPort, endPort); |
|
|
|
if (exists) |
|
|
|
EGID wire = signalEngine.MatchBlocksToWire(start.Id, end.Id, startPort, endPort); |
|
|
|
if (wire == EGID.Empty) |
|
|
|
{ |
|
|
|
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; |
|
|
|
// flip I/O around and try again |
|
|
|
wire = signalEngine.MatchBlocksToWire(end.Id, start.Id, endPort, startPort); |
|
|
|
flipped = true; |
|
|
|
// 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 |
|
|
|
} |
|
|
|
|
|
|
|
if (wire != EGID.Empty) |
|
|
|
{ |
|
|
|
Construct(start.Id, end.Id, startPort, endPort, wire, flipped); |
|
|
|
} |
|
|
|
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"); |
|
|
|
} |
|
|
|
throw new WireInvalidException("Wire not found"); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -131,25 +112,25 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
/// <param name="wire">The wire ID.</param> |
|
|
|
/// <param name="inputToOutput">Whether the wire direction goes input -> output (true) or output -> input (false, preferred).</param> |
|
|
|
public Wire(Block start, Block end, byte startPort, byte endPort, EGID wire, bool inputToOutput) |
|
|
|
: this(start.Id, end.Id, startPort, endPort, wire, inputToOutput) |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
private Wire(EGID startBlock, EGID endBlock, byte startPort, byte endPort, EGID wire, bool inputToOutput) |
|
|
|
{ |
|
|
|
this.startBlockEGID = start.Id; |
|
|
|
this.endBlockEGID = end.Id; |
|
|
|
Construct(startBlock, endBlock, startPort, endPort, wire, inputToOutput); |
|
|
|
} |
|
|
|
|
|
|
|
private void Construct(EGID startBlock, EGID endBlock, byte startPort, byte endPort, EGID wire, bool inputToOutput) |
|
|
|
{ |
|
|
|
this.startBlockEGID = startBlock; |
|
|
|
this.endBlockEGID = endBlock; |
|
|
|
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"); |
|
|
|
} |
|
|
|
endPortEGID = signalEngine.MatchBlockIOToPort(startBlock, startPort, inputToOutput).Nullable()?.ID ?? EGID.Empty; |
|
|
|
if (endPortEGID == EGID.Empty) throw new WireInvalidException("Wire end port not found"); |
|
|
|
startPortEGID = signalEngine.MatchBlockIOToPort(endBlock, endPort, !inputToOutput).Nullable()?.ID ?? EGID.Empty; |
|
|
|
if (startPortEGID == EGID.Empty) throw new WireInvalidException("Wire start port not found"); |
|
|
|
this.startPort = startPort; |
|
|
|
this.endPort = endPort; |
|
|
|
} |
|
|
@@ -160,31 +141,14 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
/// <param name="wireEgid">The wire ID.</param> |
|
|
|
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; |
|
|
|
Construct(wire.sourceBlockEGID, wire.destinationBlockEGID, wire.sourcePortUsage, wire.destinationPortUsage, |
|
|
|
wireEgid, false); |
|
|
|
} |
|
|
|
|
|
|
|
internal Wire(WireEntityStruct wire, SignalingBlock src, SignalingBlock dest) |
|
|
|
private Wire(WireEntityStruct wire, SignalingBlock src, SignalingBlock dest) |
|
|
|
: this(src, dest, wire.sourcePortUsage, wire.destinationPortUsage, wire.ID, false) |
|
|
|
{ |
|
|
|
this.wireEGID = wire.ID; |
|
|
|
this.startBlockEGID = wire.sourceBlockEGID; |
|
|
|
this.endBlockEGID = wire.destinationBlockEGID; |
|
|
|
inputToOutput = false; |
|
|
|
endPortEGID = signalEngine.MatchBlockInputToPort(dest, wire.destinationPortUsage, out bool exists); |
|
|
|
if (!exists) throw new WireInvalidException("Wire end port not found"); |
|
|
|
startPortEGID = signalEngine.MatchBlockOutputToPort(src, wire.sourcePortUsage, out exists); |
|
|
|
if (!exists) throw new WireInvalidException("Wire start port not found"); |
|
|
|
this.endPort = wire.destinationPortUsage; |
|
|
|
this.startPort = wire.sourcePortUsage; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
@@ -202,16 +166,12 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return 0f; |
|
|
|
return cds.valueAsFloat; |
|
|
|
return signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsFloat; |
|
|
|
} |
|
|
|
|
|
|
|
set |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return; |
|
|
|
cds.valueAsFloat = value; |
|
|
|
signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsFloat = value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -222,16 +182,12 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return ""; |
|
|
|
return cds.valueAsEcsString; |
|
|
|
return signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsEcsString; |
|
|
|
} |
|
|
|
|
|
|
|
set |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return; |
|
|
|
cds.valueAsEcsString.Set(value); |
|
|
|
signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsEcsString.Set(value); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -242,16 +198,12 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return default; |
|
|
|
return cds.valueAsEcsString; |
|
|
|
return signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsEcsString; |
|
|
|
} |
|
|
|
|
|
|
|
set |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return; |
|
|
|
cds.valueAsEcsString = value; |
|
|
|
signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsEcsString = value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -263,16 +215,12 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
get |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return uint.MaxValue; |
|
|
|
return cds.valueAsID; |
|
|
|
return signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsID; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
set |
|
|
|
{ |
|
|
|
ref ChannelDataStruct cds = ref signalEngine.GetChannelDataStruct(startPortEGID, out bool exists); |
|
|
|
if (!exists) return; |
|
|
|
cds.valueAsID = value; |
|
|
|
signalEngine.GetChannelDataStruct(startPortEGID).Get().valueAsID = value; |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -281,7 +229,7 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
/// </summary> |
|
|
|
public SignalingBlock Start |
|
|
|
{ |
|
|
|
get => new SignalingBlock(startBlockEGID); |
|
|
|
get => (SignalingBlock)Block.New(startBlockEGID); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
@@ -291,13 +239,21 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
get => startPort; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// The display name of the start port. |
|
|
|
/// </summary> |
|
|
|
public string StartPortName |
|
|
|
{ |
|
|
|
get => signalEngine.GetPort(startPortEGID).portNameLocalised; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// The block at the end of the wire. |
|
|
|
/// </summary> |
|
|
|
public SignalingBlock End |
|
|
|
{ |
|
|
|
get => new SignalingBlock(endBlockEGID); |
|
|
|
get => (SignalingBlock)Block.New(endBlockEGID); |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
@@ -308,6 +264,14 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
get => endPort; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// The display name of the end port. |
|
|
|
/// </summary> |
|
|
|
public string EndPortName |
|
|
|
{ |
|
|
|
get => signalEngine.GetPort(endPortEGID).portNameLocalised; |
|
|
|
} |
|
|
|
|
|
|
|
/// <summary> |
|
|
|
/// 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). |
|
|
@@ -329,15 +293,11 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
inputToOutput = false; |
|
|
|
// swap inputs and outputs |
|
|
|
EGID temp = endBlockEGID; |
|
|
|
endBlockEGID = startBlockEGID; |
|
|
|
startBlockEGID = temp; |
|
|
|
temp = endPortEGID; |
|
|
|
(endBlockEGID, startBlockEGID) = (startBlockEGID, endBlockEGID); |
|
|
|
var tempPort = endPortEGID; |
|
|
|
endPortEGID = startPortEGID; |
|
|
|
startPortEGID = temp; |
|
|
|
byte tempPortNumber = endPort; |
|
|
|
endPort = startPort; |
|
|
|
startPort = tempPortNumber; |
|
|
|
startPortEGID = tempPort; |
|
|
|
(endPort, startPort) = (startPort, endPort); |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
@@ -345,7 +305,7 @@ namespace TechbloxModdingAPI.Blocks |
|
|
|
{ |
|
|
|
if (signalEngine.Exists<WireEntityStruct>(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} aka {(StartPort != byte.MaxValue ? Start.PortName(StartPort, inputToOutput) : "")}) -> ({End.Type}::{EndPort} aka {(EndPort != byte.MaxValue ? 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})"; |
|
|
|
} |
|
|
|