Add debug interface API and improve block API
Added API for adding more information on the debug display (not object-oriented yet) Removed the setter for block type to ensure stability Made the block API return defaults if the block no longer exists Added property to check if the block exists Made a struct for the block's color property Added missing block IDs
This commit is contained in:
parent
ebea9da232
commit
1c5ce37fce
9 changed files with 206 additions and 39 deletions
0
Automation/gen_csproj.py
Executable file → Normal file
0
Automation/gen_csproj.py
Executable file → Normal file
|
@ -77,8 +77,11 @@ namespace GamecraftModdingAPI
|
|||
/// </summary>
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -86,51 +89,41 @@ namespace GamecraftModdingAPI
|
|||
/// </summary>
|
||||
public float3 Rotation
|
||||
{
|
||||
get => RotationEngine.GetRotation(Id.entityID);
|
||||
set => RotationEngine.RotateBlock(Id.entityID, value);
|
||||
get => Exists ? RotationEngine.GetRotation(Id.entityID) : float3.zero;
|
||||
set
|
||||
{
|
||||
if (Exists) RotationEngine.RotateBlock(Id.entityID, value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The block's type (ID). Changing from or to a functional part may crash the game.
|
||||
/// The block's type (ID).
|
||||
/// </summary>
|
||||
public BlockIDs Type
|
||||
{
|
||||
get => (BlockIDs) BlockEngine.GetBlockInfo<DBEntityStruct>(Id).DBID;
|
||||
set
|
||||
{
|
||||
BlockEngine.GetBlockInfo<DBEntityStruct>(Id).DBID = (uint) value;
|
||||
uint prefabId = PrefabsID.GetPrefabId((uint) value, 0);
|
||||
BlockEngine.GetBlockInfo<GFXPrefabEntityStructGPUI>(Id).prefabID = prefabId;
|
||||
BlockEngine.GetBlockInfo<PhysicsPrefabEntityStruct>(Id) = new PhysicsPrefabEntityStruct(prefabId);
|
||||
}
|
||||
}
|
||||
public BlockIDs Type => (BlockIDs) (BlockEngine.GetBlockInfo<DBEntityStruct>(Id)?.DBID ?? 0);
|
||||
|
||||
public BlockColors Color
|
||||
public BlockColor Color
|
||||
{
|
||||
get => (BlockColors) (BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id).indexInPalette % 10);
|
||||
get
|
||||
{
|
||||
byte index = BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(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)};
|
||||
}
|
||||
set
|
||||
{
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id);
|
||||
color.indexInPalette = (byte) (color.indexInPalette / 10 * 10 + value);
|
||||
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 byte ColorDarkness
|
||||
{
|
||||
get => (byte) (BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id).indexInPalette / 10);
|
||||
set
|
||||
{
|
||||
ref var color = ref BlockEngine.GetBlockInfo<ColourParameterEntityStruct>(Id);
|
||||
color.indexInPalette = (byte) (10 * (byte) value + color.indexInPalette % 10);
|
||||
color.needsUpdate = true;
|
||||
}
|
||||
}
|
||||
public bool Exists => BlockEngine.BlockExists(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Returns an array of blocks that are connected to this one.
|
||||
/// </summary>
|
||||
public Block[] GetConnectedCubes() => BlockEngine.GetConnectedBlocks(Id.entityID);
|
||||
public Block[] GetConnectedCubes() => BlockEngine.GetConnectedBlocks(Id);
|
||||
|
||||
/// <summary>
|
||||
/// Removes this block.
|
||||
|
|
|
@ -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}";
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Preset block colours
|
||||
/// </summary>
|
|
@ -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<uint> cubeStack = new Stack<uint>();
|
||||
FasterList<uint> cubesToProcess = new FasterList<uint>();
|
||||
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<T>(EGID blockID) where T : struct, IEntityComponent
|
||||
/// <summary>
|
||||
/// Get a struct of a block. Can be used to set properties.
|
||||
/// When only querying parameters, use the other overload for convenience.
|
||||
/// </summary>
|
||||
/// <param name="blockID"></param>
|
||||
/// <param name="def"></param>
|
||||
/// <typeparam name="T"></typeparam>
|
||||
/// <returns></returns>
|
||||
public ref T GetBlockInfo<T>(EGID blockID, ref T def) where T : struct, IEntityComponent
|
||||
{
|
||||
if (entitiesDB.Exists<T>(blockID))
|
||||
return ref entitiesDB.QueryEntity<T>(blockID);
|
||||
return ref def;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="blockID">The block's EGID</param>
|
||||
/// <typeparam name="T">The struct's type to get</typeparam>
|
||||
/// <returns>A copy of the struct or null</returns>
|
||||
public T? GetBlockInfo<T>(EGID blockID) where T : struct, IEntityComponent
|
||||
{
|
||||
if (entitiesDB.Exists<T>(blockID))
|
||||
return entitiesDB.QueryEntity<T>(blockID);
|
||||
return null;
|
||||
}
|
||||
|
||||
public bool BlockExists(EGID id)
|
||||
{
|
||||
return entitiesDB.Exists<DBEntityStruct>(id);
|
||||
}
|
||||
}
|
||||
}
|
|
@ -220,6 +220,11 @@ namespace GamecraftModdingAPI.Blocks
|
|||
CentreHUD,
|
||||
ObjectiveHUD,
|
||||
GameStatsHUD, //231
|
||||
GameOverBlock,
|
||||
MovementConstrainer = 246,
|
||||
RotationConstrainer,
|
||||
AdvancedMovementDampener,
|
||||
AdvancedRotationDampener,
|
||||
Mover = 250,
|
||||
Rotator,
|
||||
MovementDampener,
|
||||
|
|
|
@ -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");
|
||||
}
|
||||
|
||||
|
|
|
@ -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<bool>)MinimumSpecsCheck.CheckRequirementsMet).Method;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
30
GamecraftModdingAPI/Utility/DebugInterface.cs
Normal file
30
GamecraftModdingAPI/Utility/DebugInterface.cs
Normal file
|
@ -0,0 +1,30 @@
|
|||
using System;
|
||||
using GamecraftModdingAPI.Blocks;
|
||||
|
||||
namespace GamecraftModdingAPI.Utility
|
||||
{
|
||||
public static class DebugInterface
|
||||
{
|
||||
private static DebugInterfaceEngine _engine = new DebugInterfaceEngine();
|
||||
|
||||
/// <summary>
|
||||
/// 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.
|
||||
/// </summary>
|
||||
/// <param name="id">A global ID for the custom information</param>
|
||||
/// <param name="contentGetter">A function that returns the current information</param>
|
||||
public static void SetInfo(string id, Func<string> contentGetter) => _engine.SetInfo(id, contentGetter);
|
||||
|
||||
/// <summary>
|
||||
/// Removes an information provided by a plugin.
|
||||
/// </summary>
|
||||
/// <param name="id">The ID of the custom information</param>
|
||||
/// <returns></returns>
|
||||
public static bool RemoveInfo(string id) => _engine.RemoveInfo(id);
|
||||
|
||||
public static void Init()
|
||||
{
|
||||
GameEngineManager.AddGameEngine(_engine);
|
||||
}
|
||||
}
|
||||
}
|
84
GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs
Normal file
84
GamecraftModdingAPI/Utility/DebugInterfaceEngine.cs
Normal file
|
@ -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<string, Func<string>> _extraInfo=new Dictionary<string, Func<string>>();
|
||||
public void Ready()
|
||||
{
|
||||
SetInfo("lookedAt", LookedAt);
|
||||
}
|
||||
|
||||
public EntitiesDB entitiesDB { get; set; }
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
}
|
||||
|
||||
public void SetInfo(string id, Func<string> 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<CodeInstruction> Transpiler(IEnumerable<CodeInstruction> instructions)
|
||||
{
|
||||
var list = new List<CodeInstruction>(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<StringBuffer>)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");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue