173 lines
6.6 KiB
C#
173 lines
6.6 KiB
C#
|
using System;
|
|||
|
using System.Collections.Generic;
|
|||
|
using System.Linq;
|
|||
|
using System.Text;
|
|||
|
using System.Threading.Tasks;
|
|||
|
|
|||
|
using RobocraftX;
|
|||
|
using RobocraftX.Blocks;
|
|||
|
using RobocraftX.Blocks.Ghost;
|
|||
|
using RobocraftX.Common;
|
|||
|
using RobocraftX.Multiplayer;
|
|||
|
using RobocraftX.SimulationModeState;
|
|||
|
using RobocraftX.UECS;
|
|||
|
using Unity.Entities;
|
|||
|
using Svelto.Context;
|
|||
|
using Svelto.ECS;
|
|||
|
using Svelto.ECS.EntityStructs;
|
|||
|
using Unity.Transforms;
|
|||
|
using Unity.Mathematics;
|
|||
|
using UnityEngine;
|
|||
|
|
|||
|
using GamecraftModdingAPI.Utility;
|
|||
|
|
|||
|
namespace GamecraftModdingAPI.Blocks
|
|||
|
{
|
|||
|
/// <summary>
|
|||
|
/// Engine which executes block movement actions
|
|||
|
/// </summary>
|
|||
|
public class SignalEngine : IApiEngine
|
|||
|
{
|
|||
|
public string Name { get; } = "GamecraftModdingAPISignalGameEngine";
|
|||
|
|
|||
|
public IEntitiesDB entitiesDB { set; private get; }
|
|||
|
|
|||
|
public bool IsInGame = false;
|
|||
|
|
|||
|
private Stack<uint> cubesStack = new Stack<uint>();
|
|||
|
private bool stackInUse = false;
|
|||
|
|
|||
|
private Gamecraft.DataStructures.FasterList<uint> cubesList = new Gamecraft.DataStructures.FasterList<uint>();
|
|||
|
private bool listInUse = false;
|
|||
|
|
|||
|
public void Dispose()
|
|||
|
{
|
|||
|
IsInGame = false;
|
|||
|
}
|
|||
|
|
|||
|
public void Ready()
|
|||
|
{
|
|||
|
IsInGame = true;
|
|||
|
}
|
|||
|
|
|||
|
// implementations for Signal static class
|
|||
|
|
|||
|
public bool SetSignal(uint blockID, uint channel, float signal, out EGID clusterID)
|
|||
|
{
|
|||
|
clusterID = GetClusterEGID(blockID, channel);
|
|||
|
return SetSignal(clusterID, signal);
|
|||
|
}
|
|||
|
|
|||
|
public bool SetSignal(EGID clusterID, float signal)
|
|||
|
{
|
|||
|
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
|
|||
|
{
|
|||
|
entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal = signal;
|
|||
|
return true;
|
|||
|
}
|
|||
|
return false;
|
|||
|
}
|
|||
|
|
|||
|
public float AddSignal(uint blockID, uint channel, float signal, out EGID clusterID, bool clamp = true)
|
|||
|
{
|
|||
|
clusterID = GetClusterEGID(blockID, channel);
|
|||
|
return AddSignal(clusterID, signal, clamp);
|
|||
|
}
|
|||
|
|
|||
|
public float AddSignal(EGID clusterID, float signal, bool clamp=true)
|
|||
|
{
|
|||
|
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
|
|||
|
{
|
|||
|
ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID);
|
|||
|
chanOutSig.outputSignal += signal;
|
|||
|
if (clamp)
|
|||
|
{
|
|||
|
if (chanOutSig.outputSignal > Signals.POSITIVE_HIGH)
|
|||
|
{
|
|||
|
chanOutSig.outputSignal = Signals.POSITIVE_HIGH;
|
|||
|
}
|
|||
|
else if (chanOutSig.outputSignal < Signals.NEGATIVE_HIGH)
|
|||
|
{
|
|||
|
chanOutSig.outputSignal = Signals.NEGATIVE_HIGH;
|
|||
|
}
|
|||
|
return chanOutSig.outputSignal;
|
|||
|
}
|
|||
|
}
|
|||
|
return signal;
|
|||
|
}
|
|||
|
|
|||
|
public float GetSignal(uint blockID, uint channel, out EGID clusterID)
|
|||
|
{
|
|||
|
clusterID = GetClusterEGID(blockID, channel);
|
|||
|
return GetSignal(clusterID);
|
|||
|
}
|
|||
|
|
|||
|
public float GetSignal(EGID clusterID)
|
|||
|
{
|
|||
|
if (entitiesDB.Exists<ChannelOutputSignalDataStruct>(clusterID))
|
|||
|
{
|
|||
|
return entitiesDB.QueryEntity<ChannelOutputSignalDataStruct>(clusterID).outputSignal;
|
|||
|
}
|
|||
|
return 0f;
|
|||
|
}
|
|||
|
|
|||
|
public EGID GetClusterEGID(uint blockID, uint channel)
|
|||
|
{
|
|||
|
uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID);
|
|||
|
uint index;
|
|||
|
ElectricityEntityStruct[] structs;
|
|||
|
Logging.CommandLog($"Found {connectedCubeIDs.Length} connected cubes");
|
|||
|
for (int i = 0; i < connectedCubeIDs.Length; i++)
|
|||
|
{
|
|||
|
if (entitiesDB.TryQueryEntitiesAndIndex(new EGID(connectedCubeIDs[i], CommonExclusiveGroups.OWNED_BLOCKS_GROUP), out index, out structs)
|
|||
|
|| entitiesDB.TryQueryEntitiesAndIndex(new EGID(connectedCubeIDs[i], CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP), out index, out structs))
|
|||
|
{
|
|||
|
ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity<ConductiveClusterIdStruct>(structs[index].ID).clusterId;
|
|||
|
uint operatingChannel = entitiesDB.QueryEntity<SignalOperatingChannelStruct>(structs[index].ID).operatingChannel;
|
|||
|
Logging.CommandLog($"Channel {operatingChannel} found");
|
|||
|
EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID);
|
|||
|
if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
|
|||
|
{
|
|||
|
return eGID;
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
// failsafe; not 100% reliable
|
|||
|
foreach (ref ConductiveClusterIdStruct clusterIdStruct in entitiesDB.QueryEntities<ConductiveClusterIdStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD))
|
|||
|
{
|
|||
|
EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterIdStruct.clusterId.ID);
|
|||
|
if (clusterIdStruct.clusterId.initialized && clusterIdStruct.clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
|
|||
|
{
|
|||
|
return eGID;
|
|||
|
}
|
|||
|
}
|
|||
|
return default;
|
|||
|
}
|
|||
|
|
|||
|
private uint[] GetConductivelyConnectedBlocks(uint blockID)
|
|||
|
{
|
|||
|
if (!(stackInUse || listInUse))
|
|||
|
{
|
|||
|
stackInUse = true;
|
|||
|
listInUse = true;
|
|||
|
cubesStack.Clear();
|
|||
|
cubesList.FastClear();
|
|||
|
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; });
|
|||
|
uint[] res = cubesList.ToArray();
|
|||
|
stackInUse = false;
|
|||
|
listInUse = false;
|
|||
|
return res;
|
|||
|
}
|
|||
|
Stack<uint> cubeStack = new Stack<uint>();
|
|||
|
Gamecraft.DataStructures.FasterList<uint> cubeList = new Gamecraft.DataStructures.FasterList<uint>();
|
|||
|
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; });
|
|||
|
return cubeList.ToArray();
|
|||
|
}
|
|||
|
|
|||
|
public bool IsSimulationMode()
|
|||
|
{
|
|||
|
return SimModeUtil.IsSimulationMode(this.entitiesDB);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|