Add mostly reliable signal & channel API support
This commit is contained in:
parent
15a73ecfab
commit
2df8da1af5
15 changed files with 522 additions and 10 deletions
|
@ -33,6 +33,8 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
|
|
||||||
public static ExclusiveGroup SPAWN_POINTS_DISABLED { get { return CommonExclusiveGroups.SPAWN_POINTS_DISABLED_GROUP; } }
|
public static ExclusiveGroup SPAWN_POINTS_DISABLED { get { return CommonExclusiveGroups.SPAWN_POINTS_DISABLED_GROUP; } }
|
||||||
|
|
||||||
|
public static ExclusiveGroup OUTPUT_SIGNAL_CHANNELS { get { return CommonExclusiveGroups.CHANNEL_OUTPUT_SIGNAL_GROUPS; } }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ID of the most recently placed block
|
/// The ID of the most recently placed block
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|
|
@ -81,7 +81,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
|
|
||||||
public bool IsBuildMode()
|
public bool IsBuildMode()
|
||||||
{
|
{
|
||||||
return this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).simulationMode == SimulationMode.Build;
|
return SimModeUtil.IsBuildMode(this.entitiesDB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -21,7 +21,7 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
/// <param name="id">The block's id</param>
|
/// <param name="id">The block's id</param>
|
||||||
/// <param name="vector">The rotation amount around the x,y,z-planes</param>
|
/// <param name="vector">The rotation amount around the x,y,z-planes</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool MoveBlock(uint id, float3 vector)
|
public static bool RotateBlock(uint id, float3 vector)
|
||||||
{
|
{
|
||||||
if (rotationEngine.IsInGame && rotationEngine.IsBuildMode())
|
if (rotationEngine.IsInGame && rotationEngine.IsBuildMode())
|
||||||
{
|
{
|
||||||
|
@ -37,11 +37,11 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
/// <param name="id">The starting block's id</param>
|
/// <param name="id">The starting block's id</param>
|
||||||
/// <param name="vector">The rotation around the x,y,z-planes</param>
|
/// <param name="vector">The rotation around the x,y,z-planes</param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
public static bool MoveRotateBlocks(uint id, float3 vector)
|
public static bool RotateConnectedBlocks(uint id, float3 vector)
|
||||||
{
|
{
|
||||||
if (rotationEngine.IsInGame && rotationEngine.IsBuildMode())
|
if (rotationEngine.IsInGame && rotationEngine.IsBuildMode())
|
||||||
{
|
{
|
||||||
rotationEngine.MoveConnectedBlocks(id, vector);
|
rotationEngine.RotateConnectedBlocks(id, vector);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
|
|
|
@ -73,14 +73,14 @@ namespace GamecraftModdingAPI.Blocks
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public float3 MoveConnectedBlocks(uint blockID, Vector3 vector)
|
public float3 RotateConnectedBlocks(uint blockID, Vector3 vector)
|
||||||
{
|
{
|
||||||
throw new NotImplementedException();
|
throw new NotImplementedException();
|
||||||
}
|
}
|
||||||
|
|
||||||
public bool IsBuildMode()
|
public bool IsBuildMode()
|
||||||
{
|
{
|
||||||
return this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).simulationMode == SimulationMode.Build;
|
return SimModeUtil.IsBuildMode(this.entitiesDB);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
172
GamecraftModdingAPI/Blocks/SignalEngine.cs
Normal file
172
GamecraftModdingAPI/Blocks/SignalEngine.cs
Normal file
|
@ -0,0 +1,172 @@
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
122
GamecraftModdingAPI/Blocks/Signals.cs
Normal file
122
GamecraftModdingAPI/Blocks/Signals.cs
Normal file
|
@ -0,0 +1,122 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Svelto.ECS;
|
||||||
|
|
||||||
|
using GamecraftModdingAPI.Utility;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Blocks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// [EXPERIMENTAL] Common block signal operations
|
||||||
|
/// </summary>
|
||||||
|
public static class Signals
|
||||||
|
{
|
||||||
|
// Signal constants
|
||||||
|
public static readonly float HIGH = 1.0f;
|
||||||
|
public static readonly float POSITIVE_HIGH = HIGH;
|
||||||
|
public static readonly float NEGATIVE_HIGH = -1.0f;
|
||||||
|
public static readonly float LOW = 0.0f;
|
||||||
|
|
||||||
|
private static SignalEngine signalEngine = new SignalEngine();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set a channel to a value in the block's conductive block cluster
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The block's id</param>
|
||||||
|
/// <param name="channel">The channel (1 to 99)</param>
|
||||||
|
/// <param name="signal">The signal value (-1 to 1; not enforced)</param>
|
||||||
|
public static void SetSignalConnectedBlocks(uint id, uint channel, float signal)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
signalEngine.SetSignal(id, channel, signal, out EGID _);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set a conductive cluster channel to a value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clusterID">The channel cluster's id</param>
|
||||||
|
/// <param name="signal">The signal value (-1 to 1; not enforced)</param>
|
||||||
|
public static void SetSignalCluster(EGID clusterID, float signal)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
signalEngine.SetSignal(clusterID, signal);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a value to a channel signal in the block's conductive block cluster
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The block's id</param>
|
||||||
|
/// <param name="channel">The channel (1 to 99)</param>
|
||||||
|
/// <param name="signal">The signal value to add</param>
|
||||||
|
/// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1</param>
|
||||||
|
public static void AddSignalConnectedBlocks(uint id, uint channel, float signal, bool clamp = true)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
signalEngine.AddSignal(id, channel, signal, out EGID _, clamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Add a value to a conductive cluster channel
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clusterID">The channel cluster's id</param>
|
||||||
|
/// <param name="signal">The signal value to add</param>
|
||||||
|
/// <param name="clamp">Whether to clamp the resulting signal value between -1 and 1</param>
|
||||||
|
public static void AddSignalCluster(EGID clusterID, float signal, bool clamp = true)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
signalEngine.AddSignal(clusterID, signal, clamp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a channel's signal value from the block's conductive block cluster
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="id">The block's id</param>
|
||||||
|
/// <param name="channel">The channel (1 to 99)</param>
|
||||||
|
/// <returns>The signal value</returns>
|
||||||
|
public static float GetSignalConnectedBlocks(uint id, uint channel)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
return signalEngine.GetSignal(id, channel, out EGID _);
|
||||||
|
}
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a conductive cluster channel's signal value
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="clusterID">The channel cluster's id</param>
|
||||||
|
/// <returns>The signal value</returns>
|
||||||
|
public static float GetSignalCluster(EGID clusterID)
|
||||||
|
{
|
||||||
|
if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
|
||||||
|
{
|
||||||
|
return signalEngine.GetSignal(clusterID);
|
||||||
|
}
|
||||||
|
return 0f;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static EGID GetClusterID(uint id, uint channel)
|
||||||
|
{
|
||||||
|
return signalEngine.GetClusterEGID(id, channel);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public static void Init()
|
||||||
|
{
|
||||||
|
GameEngineManager.AddGameEngine(signalEngine);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -13,7 +13,7 @@ namespace GamecraftModdingAPI.Commands
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Engine interface to handle command operations
|
/// Engine interface to handle command operations
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface ICustomCommandEngine :IApiEngine
|
public interface ICustomCommandEngine : IApiEngine
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The command's description, shown in command help messages
|
/// The command's description, shown in command help messages
|
||||||
|
|
|
@ -60,7 +60,8 @@ namespace GamecraftModdingAPI.Events
|
||||||
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
|
/// <param name="removed">The operation to do when the event is destroyed (if applicable)</param>
|
||||||
/// <param name="type">The type of event to handle</param>
|
/// <param name="type">The type of event to handle</param>
|
||||||
/// <param name="name">The name of the engine</param>
|
/// <param name="name">The name of the engine</param>
|
||||||
public SimpleEventHandlerEngine(Action activated, Action removed, object type, string name)
|
/// <param name="simple">A useless parameter to use to avoid Python overload resolution errors</param>
|
||||||
|
public SimpleEventHandlerEngine(Action activated, Action removed, object type, string name, bool simple = true)
|
||||||
: this((IEntitiesDB _) => { activated.Invoke(); }, (IEntitiesDB _) => { removed.Invoke(); }, type, name) { }
|
: this((IEntitiesDB _) => { activated.Invoke(); }, (IEntitiesDB _) => { removed.Invoke(); }, type, name) { }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|
|
@ -9,6 +9,7 @@ using Harmony;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Utility;
|
using GamecraftModdingAPI.Utility;
|
||||||
using GamecraftModdingAPI.Events;
|
using GamecraftModdingAPI.Events;
|
||||||
|
using GamecraftModdingAPI.Tasks;
|
||||||
|
|
||||||
namespace GamecraftModdingAPI
|
namespace GamecraftModdingAPI
|
||||||
{
|
{
|
||||||
|
@ -52,6 +53,7 @@ namespace GamecraftModdingAPI
|
||||||
Logging.MetaDebugLog($"Initializing Blocks");
|
Logging.MetaDebugLog($"Initializing Blocks");
|
||||||
Blocks.Movement.Init();
|
Blocks.Movement.Init();
|
||||||
Blocks.Rotation.Init();
|
Blocks.Rotation.Init();
|
||||||
|
Blocks.Signals.Init();
|
||||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
|
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -62,8 +64,15 @@ namespace GamecraftModdingAPI
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static void Shutdown()
|
public static void Shutdown()
|
||||||
{
|
{
|
||||||
|
if (!IsInitialized)
|
||||||
|
{
|
||||||
|
Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
Scheduler.Dispose();
|
||||||
var currentAssembly = Assembly.GetExecutingAssembly();
|
var currentAssembly = Assembly.GetExecutingAssembly();
|
||||||
harmony.UnpatchAll(currentAssembly.GetName().Name);
|
harmony.UnpatchAll(currentAssembly.GetName().Name);
|
||||||
|
harmony = null;
|
||||||
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
|
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
22
GamecraftModdingAPI/Tasks/ISchedulable.cs
Normal file
22
GamecraftModdingAPI/Tasks/ISchedulable.cs
Normal file
|
@ -0,0 +1,22 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Svelto.Tasks;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Interface for asynchronous tasks
|
||||||
|
/// </summary>
|
||||||
|
public interface ISchedulable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Asynchronous task runner
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A yield-ed Svelto.Tasks-compatible object</returns>
|
||||||
|
IEnumerator<TaskContract> Run();
|
||||||
|
}
|
||||||
|
}
|
38
GamecraftModdingAPI/Tasks/Once.cs
Normal file
38
GamecraftModdingAPI/Tasks/Once.cs
Normal file
|
@ -0,0 +1,38 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Svelto.Tasks;
|
||||||
|
using Svelto.Tasks.Enumerators;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An asynchronous task to be performed once
|
||||||
|
/// </summary>
|
||||||
|
public class Once : ISchedulable
|
||||||
|
{
|
||||||
|
private Action task;
|
||||||
|
|
||||||
|
private float delay;
|
||||||
|
public IEnumerator<TaskContract> Run()
|
||||||
|
{
|
||||||
|
yield return new WaitForSecondsEnumerator(delay).Continue();
|
||||||
|
task();
|
||||||
|
yield return Yield.It;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a single-run task
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">The task to run once</param>
|
||||||
|
/// <param name="after">The delay (in seconds) before the task is run</param>
|
||||||
|
public Once(Action task, float after = 0.0f)
|
||||||
|
{
|
||||||
|
this.task = task;
|
||||||
|
this.delay = after;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
65
GamecraftModdingAPI/Tasks/Repeatable.cs
Normal file
65
GamecraftModdingAPI/Tasks/Repeatable.cs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Svelto.Tasks;
|
||||||
|
using Svelto.Tasks.Enumerators;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Tasks
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// An asynchronous repeating task
|
||||||
|
/// </summary>
|
||||||
|
public class Repeatable : ISchedulable
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Determines if the task should continue to repeat
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>Whether the task should run again (true) or end (false)</returns>
|
||||||
|
public delegate bool ShouldContinue();
|
||||||
|
|
||||||
|
private ShouldContinue shouldContinue;
|
||||||
|
|
||||||
|
private Action task;
|
||||||
|
|
||||||
|
private float delay;
|
||||||
|
|
||||||
|
public IEnumerator<TaskContract> Run()
|
||||||
|
{
|
||||||
|
while (shouldContinue())
|
||||||
|
{
|
||||||
|
task();
|
||||||
|
yield return new WaitForSecondsEnumerator(delay).Continue();
|
||||||
|
}
|
||||||
|
yield return Yield.It;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a repeating task
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">The task to repeat</param>
|
||||||
|
/// <param name="shouldContinue">The check to determine if the task should run again</param>
|
||||||
|
/// <param name="delay">The time to wait between repeats (in seconds)</param>
|
||||||
|
public Repeatable(Action task, ShouldContinue shouldContinue, float delay = 0.0f)
|
||||||
|
{
|
||||||
|
this.task = task;
|
||||||
|
this.shouldContinue = shouldContinue;
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Construct a repeating task
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="task">The task to repeat</param>
|
||||||
|
/// <param name="count">The amount of times to repeat</param>
|
||||||
|
/// <param name="delay">The time to wait between repeats (in seconds)</param>
|
||||||
|
public Repeatable(Action task, int count, float delay = 0.0f)
|
||||||
|
{
|
||||||
|
this.task = task;
|
||||||
|
this.shouldContinue = () => { return count-- != 0; };
|
||||||
|
this.delay = delay;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
55
GamecraftModdingAPI/Tasks/Scheduler.cs
Normal file
55
GamecraftModdingAPI/Tasks/Scheduler.cs
Normal file
|
@ -0,0 +1,55 @@
|
||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
|
||||||
|
using Svelto.Tasks.Lean;
|
||||||
|
using Svelto.Tasks.ExtraLean;
|
||||||
|
|
||||||
|
namespace GamecraftModdingAPI.Tasks
|
||||||
|
{
|
||||||
|
public static class Scheduler
|
||||||
|
{
|
||||||
|
public static Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunnerUI
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return RobocraftX.Schedulers.Lean.UIScheduler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunnerUI
|
||||||
|
{
|
||||||
|
get
|
||||||
|
{
|
||||||
|
return RobocraftX.Schedulers.ExtraLean.UIScheduler;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public static readonly Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner extraLeanRunner = new Svelto.Tasks.ExtraLean.Unity.UpdateMonoRunner("GamecraftModdingAPIExtraLean");
|
||||||
|
|
||||||
|
public static readonly Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunner = new Svelto.Tasks.Lean.Unity.UpdateMonoRunner("GamecraftModdingAPILean");
|
||||||
|
|
||||||
|
public static void Schedule(ISchedulable toRun, bool extraLean = false)
|
||||||
|
{
|
||||||
|
if (extraLean)
|
||||||
|
{
|
||||||
|
toRun.Run().RunOn(extraLeanRunner);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
toRun.Run().RunOn(leanRunner);
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void Dispose()
|
||||||
|
{
|
||||||
|
leanRunner.Stop();
|
||||||
|
extraLeanRunner.Stop();
|
||||||
|
leanRunner.Dispose();
|
||||||
|
extraLeanRunner.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -2,6 +2,11 @@
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
|
|
||||||
using Harmony;
|
using Harmony;
|
||||||
|
// test
|
||||||
|
using Svelto.ECS;
|
||||||
|
using RobocraftX.Blocks;
|
||||||
|
using RobocraftX.Common;
|
||||||
|
using RobocraftX.SimulationModeState;
|
||||||
|
|
||||||
using GamecraftModdingAPI.Commands;
|
using GamecraftModdingAPI.Commands;
|
||||||
using GamecraftModdingAPI.Events;
|
using GamecraftModdingAPI.Events;
|
||||||
|
@ -94,6 +99,27 @@ namespace GamecraftModdingAPI.Tests
|
||||||
|
|
||||||
public void OnLevelWasLoaded(int level) { }
|
public void OnLevelWasLoaded(int level) { }
|
||||||
|
|
||||||
public void OnUpdate() { }
|
public void OnUpdate()
|
||||||
|
{
|
||||||
|
/*
|
||||||
|
if (db != null && signalStrength != 0.0f && db.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP).simulationMode == SimulationMode.Simulation)
|
||||||
|
{
|
||||||
|
//GamecraftModdingAPI.Utility.Logging.MetaDebugLog("Simulation frame update");
|
||||||
|
foreach (ref ElectricityEntityStruct powah in db.QueryEntities<ElectricityEntityStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD))
|
||||||
|
{
|
||||||
|
ref ConductiveClusterID clusterId = ref db.QueryEntity<ConductiveClusterIdStruct>(powah.ID).clusterId;
|
||||||
|
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"ID {powah.ID.entityID} unmodded values: Power* {powah.powerMultiplier} Conductivity* {powah.conductivityMultiplier} Output* {powah.outputSignalMultiplier}");
|
||||||
|
uint operatingChannel = db.QueryEntity<SignalOperatingChannelStruct>(powah.ID).operatingChannel;
|
||||||
|
if (operatingChannel != 0)
|
||||||
|
{
|
||||||
|
EGID eGID = new EGID(operatingChannel, CommonExclusiveGroups.CHANNEL_OUTPUT_SIGNAL_GROUPS + clusterId.ID);
|
||||||
|
if (db.Exists<ChannelOutputSignalDataStruct>(eGID))
|
||||||
|
{
|
||||||
|
db.QueryEntity<ChannelOutputSignalDataStruct>(eGID).outputSignal = signalStrength;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}*/
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -167,7 +167,7 @@ namespace GamecraftModdingAPI.Utility
|
||||||
public static void MetaLog(object obj)
|
public static void MetaLog(object obj)
|
||||||
{
|
{
|
||||||
var method = (new StackTrace()).GetFrame(1).GetMethod();
|
var method = (new StackTrace()).GetFrame(1).GetMethod();
|
||||||
Log($"[{DateTime.Now.ToString()}][{method.DeclaringType.Name}.{method.Name}]{obj.ToString()}");
|
Log($"[{DateTime.Now.ToString()}][{method.DeclaringType.FullName}.{method.Name}]{obj.ToString()}");
|
||||||
}
|
}
|
||||||
|
|
||||||
// CLI logging
|
// CLI logging
|
||||||
|
|
Loading…
Reference in a new issue