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 readonly CommandUtils _commandUtils; private readonly BlockSelections _blockSelections; public BlockMod() { _blockSelections = new BlockSelections(); _commandUtils = new CommandUtils(_blockSelections); } public override void OnApplicationStart() { Main.Init(); GameClient.SetDebugInfo("PlayerInfo", GetPlayerInfo); GameClient.SetDebugInfo("BlockModInfo", GetBlockInfo); _commandUtils.RegisterBlockCommand("scaleBlocks", "Scales the selected blocks, relative to current size (current scale * new scale)." + " The block you're looking at (when selected based on that) 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 (_blockSelections.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."); }); _commandUtils.RegisterBlockCommand("scaleIndividually", "Scales the blocks you're looking at, but doesn't move them." + " The scale is relative, 1 means no change.", (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; }); _commandUtils.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); }); _commandUtils.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." + " Parameter: whether one (true) or all connected (false) blocks should be selected.") .Action(single => { _blockSelections.refBlock = new Player(PlayerType.Local).GetBlockLookedAt(); var refBlock = _blockSelections.refBlock; _blockSelections.blocks = single ? new[] {refBlock} : refBlock?.GetConnectedCubes() ?? new Block[0]; var blocks = _blockSelections.blocks; Logging.CommandLog(blocks == null ? "Selection cleared." : blocks.Length + " blocks selected."); }).Build(); CommandBuilder.Builder("selectBlocksWithID", "Selects blocks with a specific object ID.") .Action(id => _blockSelections.blocks = (_blockSelections.refBlock = ObjectIdentifier.GetByID(id).FirstOrDefault()) ?.GetConnectedCubes() ?? new Block[0]).Build(); CommandBuilder.Builder("selectSelectedBlocks", "Selects blocks that are box selected by the player.") .Action(() => { _blockSelections.blocks = new Player(PlayerType.Local).GetSelectedBlocks(); _blockSelections.refBlock = _blockSelections.blocks.Length > 0 ? _blockSelections.blocks[0] : null; }).Build(); ConsoleCommands.RegisterWithChannel("selectSendSignal", ch => { }, ChannelType.Object, "Sends a signal for selecting a given object ID for a command block."); _commandUtils.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); }); _commandUtils.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((x, y, z) => { new Player(PlayerType.Local).Velocity += new float3(x, y, z); }).Build(); CommandBuilder.Builder("pushRotatePlayer", "Adds angular velocity to the player.") .Action((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 = Player.LocalPlayer.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 = Player.LocalPlayer.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 string GetPlayerInfo() { var body = Player.LocalPlayer; if (body == null) return GetBlockInfoInBuildMode(); float3 pos = body.Position; float3 rot = body.Rotation; float3 vel = body.Velocity; float3 ave = body.AngularVelocity; return $"You are 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" + $"- Mass: {body.Mass:F}\n" + $"- Health: {body.CurrentHealth:F} / {body.InitialHealth:F}"; } private IEnumerable GetSimBodies(Block[] blocks) => blocks.Select(block => block.GetSimBody()).Distinct(); public override void OnApplicationQuit() => Main.Shutdown(); public override string Name { get; } = "BlockMod"; public override string Version { get; } = "v1.0.0"; } }