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 { /// /// Engine which executes signal actions /// public class SignalEngine : IApiEngine { public string Name { get; } = "GamecraftModdingAPISignalGameEngine"; public IEntitiesDB entitiesDB { set; private get; } public bool IsInGame = false; private Stack cubesStack = new Stack(); private bool stackInUse = false; private Gamecraft.DataStructures.FasterList cubesList = new Gamecraft.DataStructures.FasterList(); 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(clusterID)) { entitiesDB.QueryEntity(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(clusterID)) { ref ChannelOutputSignalDataStruct chanOutSig = ref entitiesDB.QueryEntity(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(clusterID)) { return entitiesDB.QueryEntity(clusterID).outputSignal; } return 0f; } public EGID GetClusterEGID(uint blockID, uint channel) { //uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID); //uint index; //ElectricityEntityStruct[] structs; EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); if (!entitiesDB.Exists(elecEGID)) { elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP); } if (!entitiesDB.Exists(elecEGID)) { return default; } ref ElectricityEntityStruct eStruct = ref entitiesDB.QueryEntity(elecEGID); ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity(eStruct.ID).clusterId; uint operatingChannel = entitiesDB.QueryEntity(eStruct.ID).operatingChannel; EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID); if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists(eGID)) { return eGID; } return default; } public uint[] GetElectricBlocks() { uint count = entitiesDB.Count(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[0]) + entitiesDB.Count(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[1]); uint i = 0; uint[] res = new uint[count]; foreach (ref var ees in entitiesDB.QueryEntities(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD)) { res[i] = ees.ID.entityID; i++; } return res; } 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 g.isIsolator; }); uint[] res = cubesList.ToArray(); stackInUse = false; listInUse = false; foreach (var id in res) { entitiesDB.QueryEntity(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; } return res; } else { Stack cubeStack = new Stack(); Gamecraft.DataStructures.FasterList cubeList = new Gamecraft.DataStructures.FasterList(); ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return g.isIsolator; }); uint[] res = cubesList.ToArray(); foreach (var id in res) { entitiesDB.QueryEntity(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false; } return res; } } public bool IsSimulationMode() { return GamecraftModdingAPI.Utility.GameState.IsSimulationMode(); } } }