A stable modding interface between Techblox and mods https://mod.exmods.org/
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.

277 lines
9.2KB

  1. using System;
  2. using Svelto.ECS;
  3. using TechbloxModdingAPI.Utility;
  4. namespace TechbloxModdingAPI.Commands
  5. {
  6. /// <summary>
  7. /// Custom Command builder.
  8. /// </summary>
  9. public class CommandBuilder
  10. {
  11. private string name;
  12. private string description;
  13. private short parameterCount;
  14. private ICustomCommandEngine commandEngine;
  15. private bool fromExisting = false;
  16. /// <summary>
  17. /// Create a new command builder.
  18. /// </summary>
  19. public CommandBuilder()
  20. {
  21. name = "";
  22. description = null;
  23. parameterCount = -1;
  24. }
  25. /// <summary>
  26. /// Create and return a command builder.
  27. /// </summary>
  28. /// <returns>The builder.</returns>
  29. public static CommandBuilder Builder()
  30. {
  31. return new CommandBuilder();
  32. }
  33. /// <summary>
  34. /// Create a new command builder.
  35. /// </summary>
  36. /// <param name="name">The command name.</param>
  37. /// <param name="description">The command description (shown in help).</param>
  38. public CommandBuilder(string name, string description = null)
  39. {
  40. this.name = name;
  41. this.description = description;
  42. parameterCount = -1;
  43. }
  44. /// <summary>
  45. /// Create and return a command builder.
  46. /// If name and description are provided, this is equivalent to <code>Builder().Name(name).Description(description)</code>
  47. /// </summary>
  48. /// <param name="name">The command name.</param>
  49. /// <param name="description">The command description (shown in help).</param>
  50. /// <returns>The builder.</returns>
  51. public static CommandBuilder Builder(string name, string description = null)
  52. {
  53. return new CommandBuilder(name, description);
  54. }
  55. /// <summary>
  56. /// Name the command.
  57. /// </summary>
  58. /// <returns>The builder.</returns>
  59. /// <param name="name">The command name.</param>
  60. public CommandBuilder Name(string name)
  61. {
  62. this.name = name;
  63. return this;
  64. }
  65. /// <summary>
  66. /// Describe the command.
  67. /// </summary>
  68. /// <returns>The builder.</returns>
  69. /// <param name="description">The command description (shown in help).</param>
  70. public CommandBuilder Description(string description)
  71. {
  72. this.description = description;
  73. return this;
  74. }
  75. /// <summary>
  76. /// Set the action the command performs.
  77. /// </summary>
  78. /// <returns>The builder.</returns>
  79. /// <param name="action">The action to perform when the command is called.</param>
  80. public CommandBuilder Action(Action action)
  81. {
  82. parameterCount = 0;
  83. commandEngine = new SimpleCustomCommandEngine(action, name, description);
  84. return this;
  85. }
  86. /// <summary>
  87. /// Set the action the command performs.
  88. /// </summary>
  89. /// <returns>The builder.</returns>
  90. /// <param name="action">The action to perform when the command is called.</param>
  91. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  92. public CommandBuilder Action<A>(Action<A> action)
  93. {
  94. parameterCount = 1;
  95. commandEngine = new SimpleCustomCommandEngine<A>(action, name, description);
  96. return this;
  97. }
  98. /// <summary>
  99. /// Set the action the command performs.
  100. /// </summary>
  101. /// <returns>The builder.</returns>
  102. /// <param name="action">The action to perform when the command is called.</param>
  103. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  104. /// <typeparam name="B">The 2nd parameter's type.</typeparam>
  105. public CommandBuilder Action<A,B>(Action<A,B> action)
  106. {
  107. parameterCount = 2;
  108. commandEngine = new SimpleCustomCommandEngine<A,B>(action, name, description);
  109. return this;
  110. }
  111. /// <summary>
  112. /// Set the action the command performs.
  113. /// </summary>
  114. /// <returns>The builder.</returns>
  115. /// <param name="action">The action to perform when the command is called.</param>
  116. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  117. /// <typeparam name="B">The 2nd parameter's type.</typeparam>
  118. /// <typeparam name="C">The 3rd parameter's type.</typeparam>
  119. public CommandBuilder Action<A,B,C>(Action<A,B,C> action)
  120. {
  121. parameterCount = 3;
  122. commandEngine = new SimpleCustomCommandEngine<A,B,C>(action, name, description);
  123. return this;
  124. }
  125. /// <summary>
  126. /// Build the command from an existing command.
  127. /// </summary>
  128. /// <returns>The command. Use Invoke() to execute it.</returns>
  129. public SimpleCustomCommandEngine FromExisting()
  130. {
  131. if (string.IsNullOrWhiteSpace(name))
  132. {
  133. throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called");
  134. }
  135. if (!ExistingCommands.Exists(name))
  136. {
  137. throw new CommandNotFoundException("Command cannot be built from existing because it does not exist.");
  138. }
  139. fromExisting = true;
  140. return new SimpleCustomCommandEngine(
  141. () => { ExistingCommands.Call(name); },
  142. name,
  143. description);
  144. }
  145. /// <summary>
  146. /// Build the command from an existing command.
  147. /// </summary>
  148. /// <returns>The command. Use Invoke() to execute it.</returns>
  149. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  150. public SimpleCustomCommandEngine<A> FromExisting<A>()
  151. {
  152. if (string.IsNullOrWhiteSpace(name))
  153. {
  154. throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called");
  155. }
  156. if (!ExistingCommands.Exists(name))
  157. {
  158. throw new CommandNotFoundException("Command cannot be built from existing because it does not exist.");
  159. }
  160. fromExisting = true;
  161. return new SimpleCustomCommandEngine<A>(
  162. (A a) => { ExistingCommands.Call<A>(name, a); },
  163. name,
  164. description);
  165. }
  166. /// <summary>
  167. /// Build the command from an existing command.
  168. /// </summary>
  169. /// <returns>The command. Use Invoke() to execute it.</returns>
  170. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  171. /// <typeparam name="B">The 2nd parameter's type.</typeparam>
  172. public SimpleCustomCommandEngine<A,B> FromExisting<A,B>()
  173. {
  174. if (string.IsNullOrWhiteSpace(name))
  175. {
  176. throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called");
  177. }
  178. if (!ExistingCommands.Exists(name))
  179. {
  180. throw new CommandNotFoundException("Command cannot be built from existing because it does not exist.");
  181. }
  182. fromExisting = true;
  183. return new SimpleCustomCommandEngine<A,B>(
  184. (A a, B b) => { ExistingCommands.Call<A,B>(name, a, b); },
  185. name,
  186. description);
  187. }
  188. /// <summary>
  189. /// Build the command from an existing command.
  190. /// </summary>
  191. /// <returns>The command. Use Invoke() to execute it.</returns>
  192. /// <typeparam name="A">The 1st parameter's type.</typeparam>
  193. /// <typeparam name="B">The 2nd parameter's type.</typeparam>
  194. /// <typeparam name="C">The 3rd parameter's type.</typeparam>
  195. public SimpleCustomCommandEngine<A,B,C> FromExisting<A,B,C>()
  196. {
  197. if (string.IsNullOrWhiteSpace(name))
  198. {
  199. throw new CommandParameterMissingException("Command name must be defined before FromExisting() is called");
  200. }
  201. if (!ExistingCommands.Exists(name))
  202. {
  203. throw new CommandNotFoundException("Command cannot be built from existing because it does not exist.");
  204. }
  205. fromExisting = true;
  206. return new SimpleCustomCommandEngine<A,B,C>(
  207. (A a, B b, C c) => { ExistingCommands.Call<A,B,C>(name, a, b, c); },
  208. name,
  209. description);
  210. }
  211. /// <summary>
  212. /// Build the command.
  213. /// </summary>
  214. /// <returns>The built command.</returns>
  215. /// <param name="register">Automatically register the command with CommandManager.AddCommand()?</param>
  216. public ICustomCommandEngine Build(bool register = true)
  217. {
  218. if (string.IsNullOrWhiteSpace(name))
  219. {
  220. throw new CommandParameterMissingException("Command name must be defined before Build() is called");
  221. }
  222. if (fromExisting)
  223. {
  224. throw new CommandAlreadyBuiltException("Command was already built by FromExisting()");
  225. }
  226. if (commandEngine == null)
  227. {
  228. throw new CommandParameterMissingException("Command action must be defined before Build() is called");
  229. }
  230. if (string.IsNullOrWhiteSpace(description))
  231. {
  232. Logging.LogWarning($"Command {FullName()} was built without a description");
  233. }
  234. if (register)
  235. {
  236. CommandManager.AddCommand(commandEngine);
  237. Logging.MetaDebugLog($"Command {FullName()} was automatically registered");
  238. }
  239. return commandEngine;
  240. }
  241. /// <summary>
  242. /// Get the full command name, in the form [name]::[description]::[# of parameters]
  243. /// </summary>
  244. /// <returns>The name.</returns>
  245. public string FullName()
  246. {
  247. if (string.IsNullOrWhiteSpace(description))
  248. {
  249. return name + "::" + parameterCount;
  250. }
  251. return name + "::" + description + "::" + parameterCount;
  252. }
  253. }
  254. }