IC Instance Restore on Ctrl + Z

Undo a craft with Ctrl + Z and redo with Ctrl + Y

目前為 2024-12-23 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name IC Instance Restore on Ctrl + Z
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6.2
  5. // @license MIT
  6. // @description Undo a craft with Ctrl + Z and redo with Ctrl + Y
  7. // @icon https://i.imgur.com/WlkWOkU.png
  8. // @author @activetutorial on discord
  9. // @match https://neal.fun/infinite-craft/
  10. // @run-at document-end
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. (function () {
  15. 'use strict';
  16.  
  17. window.controlzdata = {
  18. ingredientInstances: {
  19. deletedInstances: [],
  20. InstanceIds: []
  21. },
  22. resultInstances: {
  23. deletedInstances: [],
  24. InstanceIds: []
  25. },
  26. infinitecraft: null,
  27.  
  28. updateIds: function (oldId, newId) { // To fix the bug that I could't explain
  29. const replaceId = (list) => {
  30. for (let pair of list) {
  31. const index = pair.indexOf(oldId);
  32. if (index !== -1) {
  33. pair[index] = newId;
  34. }
  35. }
  36. };
  37.  
  38. replaceId(this.resultInstances.InstanceIds);
  39. replaceId(this.ingredientInstances.InstanceIds);
  40. },
  41.  
  42. deleteInstance: function (id) {
  43. const instances = this.infinitecraft.instances;
  44. const index = instances.findIndex(instance => instance.id === id);
  45.  
  46. if (index !== -1) {
  47. const deletedInstance = { ...instances[index] };
  48. instances.splice(index, 1);
  49. return deletedInstance; // Return deleted instance
  50. }
  51. return null;
  52. },
  53.  
  54. makeInstance: function (instanceCopy) {
  55. instanceCopy.left -= 10; // Move it in the oppisite direction that duplicateInstance does
  56. instanceCopy.top += 10;
  57. this.infinitecraft.duplicateInstance(instanceCopy);
  58. const newInstance = this.infinitecraft.instances.at(-1);
  59.  
  60. if (newInstance) {
  61. this.updateIds(instanceCopy.id, newInstance.id);
  62. }
  63.  
  64. return newInstance ? newInstance.id : null; // Return id of recreated instance
  65. },
  66.  
  67. restoreInstances: function () {
  68. if (this.ingredientInstances.deletedInstances.length > 0) {
  69. const instancePair = this.ingredientInstances.deletedInstances.pop();
  70. const [instanceA, instanceB] = instancePair;
  71.  
  72. const instanceAId = this.makeInstance(instanceA); // Reinstate ingredients
  73. const instanceBId = this.makeInstance(instanceB);
  74.  
  75. if (instanceAId && instanceBId) {
  76. this.ingredientInstances.InstanceIds.push([instanceAId, instanceBId]);
  77. }
  78.  
  79. const resultInstanceId = this.resultInstances.InstanceIds.pop()?.[0];
  80. if (resultInstanceId) {
  81. const deletedInstance = this.deleteInstance(resultInstanceId); // Delete result instance
  82. if (deletedInstance) {
  83. this.resultInstances.deletedInstances.push(deletedInstance);
  84. }
  85. }
  86. }
  87. },
  88.  
  89. unrestoreInstances: function () {
  90. if (this.ingredientInstances.InstanceIds.length > 0) {
  91. const lastRestoredIds = this.ingredientInstances.InstanceIds.pop();
  92. const [instanceAId, instanceBId] = lastRestoredIds;
  93.  
  94. const instanceA = this.deleteInstance(instanceAId); // Delete ingredient instances
  95. const instanceB = this.deleteInstance(instanceBId);
  96.  
  97. if (instanceA && instanceB) {
  98. this.ingredientInstances.deletedInstances.push([instanceA, instanceB]);
  99. }
  100.  
  101. if (this.resultInstances.deletedInstances.length > 0) {
  102. const deletedInstance = this.resultInstances.deletedInstances.pop();
  103. const newInstanceId = this.makeInstance(deletedInstance); // Make result instances
  104. if (newInstanceId) {
  105. this.resultInstances.InstanceIds.push([newInstanceId]);
  106. }
  107. }
  108. }
  109. }
  110. };
  111.  
  112. function start() {
  113. if (window.$nuxt && window.$nuxt.$root && window.$nuxt.$root.$children[1] && window.$nuxt.$root.$children[1].$children[0]) { // Wait for Nuxt
  114.  
  115. window.controlzdata.infinitecraft = window.$nuxt.$root.$children[1].$children[0].$children[0]; // Assign Infinite Craft
  116. const ogGCR = window.controlzdata.infinitecraft.getCraftResponse;
  117. window.controlzdata.infinitecraft.getCraftResponse = async function (instanceA, instanceB) { // Patch getCraftResponse to intercept and save stuff
  118. const response = await ogGCR.apply(this, arguments);
  119.  
  120. if (instanceA.elem && instanceB.elem) { // Used to detect if it's used through GUI or console
  121. window.controlzdata.ingredientInstances.deletedInstances.push([{ ...instanceA }, { ...instanceB }]);
  122. window.controlzdata.resultInstances.InstanceIds.push([this.instanceId += 2]);
  123. window.controlzdata.resultInstances.deletedInstances = [];
  124. window.controlzdata.ingredientInstances.InstanceIds = [];
  125. }
  126.  
  127. return response;
  128. };
  129.  
  130. document.addEventListener("keydown", function (event) { // To make the script acctually do something
  131. if (event.ctrlKey && event.key === "z") {
  132. window.controlzdata.restoreInstances();
  133. }
  134. if (event.ctrlKey && event.key === "y") {
  135. window.controlzdata.unrestoreInstances();
  136. }
  137. });
  138. } else {
  139. setTimeout(start, 2000); // Change the timeout if it still conflicts with outher scripts
  140. }
  141. }
  142.  
  143. start();
  144. })();