|
123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282 |
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using Gamecraft.Wires;
- using GamecraftModdingAPI;
- using GamecraftModdingAPI.Blocks;
- using GamecraftModdingAPI.Commands;
- using GamecraftModdingAPI.Players;
- using GamecraftModdingAPI.Utility;
- using IllusionPlugin;
- using RobocraftX.CommandLine.Custom;
- using Unity.Mathematics;
- using uREPL;
- using Main = GamecraftModdingAPI.Main;
-
- namespace BlockMod
- {
- public class BlockMod : IEnhancedPlugin
- {
- private Block[] blocks = new Block[0];
- private Block refBlock;
-
- public override void OnApplicationStart()
- {
- Main.Init();
- GameClient.SetDebugInfo("BlockModInfo", GetBlockInfo);
- 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 (!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);
- foreach (var block in blocks)
- {
- block.Scale *= scale;
- block.Position = reference + (block.Position - reference) * scale;
- }
-
- Logging.CommandLog("Blocks scaled.");
- });
- 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 (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation
- float3 scale = new float3(scaleX, scaleY, scaleZ);
- foreach (var block in blocks)
- block.Scale *= scale;
- });
- 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 (!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};
- });
-
- 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.")
- .Action<bool>(single =>
- {
- refBlock = new Player(PlayerType.Local).GetBlockLookedAt();
- blocks = single ? new[] {refBlock} : refBlock?.GetConnectedCubes() ?? new Block[0];
- Logging.CommandLog(blocks == null ? "Selection cleared." : blocks.Length + " blocks selected.");
- }).Build();
- CommandBuilder.Builder("selectBlocksWithID", "Selects blocks with a specific object ID.")
- .Action<char>(id =>
- blocks = (refBlock = ObjectIdentifier.GetByID(id).FirstOrDefault())?.GetConnectedCubes() ??
- new Block[0]).Build();
- CommandBuilder.Builder("selectSelectedBlocks", "Selects blocks that are box selected by the player.")
- .Action(() =>
- {
- blocks = new Player(PlayerType.Local).GetSelectedBlocks();
- refBlock = blocks.Length > 0 ? blocks[0] : null;
- }).Build();
-
- ConsoleCommands.RegisterWithChannel("selectSendSignal", ch => { }, ChannelType.Object,
- "Sends a signal for selecting a given object ID for a command block.");
-
- 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);
- });
- 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);
- });
- CommandBuilder.Builder("pushPlayer", "Adds velocity to the player.")
- .Action<float, float, float>((x, y, z) =>
- {
- new Player(PlayerType.Local).Velocity += new float3(x, y, z);
- }).Build();
- CommandBuilder.Builder("pushRotatePlayer", "Adds angular velocity to the player.")
- .Action<float, float, float>((x, y, z) =>
- {
- new Player(PlayerType.Local).AngularVelocity += new float3(x, y, z);
- }).Build();
- }
-
- private string GetBlockInfo()
- {
- if (GameState.IsBuildMode())
- return GetBlockInfoInBuildMode();
- if (GameState.IsSimulationMode())
- return GetBodyInfoInSimMode();
-
- return "Switching modes...";
- }
-
- private static string GetBlockInfoInBuildMode()
- {
- var block = new Player(PlayerType.Local).GetBlockLookedAt();
- if (block == null) return "";
- float3 pos = block.Position;
- float3 rot = block.Rotation;
- float3 scale = block.Scale;
- return $"Block: {block.Type} at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
- $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
- $"- Color: {block.Color.Color} darkness: {block.Color.Darkness}\n" +
- $"- Scale: {scale.x:F} {scale.y:F} {scale.z:F}\n" +
- $"- Label: {block.Label}\n" +
- $"- ID: {block.Id}";
- }
-
- private static string GetBodyInfoInSimMode()
- {
- var body = new Player(PlayerType.Local).GetSimBodyLookedAt();
- if (body == null) return GetBlockInfoInBuildMode();
- float3 pos = body.Position;
- float3 rot = body.Rotation;
- float3 vel = body.Velocity;
- float3 ave = body.AngularVelocity;
- float3 com = body.CenterOfMass;
- Cluster cluster = body.Cluster;
- return $"Body at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
- $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
- $"- Velocity: {vel.x:F} {vel.y:F} {vel.z:F}\n" +
- $"- Angular velocity: {ave.x:F} {ave.y:F} {ave.z:F}\n" +
- $"- {(body.Static ? "Static body" : $"Mass: {body.Mass:F} center: {com.x:F} {com.y:F} {com.z:F}")}\n" +
- $"- Volume: {body.Volume:F}\n" +
- $"- Chunk health: {body.CurrentHealth:F} / {body.InitialHealth:F} - Multiplier: {body.HealthMultiplier:F}\n" +
- $"- Cluster health: {cluster?.CurrentHealth:F} / {cluster?.InitialHealth:F} - Multiplier: {cluster?.HealthMultiplier:F}";
- }
-
- private bool CheckNoBlocks(Block[] blocks)
- {
- if (blocks.Length == 0)
- {
- Logging.CommandLogWarning("No blocks selected. Use selectBlocks first.");
- return true;
- }
-
- return false;
- }
-
- 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 Block[] SelectBlocks(char id)
- {
- var blocks = ObjectIdentifier.GetByID(id).SelectMany(oid => oid.GetConnectedCubes())
- .ToArray();
- return blocks;
- }
-
- private void RegisterBlockCommandInternal(string name, string desc, Action<string, Block[], Block> action)
- {
- RuntimeCommands.Register<string>(name, a1 =>
- {
- action(a1, blocks, refBlock);
- }, desc);
- ConsoleCommands.RegisterWithChannel<string>(name, (a1, ch) =>
- {
- Console.WriteLine($"Command {name} with args {a1} and channel {ch} executing");
- var blks = SelectBlocks(ch);
- action(a1, blks, blks[0]);
- }, ChannelType.Object, desc);
- }
-
- private void RegisterBlockCommand(string name, string desc, Action<float, float, float, Block[], Block> action)
- {
- RegisterBlockCommandInternal(name, desc, (args, bs, b) =>
- {
- var argsa = args.Split(' ');
- if (argsa.Length < 3)
- {
- Log.Error("Too few arguments. Needed arguments are: <x> <y> <z> and [id] is optional.");
- return;
- }
-
- if (!float.TryParse(argsa[0], out float x) || !float.TryParse(argsa[1], out float y) ||
- !float.TryParse(argsa[2], out float z))
- {
- Log.Error("Could not parse arguments as floats.");
- return;
- }
-
- if (argsa.Length > 3)
- {
- if (argsa[3].Length == 0)
- {
- Log.Error("Missing channel.");
- return;
- }
-
- var blocks = SelectBlocks(argsa[3][0]);
- if (CheckNoBlocks(blocks)) return;
- action(x, y, z, blocks, blocks[0]);
- }
- else if (!CheckNoBlocks(bs))
- action(x, y, z, bs, b);
- });
- }
-
- private void RegisterBlockCommand(string name, string desc, Action<string, byte, Block[], Block> action)
- {
- RegisterBlockCommandInternal(name, desc, (args, bs, b) =>
- {
- var argsa = args.Split(' ');
- if (argsa.Length < 2)
- {
- Log.Error("Too few arguments. Needed arguments are: <color> <darkness> and [id] is optional.");
- return;
- }
-
- if (!byte.TryParse(argsa[1], out byte darkness))
- {
- Log.Error("Could not parse color darkness.");
- return;
- }
-
- if (argsa.Length > 2)
- {
- if (argsa[2].Length == 0)
- {
- Log.Error("Missing channel.");
- return;
- }
-
- var blocks = SelectBlocks(argsa[2][0]);
- if (CheckNoBlocks(blocks)) return;
- action(argsa[0], darkness, blocks, blocks[0]);
- }
- else if(!CheckNoBlocks(bs))
- action(argsa[0], darkness, bs, b);
- });
- }
-
- public override string Name { get; } = "BlockMod";
- public override string Version { get; } = "v1.0.0";
- }
- }
|