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.

TweakableEngine.cs 20KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456
  1. using System;
  2. using System.Reflection;
  3. using RobocraftX.Blocks;
  4. using Gamecraft.Wires;
  5. using Svelto.ECS;
  6. using GamecraftModdingAPI.Utility;
  7. using GamecraftModdingAPI.Engines;
  8. namespace GamecraftModdingAPI.Blocks
  9. {
  10. public class TweakableEngine : IApiEngine
  11. {
  12. public string Name { get; } = "GamecraftModdingAPITweakableGameEngine";
  13. public EntitiesDB entitiesDB { set; private get; }
  14. public bool isRemovable => false;
  15. public bool IsInGame = false;
  16. public void Dispose()
  17. {
  18. IsInGame = false;
  19. }
  20. public void Ready()
  21. {
  22. IsInGame = true;
  23. }
  24. // Implementations for Tweakable static class
  25. public T GetStatAny<T>(EGID blockID, TweakableStat stat)
  26. {
  27. switch (stat)
  28. {
  29. case TweakableStat.TopSpeed:
  30. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  31. {
  32. return (T)(object)entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).maxVelocity;
  33. }
  34. break;
  35. case TweakableStat.Torque:
  36. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  37. {
  38. return (T)(object)entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).maxForce;
  39. }
  40. break;
  41. case TweakableStat.MaxExtension:
  42. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  43. {
  44. return (T)(object)entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID).maxDeviation;
  45. }
  46. break;
  47. case TweakableStat.MinAngle:
  48. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  49. {
  50. return (T)(object)entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).minDeviation;
  51. }
  52. break;
  53. case TweakableStat.MaxAngle:
  54. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  55. {
  56. return (T)(object)entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).maxDeviation;
  57. }
  58. break;
  59. case TweakableStat.Reverse:
  60. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  61. {
  62. return (T)(object)entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).reverse;
  63. }
  64. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  65. {
  66. return (T)(object)entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).reverse;
  67. }
  68. break;
  69. case TweakableStat.StartValue:
  70. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  71. {
  72. return (T)(object)entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID).startValue;
  73. }
  74. break;
  75. }
  76. return default(T);
  77. }
  78. public T GetStatAny<T>(uint blockID, TweakableStat stat)
  79. {
  80. return GetStatAny<T>(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat);
  81. }
  82. public dynamic GetStatDynamic(EGID blockID, TweakableStat stat)
  83. {
  84. switch (stat)
  85. {
  86. case TweakableStat.TopSpeed:
  87. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  88. {
  89. return entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).maxVelocity;
  90. }
  91. break;
  92. case TweakableStat.Torque:
  93. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  94. {
  95. return entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).maxForce;
  96. }
  97. break;
  98. case TweakableStat.MaxExtension:
  99. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  100. {
  101. return entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID).maxDeviation;
  102. }
  103. break;
  104. case TweakableStat.MinAngle:
  105. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  106. {
  107. return entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).minDeviation;
  108. }
  109. break;
  110. case TweakableStat.MaxAngle:
  111. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  112. {
  113. return entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).maxDeviation;
  114. }
  115. break;
  116. case TweakableStat.Reverse:
  117. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  118. {
  119. return entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID).reverse;
  120. }
  121. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  122. {
  123. return entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID).reverse;
  124. }
  125. break;
  126. case TweakableStat.StartValue:
  127. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  128. {
  129. return entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID).startValue;
  130. }
  131. break;
  132. }
  133. return null;
  134. }
  135. public dynamic GetStatDynamic(uint blockID, TweakableStat stat)
  136. {
  137. return GetStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat);
  138. }
  139. public T SetStatAny<T>(EGID blockID, TweakableStat stat, T value)
  140. {
  141. switch (stat)
  142. {
  143. case TweakableStat.TopSpeed:
  144. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  145. {
  146. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  147. refStruct.maxVelocity = (float)(object)value;
  148. return (T)(object)refStruct.maxVelocity;
  149. }
  150. break;
  151. case TweakableStat.Torque:
  152. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  153. {
  154. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  155. refStruct.maxForce = (float)(object)value;
  156. return (T)(object)refStruct.maxForce;
  157. }
  158. break;
  159. case TweakableStat.MaxExtension:
  160. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  161. {
  162. ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID);
  163. refStruct.maxDeviation = (float)(object)value;
  164. return (T)(object)refStruct.maxDeviation;
  165. }
  166. break;
  167. case TweakableStat.MinAngle:
  168. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  169. {
  170. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  171. refStruct.minDeviation = (float)(object)value;
  172. return (T)(object)refStruct.minDeviation;
  173. }
  174. break;
  175. case TweakableStat.MaxAngle:
  176. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  177. {
  178. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  179. refStruct.maxDeviation = (float)(object)value;
  180. return (T)(object)refStruct.maxDeviation;
  181. }
  182. break;
  183. case TweakableStat.Reverse:
  184. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  185. {
  186. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  187. refStruct.reverse = (bool)(object)value;
  188. return (T)(object)refStruct.reverse;
  189. }
  190. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  191. {
  192. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  193. refStruct.reverse = (bool)(object)value;
  194. return (T)(object)refStruct.reverse;
  195. }
  196. break;
  197. case TweakableStat.StartValue:
  198. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  199. {
  200. ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID);
  201. refStruct.startValue = (float)(object)value;
  202. return (T)(object)refStruct.startValue;
  203. }
  204. break;
  205. }
  206. return default(T);
  207. }
  208. public T SetStatAny<T>(uint blockID, TweakableStat stat, T value)
  209. {
  210. return SetStatAny<T>(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
  211. }
  212. public dynamic SetStatDynamic(EGID blockID, TweakableStat stat, dynamic value)
  213. {
  214. switch (stat)
  215. {
  216. case TweakableStat.TopSpeed:
  217. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  218. {
  219. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  220. refStruct.maxVelocity = value;
  221. return refStruct.maxVelocity;
  222. }
  223. break;
  224. case TweakableStat.Torque:
  225. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  226. {
  227. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  228. refStruct.maxForce = value;
  229. return refStruct.maxForce;
  230. }
  231. break;
  232. case TweakableStat.MaxExtension:
  233. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  234. {
  235. ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID);
  236. refStruct.maxDeviation = value;
  237. return refStruct.maxDeviation;
  238. }
  239. break;
  240. case TweakableStat.MinAngle:
  241. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  242. {
  243. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  244. refStruct.minDeviation = value;
  245. return refStruct.minDeviation;
  246. }
  247. break;
  248. case TweakableStat.MaxAngle:
  249. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  250. {
  251. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  252. refStruct.maxDeviation = value;
  253. return refStruct.maxDeviation;
  254. }
  255. break;
  256. case TweakableStat.Reverse:
  257. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  258. {
  259. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  260. refStruct.reverse = value;
  261. return refStruct.reverse;
  262. }
  263. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  264. {
  265. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  266. refStruct.reverse = value;
  267. return refStruct.reverse;
  268. }
  269. break;
  270. case TweakableStat.StartValue:
  271. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  272. {
  273. ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID);
  274. refStruct.startValue = value;
  275. return refStruct.startValue;
  276. }
  277. break;
  278. }
  279. return null;
  280. }
  281. public dynamic SetStatDynamic(uint blockID, TweakableStat stat, dynamic value)
  282. {
  283. return SetStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
  284. }
  285. public T AddStatAny<T>(EGID blockID, TweakableStat stat, T value)
  286. {
  287. switch (stat)
  288. {
  289. case TweakableStat.TopSpeed:
  290. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  291. {
  292. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  293. refStruct.maxVelocity += (float)(object)value;
  294. return (T)(object)refStruct.maxVelocity;
  295. }
  296. break;
  297. case TweakableStat.Torque:
  298. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  299. {
  300. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  301. refStruct.maxForce += (float)(object)value;
  302. return (T)(object)refStruct.maxForce;
  303. }
  304. break;
  305. case TweakableStat.MaxExtension:
  306. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  307. {
  308. ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID);
  309. refStruct.maxDeviation += (float)(object)value;
  310. return (T)(object)refStruct.maxDeviation;
  311. }
  312. break;
  313. case TweakableStat.MinAngle:
  314. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  315. {
  316. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  317. refStruct.minDeviation += (float)(object)value;
  318. return (T)(object)refStruct.minDeviation;
  319. }
  320. break;
  321. case TweakableStat.MaxAngle:
  322. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  323. {
  324. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  325. refStruct.maxDeviation += (float)(object)value;
  326. return (T)(object)refStruct.maxDeviation;
  327. }
  328. break;
  329. case TweakableStat.Reverse:
  330. // '+' is associated with logical OR in some fields, so it technically isn't invalid to "add" booleans
  331. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  332. {
  333. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  334. refStruct.reverse = refStruct.reverse || (bool)(object)value;
  335. return (T)(object)refStruct.reverse;
  336. }
  337. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  338. {
  339. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  340. refStruct.reverse = refStruct.reverse || (bool)(object)value;
  341. return (T)(object)refStruct.reverse;
  342. }
  343. break;
  344. case TweakableStat.StartValue:
  345. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  346. {
  347. ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID);
  348. refStruct.startValue += (float)(object)value;
  349. return (T)(object)refStruct.startValue;
  350. }
  351. break;
  352. }
  353. return default(T);
  354. }
  355. public T AddStatAny<T>(uint blockID, TweakableStat stat, T value)
  356. {
  357. return AddStatAny<T>(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
  358. }
  359. public dynamic AddStatDynamic(EGID blockID, TweakableStat stat, dynamic value)
  360. {
  361. switch (stat)
  362. {
  363. case TweakableStat.TopSpeed:
  364. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  365. {
  366. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  367. refStruct.maxVelocity += value;
  368. return refStruct.maxVelocity;
  369. }
  370. break;
  371. case TweakableStat.Torque:
  372. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  373. {
  374. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  375. refStruct.maxForce += value;
  376. return refStruct.maxForce;
  377. }
  378. break;
  379. case TweakableStat.MaxExtension:
  380. if (entitiesDB.Exists<PistonReadOnlyStruct>(blockID))
  381. {
  382. ref PistonReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<PistonReadOnlyStruct>(blockID);
  383. refStruct.maxDeviation += value;
  384. return refStruct.maxDeviation;
  385. }
  386. break;
  387. case TweakableStat.MinAngle:
  388. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  389. {
  390. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  391. refStruct.minDeviation += value;
  392. return refStruct.minDeviation;
  393. }
  394. break;
  395. case TweakableStat.MaxAngle:
  396. if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  397. {
  398. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  399. refStruct.maxDeviation += value;
  400. return refStruct.maxDeviation;
  401. }
  402. break;
  403. case TweakableStat.Reverse:
  404. // '+' is associated with logical OR in some fields, so it technically isn't invalid to "add" booleans
  405. if (entitiesDB.Exists<MotorReadOnlyStruct>(blockID))
  406. {
  407. ref MotorReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<MotorReadOnlyStruct>(blockID);
  408. refStruct.reverse = refStruct.reverse || value;
  409. return refStruct.reverse;
  410. }
  411. else if (entitiesDB.Exists<ServoReadOnlyStruct>(blockID))
  412. {
  413. ref ServoReadOnlyStruct refStruct = ref entitiesDB.QueryEntity<ServoReadOnlyStruct>(blockID);
  414. refStruct.reverse = refStruct.reverse || value;
  415. return refStruct.reverse;
  416. }
  417. break;
  418. case TweakableStat.StartValue:
  419. if (entitiesDB.Exists<SignalGeneratorEntityStruct>(blockID))
  420. {
  421. ref SignalGeneratorEntityStruct refStruct = ref entitiesDB.QueryEntity<SignalGeneratorEntityStruct>(blockID);
  422. refStruct.startValue += value;
  423. return refStruct.startValue;
  424. }
  425. break;
  426. }
  427. return null;
  428. }
  429. public dynamic AddStatDynamic(uint blockID, TweakableStat stat, dynamic value)
  430. {
  431. return AddStatDynamic(new EGID(blockID, BlockIdentifiers.OWNED_BLOCKS), stat, value);
  432. }
  433. }
  434. }