Fix signal API & docs and improve API Init

This commit is contained in:
NGnius (Graham) 2019-12-25 16:16:17 -05:00
parent 2df8da1af5
commit b796751420
12 changed files with 206 additions and 47 deletions

View file

@ -81,7 +81,7 @@ namespace GamecraftModdingAPI.Blocks
public bool IsBuildMode() public bool IsBuildMode()
{ {
return SimModeUtil.IsBuildMode(this.entitiesDB); return GamecraftModdingAPI.Utility.GameState.IsBuildMode();
} }
} }
} }

View file

@ -80,7 +80,7 @@ namespace GamecraftModdingAPI.Blocks
public bool IsBuildMode() public bool IsBuildMode()
{ {
return SimModeUtil.IsBuildMode(this.entitiesDB); return GamecraftModdingAPI.Utility.GameState.IsBuildMode();
} }
} }
} }

View file

@ -113,37 +113,43 @@ namespace GamecraftModdingAPI.Blocks
public EGID GetClusterEGID(uint blockID, uint channel) public EGID GetClusterEGID(uint blockID, uint channel)
{ {
uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID); //uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID);
uint index; //uint index;
ElectricityEntityStruct[] structs; //ElectricityEntityStruct[] structs;
Logging.CommandLog($"Found {connectedCubeIDs.Length} connected cubes"); EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP);
for (int i = 0; i < connectedCubeIDs.Length; i++) if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
{ {
if (entitiesDB.TryQueryEntitiesAndIndex(new EGID(connectedCubeIDs[i], CommonExclusiveGroups.OWNED_BLOCKS_GROUP), out index, out structs) elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP);
|| 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 if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID))
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); return default;
if (clusterIdStruct.clusterId.initialized && clusterIdStruct.clusterId.isConductive && entitiesDB.Exists<ChannelOutputSignalDataStruct>(eGID)) }
{ ref ElectricityEntityStruct eStruct = ref entitiesDB.QueryEntity<ElectricityEntityStruct>(elecEGID);
return eGID; 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; 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) private uint[] GetConductivelyConnectedBlocks(uint blockID)
{ {
if (!(stackInUse || listInUse)) if (!(stackInUse || listInUse))
@ -152,21 +158,34 @@ namespace GamecraftModdingAPI.Blocks
listInUse = true; listInUse = true;
cubesStack.Clear(); cubesStack.Clear();
cubesList.FastClear(); cubesList.FastClear();
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; }); ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return g.isIsolator; });
uint[] res = cubesList.ToArray(); uint[] res = cubesList.ToArray();
stackInUse = false; stackInUse = false;
listInUse = false; listInUse = false;
foreach (var id in res)
{
entitiesDB.QueryEntity<GridConnectionsEntityStruct>(id, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).isProcessed = false;
}
return res; return res;
} }
Stack<uint> cubeStack = new Stack<uint>(); else
Gamecraft.DataStructures.FasterList<uint> cubeList = new Gamecraft.DataStructures.FasterList<uint>(); {
ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubesStack, cubesList, (in GridConnectionsEntityStruct g) => { return false; }); Stack<uint> cubeStack = new Stack<uint>();
return cubeList.ToArray(); 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() public bool IsSimulationMode()
{ {
return SimModeUtil.IsSimulationMode(this.entitiesDB); return GamecraftModdingAPI.Utility.GameState.IsSimulationMode();
} }
} }
} }

View file

@ -24,7 +24,7 @@ namespace GamecraftModdingAPI.Blocks
private static SignalEngine signalEngine = new SignalEngine(); private static SignalEngine signalEngine = new SignalEngine();
/// <summary> /// <summary>
/// Set a channel to a value in the block's conductive block cluster /// Set the electric block's channel to a value
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="id">The block's id</param>
/// <param name="channel">The channel (1 to 99)</param> /// <param name="channel">The channel (1 to 99)</param>
@ -51,7 +51,7 @@ namespace GamecraftModdingAPI.Blocks
} }
/// <summary> /// <summary>
/// Add a value to a channel signal in the block's conductive block cluster /// Add a value to an electric block's channel signal
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="id">The block's id</param>
/// <param name="channel">The channel (1 to 99)</param> /// <param name="channel">The channel (1 to 99)</param>
@ -80,12 +80,12 @@ namespace GamecraftModdingAPI.Blocks
} }
/// <summary> /// <summary>
/// Get a channel's signal value from the block's conductive block cluster /// Get a electric block's channel's signal value
/// </summary> /// </summary>
/// <param name="id">The block's id</param> /// <param name="id">The block's id</param>
/// <param name="channel">The channel (1 to 99)</param> /// <param name="channel">The channel (1 to 99)</param>
/// <returns>The signal value</returns> /// <returns>The signal value</returns>
public static float GetSignalConnectedBlocks(uint id, uint channel) public static float GetSignalBlock(uint id, uint channel)
{ {
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) if (signalEngine.IsInGame && signalEngine.IsSimulationMode())
{ {
@ -108,6 +108,21 @@ namespace GamecraftModdingAPI.Blocks
return 0f; return 0f;
} }
/// <summary>
/// Get the ID of every electricity consumer in the game world
/// </summary>
/// <returns>The block IDs</returns>
public static uint[] GetElectricBlocks()
{
return signalEngine.GetElectricBlocks();
}
/// <summary>
/// Get the conductive cluster's unique identifier for an electric block
/// </summary>
/// <param name="id">The block's id</param>
/// <param name="channel"></param>
/// <returns>The unique ID</returns>
public static EGID GetClusterID(uint id, uint channel) public static EGID GetClusterID(uint id, uint channel)
{ {
return signalEngine.GetClusterEGID(id, channel); return signalEngine.GetClusterEGID(id, channel);

View file

@ -33,11 +33,13 @@ namespace GamecraftModdingAPI.Commands
public void Dispose() public void Dispose()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Unregister(this.Name); CommandRegistrationHelper.Unregister(this.Name);
} }
public void Ready() public void Ready()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Register(this.Name, this.runCommand, this.Description); CommandRegistrationHelper.Register(this.Name, this.runCommand, this.Description);
} }

View file

@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands
public void Dispose() public void Dispose()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Unregister(this.Name); CommandRegistrationHelper.Unregister(this.Name);
} }
public void Ready() public void Ready()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Register<A>(this.Name, this.runCommand, this.Description); CommandRegistrationHelper.Register<A>(this.Name, this.runCommand, this.Description);
} }

View file

@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands
public void Dispose() public void Dispose()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Unregister(this.Name); CommandRegistrationHelper.Unregister(this.Name);
} }
public void Ready() public void Ready()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Register<A,B>(this.Name, this.runCommand, this.Description); CommandRegistrationHelper.Register<A,B>(this.Name, this.runCommand, this.Description);
} }

View file

@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands
public void Dispose() public void Dispose()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Unregister(this.Name); CommandRegistrationHelper.Unregister(this.Name);
} }
public void Ready() public void Ready()
{ {
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}");
CommandRegistrationHelper.Register<A,B,C>(this.Name, this.runCommand, this.Description); CommandRegistrationHelper.Register<A,B,C>(this.Name, this.runCommand, this.Description);
} }

View file

@ -25,6 +25,8 @@ namespace GamecraftModdingAPI
get { return harmony != null; } get { return harmony != null; }
} }
private static int referenceCount = 0;
/// <summary> /// <summary>
/// Initializes the GamecraftModdingAPI. /// Initializes the GamecraftModdingAPI.
/// Call this as soon as possible after Gamecraft starts up. /// Call this as soon as possible after Gamecraft starts up.
@ -32,6 +34,8 @@ namespace GamecraftModdingAPI
/// </summary> /// </summary>
public static void Init() public static void Init()
{ {
referenceCount++;
if (referenceCount > 1) { return; }
if (IsInitialized) if (IsInitialized)
{ {
Logging.LogWarning("GamecraftModdingAPI.Main.Init() called but API is already initialized!"); Logging.LogWarning("GamecraftModdingAPI.Main.Init() called but API is already initialized!");
@ -41,6 +45,9 @@ namespace GamecraftModdingAPI
var currentAssembly = Assembly.GetExecutingAssembly(); var currentAssembly = Assembly.GetExecutingAssembly();
harmony = HarmonyInstance.Create(currentAssembly.GetName().Name); harmony = HarmonyInstance.Create(currentAssembly.GetName().Name);
harmony.PatchAll(currentAssembly); harmony.PatchAll(currentAssembly);
// init utility
Logging.MetaDebugLog($"Initializing Utility");
Utility.GameState.Init();
// create default event emitters // create default event emitters
Logging.MetaDebugLog($"Initializing Events"); Logging.MetaDebugLog($"Initializing Events");
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false)); EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false));
@ -64,16 +71,20 @@ namespace GamecraftModdingAPI
/// </summary> /// </summary>
public static void Shutdown() public static void Shutdown()
{ {
if (!IsInitialized) if (referenceCount > 0) { referenceCount--; }
if (referenceCount == 0)
{ {
Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!"); if (!IsInitialized)
return; {
Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!");
return;
}
Scheduler.Dispose();
var currentAssembly = Assembly.GetExecutingAssembly();
harmony.UnpatchAll(currentAssembly.GetName().Name);
harmony = null;
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
} }
Scheduler.Dispose();
var currentAssembly = Assembly.GetExecutingAssembly();
harmony.UnpatchAll(currentAssembly.GetName().Name);
harmony = null;
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} shutdown");
} }
} }
} }

View file

@ -31,15 +31,30 @@ namespace GamecraftModdingAPI.Tasks
public static readonly Svelto.Tasks.Lean.Unity.UpdateMonoRunner leanRunner = new Svelto.Tasks.Lean.Unity.UpdateMonoRunner("GamecraftModdingAPILean"); 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) public static void Schedule(ISchedulable toRun, bool extraLean = false, bool ui = false)
{ {
if (extraLean) if (extraLean)
{ {
toRun.Run().RunOn(extraLeanRunner); if (ui)
{
toRun.Run().RunOn(extraLeanRunnerUI);
}
else
{
toRun.Run().RunOn(extraLeanRunner);
}
} }
else else
{ {
toRun.Run().RunOn(leanRunner); if (ui)
{
toRun.Run().RunOn(leanRunnerUI);
}
else
{
toRun.Run().RunOn(leanRunner);
}
} }
} }

View file

@ -0,0 +1,48 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace GamecraftModdingAPI.Utility
{
/// <summary>
/// Utility to get the state of the current Gamecraft game
/// </summary>
public static class GameState
{
private static GameStateEngine gameEngine = new GameStateEngine();
/// <summary>
/// Is the game in edit mode?
/// </summary>
/// <returns>Whether the game is in build mode</returns>
public static bool IsBuildMode()
{
return gameEngine.IsBuildMode();
}
/// <summary>
/// Is the game in simulation mode?
/// </summary>
/// <returns>Whether the game is in simulation mode</returns>
public static bool IsSimulationMode()
{
return gameEngine.IsSimulationMode();
}
/// <summary>
/// Is a game loaded?
/// </summary>
/// <returns>Whether Gamecraft has a game open (false = Main Menu)</returns>
public static bool IsInGame()
{
return gameEngine.IsInGame;
}
public static void Init()
{
GameEngineManager.AddGameEngine(gameEngine);
}
}
}

View file

@ -0,0 +1,43 @@
using Svelto.ECS;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using RobocraftX.SimulationModeState;
namespace GamecraftModdingAPI.Utility
{
class GameStateEngine : IApiEngine
{
public string Name { get; } = "GamecraftModdingAPIGameStateGameEngine";
public IEntitiesDB entitiesDB { set; private get; }
private bool _isInGame = false;
public bool IsInGame { get { return _isInGame; } }
public void Dispose()
{
_isInGame = false;
}
public void Ready()
{
_isInGame = true;
}
public bool IsBuildMode()
{
return _isInGame && SimModeUtil.IsBuildMode(entitiesDB);
}
public bool IsSimulationMode()
{
return _isInGame && SimModeUtil.IsSimulationMode(entitiesDB);
}
}
}