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.

250 lines
11KB

  1. using System;
  2. using System.Collections.Generic;
  3. using System.Linq;
  4. using Gamecraft.Wires.ChannelsCommon;
  5. using GamecraftModdingAPI;
  6. using GamecraftModdingAPI.Blocks;
  7. using GamecraftModdingAPI.Commands;
  8. using GamecraftModdingAPI.Engines;
  9. using GamecraftModdingAPI.Players;
  10. using GamecraftModdingAPI.Utility;
  11. using HarmonyLib;
  12. using IllusionPlugin;
  13. using RobocraftX.Character.Weapons;
  14. using RobocraftX.CommandLine.Custom;
  15. using RobocraftX.Common.Players;
  16. using Svelto.ECS;
  17. using Svelto.ECS.Internal;
  18. using Unity.Mathematics;
  19. using Main = GamecraftModdingAPI.Main;
  20. namespace BlockMod
  21. {
  22. public class BlockMod : IPlugin
  23. {
  24. public void OnApplicationStart()
  25. {
  26. Main.Init();
  27. GameClient.SetDebugInfo("BlockModInfo", GetBlockInfo);
  28. Block[] blocks = new Block[0];
  29. Block refBlock = null;
  30. CommandBuilder.Builder("scaleBlocks",
  31. "Scales the blocks you're looking at, relative to current size (current scale * new scale)." +
  32. " The block you're looking at stays where it is, everything else is moved next to it." +
  33. " The command remembers the cluster of blocks, use forgetBlocks to forget it.")
  34. .Action<float, float, float>((scaleX, scaleY, scaleZ) =>
  35. {
  36. if(CheckNoBlocks(blocks)) return;
  37. // ReSharper disable once PossibleNullReferenceException
  38. float3 reference = refBlock.Position;
  39. float3 scale = new float3(scaleX, scaleY, scaleZ);
  40. foreach (var block in blocks)
  41. {
  42. block.Scale *= scale;
  43. block.Position = reference + (block.Position - reference) * scale;
  44. }
  45. Logging.CommandLog("Blocks scaled.");
  46. }).Build();
  47. CommandBuilder.Builder("scaleIndividually", "Scales the blocks you're looking at, but doesn't move them." +
  48. "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.")
  49. .Action<float, float, float>((scaleX, scaleY, scaleZ) =>
  50. {
  51. if(CheckNoBlocks(blocks)) return;
  52. float3 scale = new float3(scaleX, scaleY, scaleZ);
  53. foreach (var block in blocks)
  54. block.Scale *= scale;
  55. }).Build();
  56. CommandBuilder.Builder("moveBlocks", "Moves the blocks around.")
  57. .Action<float, float, float>((x, y, z) =>
  58. {
  59. if (CheckNoBlocks(blocks)) return;
  60. if (GameState.IsBuildMode())
  61. foreach (var block in blocks)
  62. block.Position += new float3(x, y, z);
  63. else if (GameState.IsSimulationMode())
  64. foreach (var body in GetSimBodies(blocks))
  65. body.Position += new float3(x, y, z);
  66. }).Build();
  67. CommandBuilder.Builder("colorBlocks", "Colors the blocks you're looking at")
  68. .Action<string, byte>((color, darkness) =>
  69. {
  70. if(CheckNoBlocks(blocks)) return;
  71. if (!Enum.TryParse(color, true, out BlockColors clr))
  72. {
  73. Logging.CommandLogWarning("Color " + color + " not found");
  74. }
  75. foreach (var block in blocks)
  76. block.Color = new BlockColor {Color = clr, Darkness = darkness};
  77. }).Build();
  78. CommandBuilder.Builder("selectBlocksLookedAt", "Selects blocks (1 or more) to change. Only works in build mode, however the blocks can be changed afterwards." +
  79. " Paramter: whether one (true) or all connected (false) blocks should be selected.")
  80. .Action<bool>(single =>
  81. {
  82. refBlock = new Player(PlayerType.Local).GetBlockLookedAt();
  83. blocks = single ? new[] {refBlock} : refBlock?.GetConnectedCubes() ?? new Block[0];
  84. Logging.CommandLog(blocks == null ? "Selection cleared." : blocks.Length + " blocks selected.");
  85. }).Build();
  86. CommandBuilder.Builder("selectBlocksWithID", "Selects blocks with a specific object ID.")
  87. .Action<char>(id =>
  88. blocks = (refBlock = ObjectIdentifier.GetByID(id).FirstOrDefault())?.GetConnectedCubes() ??
  89. new Block[0]).Build();
  90. ConsoleCommands.RegisterWithChannel("selectBlocksFromChannel", id =>
  91. {
  92. blocks = ObjectIdentifier.GetBySimID(id).SelectMany(block => block.GetConnectedCubes()).ToArray();
  93. },
  94. BinaryChannelUtilities.ChannelType.Object);
  95. CommandBuilder.Builder("pushBlocks", "Adds velocity to the selected blocks. Only works in simulation.")
  96. .Action<float, float, float>((x, y, z) =>
  97. {
  98. foreach (var block in GetSimBodies(blocks))
  99. block.Velocity += new float3(x, y, z);
  100. }).Build();
  101. CommandBuilder.Builder("pushRotateBlocks", "Adds angular velocity to the selected blocks. Only works in simulation.")
  102. .Action<float, float, float>((x, y, z) =>
  103. {
  104. foreach (var block in GetSimBodies(blocks))
  105. block.AngularVelocity += new float3(x, y, z);
  106. }).Build();
  107. CommandBuilder.Builder("pushPlayer", "Adds velocity to the player.")
  108. .Action<float, float, float>((x, y, z) =>
  109. {
  110. new Player(PlayerType.Local).Velocity += new float3(x, y, z);
  111. }).Build();
  112. CommandBuilder.Builder("pushRotatePlayer", "Adds angular velocity to the player.")
  113. .Action<float, float, float>((x, y, z) =>
  114. {
  115. new Player(PlayerType.Local).AngularVelocity += new float3(x, y, z);
  116. }).Build();
  117. GameEngineManager.AddGameEngine(new Test());
  118. }
  119. private class Test : IApiEngine
  120. {
  121. public void Ready()
  122. {
  123. try
  124. {
  125. CommandBuilder.Builder("weaponTest").Action(() =>
  126. {
  127. var type = AccessTools.TypeByName("RobocraftX.Character.Weapons.CharacterEquippedWeaponStruct");
  128. var dict = QueryEntitiesAndIndexInternal(
  129. new EGID(new Player(PlayerType.Local).Id, PlayersExclusiveGroups.LocalPlayers),
  130. out uint i, type);
  131. var dtype = typeof(ITypeSafeDictionary<>).MakeGenericType(type);
  132. var obj = Convert.ChangeType(dict, dtype);
  133. Array arr = (Array) AccessTools.PropertyGetter(dtype, "unsafeValues")
  134. .Invoke(obj, new object[0]);
  135. foreach (var element in arr)
  136. element.GetType().GetField("equippedWeaponType")
  137. .SetValue(element, WeaponType.PISTOL);
  138. }).Build();
  139. }
  140. catch
  141. {
  142. // ignored
  143. }
  144. }
  145. private ITypeSafeDictionary QueryEntitiesAndIndexInternal(EGID entityGID, out uint index, Type type)
  146. {
  147. index = 0U;
  148. ITypeSafeDictionary typeSafeDictionary;
  149. if (!QueryEntityDictionary(entityGID.groupID, out typeSafeDictionary, type))
  150. return null;
  151. return !typeSafeDictionary.TryFindIndex(entityGID.entityID, out index) ? null : typeSafeDictionary;
  152. }
  153. private bool QueryEntityDictionary(
  154. uint group,
  155. out ITypeSafeDictionary typeSafeDictionary,
  156. Type type)
  157. {
  158. object[] ps = {group, type, null};
  159. bool ret = (bool) AccessTools.Method("Svelto.ECS.EntitiesDB:UnsafeQueryEntityDictionary")
  160. .Invoke(entitiesDB, ps);
  161. typeSafeDictionary = (ITypeSafeDictionary) ps[2];
  162. return ret;
  163. }
  164. public EntitiesDB entitiesDB { get; set; }
  165. public void Dispose()
  166. {
  167. }
  168. public string Name { get; } = "TestEngine";
  169. public bool isRemovable { get; } = true;
  170. }
  171. private string GetBlockInfo()
  172. {
  173. if (GameState.IsBuildMode())
  174. {
  175. var block = new Player(PlayerType.Local).GetBlockLookedAt();
  176. float3 pos = block.Position;
  177. float3 rot = block.Rotation;
  178. float3 scale = block.Scale;
  179. return $"Block: {block.Type} at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
  180. $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
  181. $"- Color: {block.Color.Color} darkness: {block.Color.Darkness}\n" +
  182. $"- Scale: {scale.x:F} {scale.y:F} {scale.z:F}\n" +
  183. $"- Label: {block.Label}";
  184. }
  185. if (GameState.IsSimulationMode())
  186. {
  187. var body = new Player(PlayerType.Local).GetSimBodyLookedAt();
  188. float3 pos = body.Position;
  189. float3 rot = body.Rotation;
  190. float3 vel = body.Velocity;
  191. float3 ave = body.AngularVelocity;
  192. float3 com = body.CenterOfMass;
  193. return $"Body at {pos.x:F} {pos.y:F} {pos.z:F}\n" +
  194. $"- Rotation: {rot.x:F}° {rot.y:F}° {rot.z:F}°\n" +
  195. $"- Velocity: {vel.x:F} {vel.y:F} {vel.z:F}\n" +
  196. $"- Angular velocity: {ave.x:F} {ave.y:F} {ave.z:F}\n" +
  197. $"- {(body.Static ? "Static body" : $"Mass: {body.Mass:F} center: {com.x:F} {com.y:F} {com.z:F}")}";
  198. }
  199. return "Switching modes...";
  200. }
  201. private bool CheckNoBlocks(Block[] blocks)
  202. {
  203. if (blocks.Length == 0)
  204. {
  205. Logging.CommandLogWarning("No blocks selected. Use selectBlocks first.");
  206. return true;
  207. }
  208. return false;
  209. }
  210. public IEnumerable<SimBody> GetSimBodies(Block[] blocks)
  211. => blocks.Select(block => block.GetSimBody()).Distinct();
  212. public void OnApplicationQuit()
  213. {
  214. }
  215. public void OnLevelWasLoaded(int level)
  216. {
  217. }
  218. public void OnLevelWasInitialized(int level)
  219. {
  220. }
  221. public void OnUpdate()
  222. {
  223. }
  224. public void OnFixedUpdate()
  225. {
  226. }
  227. public string Name { get; } = "BlockMod";
  228. public string Version { get; } = "v1.0.0";
  229. }
  230. }