@@ -14,25 +14,31 @@ using Svelto.Tasks.ExtraLean; | |||
using RobocraftX; | |||
using RobocraftX.Schedulers; | |||
using GamecraftModdingAPI.Commands; | |||
using GamecraftModdingAPI.Tasks; | |||
using GamecraftModdingAPI.Utility; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("Chain")] | |||
class ChainCommandEngine : CustomCommandEngine | |||
//[CustomCommand("Chain")] | |||
class ChainCommandEngine : ICustomCommandEngine | |||
{ | |||
public ChainCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Run two commands one after the other"; | |||
public string Name => "Chain"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<string, string>("Chain", ChainCommand, "Run two commands, one after the other"); | |||
CommandRegistrationHelper.Register<string, string>(Name, ChainCommand, Description); | |||
} | |||
private void ChainCommand(string command1, string command2) | |||
{ | |||
string command1a = decomma(command1); | |||
string command2a = decomma(command2); | |||
ScheduleCommands(command1a, command2a).RunOn(ExtraLean.CharacterUpdateScheduler); | |||
ScheduleCommands(command1a, command2a).RunOn(Scheduler.extraLeanRunner); | |||
} | |||
private IEnumerator<TaskContract> ScheduleCommands(string c1, string c2) | |||
@@ -41,12 +47,12 @@ namespace ExtraCommands.Basics | |||
bool success1 = uREPL.Evaluator.Evaluate(c1).type == CompileResult.Type.Success; | |||
if (!success1) | |||
{ | |||
uREPL.Log.Error("First command was not executed successfully"); | |||
Logging.CommandLogError("First command was not executed successfully"); | |||
} | |||
bool success2 = uREPL.Evaluator.Evaluate(c2).type == CompileResult.Type.Success; | |||
if (!success2) | |||
{ | |||
uREPL.Log.Error("Second command was not executed successfully"); | |||
Logging.CommandLogError("Second command was not executed successfully"); | |||
} | |||
} | |||
@@ -55,9 +61,9 @@ namespace ExtraCommands.Basics | |||
return strIn.Replace(", ", " "); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("Chain"); | |||
CommandRegistrationHelper.Unregister("Chain"); | |||
} | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
using System; | |||
using System.Reflection; | |||
using Harmony; | |||
using UnityEngine; | |||
using Unity.Entities; | |||
using RobocraftX; | |||
using RobocraftX.GUI.CommandLine; | |||
using RobocraftX.Multiplayer; | |||
using Svelto.ECS; | |||
using Svelto.Context; | |||
namespace ExtraCommands | |||
{ | |||
[HarmonyPatch] | |||
class CommandLineCompositionRootSaveCommandPatch | |||
{ | |||
static void Postfix(UnityContext<FullGameCompositionRoot> contextHolder, EnginesRoot enginesRoot, World physicsWorld, Action reloadGame, MultiplayerInitParameters multiplayerParameters) | |||
{ | |||
int engineCount = 0; | |||
MethodInfo commandHelp = Harmony.AccessTools.Method(Harmony.AccessTools.TypeByName("RobocraftX.GUI.CommandLine.CommandLineUtility"), "SaveCommandHelp", new Type[] { typeof(string), typeof(string) }); | |||
foreach (Type t in typeof(CustomCommandEngine).Assembly.GetTypes()) | |||
{ | |||
CustomCommandAttribute[] attributes = (CustomCommandAttribute[])t.GetCustomAttributes(typeof(CustomCommandAttribute), false); | |||
CustomCommandEngine inst = null; | |||
foreach (CustomCommandAttribute attr in attributes) | |||
{ | |||
if (attr != null && t.IsSubclassOf(typeof(CustomCommandEngine))) | |||
{ | |||
if (inst == null) | |||
{ | |||
// create instance by getting the constructor through reflection | |||
inst = (CustomCommandEngine)t.GetConstructor(new Type[] { typeof(UnityContext<FullGameCompositionRoot>), typeof(EnginesRoot), typeof(World), typeof(Action), typeof(MultiplayerInitParameters) }) | |||
.Invoke(new object[] { contextHolder, enginesRoot, physicsWorld, reloadGame, multiplayerParameters }); | |||
// add to engineRoot | |||
enginesRoot.AddEngine(inst); | |||
engineCount++; | |||
} | |||
} | |||
} | |||
} | |||
Debug.Log($"Added {engineCount} custom command engines"); | |||
} | |||
static MethodBase TargetMethod(HarmonyInstance instance) | |||
{ | |||
return _ComposeMethodInfo(CommandLineCompositionRoot.Compose<UnityContext<FullGameCompositionRoot>>); | |||
} | |||
private static MethodInfo _ComposeMethodInfo(Action<UnityContext<FullGameCompositionRoot>, EnginesRoot, World, Action, MultiplayerInitParameters> a) | |||
{ | |||
return a.Method; | |||
} | |||
} | |||
} |
@@ -1,18 +1,35 @@ | |||
using System; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands | |||
{ | |||
[AttributeUsage(AttributeTargets.Class, AllowMultiple = true)] | |||
public class CustomCommandAttribute: Attribute | |||
{ | |||
public string Name { get; protected set; } | |||
public readonly string Name; | |||
public readonly string Description; | |||
public string Description { get; protected set; } | |||
public readonly bool IsFactory; | |||
public CustomCommandAttribute(string name = "", string description = "") | |||
public CustomCommandAttribute(string name = "", string description = "", bool factory = false) | |||
{ | |||
this.Name = name; | |||
this.Description = description; | |||
this.IsFactory = factory; | |||
} | |||
public static bool IsCompatible(Type t) | |||
{ | |||
foreach (var i in t.GetInterfaces()) | |||
{ | |||
if (i == typeof(ICustomCommandEngine)) | |||
{ | |||
return true; | |||
} | |||
} | |||
return false; | |||
} | |||
} | |||
} |
@@ -1,39 +0,0 @@ | |||
using RobocraftX.GUI.CommandLine; | |||
using RobocraftX.Multiplayer; | |||
using Svelto.Context; | |||
using Svelto.ECS; | |||
using System; | |||
using Unity.Entities; | |||
using RobocraftX; | |||
namespace ExtraCommands | |||
{ | |||
class CustomCommandEngine : IQueryingEntitiesEngine, IEngine, IDisposable | |||
{ | |||
protected UnityContext<FullGameCompositionRoot> context; | |||
protected EnginesRoot enginesRoot; | |||
protected World physWorld; | |||
protected Action reloadGame; | |||
protected MultiplayerInitParameters multiplayerInitParameters; | |||
public CustomCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) | |||
{ | |||
this.context = ctxHolder; | |||
this.enginesRoot = enginesRoot; | |||
this.physWorld = physW; | |||
this.reloadGame = reloadGame; | |||
this.multiplayerInitParameters = mpParams; | |||
} | |||
public IEntitiesDB entitiesDB { set; get; } | |||
virtual public void Dispose() { } | |||
// NOTE: Ready() should call CustomCommandUtility.Register to add the command to the command line | |||
virtual public void Ready() { } | |||
} | |||
} |
@@ -1,54 +0,0 @@ | |||
using System; | |||
using System.Collections.Generic; | |||
using System.Linq; | |||
using System.Text; | |||
using System.Threading.Tasks; | |||
using uREPL; | |||
using RobocraftX.CommandLine.Custom; | |||
namespace ExtraCommands | |||
{ | |||
static class CustomCommandUtility | |||
{ | |||
public static void Register(string name, Action action, string desc) | |||
{ | |||
RuntimeCommands.Register(name, action, desc); | |||
ConsoleCommands.Register(name, action, desc); | |||
} | |||
public static void Register(string name, Action<object> action, string desc) | |||
{ | |||
RuntimeCommands.Register<object>(name, action, desc); | |||
} | |||
public static void Register<Param0>(string name, Action<Param0> action, string desc) | |||
{ | |||
RuntimeCommands.Register<Param0>(name, action, desc); | |||
ConsoleCommands.Register<Param0>(name, action, desc); | |||
} | |||
public static void Register<Param0, Param1>(string name, Action<Param0, Param1> action, string desc) | |||
{ | |||
RuntimeCommands.Register<Param0, Param1>(name, action, desc); | |||
ConsoleCommands.Register<Param0, Param1>(name, action, desc); | |||
} | |||
public static void Register(string name, Action<object, object, object> action, string desc) | |||
{ | |||
RuntimeCommands.Register<object, object, object>(name, action, desc); | |||
ConsoleCommands.Register<object, object, object>(name, action, desc); | |||
} | |||
public static void Register<Param0, Param1, Param2>(string name, Action<Param0, Param1, Param2> action, string desc) | |||
{ | |||
RuntimeCommands.Register<Param0, Param1, Param2>(name, action, desc); | |||
ConsoleCommands.Register<Param0, Param1, Param2>(name, action, desc); | |||
} | |||
public static void Unregister(string name) | |||
{ | |||
RuntimeCommands.Unregister(name); | |||
ConsoleCommands.Unregister(name); | |||
} | |||
} | |||
} |
@@ -10,6 +10,8 @@ using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
using GamecraftModdingAPI.Commands; | |||
// checklist of things to rename to make this command your own: | |||
// [ ] namespace ExtraCommands.Example -> namespace ExtraCommands.[your command's namespace] | |||
// [ ] class ExampleCommandEngine : CustomCommandEngine -> class [your command name]CommandEngine : CustomCommandEngine | |||
@@ -25,24 +27,26 @@ namespace ExtraCommands.Example | |||
{ | |||
// !!! Uncomment the line below this !!! | |||
// [CustomCommand("Example")] | |||
class ExampleCommandEngine : CustomCommandEngine | |||
class ExampleCommandEngine : ICustomCommandEngine | |||
{ | |||
// This class is a custom implementation of CustomCommandEngine specific to this command | |||
// You can use Svelto.ECS.IEntityDB entitiesDB to query game entities or one of the protected variables for other things | |||
// More documentation on Svelto.ECS: https://github.com/sebas77/Svelto.ECS | |||
// Unfortunately the documentation is severely lacking and out of date; you may have better luck decompiling Svelto.ECS.dll | |||
// See CustomCommandEngine.cs for more information on the super class | |||
public string Description => "This is an example command which does nothing!"; | |||
public ExampleCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Name => "Example"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
// This class is a custom implementation of CustomCommandEngine specific to this command | |||
// You can use Svelto.ECS.IEntityDB entitiesDB to query game entities or one of the protected variables for other things | |||
// More documentation on Svelto.ECS: https://github.com/sebas77/Svelto.ECS | |||
// Unfortunately the documentation is severely lacking and out of date; you may have better luck decompiling Svelto.ECS.dll | |||
// See CustomCommandEngine.cs for more information on the super class | |||
// Ready() is called when the command is registered in-game (this happens whenever you load a game) | |||
public override void Ready() | |||
// Ready() is called when the command is registered in-game (this happens whenever you load a game) | |||
public void Ready() | |||
{ | |||
// CustomCommandUtility.Register has multiple overloads depending on how many parameters you want to pass to your command | |||
// See CustomCommandUtility.cs for more information | |||
CustomCommandUtility.Register("Example", ExampleCommand, "This is an example command which does nothing!"); | |||
CommandRegistrationHelper.Register(Name, ExampleCommand, Description); | |||
} | |||
// ExampleCommand() is called whenever the command is executed. This can accept up to three parameters | |||
@@ -53,11 +57,11 @@ namespace ExtraCommands.Example | |||
} | |||
// Dispose() is called when the command is unregistered in-game (this happens whenever you leave a game) | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
// You must unregister the command so it doesn't waste memory and so | |||
// it can be re-registered next time | |||
CustomCommandUtility.Unregister("Example"); | |||
CommandRegistrationHelper.Unregister(Name); | |||
} | |||
} | |||
} |
@@ -10,18 +10,22 @@ using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("Exit")] | |||
class ExitCommandEngine : CustomCommandEngine | |||
class ExitCommandEngine : ICustomCommandEngine | |||
{ | |||
public ExitCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Close Gamecraft without any prompts"; | |||
public string Name => "Exit"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register("Exit", ExitCommand, "Forcefully close Gamecraft"); | |||
CommandRegistrationHelper.Register(Name, ExitCommand, Description); | |||
} | |||
private void ExitCommand() | |||
@@ -29,9 +33,9 @@ namespace ExtraCommands.Basics | |||
Application.Quit(); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("Exit"); | |||
CommandRegistrationHelper.Unregister(Name); | |||
} | |||
} | |||
} |
@@ -1,38 +1,53 @@ | |||
using System; | |||
using IllusionPlugin; | |||
using UnityEngine; | |||
using Harmony; | |||
//using UnityEngine; | |||
using System.Reflection; | |||
using GamecraftModdingAPI.Commands; | |||
using GamecraftModdingAPI.Utility; | |||
namespace ExtraCommands | |||
{ | |||
public class Plugin : IllusionPlugin.IEnhancedPlugin | |||
{ | |||
public static HarmonyInstance harmony { get; protected set; } | |||
public string[] Filter { get; } = new string[] { "RobocraftX", "Gamecraft", "GamecraftPreview" }; | |||
public string Name { get; } = "ExtraCommands"; | |||
public string Version { get; } = "v0.0.3"; | |||
public string Version { get; } = Assembly.GetExecutingAssembly().GetName().Version.ToString(); | |||
public string HarmonyID { get; } = "org.git.exmods.extracommands.extracommands"; | |||
public void OnApplicationQuit() | |||
{ | |||
harmony.UnpatchAll(HarmonyID); | |||
Debug.Log("ExtraCommands shutdown & unpatch complete"); | |||
GamecraftModdingAPI.Main.Shutdown(); | |||
} | |||
public void OnApplicationStart() | |||
{ | |||
if (harmony == null) | |||
{ | |||
harmony = HarmonyInstance.Create(HarmonyID); | |||
harmony.PatchAll(Assembly.GetExecutingAssembly()); | |||
} | |||
Debug.Log("ExtraCommands start & patch complete"); | |||
} | |||
public void OnApplicationStart() | |||
{ | |||
GamecraftModdingAPI.Main.Init(); | |||
object[] empty = new object[] { }; | |||
int engineCount = 0; | |||
foreach (Type t in Assembly.GetExecutingAssembly().GetTypes()) | |||
{ | |||
CustomCommandAttribute[] attributes = (CustomCommandAttribute[])t.GetCustomAttributes(typeof(CustomCommandAttribute), false); | |||
ICustomCommandEngine inst = null; | |||
foreach (CustomCommandAttribute attr in attributes) | |||
{ | |||
if (attr != null && CustomCommandAttribute.IsCompatible(t)) | |||
{ | |||
if (inst == null) | |||
{ | |||
// create instance by getting the constructor through reflection | |||
inst = (ICustomCommandEngine)t.GetConstructor(new Type[] { }).Invoke(empty); | |||
CommandManager.AddCommand(inst); | |||
engineCount++; | |||
} | |||
} | |||
} | |||
} | |||
Logging.MetaLog($"Added {engineCount} custom command engines"); | |||
} | |||
public void OnFixedUpdate() | |||
{ | |||
@@ -14,124 +14,37 @@ using RobocraftX.UECS; | |||
using Unity.Transforms; | |||
using Unity.Mathematics; | |||
using GamecraftModdingAPI.Blocks; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Building | |||
{ | |||
[CustomCommand("MoveBlocks", "Move all blocks (including ground) from their original position")] | |||
//[CustomCommand("MoveBlocks", "Move all blocks (including ground) from their original position")] | |||
[CustomCommand("MoveLastBlock", "Move last block from original position")] | |||
class MoveBlocksCommandEngine : CustomCommandEngine | |||
class MoveBlocksCommandEngine : ICustomCommandEngine | |||
{ | |||
public MoveBlocksCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public override void Ready() | |||
{ | |||
CustomCommandUtility.Register<float, float, float>("MoveBlocks", MoveBlocksCommand, "Move all blocks (including ground) from their original position"); | |||
CustomCommandUtility.Register<float, float, float>("MoveLastBlock", MoveLastBlockCommand, "Move last block from original position"); | |||
} | |||
// Move every block by vector (x,y,z) | |||
private void MoveBlocksCommand(float x, float y, float z) | |||
{ | |||
ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
if (simMode.simulationMode != SimulationMode.Build) | |||
{ | |||
uREPL.Log.Error("Blocks can only be moved in Build Mode"); | |||
return; | |||
} | |||
uint count = this.entitiesDB.Count<PositionEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
float3 translationVector = new float3(x,y,z); | |||
for (uint i = 0; i < count; i++) | |||
{ | |||
TranslateSingleBlock(i, translationVector); | |||
} | |||
uREPL.Log.Output($"Moved {count} blocks"); | |||
} | |||
public string Description => "Move blocks"; | |||
// Move block with highest index by vector (x,y,z) | |||
private void MoveLastBlockCommand(float x, float y, float z) | |||
{ | |||
uint count = entitiesDB.Count<PositionEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
if (simMode.simulationMode != SimulationMode.Build) | |||
{ | |||
uREPL.Log.Error("Blocks can only be moved in Build Mode"); | |||
return; | |||
} | |||
float3 newPos = TranslateConnectedBlocks(count-1, new float3(x,y,z)); | |||
uREPL.Log.Output($"Moved block to ({newPos.x},{newPos.y},{newPos.z})"); | |||
} | |||
public string Name => "MoveBlocks"; | |||
// Move the block denoted by blockID by translationVector (old_position += translationVector) | |||
private float3 TranslateSingleBlock(uint blockID, float3 translationVector) | |||
{ | |||
ref PositionEntityStruct posStruct = ref this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
// main (persistent) position | |||
posStruct.position.x += translationVector.x; | |||
posStruct.position.y += translationVector.y; | |||
posStruct.position.z += translationVector.z; | |||
// placement grid position | |||
gridStruct.position.x += translationVector.x; | |||
gridStruct.position.y += translationVector.y; | |||
gridStruct.position.z += translationVector.z; | |||
// rendered position | |||
transStruct.position.x += translationVector.x; | |||
transStruct.position.y += translationVector.y; | |||
transStruct.position.z += translationVector.z; | |||
// collision position | |||
this.physWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Translation | |||
{ | |||
Value = posStruct.position | |||
}); | |||
return posStruct.position; | |||
} | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
private float3 TranslateConnectedBlocks(uint blockID, float3 translationVector) | |||
{ | |||
//float3 newPosition = TranslateSingleBlock(blockID, translationVector); | |||
HashSet<uint> processedCubes = new HashSet<uint>(); | |||
Stack<uint> cubeStack = new Stack<uint>(); | |||
cubeStack.Push(blockID); | |||
uint count; | |||
GridConnectionsEntityStruct blockConnections; | |||
MachineGraphConnectionEntityStruct[] connections; | |||
while (cubeStack.Count > 0) // find all inter-connected blocks | |||
{ | |||
uint connectedBlockID = cubeStack.Pop(); | |||
processedCubes.Add(connectedBlockID); | |||
ScalingEntityStruct scale = entitiesDB.QueryEntity<ScalingEntityStruct>(connectedBlockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
//uREPL.Log.Output($"Catching {connectedBlockID} with scale {scale.scale}"); | |||
blockConnections = entitiesDB.QueryEntity<GridConnectionsEntityStruct>(connectedBlockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
connections = entitiesDB.QueryEntities<MachineGraphConnectionEntityStruct>(blockConnections.connectionGroup, out count); | |||
public void Ready() | |||
{ | |||
//CustomCommandUtility.Register<float, float, float>("MoveBlocks", MoveBlocksCommand, "Move all blocks (including ground) from their original position"); | |||
CommandRegistrationHelper.Register<float, float, float>("MoveLastBlock", MoveLastBlockCommand, "Move last block from original position"); | |||
} | |||
foreach (MachineGraphConnectionEntityStruct conn in connections) | |||
{ | |||
if (!processedCubes.Contains(conn.connectedBlock.entityID) | |||
&& blockConnections.isConnectionGroupAssigned | |||
&& (conn.oppositeConnectionEgid.entityID != 0u | |||
|| conn.oppositeConnectionEgid.entityID != conn.connectedBlock.entityID)) | |||
{ | |||
//uREPL.Log.Output($"Block {connectedBlockID} connects to {conn.connectedBlock.entityID} (opposite {conn.oppositeConnectionEgid.entityID})"); | |||
cubeStack.Push(conn.connectedBlock.entityID); | |||
} | |||
} | |||
} | |||
foreach (uint id in processedCubes) | |||
{ | |||
TranslateSingleBlock(id, translationVector); | |||
} | |||
//uREPL.Log.Output($"Found {processedCubes.Count} connected blocks"); | |||
return this.entitiesDB.QueryEntity<PositionEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP).position; | |||
} | |||
private void MoveLastBlockCommand(float x, float y, float z) | |||
{ | |||
float3 vector = new float3(x, y, z); | |||
Movement.MoveConnectedBlocks(BlockIdentifiers.LatestBlockID, vector); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("MoveBlocks"); | |||
CustomCommandUtility.Unregister("MoveLastBlock"); | |||
//CommandRegistrationHelper.Unregister("MoveBlocks"); | |||
CommandRegistrationHelper.Unregister("MoveLastBlock"); | |||
} | |||
} | |||
} |
@@ -14,137 +14,37 @@ using Unity.Transforms; | |||
using Unity.Mathematics; | |||
using UnityEngine; | |||
using GamecraftModdingAPI.Commands; | |||
using GamecraftModdingAPI.Blocks; | |||
namespace ExtraCommands.Building | |||
{ | |||
//[CustomCommand("RotateBlocks", "Rotate all blocks (including ground) from their original position")] | |||
[CustomCommand("RotateLastBlock", "Rotate last block from original position")] | |||
class RotateBlocksCommandEngine : CustomCommandEngine | |||
class RotateBlocksCommandEngine : ICustomCommandEngine | |||
{ | |||
public RotateBlocksCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Rotate last block from original position"; | |||
public override void Ready() | |||
{ | |||
//CustomCommandUtility.Register<float, float, float>("RotateBlocks", RotateBlocksCommand, "Rotate all blocks (including ground) from their original position"); | |||
CustomCommandUtility.Register<float, float, float>("RotateLastBlock", RotateLastBlockCommand, "Rotate last block from original position"); | |||
} | |||
public string Name => "RotateLastBlock"; | |||
// Move every block by vector (x,y,z) | |||
private void RotateBlocksCommand(float x, float y, float z) | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public void Ready() | |||
{ | |||
Vector3 eulerAngles = new Vector3(x, y, z); | |||
ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
if (simMode.simulationMode != SimulationMode.Build) | |||
{ | |||
uREPL.Log.Error("Blocks can only be moved in Build Mode"); | |||
return; | |||
} | |||
uint count = entitiesDB.Count<RotationEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
for (uint i = 0; i < count; i++) | |||
{ | |||
RotateSingleBlock(i, eulerAngles); | |||
} | |||
uREPL.Log.Output($"Moved {count} blocks"); | |||
CommandRegistrationHelper.Register<float, float, float>(Name, RotateLastBlockCommand, Description); | |||
} | |||
// Move block with highest index by vector (x,y,z) | |||
private void RotateLastBlockCommand(float x, float y, float z) | |||
{ | |||
Vector3 eulerAngles = new Vector3(x, y, z); | |||
ref SimulationModeStateEntityStruct simMode = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
if (simMode.simulationMode != SimulationMode.Build) | |||
{ | |||
uREPL.Log.Error("Blocks can only be moved in Build Mode"); | |||
return; | |||
} | |||
uint count = entitiesDB.Count<RotationEntityStruct>(CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
if (count == 0) | |||
{ | |||
uREPL.Log.Error("No block found"); | |||
return; | |||
} | |||
Vector3 newRotation = RotateSingleBlock(count - 1, eulerAngles); | |||
uREPL.Log.Output($"Rotated block to ({newRotation.x},{newRotation.y},{newRotation.z})"); | |||
} | |||
private float3 RotateSingleBlock(uint blockID, Vector3 rotationVector) | |||
{ | |||
ref RotationEntityStruct rotStruct = ref this.entitiesDB.QueryEntity<RotationEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref GridRotationStruct gridStruct = ref this.entitiesDB.QueryEntity<GridRotationStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref LocalTransformEntityStruct transStruct = ref this.entitiesDB.QueryEntity<LocalTransformEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
ref UECSPhysicsEntityStruct phyStruct = ref this.entitiesDB.QueryEntity<UECSPhysicsEntityStruct>(blockID, CommonExclusiveGroups.OWNED_BLOCKS_GROUP); | |||
// main (persistent) position | |||
Quaternion newRotation = (Quaternion)rotStruct.rotation; | |||
newRotation.eulerAngles += rotationVector; | |||
rotStruct.rotation = (quaternion)newRotation; | |||
// placement grid rotation | |||
Quaternion newGridRotation = (Quaternion)gridStruct.rotation; | |||
newGridRotation.eulerAngles += rotationVector; | |||
gridStruct.rotation = (quaternion)newGridRotation; | |||
// rendered position | |||
Quaternion newTransRotation = (Quaternion)rotStruct.rotation; | |||
newTransRotation.eulerAngles += rotationVector; | |||
transStruct.rotation = newTransRotation; | |||
// collision position | |||
this.physWorld.EntityManager.SetComponentData(phyStruct.uecsEntity, new Rotation | |||
{ | |||
Value = rotStruct.rotation | |||
}); | |||
return ((Quaternion)rotStruct.rotation).eulerAngles; | |||
} | |||
// unused; for future reference | |||
private void ToggleMode() | |||
{ | |||
ref SimulationModeStateEntityStruct ptr = ref this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
ref SimulationFrameEntityStruct ptr2 = ref this.entitiesDB.QueryUniqueEntity<SimulationFrameEntityStruct>(SimulationFrame.SimulationFrameGroup); | |||
switch (ptr.simulationMode) | |||
{ | |||
case SimulationMode.Build: | |||
ptr.nextSimulationMode = SimulationMode.SwitchToSim; | |||
return; | |||
case SimulationMode.SwitchToSim: | |||
case SimulationMode.SwitchToBuild: | |||
return; | |||
case SimulationMode.Simulation: | |||
ptr.nextSimulationMode = SimulationMode.SwitchToBuild; | |||
ptr.rigidBodiesCreated = false; | |||
return; | |||
default: | |||
throw new ArgumentOutOfRangeException(); | |||
} | |||
} | |||
// unused; for future reference | |||
private IEnumerator<TaskContract> TriggerSwitchToSimTask() | |||
{ | |||
this.ToggleMode(); | |||
yield break; | |||
} | |||
// unused; for future reference | |||
private IEnumerator<TaskContract> WaitThenTriggerSwitchToBuildTask() | |||
{ | |||
while (true) | |||
{ | |||
SimulationModeStateEntityStruct modeStruct = this.entitiesDB.QueryUniqueEntity<SimulationModeStateEntityStruct>(SimulationModeStateExclusiveGroups.GAME_STATE_GROUP); | |||
if (modeStruct.simulationMode == SimulationMode.Simulation) | |||
{ | |||
this.ToggleMode(); | |||
break; | |||
} else | |||
{ | |||
yield return Yield.It; | |||
} | |||
} | |||
yield break; | |||
float3 eulerAngles = new float3(x, y, z); | |||
GamecraftModdingAPI.Blocks.Rotation.RotateBlock(BlockIdentifiers.LatestBlockID, eulerAngles); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
//CustomCommandUtility.Unregister("RotateBlocks"); | |||
CustomCommandUtility.Unregister("RotateLastBlock"); | |||
CommandRegistrationHelper.Unregister("RotateLastBlock"); | |||
} | |||
} | |||
} |
@@ -14,20 +14,23 @@ using Unity.Mathematics; | |||
using RobocraftX.Character.Camera; | |||
using RobocraftX.Character.Factories; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("RotateTo")] | |||
class RotatePlayerCommandEngine : CustomCommandEngine | |||
[CustomCommand("Rotation")] | |||
class RotatePlayerCommandEngine : ICustomCommandEngine | |||
{ | |||
public string Description => "Rotation"; | |||
public RotatePlayerCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Name => "Rotation commands"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<float, float>("RotateAbsolute", RotateAbsoluteCommand, "Rotate the player camera to the entered rotation"); | |||
CustomCommandUtility.Register<float, float>("RotateRelative", RotateRelativeCommand, "Rotate the player camera by the entered rotation"); | |||
CommandRegistrationHelper.Register<float, float>("RotateAbsolute", RotateAbsoluteCommand, "Rotate the player camera to the entered rotation"); | |||
CommandRegistrationHelper.Register<float, float>("RotateRelative", RotateRelativeCommand, "Rotate the player camera by the entered rotation"); | |||
} | |||
@@ -79,10 +82,10 @@ namespace ExtraCommands.Basics | |||
} | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("RotateAbsolute"); | |||
CustomCommandUtility.Unregister("RotateRelative"); | |||
CommandRegistrationHelper.Unregister("RotateAbsolute"); | |||
CommandRegistrationHelper.Unregister("RotateRelative"); | |||
} | |||
} | |||
} |
@@ -10,18 +10,22 @@ using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("SetFieldOfView")] | |||
class SetFOVCommandEngine : CustomCommandEngine | |||
class SetFOVCommandEngine : ICustomCommandEngine | |||
{ | |||
public SetFOVCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Set the camera's field of view"; | |||
public string Name => "SetFieldOfView"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<float>("SetFieldOfView", SetFieldOfViewCommand, "Set the camera's field of view"); | |||
CommandRegistrationHelper.Register<float>(Name, SetFieldOfViewCommand, Description); | |||
} | |||
private void SetFieldOfViewCommand(float newFoV) | |||
@@ -29,9 +33,9 @@ namespace ExtraCommands.Basics | |||
Camera.main.fieldOfView = newFoV; | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("SetFieldOfView"); | |||
CommandRegistrationHelper.Unregister(Name); | |||
} | |||
} | |||
} |
@@ -10,18 +10,22 @@ using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("SetTargetFPS")] | |||
class SetTargetFramerateCommandEngine : CustomCommandEngine | |||
class SetTargetFramerateCommandEngine : ICustomCommandEngine | |||
{ | |||
public SetTargetFramerateCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Set Gamecraft's target FPS'"; | |||
public string Name => "SetTargetFPS"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<int>("SetTargetFPS", SetFramerateCommand, "Set Gamecraft's target FPS"); | |||
CommandRegistrationHelper.Register<int>(Name, SetFramerateCommand, Description); | |||
} | |||
private void SetFramerateCommand(int newFoV) | |||
@@ -29,9 +33,9 @@ namespace ExtraCommands.Basics | |||
Application.targetFrameRate = newFoV; | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("SetTargetFPS"); | |||
CommandRegistrationHelper.Unregister(Name); | |||
} | |||
} | |||
} |
@@ -11,20 +11,25 @@ using Svelto.Context; | |||
using RobocraftX; | |||
using RobocraftX.Physics; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Waypoints | |||
{ | |||
[CustomCommand] | |||
class TeleportWaypointCommandEngine : CustomCommandEngine | |||
[CustomCommand("Waypoints")] | |||
class TeleportWaypointCommandEngine : ICustomCommandEngine | |||
{ | |||
private Dictionary<object, float[]> _waypoints = new Dictionary<object, float[]>(); | |||
public TeleportWaypointCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public override void Ready() | |||
public string Description => ""; | |||
public string Name => "Waypoints"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<object>("CreateWaypoint", CreateWaypointCommand, "Create a waypoint in your current location"); | |||
CustomCommandUtility.Register<object>("TeleportPlayerWaypoint", TeleportToWaypointCommand, "Teleport to a waypoint"); | |||
CommandRegistrationHelper.Register<object>("CreateWaypoint", CreateWaypointCommand, "Create a waypoint in your current location"); | |||
CommandRegistrationHelper.Register<object>("TeleportPlayerWaypoint", TeleportToWaypointCommand, "Teleport to a waypoint"); | |||
} | |||
private void CreateWaypointCommand(object name) | |||
@@ -45,10 +50,10 @@ namespace ExtraCommands.Waypoints | |||
uREPL.RuntimeCommands.Call<float, float, float>("TeleportPlayerAbsolute", loc[0], loc[1], loc[2]); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("CreateWaypoint"); | |||
CustomCommandUtility.Unregister("TeleportPlayerWaypoint"); | |||
CommandRegistrationHelper.Unregister("CreateWaypoint"); | |||
CommandRegistrationHelper.Unregister("TeleportPlayerWaypoint"); | |||
} | |||
} | |||
} |
@@ -1,57 +0,0 @@ | |||
using System; | |||
using System.Reflection; | |||
using Harmony; | |||
using RobocraftX.GUI.CommandLine; | |||
using RobocraftX.Multiplayer; | |||
using RobocraftX.StateSync; | |||
using RobocraftX.Character; | |||
using RobocraftX.Character.Movement; | |||
using RobocraftX.Common.Input; | |||
using Svelto.ECS; | |||
using Unity.Entities; | |||
using UnityEngine; | |||
using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
namespace ExtraCommands.Basics | |||
{ | |||
//[HarmonyPatch] | |||
//[CustomCommand("ToggleJumpEnabled")] | |||
class ToggleJumpCommandEngine : CustomCommandEngine | |||
{ | |||
private static bool isJumpEnabled = false; | |||
public ToggleJumpCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public override void Ready() | |||
{ | |||
CustomCommandUtility.Register<bool>("ToggleJumpEnabled", ToggleJumpCommand, "Enable or disable the character's ability to jump"); | |||
} | |||
private void ToggleJumpCommand(bool isEnabled) | |||
{ | |||
isJumpEnabled = isEnabled; | |||
} | |||
public override void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("ToggleJumpEnabled"); | |||
} | |||
public static void Postfix (ref CharacterInputEntityStruct input, InputStruct entity) | |||
{ | |||
if (entity.CheckInputAction(ActionInput.Up) && !isJumpEnabled) | |||
{ | |||
input.action.y -= 1f; | |||
} | |||
} | |||
public static MethodBase TargetMethod(HarmonyInstance instance) | |||
{ | |||
Type targetType = Harmony.AccessTools.TypeByName("RobocraftX.Character.Input.CharacterInputEngine"); | |||
return Harmony.AccessTools.Method(targetType, "SaveInput", new Type[] { typeof(CharacterInputEntityStruct), typeof(InputStruct) }); | |||
} | |||
} | |||
} |
@@ -10,18 +10,22 @@ using uREPL; | |||
using Svelto.Context; | |||
using RobocraftX; | |||
using GamecraftModdingAPI.Commands; | |||
namespace ExtraCommands.Basics | |||
{ | |||
[CustomCommand("Wait")] | |||
class WaitCommandEngine : CustomCommandEngine | |||
class WaitCommandEngine : ICustomCommandEngine | |||
{ | |||
public WaitCommandEngine(UnityContext<FullGameCompositionRoot> ctxHolder, EnginesRoot enginesRoot, World physW, Action reloadGame, MultiplayerInitParameters mpParams) : base(ctxHolder, enginesRoot, physW, reloadGame, mpParams) | |||
{ | |||
} | |||
public string Description => "Delay execution (freeze the game) for a length of time (ms)"; | |||
public string Name => "Wait"; | |||
public IEntitiesDB entitiesDB { set; private get; } | |||
public override void Ready() | |||
public void Ready() | |||
{ | |||
CustomCommandUtility.Register<int>("Wait", WaitCommand, "Delay execution (freeze the game) for a length of time (ms)"); | |||
CommandRegistrationHelper.Register<int>("Wait", WaitCommand, "Delay execution (freeze the game) for a length of time (ms)"); | |||
} | |||
private void WaitCommand(int ms) | |||
@@ -29,9 +33,9 @@ namespace ExtraCommands.Basics | |||
System.Threading.Thread.Sleep(ms); | |||
} | |||
public override void Dispose() | |||
public void Dispose() | |||
{ | |||
CustomCommandUtility.Unregister("Wait"); | |||
CommandRegistrationHelper.Unregister("Wait"); | |||
} | |||
} | |||
} |