@@ -81,7 +81,7 @@ namespace GamecraftModdingAPI.Blocks | |||
public bool IsBuildMode() | |||
{ | |||
return SimModeUtil.IsBuildMode(this.entitiesDB); | |||
return GamecraftModdingAPI.Utility.GameState.IsBuildMode(); | |||
} | |||
} | |||
} |
@@ -80,7 +80,7 @@ namespace GamecraftModdingAPI.Blocks | |||
public bool IsBuildMode() | |||
{ | |||
return SimModeUtil.IsBuildMode(this.entitiesDB); | |||
return GamecraftModdingAPI.Utility.GameState.IsBuildMode(); | |||
} | |||
} | |||
} |
@@ -113,37 +113,43 @@ namespace GamecraftModdingAPI.Blocks | |||
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++) | |||
//uint[] connectedCubeIDs = GetConductivelyConnectedBlocks(blockID); | |||
//uint index; | |||
//ElectricityEntityStruct[] structs; | |||
EGID elecEGID = new EGID(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID)) | |||
{ | |||
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; | |||
} | |||
} | |||
elecEGID = new EGID(blockID, CommonExclusiveGroups.FUNCTIONAL_BLOCK_PART_GROUP); | |||
} | |||
// failsafe; not 100% reliable | |||
foreach (ref ConductiveClusterIdStruct clusterIdStruct in entitiesDB.QueryEntities<ConductiveClusterIdStruct>(CommonExclusiveGroups.FUNCTIONAL_CUBES_IN_BOTH_SIM_AND_BUILD)) | |||
if (!entitiesDB.Exists<ElectricityEntityStruct>(elecEGID)) | |||
{ | |||
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; | |||
} | |||
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)) | |||
@@ -152,21 +158,34 @@ namespace GamecraftModdingAPI.Blocks | |||
listInUse = true; | |||
cubesStack.Clear(); | |||
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(); | |||
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; | |||
} | |||
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); | |||
return GamecraftModdingAPI.Utility.GameState.IsSimulationMode(); | |||
} | |||
} | |||
} |
@@ -24,7 +24,7 @@ namespace GamecraftModdingAPI.Blocks | |||
private static SignalEngine signalEngine = new SignalEngine(); | |||
/// <summary> | |||
/// Set a channel to a value in the block's conductive block cluster | |||
/// Set the electric block's channel to a value | |||
/// </summary> | |||
/// <param name="id">The block's id</param> | |||
/// <param name="channel">The channel (1 to 99)</param> | |||
@@ -51,7 +51,7 @@ namespace GamecraftModdingAPI.Blocks | |||
} | |||
/// <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> | |||
/// <param name="id">The block's id</param> | |||
/// <param name="channel">The channel (1 to 99)</param> | |||
@@ -80,12 +80,12 @@ namespace GamecraftModdingAPI.Blocks | |||
} | |||
/// <summary> | |||
/// Get a channel's signal value from the block's conductive block cluster | |||
/// Get a electric block's channel's signal value | |||
/// </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) | |||
public static float GetSignalBlock(uint id, uint channel) | |||
{ | |||
if (signalEngine.IsInGame && signalEngine.IsSimulationMode()) | |||
{ | |||
@@ -108,6 +108,21 @@ namespace GamecraftModdingAPI.Blocks | |||
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) | |||
{ | |||
return signalEngine.GetClusterEGID(id, channel); | |||
@@ -33,11 +33,13 @@ namespace GamecraftModdingAPI.Commands | |||
public void Dispose() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Unregister(this.Name); | |||
} | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register(this.Name, this.runCommand, this.Description); | |||
} | |||
@@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands | |||
public void Dispose() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Unregister(this.Name); | |||
} | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A>(this.Name, this.runCommand, this.Description); | |||
} | |||
@@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands | |||
public void Dispose() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Unregister(this.Name); | |||
} | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A,B>(this.Name, this.runCommand, this.Description); | |||
} | |||
@@ -24,11 +24,13 @@ namespace GamecraftModdingAPI.Commands | |||
public void Dispose() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Unregistering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Unregister(this.Name); | |||
} | |||
public void Ready() | |||
{ | |||
GamecraftModdingAPI.Utility.Logging.MetaDebugLog($"Registering SimpleCustomCommandEngine {this.Name}"); | |||
CommandRegistrationHelper.Register<A,B,C>(this.Name, this.runCommand, this.Description); | |||
} | |||
@@ -25,6 +25,8 @@ namespace GamecraftModdingAPI | |||
get { return harmony != null; } | |||
} | |||
private static int referenceCount = 0; | |||
/// <summary> | |||
/// Initializes the GamecraftModdingAPI. | |||
/// Call this as soon as possible after Gamecraft starts up. | |||
@@ -32,6 +34,8 @@ namespace GamecraftModdingAPI | |||
/// </summary> | |||
public static void Init() | |||
{ | |||
referenceCount++; | |||
if (referenceCount > 1) { return; } | |||
if (IsInitialized) | |||
{ | |||
Logging.LogWarning("GamecraftModdingAPI.Main.Init() called but API is already initialized!"); | |||
@@ -41,6 +45,9 @@ namespace GamecraftModdingAPI | |||
var currentAssembly = Assembly.GetExecutingAssembly(); | |||
harmony = HarmonyInstance.Create(currentAssembly.GetName().Name); | |||
harmony.PatchAll(currentAssembly); | |||
// init utility | |||
Logging.MetaDebugLog($"Initializing Utility"); | |||
Utility.GameState.Init(); | |||
// create default event emitters | |||
Logging.MetaDebugLog($"Initializing Events"); | |||
EventManager.AddEventEmitter(new SimpleEventEmitterEngine(EventType.ApplicationInitialized, "GamecraftModdingAPIApplicationInitializedEventEmitter", false)); | |||
@@ -64,16 +71,20 @@ namespace GamecraftModdingAPI | |||
/// </summary> | |||
public static void Shutdown() | |||
{ | |||
if (!IsInitialized) | |||
if (referenceCount > 0) { referenceCount--; } | |||
if (referenceCount == 0) | |||
{ | |||
Logging.LogWarning("GamecraftModdingAPI.Main.Shutdown() called but API is not initialized!"); | |||
return; | |||
if (!IsInitialized) | |||
{ | |||
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"); | |||
} | |||
} | |||
} |
@@ -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 void Schedule(ISchedulable toRun, bool extraLean = false) | |||
public static void Schedule(ISchedulable toRun, bool extraLean = false, bool ui = false) | |||
{ | |||
if (extraLean) | |||
{ | |||
toRun.Run().RunOn(extraLeanRunner); | |||
if (ui) | |||
{ | |||
toRun.Run().RunOn(extraLeanRunnerUI); | |||
} | |||
else | |||
{ | |||
toRun.Run().RunOn(extraLeanRunner); | |||
} | |||
} | |||
else | |||
{ | |||
toRun.Run().RunOn(leanRunner); | |||
if (ui) | |||
{ | |||
toRun.Run().RunOn(leanRunnerUI); | |||
} | |||
else | |||
{ | |||
toRun.Run().RunOn(leanRunner); | |||
} | |||
} | |||
} | |||
@@ -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); | |||
} | |||
} | |||
} |
@@ -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); | |||
} | |||
} | |||
} |