IC Instance Restore on Ctrl + Z

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

  1. // ==UserScript==
  2. // @name IC Instance Restore on Ctrl + Z
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.6.5
  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.AT ||= {}).controlzdata = {
  18. ingredientInstances: {
  19. deletedInstances: [],
  20. InstanceIds: []
  21. },
  22. resultInstances: {
  23. deletedInstances: [],
  24. InstanceIds: []
  25. },
  26. infinitecraft: null,
  27.  
  28. processInstance: function (instanceCopy) {
  29. if (instanceCopy.isNew) {
  30. instanceCopy.isNew = false;
  31. }
  32. },
  33.  
  34. updateIds: function (oldId, newId) {
  35. const replaceId = (list) => {
  36. for (let pair of list) {
  37. const index = pair.indexOf(oldId);
  38. if (index !== -1) {
  39. pair[index] = newId;
  40. }
  41. }
  42. };
  43.  
  44. replaceId(this.resultInstances.InstanceIds);
  45. replaceId(this.ingredientInstances.InstanceIds);
  46. },
  47.  
  48. deleteInstance: function (id) {
  49. const instances = this.infinitecraft.instances;
  50. const index = instances.findIndex(instance => instance.id === id);
  51.  
  52. if (index !== -1) {
  53. const deletedInstance = { ...instances[index] };
  54. instances.splice(index, 1);
  55. return deletedInstance; // Return deleted instance
  56. }
  57. return null;
  58. },
  59.  
  60. makeInstance: function (instanceCopy) {
  61. this.processInstance(instanceCopy); // Remove pinwheel and therefore also the pinwheel glitch
  62.  
  63. const newInstance = Object.assign({}, instanceCopy);
  64. newInstance.id = this.infinitecraft.instanceId++;
  65. newInstance.elem = null;
  66. newInstance.hasMoved = false;
  67. newInstance.fromPanel = false;
  68. newInstance.disabled = false;
  69. this.infinitecraft.instances.push(newInstance);
  70.  
  71. this.infinitecraft.$nextTick(() => {
  72. newInstance.elem = document.getElementById("instance-" + newInstance.id);
  73. if (newInstance.elem) {
  74. this.infinitecraft.setInstancePosition(newInstance, newInstance.left, newInstance.top);
  75. this.infinitecraft.setInstanceZIndex(newInstance, this.infinitecraft.instanceId);
  76. }
  77. });
  78.  
  79. if (newInstance) {
  80. this.updateIds(instanceCopy.id, newInstance.id);
  81. }
  82.  
  83. return newInstance ? newInstance.id : null; // Return id of recreated instance
  84. },
  85.  
  86. restoreInstances: function () {
  87. if (this.ingredientInstances.deletedInstances.length > 0) {
  88. const instancePair = this.ingredientInstances.deletedInstances.pop();
  89. const [instanceA, instanceB] = instancePair;
  90.  
  91. const instanceAId = this.makeInstance(instanceA); // Reinstate ingredients
  92. const instanceBId = this.makeInstance(instanceB);
  93.  
  94. if (instanceAId && instanceBId) {
  95. this.ingredientInstances.InstanceIds.push([instanceAId, instanceBId]);
  96. }
  97.  
  98. const resultInstanceId = this.resultInstances.InstanceIds.pop()?.[0];
  99. if (resultInstanceId) {
  100. const deletedInstance = this.deleteInstance(resultInstanceId); // Delete result instance
  101. if (deletedInstance) {
  102. this.resultInstances.deletedInstances.push(deletedInstance);
  103. }
  104. }
  105. }
  106. },
  107.  
  108. unrestoreInstances: function () {
  109. if (this.ingredientInstances.InstanceIds.length > 0) {
  110. const lastRestoredIds = this.ingredientInstances.InstanceIds.pop();
  111. const [instanceAId, instanceBId] = lastRestoredIds;
  112.  
  113. const instanceA = this.deleteInstance(instanceAId); // Delete ingredient instances
  114. const instanceB = this.deleteInstance(instanceBId);
  115.  
  116. if (instanceA && instanceB) {
  117. this.ingredientInstances.deletedInstances.push([instanceA, instanceB]);
  118. }
  119.  
  120. if (this.resultInstances.deletedInstances.length > 0) {
  121. const deletedInstance = this.resultInstances.deletedInstances.pop();
  122. const newInstanceId = this.makeInstance(deletedInstance); // Make result instances
  123. if (newInstanceId) {
  124. this.resultInstances.InstanceIds.push([newInstanceId]);
  125. }
  126. }
  127. }
  128. },
  129.  
  130. start: function () {
  131. if (document.querySelector(".container").__vue__) { // Wait for Nuxt
  132.  
  133. this.infinitecraft = document.querySelector(".container").__vue__; // Assign Infinite Craft
  134. const ogGCR = this.infinitecraft.getCraftResponse;
  135. this.infinitecraft.getCraftResponse = async function (instanceA, instanceB) { // Patch getCraftResponse to intercept and save stuff
  136. const response = await ogGCR.apply(this, arguments);
  137.  
  138. if (instanceA.elem && instanceB.elem) { // Used to detect if it's used through GUI or console
  139. window.AT.controlzdata.ingredientInstances.deletedInstances.push([{ ...instanceA }, { ...instanceB }]);
  140. window.AT.controlzdata.resultInstances.InstanceIds.push([this.instanceId]);
  141. window.AT.controlzdata.resultInstances.deletedInstances = [];
  142. window.AT.controlzdata.ingredientInstances.InstanceIds = [];
  143. }
  144.  
  145. return response;
  146. };
  147.  
  148. document.addEventListener("keydown", function (event) { // To make the script actually do something
  149. if (event.ctrlKey && event.key === "z") {
  150. window.AT.controlzdata.restoreInstances();
  151. }
  152. if (event.ctrlKey && event.key === "y") {
  153. window.AT.controlzdata.unrestoreInstances();
  154. }
  155. });
  156. } else {
  157. setTimeout(this.start.bind(this), 2000); // Change the timeout if it still conflicts with other scripts
  158. }
  159. }
  160. };
  161.  
  162. window.AT.controlzdata.start();
  163. })();

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址