Tools for building games mainly focused on changing block properties. And noclip.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

239 lines
10KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Gamecraft.Wires;
  5. using Gamecraft.Wires.ChannelsCommon;
  6. using GamecraftModdingAPI;
  7. using GamecraftModdingAPI.Blocks;
  8. using GamecraftModdingAPI.Commands;
  9. using GamecraftModdingAPI.Players;
  10. using GamecraftModdingAPI.Utility;
  11. using IllusionPlugin;
  12. using RobocraftX.CommandLine.Custom;
  13. using Unity.Mathematics;
  14. using uREPL;
  15. using Main = GamecraftModdingAPI.Main;
  16. namespace BlockMod
  17. {
  18. public class BlockMod : IPlugin
  19. {
  20. private Block[] blocks = new Block[0];
  21. private Block refBlock;
  22. public void OnApplicationStart()
  23. {
  24. Main.Init();
  25. GameClient.SetDebugInfo("BlockModInfo", GetBlockInfo);
  26. RegisterBlockCommand("scaleBlocks",
  27. "Scales the blocks you're looking at, relative to current size (current scale * new scale)." +
  28. " The block you're looking at stays where it is, everything else is moved next to it.",
  29. (scaleX, scaleY, scaleZ, blocks, refBlock) =>
  30. {
  31. if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation
  32. if (CheckNoBlocks(blocks)) return;
  33. // ReSharper disable once PossibleNullReferenceException
  34. float3 reference = refBlock.Position;
  35. float3 scale = new float3(scaleX, scaleY, scaleZ);
  36. foreach (var block in blocks)
  37. {
  38. block.Scale *= scale;
  39. block.Position = reference + (block.Position - reference) * scale;
  40. }
  41. Logging.CommandLog("Blocks scaled.");
  42. });
  43. RegisterBlockCommand("scaleIndividually", "Scales the blocks you're looking at, but doesn't move them." +
  44. "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.",
  45. (scaleX, scaleY, scaleZ, blocks, refBlock) =>
  46. {
  47. if (!GameState.IsBuildMode()) return; //Scaling & positioning is weird in simulation
  48. float3 scale = new float3(scaleX, scaleY, scaleZ);
  49. foreach (var block in blocks)
  50. block.Scale *= scale;
  51. });
  52. RegisterBlockCommand("moveBlocks", "Moves the blocks around.", (x, y, z, blocks, refBlock) =>
  53. {
  54. if (GameState.IsBuildMode())
  55. foreach (var block in blocks)
  56. block.Position += new float3(x, y, z);
  57. else if (GameState.IsSimulationMode())
  58. foreach (var body in GetSimBodies(blocks))
  59. body.Position += new float3(x, y, z);
  60. });
  61. RegisterBlockCommand("colorBlocks", "Colors the blocks you're looking at",
  62. (color, darkness, blocks, refBlock) =>
  63. {
  64. if (!Enum.TryParse(color, true, out BlockColors clr))
  65. {
  66. Logging.CommandLogWarning("Color " + color + " not found");
  67. }
  68. foreach (var block in blocks)
  69. block.Color = new BlockColor {Color = clr, Darkness = darkness};
  70. });
  71. CommandBuilder.Builder("selectBlocksLookedAt", "Selects blocks (1 or more) to change. Only works in build mode, however the blocks can be changed afterwards." +
  72. " Paramter: whether one (true) or all connected (false) blocks should be selected.")
  73. .Action<bool>(single =>
  74. {
  75. refBlock = new Player(PlayerType.Local).GetBlockLookedAt();
  76. blocks = single ? new[] {refBlock} : refBlock?.GetConnectedCubes() ?? new Block[0];
  77. Logging.CommandLog(blocks == null ? "Selection cleared." : blocks.Length + " blocks selected.");
  78. }).Build();
  79. CommandBuilder.Builder("selectBlocksWithID", "Selects blocks with a specific object ID.")
  80. .Action<char>(id =>
  81. blocks = (refBlock = ObjectIdentifier.GetByID(id).FirstOrDefault())?.GetConnectedCubes() ??
  82. new Block[0]).Build();
  83. CommandBuilder.Builder("selectSelectedBlocks", "Selects blocks that are box selected by the player.")
  84. .Action(() =>
  85. {
  86. blocks = new Player(PlayerType.Local).GetSelectedBlocks();
  87. refBlock = blocks.Length > 0 ? blocks[0] : null;
  88. }).Build();
  89. ConsoleCommands.RegisterWithChannel("selectSendSignal", ch =>
  90. {
  91. }, ChannelType.Object,
  92. "Sends a signal for selecting a given object ID for a command block.");
  93. RegisterBlockCommand("pushBlocks", "Adds velocity to the selected blocks. Only works in simulation.",
  94. (x, y, z, blocks, refBlock) =>
  95. {
  96. foreach (var block in GetSimBodies(blocks))
  97. block.Velocity += new float3(x, y, z);
  98. });
  99. RegisterBlockCommand("pushRotateBlocks",
  100. "Adds angular velocity to the selected blocks. Only works in simulation.",
  101. (x, y, z, blocks, refBlock) =>
  102. {
  103. foreach (var block in GetSimBodies(blocks))
  104. block.AngularVelocity += new float3(x, y, z);
  105. });
  106. CommandBuilder.Builder("pushPlayer", "Adds velocity to the player.")
  107. .Action<float, float, float>((x, y, z) =>
  108. {
  109. new Player(PlayerType.Local).Velocity += new float3(x, y, z);
  110. }).Build();
  111. CommandBuilder.Builder("pushRotatePlayer", "Adds angular velocity to the player.")
  112. .Action<float, float, float>((x, y, z) =>
  113. {
  114. new Player(PlayerType.Local).AngularVelocity += new float3(x, y, z);
  115. }).Build();
  116. }
  117. private string GetBlockInfo()
  118. {
  119. if (GameState.IsBuildMode())
  120. return GetBlockInfoInBuildMode();
  121. if (GameState.IsSimulationMode())
  122. return GetBodyInfoInSimMode();
  123. return "Switching modes...";
  124. }
  125. private static string GetBlockInfoInBuildMode()
  126. {
  127. var block = new Player(PlayerType.Local).GetBlockLookedAt();
  128. if (block == null) return "";
  129. float3 pos = block.Position;
  130. float3 rot = block.Rotation;
  131. float3 scale = block.Scale;
  132. return $"Block: {block.Type} at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
  133. $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
  134. $"- Color: {block.Color.Color} darkness: {block.Color.Darkness}\n" +
  135. $"- Scale: {scale.x:F} {scale.y:F} {scale.z:F}\n" +
  136. $"- Label: {block.Label}";
  137. }
  138. private static string GetBodyInfoInSimMode()
  139. {
  140. var body = new Player(PlayerType.Local).GetSimBodyLookedAt();
  141. if (body == null) return GetBlockInfoInBuildMode();
  142. float3 pos = body.Position;
  143. float3 rot = body.Rotation;
  144. float3 vel = body.Velocity;
  145. float3 ave = body.AngularVelocity;
  146. float3 com = body.CenterOfMass;
  147. return $"Body at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
  148. $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
  149. $"- Velocity: {vel.x:F} {vel.y:F} {vel.z:F}\n" +
  150. $"- Angular velocity: {ave.x:F} {ave.y:F} {ave.z:F}\n" +
  151. $"- {(body.Static ? "Static body" : $"Mass: {body.Mass:F} center: {com.x:F} {com.y:F} {com.z:F}")}";
  152. }
  153. private bool CheckNoBlocks(Block[] blocks)
  154. {
  155. if (blocks.Length == 0)
  156. {
  157. Logging.CommandLogWarning("No blocks selected. Use selectBlocks first.");
  158. return true;
  159. }
  160. return false;
  161. }
  162. private IEnumerable<SimBody> GetSimBodies(Block[] blocks)
  163. => blocks.Select(block => block.GetSimBody()).Distinct();
  164. private Block[] SelectBlocks(byte id)
  165. {
  166. var blocks = ObjectIdentifier.GetBySimID(id).SelectMany(block => block.GetConnectedCubes()).ToArray();
  167. return blocks;
  168. }
  169. private void RegisterBlockCommand(string name, string desc, Action<string, byte, Block[], Block> action)
  170. {
  171. RuntimeCommands.Register<string, byte>(name, (a1, a2) =>
  172. {
  173. if (CheckNoBlocks(blocks)) return;
  174. action(a1, a2, blocks, refBlock);
  175. }, desc);
  176. ConsoleCommands.RegisterWithChannel<string, byte>(name, (a1, a2, ch) =>
  177. {
  178. var blks = SelectBlocks(ch);
  179. if (CheckNoBlocks(blks)) return;
  180. action(a1, a2, blks, blks[0]);
  181. }, ChannelType.Object, desc);
  182. }
  183. private void RegisterBlockCommand(string name, string desc, Action<float, float, float, Block[], Block> action)
  184. {
  185. RuntimeCommands.Register<float, float, float>(name, (x, y, z) =>
  186. {
  187. if (CheckNoBlocks(blocks)) return;
  188. action(x, y, z, blocks, refBlock);
  189. },
  190. desc);
  191. ConsoleCommands.RegisterWithChannel<float, float, float>(name, (x, y, z, ch) =>
  192. {
  193. var blks = SelectBlocks(ch);
  194. if (CheckNoBlocks(blks)) return;
  195. action(x, y, z, blks, blks[0]);
  196. }, ChannelType.Object, desc);
  197. }
  198. public void OnApplicationQuit()
  199. {
  200. }
  201. public void OnLevelWasLoaded(int level)
  202. {
  203. }
  204. public void OnLevelWasInitialized(int level)
  205. {
  206. }
  207. public void OnUpdate()
  208. {
  209. }
  210. public void OnFixedUpdate()
  211. {
  212. }
  213. public string Name { get; } = "BlockMod";
  214. public string Version { get; } = "v1.0.0";
  215. }
  216. }