diff --git a/Automation/gen_csproj.py b/Automation/gen_csproj.py
old mode 100755
new mode 100644
diff --git a/GamecraftModdingAPI/Block.cs b/GamecraftModdingAPI/Block.cs
index 336215e..db220dc 100644
--- a/GamecraftModdingAPI/Block.cs
+++ b/GamecraftModdingAPI/Block.cs
@@ -77,8 +77,11 @@ namespace GamecraftModdingAPI
///
public float3 Position
{
- get => MovementEngine.GetPosition(Id.entityID);
- set => MovementEngine.MoveBlock(Id.entityID, value);
+ get => Exists ? MovementEngine.GetPosition(Id.entityID) : float3.zero;
+ set
+ {
+ if (Exists) MovementEngine.MoveBlock(Id.entityID, value);
+ }
}
///
@@ -86,51 +89,41 @@ namespace GamecraftModdingAPI
///
public float3 Rotation
{
- get => RotationEngine.GetRotation(Id.entityID);
- set => RotationEngine.RotateBlock(Id.entityID, value);
- }
-
- ///
- /// The block's type (ID). Changing from or to a functional part may crash the game.
- ///
- public BlockIDs Type
- {
- get => (BlockIDs) BlockEngine.GetBlockInfo(Id).DBID;
+ get => Exists ? RotationEngine.GetRotation(Id.entityID) : float3.zero;
set
{
- BlockEngine.GetBlockInfo(Id).DBID = (uint) value;
- uint prefabId = PrefabsID.GetPrefabId((uint) value, 0);
- BlockEngine.GetBlockInfo(Id).prefabID = prefabId;
- BlockEngine.GetBlockInfo(Id) = new PhysicsPrefabEntityStruct(prefabId);
+ if (Exists) RotationEngine.RotateBlock(Id.entityID, value);
}
}
- public BlockColors Color
+ ///
+ /// The block's type (ID).
+ ///
+ public BlockIDs Type => (BlockIDs) (BlockEngine.GetBlockInfo(Id)?.DBID ?? 0);
+
+ public BlockColor Color
{
- get => (BlockColors) (BlockEngine.GetBlockInfo(Id).indexInPalette % 10);
- set
+ get
{
- ref var color = ref BlockEngine.GetBlockInfo(Id);
- color.indexInPalette = (byte) (color.indexInPalette / 10 * 10 + value);
- color.needsUpdate = true;
+ byte index = BlockEngine.GetBlockInfo(Id)?.indexInPalette ?? byte.MaxValue;
+ if (index == byte.MaxValue) return new BlockColor {Color = BlockColors.Default};
+ return new BlockColor {Color = (BlockColors) (index % 10), Darkness = (byte) (index / 10)};
}
- }
-
- public byte ColorDarkness
- {
- get => (byte) (BlockEngine.GetBlockInfo(Id).indexInPalette / 10);
set
{
- ref var color = ref BlockEngine.GetBlockInfo(Id);
- color.indexInPalette = (byte) (10 * (byte) value + color.indexInPalette % 10);
+ var def = new ColourParameterEntityStruct();
+ ref var color = ref BlockEngine.GetBlockInfo(Id, ref def);
+ color.indexInPalette = (byte) (value.Color + value.Darkness * 10);
color.needsUpdate = true;
}
}
+ public bool Exists => BlockEngine.BlockExists(Id);
+
///
/// Returns an array of blocks that are connected to this one.
///
- public Block[] GetConnectedCubes() => BlockEngine.GetConnectedBlocks(Id.entityID);
+ public Block[] GetConnectedCubes() => BlockEngine.GetConnectedBlocks(Id);
///
/// Removes this block.
diff --git a/GamecraftModdingAPI/Blocks/BlockColors.cs b/GamecraftModdingAPI/Blocks/BlockColor.cs
similarity index 50%
rename from GamecraftModdingAPI/Blocks/BlockColors.cs
rename to GamecraftModdingAPI/Blocks/BlockColor.cs
index 146bcbf..fc87eb7 100644
--- a/GamecraftModdingAPI/Blocks/BlockColors.cs
+++ b/GamecraftModdingAPI/Blocks/BlockColor.cs
@@ -1,5 +1,16 @@
-namespace GamecraftModdingAPI.Blocks
+namespace GamecraftModdingAPI.Blocks
{
+ public struct BlockColor
+ {
+ public BlockColors Color;
+ public byte Darkness;
+
+ public override string ToString()
+ {
+ return $"{nameof(Color)}: {Color}, {nameof(Darkness)}: {Darkness}";
+ }
+ }
+
///
/// Preset block colours
///
diff --git a/GamecraftModdingAPI/Blocks/BlockEngine.cs b/GamecraftModdingAPI/Blocks/BlockEngine.cs
index a851643..f678501 100644
--- a/GamecraftModdingAPI/Blocks/BlockEngine.cs
+++ b/GamecraftModdingAPI/Blocks/BlockEngine.cs
@@ -25,20 +25,50 @@ namespace GamecraftModdingAPI.Blocks
{
}
- public Block[] GetConnectedBlocks(uint blockID)
+ public Block[] GetConnectedBlocks(EGID blockID)
{
+ if (!BlockExists(blockID)) return new Block[0];
Stack cubeStack = new Stack();
FasterList cubesToProcess = new FasterList();
- ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID, cubeStack, cubesToProcess, (in GridConnectionsEntityStruct g) => { return false; });
+ ConnectedCubesUtility.TreeTraversal.GetConnectedCubes(entitiesDB, blockID.entityID, cubeStack, cubesToProcess, (in GridConnectionsEntityStruct g) => { return false; });
var ret = new Block[cubesToProcess.count];
for (int i = 0; i < cubesToProcess.count; i++)
ret[i] = new Block(cubesToProcess[i]);
return ret;
}
- public ref T GetBlockInfo(EGID blockID) where T : struct, IEntityComponent
+ ///
+ /// Get a struct of a block. Can be used to set properties.
+ /// When only querying parameters, use the other overload for convenience.
+ ///
+ ///
+ ///
+ ///
+ ///
+ public ref T GetBlockInfo(EGID blockID, ref T def) where T : struct, IEntityComponent
{
- return ref entitiesDB.QueryEntity(blockID);
+ if (entitiesDB.Exists(blockID))
+ return ref entitiesDB.QueryEntity(blockID);
+ return ref def;
+ }
+
+ ///
+ /// Get a struct of a block. Can only be used to retrieve information.
+ /// Use the overload with a default parameter to get the struct by reference to set values.
+ ///
+ /// The block's EGID
+ /// The struct's type to get
+ /// A copy of the struct or null
+ public T? GetBlockInfo(EGID blockID) where T : struct, IEntityComponent
+ {
+ if (entitiesDB.Exists(blockID))
+ return entitiesDB.QueryEntity(blockID);
+ return null;
+ }
+
+ public bool BlockExists(EGID id)
+ {
+ return entitiesDB.Exists(id);
}
}
}
\ No newline at end of file
diff --git a/GamecraftModdingAPI/Blocks/BlockIDs.cs b/GamecraftModdingAPI/Blocks/BlockIDs.cs
index 1a7a77a..bba2583 100644
--- a/GamecraftModdingAPI/Blocks/BlockIDs.cs
+++ b/GamecraftModdingAPI/Blocks/BlockIDs.cs
@@ -220,6 +220,11 @@ namespace GamecraftModdingAPI.Blocks
CentreHUD,
ObjectiveHUD,
GameStatsHUD, //231
+ GameOverBlock,
+ MovementConstrainer = 246,
+ RotationConstrainer,
+ AdvancedMovementDampener,
+ AdvancedRotationDampener,
Mover = 250,
Rotator,
MovementDampener,
diff --git a/GamecraftModdingAPI/Main.cs b/GamecraftModdingAPI/Main.cs
index e8ab256..3b15de8 100644
--- a/GamecraftModdingAPI/Main.cs
+++ b/GamecraftModdingAPI/Main.cs
@@ -72,6 +72,7 @@ namespace GamecraftModdingAPI
// init object-oriented classes
Player.Init();
Block.Init();
+ DebugInterface.Init();
Logging.MetaLog($"{currentAssembly.GetName().Name} v{currentAssembly.GetName().Version} initialized");
}
diff --git a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
index 307b3f6..2e97df7 100644
--- a/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
+++ b/GamecraftModdingAPI/Tests/GamecraftModdingAPIPluginTest.cs
@@ -13,6 +13,7 @@ using GamecraftModdingAPI.Commands;
using GamecraftModdingAPI.Events;
using GamecraftModdingAPI.Utility;
using GamecraftModdingAPI.Blocks;
+using RobocraftX.FrontEnd;
namespace GamecraftModdingAPI.Tests
{
@@ -174,9 +175,6 @@ namespace GamecraftModdingAPI.Tests
CommandBuilder.Builder("getBlock")
.Action(() => uREPL.Log.Output(new Player(Players.PlayerType.Local).GetBlockLookedAt()+"")).Build();
- CommandBuilder.Builder("changeToAluminium")
- .Action(() => new Player(Players.PlayerType.Local).GetBlockLookedAt().Type = BlockIDs.AluminiumCube)
- .Build();
CommandBuilder.Builder("Error", "Throw an error to make sure SimpleCustomCommandEngine's wrapper catches it.")
.Action(() => { throw new Exception("Error Command always throws an error"); })
@@ -246,5 +244,20 @@ namespace GamecraftModdingAPI.Tests
public void OnLevelWasLoaded(int level) { }
public void OnUpdate() { }
+
+ [HarmonyPatch]
+ public class MinimumSpecsPatch
+ {
+ public static bool Prefix(ref bool __result)
+ {
+ __result = true;
+ return false;
+ }
+
+ public static MethodInfo TargetMethod()
+ {
+ return ((Func)MinimumSpecsCheck.CheckRequirementsMet).Method;
+ }
+ }
}
}
diff --git a/GamecraftModdingAPI/Utility/DebugInterface.cs b/GamecraftModdingAPI/Utility/DebugInterface.cs
new file mode 100644
index 0000000..1d5499e
--- /dev/null
+++ b/GamecraftModdingAPI/Utility/DebugInterface.cs
@@ -0,0 +1,30 @@
+using System;
+using GamecraftModdingAPI.Blocks;
+
+namespace GamecraftModdingAPI.Utility
+{
+ public static class DebugInterface
+ {
+ private static DebugInterfaceEngine _engine = new DebugInterfaceEngine();
+
+ ///
+ /// Saves the extra information to be displayed on the debug view.
+ /// The provided getter function is called each time the view updates so make sure it returns quickly.
+ ///
+ /// A global ID for the custom information
+ /// A function that returns the current information
+ public static void SetInfo(string id, Func contentGetter) => _engine.SetInfo(id, contentGetter);
+
+ ///
+ /// Removes an information provided by a plugin.
+ ///
+ /// The ID of the custom information
+ ///
+ public static bool RemoveInfo(string id) => _engine.RemoveInfo(id);
+
+ public static void Init()
+ {
+ GameEngineManager.AddGameEngine(_engine);
+ }
+ }
+}
\ No newline at end of file
diff --git a/GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs b/GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs
new file mode 100644
index 0000000..2d470bb
--- /dev/null
+++ b/GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs
@@ -0,0 +1,84 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Reflection;
+using System.Reflection.Emit;
+using System.Text.Formatting;
+using GamecraftModdingAPI.Blocks;
+using GamecraftModdingAPI.Engines;
+using GamecraftModdingAPI.Players;
+using HarmonyLib;
+using RobocraftX.GUI.Debug;
+using Svelto.ECS;
+using Svelto.ECS.Experimental;
+
+namespace GamecraftModdingAPI.Utility
+{
+ public class DebugInterfaceEngine : IApiEngine
+ {
+ private static Dictionary> _extraInfo=new Dictionary>();
+ public void Ready()
+ {
+ SetInfo("lookedAt", LookedAt);
+ }
+
+ public EntitiesDB entitiesDB { get; set; }
+
+ public void Dispose()
+ {
+ }
+
+ public void SetInfo(string id, Func contentGetter) => _extraInfo[id] = contentGetter;
+ public bool RemoveInfo(string id) => _extraInfo.Remove(id);
+
+ private Player player;
+ private string LookedAt()
+ {
+ if (player == null)
+ player = new Player(PlayerType.Local);
+ Block block = player.GetBlockLookedAt();
+ if (block == null) return "Block: none";
+ return "Block: " + block.Type + "\nColor: " + block.Color + "\n" + "At: " + block.Position;
+ }
+
+ public string Name { get; } = "GamecraftModdingAPIDebugInterfaceGameEngine";
+ public bool isRemovable { get; } = true;
+
+ [HarmonyPatch]
+ private class Patch
+ {
+ public static IEnumerable Transpiler(IEnumerable instructions)
+ {
+ var list = new List(instructions);
+ try
+ {
+ //Before setting the text from the StringBuffer
+ int index = list.FindLastIndex(inst => inst.opcode == OpCodes.Ldfld);
+ var array = new CodeInstruction[]
+ {
+ new CodeInstruction(OpCodes.Ldloc_0), //StringBuffer
+ new CodeInstruction(OpCodes.Call, ((Action)AddInfo).Method)
+ };
+ list.InsertRange(index, array);
+ }
+ catch (Exception e)
+ {
+ Console.WriteLine(e);
+ }
+
+ return list;
+ }
+
+ public static void AddInfo(StringBuffer sb)
+ {
+ foreach (var info in _extraInfo.Values)
+ sb.Append(info() + "\n");
+ }
+
+ public static MethodInfo TargetMethod()
+ {
+ return AccessTools.Method("RobocraftX.GUI.Debug.DebugDisplayEngine:UpdateDisplay");
+ }
+ }
+ }
+}
\ No newline at end of file