Magically import images and more into Gamecraft as blocks
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.

125 lines
4.3KB

  1. using System;
  2. using System.Diagnostics;
  3. using System.IO;
  4. using System.Net;
  5. using System.Text;
  6. using Unity.Mathematics;
  7. using GamecraftModdingAPI;
  8. using GamecraftModdingAPI.Blocks;
  9. using GamecraftModdingAPI.Commands;
  10. using GamecraftModdingAPI.Players;
  11. using GamecraftModdingAPI.Utility;
  12. namespace Pixi.Robots
  13. {
  14. public static class RobotCommands
  15. {
  16. private static double blockSize = 0.2;
  17. public static void CreateRobotFileCommand()
  18. {
  19. CommandBuilder.Builder()
  20. .Name("PixiBotFile")
  21. .Description("Converts a robot file from RCBUP into Gamecraft blocks. Larger robots will freeze your game until conversion completes.")
  22. .Action<string>(ImportRobotFile)
  23. .Build();
  24. }
  25. public static void CreateRobotCRFCommand()
  26. {
  27. CommandBuilder.Builder()
  28. .Name("PixiBot")
  29. .Description("Downloads a robot from Robocraft's Factory and converts it into Gamecraft blocks. Larger robots will freeze your game until conversion completes.")
  30. .Action<string>(ImportRobotOnline)
  31. .Build();
  32. }
  33. private static void ImportRobotFile(string filepath)
  34. {
  35. string file;
  36. try
  37. {
  38. file = File.ReadAllText(filepath);
  39. }
  40. catch (Exception e)
  41. {
  42. Logging.CommandLogError($"Failed to load robot data. Reason: {e.Message}");
  43. Logging.MetaLog(e);
  44. return;
  45. }
  46. RobotStruct? robot = CubeUtility.ParseRobotInfo(file);
  47. if (!robot.HasValue)
  48. {
  49. Logging.CommandLogError($"Failed to parse robot data. File format was not recognised.");
  50. return;
  51. }
  52. float3 position = new Player(PlayerType.Local).Position;
  53. position.y += (float)blockSize;
  54. CubeInfo[] cubes = CubeUtility.ParseCubes(robot.Value);
  55. Block[] blocks = new Block[cubes.Length];
  56. for (int c = 0; c < cubes.Length; c++) // sometimes I wish this were C++
  57. {
  58. CubeInfo cube = cubes[c];
  59. float3 realPosition = (cube.position * (float)blockSize) + position;
  60. blocks[c] = Block.PlaceNew(cube.block, realPosition, cube.rotation, cube.color, cube.darkness, scale: cube.scale);
  61. }
  62. for (int c = 0; c < cubes.Length; c++)
  63. {
  64. CubeInfo cube = cubes[c];
  65. // the goal is for this to never evaluate to true (ie all cubes are translated correctly)
  66. if (!string.IsNullOrEmpty(cube.name) && cube.block == BlockIDs.TextBlock)
  67. {
  68. blocks[c].Specialise<TextBlock>().Text = cube.name;
  69. }
  70. }
  71. Logging.CommandLog($"Placed {robot.Value.name} by {robot.Value.addedByDisplayName} ({cubes.Length} cubes) beside you");
  72. }
  73. private static void ImportRobotOnline(string robotName)
  74. {
  75. Stopwatch timer = Stopwatch.StartNew();
  76. // download robot data
  77. RobotStruct robot;
  78. try
  79. {
  80. RobotBriefStruct[] botList = RoboAPIUtility.ListRobots(robotName);
  81. if (botList.Length == 0)
  82. throw new Exception("Failed to find robot");
  83. robot = RoboAPIUtility.QueryRobotInfo(botList[0].itemId);
  84. }
  85. catch (Exception e)
  86. {
  87. Logging.CommandLogError($"Failed to download robot data. Reason: {e.Message}");
  88. Logging.MetaLog(e);
  89. timer.Stop();
  90. return;
  91. }
  92. timer.Stop();
  93. Logging.MetaLog($"Completed API calls in {timer.ElapsedMilliseconds}ms");
  94. float3 position = new Player(PlayerType.Local).Position;
  95. position.y += (float)blockSize;
  96. CubeInfo[] cubes = CubeUtility.ParseCubes(robot);
  97. Block[] blocks = new Block[cubes.Length];
  98. for (int c = 0; c < cubes.Length; c++) // sometimes I wish this were C++
  99. {
  100. CubeInfo cube = cubes[c];
  101. float3 realPosition = (cube.position * (float)blockSize) + position;
  102. blocks[c] = Block.PlaceNew(cube.block, realPosition, cube.rotation, cube.color, cube.darkness, scale: cube.scale);
  103. }
  104. for (int c = 0; c < cubes.Length; c++)
  105. {
  106. CubeInfo cube = cubes[c];
  107. // the goal is for this to never evaluate to true (ie all cubes are translated correctly)
  108. if (!string.IsNullOrEmpty(cube.name) && cube.block == BlockIDs.TextBlock)
  109. {
  110. blocks[c].Specialise<TextBlock>().Text = cube.name;
  111. }
  112. }
  113. Logging.CommandLog($"Placed {robot.name} by {robot.addedByDisplayName} ({cubes.Length} cubes) beside you");
  114. }
  115. }
  116. }