TechbloxModdingAPI/GamecraftModdingAPI/Blocks/SignalEngine.cs
2020-01-03 19:54:35 -05:00

191 lines
7.1 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 signal 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;
EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
{
elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP);
}
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
{
return default;
}
ref ElectricityEntityStruct eStruct = ref entitiesDB.QueryEntity<ElectricityEntityStruct>(elecEGID);
ref ConductiveClusterID clusterId = ref entitiesDB.QueryEntity<ConductiveClusterIdStruct>(eStruct.ID).clusterId;
uint operatingChannel = entitiesDB.QueryEntity<SignalOperatingChannelStruct>(eStruct.ID).operatingChannel;
EGID eGID = new EGID(channel, BlockIdentifiers.OUTPUT_SIGNAL_CHANNELS + clusterId.ID);
if (clusterId.initialized && clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID))
{
return eGID;
}
return default;
}
public uint[] GetElectricBlocks()
{
uint count = entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[0])
+ entitiesDB.Count<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD[1]);
uint i = 0;
uint[] res = new uint[count];
foreach (ref var ees in entitiesDB.QueryEntities<ElectricityEntityStruct>(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<GridConnectionsEntityStruct>(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
}
return res;
}
else
{
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 g.isIsolator; });
uint[] res = cubesList.ToArray();
foreach (var id in res)
{
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
}
return res;
}
}
public bool IsSimulationMode()
{
return GamecraftModdingAPI.Utility.GameState.IsSimulationMode();
}
}
}