BuildingTools/BlockMod/BlockMod.cs

239 lines
10 KiB
C#
Raw Normal View History

2020-06-03 01:12:03 +00:00
using System;
using System.Collections.Generic;
2020-06-03 01:12:03 +00:00
using System.Linq;
using Gamecraft.Wires;
using Gamecraft.Wires.ChannelsCommon;
2020-06-03 01:12:03 +00:00
using GamecraftModdingAPI;
using GamecraftModdingAPI.Blocks;
2020-06-03 01:12:03 +00:00
using GamecraftModdingAPI.Commands;
using GamecraftModdingAPI.Players;
using GamecraftModdingAPI.Utility;
using IllusionPlugin;
using RobocraftX.CommandLine.Custom;
2020-06-03 01:12:03 +00:00
using Unity.Mathematics;
using uREPL;
using Main = GamecraftModdingAPI.Main;
2020-06-03 01:12:03 +00:00
namespace BlockMod
{
public class BlockMod : IPlugin
{
private Block[] blocks = new Block[0];
private Block refBlock;
2020-06-03 01:12:03 +00:00
public 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) =>
2020-06-03 01:12:03 +00:00
{
if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation
if (CheckNoBlocks(blocks)) return;
// ReSharper disable once PossibleNullReferenceException
float3 reference = refBlock.Position;
2020-06-03 01:12:03 +00:00
float3 scale = new float3(scaleX, scaleY, scaleZ);
foreach (var block in blocks)
2020-06-03 01:12:03 +00:00
{
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) =>
2020-06-03 01:12:03 +00:00
{
if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation
2020-06-03 01:12:03 +00:00
float3 scale = new float3(scaleX, scaleY, scaleZ);
foreach (var block in blocks)
2020-06-03 01:12:03 +00:00
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();
2020-06-07 22:18:05 +00:00
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);
2020-06-03 01:12:03 +00:00
}).Build();
}
2020-06-03 01:12:03 +00:00
private string GetBlockInfo()
{
if (GameState.IsBuildMode())
return GetBlockInfoInBuildMode();
2020-06-03 01:12:03 +00:00
if (GameState.IsSimulationMode())
return GetBodyInfoInSimMode();
2020-06-03 01:12:03 +00:00
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}";
}
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;
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}")}";
}
private bool CheckNoBlocks(Block[] blocks)
2020-06-03 01:12:03 +00:00
{
if (blocks.Length == 0)
{
Logging.CommandLogWarning("No blocks selected. Use selectBlocks first.");
return true;
}
2020-06-03 01:12:03 +00:00
return false;
2020-06-03 01:12:03 +00:00
}
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(string name, string desc, Action<string, byte, Block[], Block> action)
{
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]);
}, 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]);
}, ChannelType.Object, desc);
}
2020-06-03 01:12:03 +00:00
public void OnApplicationQuit()
{
}
public void OnLevelWasLoaded(int level)
{
}
public void OnLevelWasInitialized(int level)
{
}
public void OnUpdate()
{
}
public void OnFixedUpdate()
{
}
public string Name { get; } = "BlockMod";
public string Version { get; } = "v1.0.0";
}
}