|
|
@@ -16,25 +16,26 @@ using RobocraftX.Common.Players; |
|
|
|
using Svelto.ECS; |
|
|
|
using Svelto.ECS.Internal; |
|
|
|
using Unity.Mathematics; |
|
|
|
using uREPL; |
|
|
|
using Main = GamecraftModdingAPI.Main; |
|
|
|
|
|
|
|
namespace BlockMod |
|
|
|
{ |
|
|
|
public class BlockMod : IPlugin |
|
|
|
{ |
|
|
|
private Block[] blocks = new Block[0]; |
|
|
|
private Block refBlock; |
|
|
|
public void OnApplicationStart() |
|
|
|
{ |
|
|
|
Main.Init(); |
|
|
|
GameClient.SetDebugInfo("BlockModInfo", GetBlockInfo); |
|
|
|
Block[] blocks = new Block[0]; |
|
|
|
Block refBlock = null; |
|
|
|
CommandBuilder.Builder("scaleBlocks", |
|
|
|
"Scales the blocks you're looking at, relative to current size (current scale * new scale)." + |
|
|
|
" The block you're looking at stays where it is, everything else is moved next to it." + |
|
|
|
" The command remembers the cluster of blocks, use forgetBlocks to forget it.") |
|
|
|
.Action<float, float, float>((scaleX, scaleY, scaleZ) => |
|
|
|
RegisterBlockCommand("scaleBlocks", |
|
|
|
"Scales the blocks you're looking at, relative to current size (current scale * new scale)." + |
|
|
|
" The block you're looking at stays where it is, everything else is moved next to it.", |
|
|
|
(scaleX, scaleY, scaleZ, blocks, refBlock) => |
|
|
|
{ |
|
|
|
if(CheckNoBlocks(blocks)) return; |
|
|
|
if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation |
|
|
|
if (CheckNoBlocks(blocks)) return; |
|
|
|
// ReSharper disable once PossibleNullReferenceException |
|
|
|
float3 reference = refBlock.Position; |
|
|
|
float3 scale = new float3(scaleX, scaleY, scaleZ); |
|
|
@@ -45,38 +46,36 @@ namespace BlockMod |
|
|
|
} |
|
|
|
|
|
|
|
Logging.CommandLog("Blocks scaled."); |
|
|
|
}).Build(); |
|
|
|
CommandBuilder.Builder("scaleIndividually", "Scales the blocks you're looking at, but doesn't move them." + |
|
|
|
"The scale is relative, 1 means no change. Look at a block previously scaled to scale all of the blocks that were connected to it.") |
|
|
|
.Action<float, float, float>((scaleX, scaleY, scaleZ) => |
|
|
|
}); |
|
|
|
RegisterBlockCommand("scaleIndividually", "Scales the blocks you're looking at, but doesn't move them." + |
|
|
|
"The scale is relative, 1 means no change. Look at a block previously scaled to scale all of the blocks that were connected to it.", |
|
|
|
(scaleX, scaleY, scaleZ, blocks, refBlock) => |
|
|
|
{ |
|
|
|
if(CheckNoBlocks(blocks)) return; |
|
|
|
if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation |
|
|
|
float3 scale = new float3(scaleX, scaleY, scaleZ); |
|
|
|
foreach (var block in blocks) |
|
|
|
block.Scale *= scale; |
|
|
|
}).Build(); |
|
|
|
CommandBuilder.Builder("moveBlocks", "Moves the blocks around.") |
|
|
|
.Action<float, float, float>((x, y, z) => |
|
|
|
{ |
|
|
|
if (CheckNoBlocks(blocks)) return; |
|
|
|
if (GameState.IsBuildMode()) |
|
|
|
foreach (var block in blocks) |
|
|
|
block.Position += new float3(x, y, z); |
|
|
|
else if (GameState.IsSimulationMode()) |
|
|
|
foreach (var body in GetSimBodies(blocks)) |
|
|
|
body.Position += new float3(x, y, z); |
|
|
|
}).Build(); |
|
|
|
CommandBuilder.Builder("colorBlocks", "Colors the blocks you're looking at") |
|
|
|
.Action<string, byte>((color, darkness) => |
|
|
|
}); |
|
|
|
RegisterBlockCommand("moveBlocks", "Moves the blocks around.", (x, y, z, blocks, refBlock) => |
|
|
|
{ |
|
|
|
if (GameState.IsBuildMode()) |
|
|
|
foreach (var block in blocks) |
|
|
|
block.Position += new float3(x, y, z); |
|
|
|
else if (GameState.IsSimulationMode()) |
|
|
|
foreach (var body in GetSimBodies(blocks)) |
|
|
|
body.Position += new float3(x, y, z); |
|
|
|
}); |
|
|
|
RegisterBlockCommand("colorBlocks", "Colors the blocks you're looking at", |
|
|
|
(color, darkness, blocks, refBlock) => |
|
|
|
{ |
|
|
|
if(CheckNoBlocks(blocks)) return; |
|
|
|
if (!Enum.TryParse(color, true, out BlockColors clr)) |
|
|
|
{ |
|
|
|
Logging.CommandLogWarning("Color " + color + " not found"); |
|
|
|
} |
|
|
|
|
|
|
|
foreach (var block in blocks) |
|
|
|
block.Color = new BlockColor {Color = clr, Darkness = darkness}; |
|
|
|
}).Build(); |
|
|
|
}); |
|
|
|
|
|
|
|
CommandBuilder.Builder("selectBlocksLookedAt", "Selects blocks (1 or more) to change. Only works in build mode, however the blocks can be changed afterwards." + |
|
|
|
" Paramter: whether one (true) or all connected (false) blocks should be selected.") |
|
|
@@ -90,24 +89,20 @@ namespace BlockMod |
|
|
|
.Action<char>(id => |
|
|
|
blocks = (refBlock = ObjectIdentifier.GetByID(id).FirstOrDefault())?.GetConnectedCubes() ?? |
|
|
|
new Block[0]).Build(); |
|
|
|
ConsoleCommands.RegisterWithChannel("selectBlocksFromChannel", id => |
|
|
|
{ |
|
|
|
blocks = ObjectIdentifier.GetBySimID(id).SelectMany(block => block.GetConnectedCubes()).ToArray(); |
|
|
|
}, |
|
|
|
BinaryChannelUtilities.ChannelType.Object); |
|
|
|
|
|
|
|
CommandBuilder.Builder("pushBlocks", "Adds velocity to the selected blocks. Only works in simulation.") |
|
|
|
.Action<float, float, float>((x, y, z) => |
|
|
|
RegisterBlockCommand("pushBlocks", "Adds velocity to the selected blocks. Only works in simulation.", |
|
|
|
(x, y, z, blocks, refBlock) => |
|
|
|
{ |
|
|
|
foreach (var block in GetSimBodies(blocks)) |
|
|
|
block.Velocity += new float3(x, y, z); |
|
|
|
}).Build(); |
|
|
|
CommandBuilder.Builder("pushRotateBlocks", "Adds angular velocity to the selected blocks. Only works in simulation.") |
|
|
|
.Action<float, float, float>((x, y, z) => |
|
|
|
}); |
|
|
|
RegisterBlockCommand("pushRotateBlocks", |
|
|
|
"Adds angular velocity to the selected blocks. Only works in simulation.", |
|
|
|
(x, y, z, blocks, refBlock) => |
|
|
|
{ |
|
|
|
foreach (var block in GetSimBodies(blocks)) |
|
|
|
block.AngularVelocity += new float3(x, y, z); |
|
|
|
}).Build(); |
|
|
|
}); |
|
|
|
CommandBuilder.Builder("pushPlayer", "Adds velocity to the player.") |
|
|
|
.Action<float, float, float>((x, y, z) => |
|
|
|
{ |
|
|
@@ -118,66 +113,8 @@ namespace BlockMod |
|
|
|
{ |
|
|
|
new Player(PlayerType.Local).AngularVelocity += new float3(x, y, z); |
|
|
|
}).Build(); |
|
|
|
GameEngineManager.AddGameEngine(new Test()); |
|
|
|
} |
|
|
|
|
|
|
|
private class Test : IApiEngine |
|
|
|
{ |
|
|
|
public void Ready() |
|
|
|
{ |
|
|
|
try |
|
|
|
{ |
|
|
|
CommandBuilder.Builder("weaponTest").Action(() => |
|
|
|
{ |
|
|
|
var type = AccessTools.TypeByName("RobocraftX.Character.Weapons.CharacterEquippedWeaponStruct"); |
|
|
|
var dict = QueryEntitiesAndIndexInternal( |
|
|
|
new EGID(new Player(PlayerType.Local).Id, PlayersExclusiveGroups.LocalPlayers), |
|
|
|
out uint i, type); |
|
|
|
var dtype = typeof(ITypeSafeDictionary<>).MakeGenericType(type); |
|
|
|
var obj = Convert.ChangeType(dict, dtype); |
|
|
|
Array arr = (Array) AccessTools.PropertyGetter(dtype, "unsafeValues") |
|
|
|
.Invoke(obj, new object[0]); |
|
|
|
foreach (var element in arr) |
|
|
|
element.GetType().GetField("equippedWeaponType") |
|
|
|
.SetValue(element, WeaponType.PISTOL); |
|
|
|
}).Build(); |
|
|
|
} |
|
|
|
catch |
|
|
|
{ |
|
|
|
// ignored |
|
|
|
} |
|
|
|
} |
|
|
|
|
|
|
|
private ITypeSafeDictionary QueryEntitiesAndIndexInternal(EGID entityGID, out uint index, Type type) |
|
|
|
{ |
|
|
|
index = 0U; |
|
|
|
ITypeSafeDictionary typeSafeDictionary; |
|
|
|
if (!QueryEntityDictionary(entityGID.groupID, out typeSafeDictionary, type)) |
|
|
|
return null; |
|
|
|
return !typeSafeDictionary.TryFindIndex(entityGID.entityID, out index) ? null : typeSafeDictionary; |
|
|
|
} |
|
|
|
|
|
|
|
private bool QueryEntityDictionary( |
|
|
|
uint group, |
|
|
|
out ITypeSafeDictionary typeSafeDictionary, |
|
|
|
Type type) |
|
|
|
{ |
|
|
|
object[] ps = {group, type, null}; |
|
|
|
bool ret = (bool) AccessTools.Method("Svelto.ECS.EntitiesDB:UnsafeQueryEntityDictionary") |
|
|
|
.Invoke(entitiesDB, ps); |
|
|
|
typeSafeDictionary = (ITypeSafeDictionary) ps[2]; |
|
|
|
return ret; |
|
|
|
} |
|
|
|
|
|
|
|
public EntitiesDB entitiesDB { get; set; } |
|
|
|
public void Dispose() |
|
|
|
{ |
|
|
|
} |
|
|
|
|
|
|
|
public string Name { get; } = "TestEngine"; |
|
|
|
public bool isRemovable { get; } = true; |
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
private string GetBlockInfo() |
|
|
|
{ |
|
|
|
if (GameState.IsBuildMode()) |
|
|
@@ -221,9 +158,57 @@ namespace BlockMod |
|
|
|
return false; |
|
|
|
} |
|
|
|
|
|
|
|
public IEnumerable<SimBody> GetSimBodies(Block[] blocks) |
|
|
|
private IEnumerable<SimBody> GetSimBodies(Block[] blocks) |
|
|
|
=> blocks.Select(block => block.GetSimBody()).Distinct(); |
|
|
|
|
|
|
|
private Block[] SelectBlocks(byte id) |
|
|
|
{ |
|
|
|
var blocks = ObjectIdentifier.GetBySimID(id).SelectMany(block => block.GetConnectedCubes()).ToArray(); |
|
|
|
return blocks; |
|
|
|
} |
|
|
|
|
|
|
|
//private void RegisterBlockCommand<T>(string name, string desc, T action) where T : Delegate |
|
|
|
private void RegisterBlockCommand(string name, string desc, Action<string, byte, Block[], Block> action) |
|
|
|
{ |
|
|
|
/*switch (action) |
|
|
|
{ |
|
|
|
case Action<Block[], Block> act |
|
|
|
break; |
|
|
|
case Action<float, float, float, Block[], Block> act: |
|
|
|
break; |
|
|
|
default: |
|
|
|
Logging.LogWarning("Unexpected parameters for command: " + name); |
|
|
|
break; |
|
|
|
}*/ |
|
|
|
RuntimeCommands.Register<string, byte>(name, (a1, a2) => |
|
|
|
{ |
|
|
|
if (CheckNoBlocks(blocks)) return; |
|
|
|
action(a1, a2, blocks, refBlock); |
|
|
|
}, desc); |
|
|
|
ConsoleCommands.RegisterWithChannel<string, byte>(name, (a1, a2, ch) => |
|
|
|
{ |
|
|
|
var blks = SelectBlocks(ch); |
|
|
|
if (CheckNoBlocks(blks)) return; |
|
|
|
action(a1, a2, blks, blks[0]); |
|
|
|
}, BinaryChannelUtilities.ChannelType.Object, desc); |
|
|
|
} |
|
|
|
|
|
|
|
private void RegisterBlockCommand(string name, string desc, Action<float, float, float, Block[], Block> action) |
|
|
|
{ |
|
|
|
RuntimeCommands.Register<float, float, float>(name, (x, y, z) => |
|
|
|
{ |
|
|
|
if (CheckNoBlocks(blocks)) return; |
|
|
|
action(x, y, z, blocks, refBlock); |
|
|
|
}, |
|
|
|
desc); |
|
|
|
ConsoleCommands.RegisterWithChannel<float, float, float>(name, (x, y, z, ch) => |
|
|
|
{ |
|
|
|
var blks = SelectBlocks(ch); |
|
|
|
if (CheckNoBlocks(blks)) return; |
|
|
|
action(x, y, z, blks, blks[0]); |
|
|
|
}, BinaryChannelUtilities.ChannelType.Object, desc); |
|
|
|
} |
|
|
|
|
|
|
|
public void OnApplicationQuit() |
|
|
|
{ |
|
|
|
} |
|
|
|