IC Auto Crafter

Automatically craft by inputting a lineage.

当前为 2025-01-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name IC Auto Crafter
  3. // @namespace http://tampermonkey.net/
  4. // @version 1.3
  5. // @license MIT
  6. // @description Automatically craft by inputting a lineage.
  7. // @icon https://i.imgur.com/WlkWOkU.png
  8. // @author @activetutorial on discord
  9. // @match https://neal.fun/infinite-craft/
  10. // @match http://localhost:3000/infinite-craft/
  11. // @run-at document-end
  12. // @grant none
  13. // ==/UserScript==
  14.  
  15. (function() {
  16. "use strict";
  17.  
  18. (window.AT ||= {}).autocrafterdata = {
  19. iconthing: "data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iaXNvLTg4NTktMSI/Pg0KPCEtLSBVcGxvYWRlZCB0bzogU1ZHIFJlcG8sIHd3dy5zdmdyZXBvLmNvbSwgR2VuZXJhdG9yOiBTVkcgUmVwbyBNaXhlciBUb29scyAtLT4NCjwhRE9DVFlQRSBzdmcgUFVCTElDICItLy9XM0MvL0RURCBTVkcgMS4xLy9FTiIgImh0dHA6Ly93d3cudzMub3JnL0dyYXBoaWNzL1NWRy8xLjEvRFREL3N2ZzExLmR0ZCI+DQo8c3ZnIGZpbGw9IiMwMDAwMDAiIHZlcnNpb249IjEuMSIgaWQ9IkNhcGFfMSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiB4bWxuczp4bGluaz0iaHR0cDovL3d3dy53My5vcmcvMTk5OS94bGluayIgDQoJIHdpZHRoPSI4MDBweCIgaGVpZ2h0PSI4MDBweCIgdmlld0JveD0iMCAwIDQ1LjM2MyA0NS4zNjMiDQoJIHhtbDpzcGFjZT0icHJlc2VydmUiPg0KPGc+DQoJPGc+DQoJCTxwYXRoIGQ9Ik0xLjc4OCwxNi45NDVjMC4zODgsMC4zODUsMC45MTMsMC42MDEsMS40NTksMC42MDFsMjcuNDkzLTAuMDM1djMuODMxYzAuMDAzLDAuODM2LDAuNTU2LDEuNTg2LDEuMzI5LDEuOTA0DQoJCQljMC43NzEsMC4zMTQsMS42NTgsMC4xMzUsMi4yNDYtMC40NTlsOS4wOTEtOS4xOGMxLjA2Mi0xLjA3MSwxLjA2LTIuODAxLTAuMDA5LTMuODY4bC05LjEzNy05LjEzNA0KCQkJYy0wLjU5LTAuNTkxLTEuNDc5LTAuNzY4LTIuMjUtMC40NDZjLTAuNzcsMC4zMTktMS4yNzEsMS4wNzQtMS4yNywxLjkwOEwzMC43NCw1LjlMMy4yMTksNS45MzcNCgkJCUMyLjA4LDUuOTQsMS4xNjEsNi44NjQsMS4xNjMsOC4wMDRsMC4wMTgsNy40ODNDMS4xODIsMTYuMDM0LDEuNDAxLDE2LjU2LDEuNzg4LDE2Ljk0NXoiLz4NCgkJPHBhdGggZD0iTTQyLjE0NiwyNy45MDFsLTI3LjUyMi0wLjAzNWwtMC4wMDEtMy44MzRjMC4wMDItMC44MzUtMC41LTEuNTg3LTEuMjctMS45MDdjLTAuNzcxLTAuMzIxLTEuNjYtMC4xNDYtMi4yNSwwLjQ0NQ0KCQkJbC05LjEzNiw5LjEzNWMtMS4wNjcsMS4wNjQtMS4wNzEsMi43OTYtMC4wMDksMy44NjZsOS4wOSw5LjE4MWMwLjU4OCwwLjU5NiwxLjQ3NSwwLjc3MiwyLjI0NywwLjQ1OA0KCQkJYzAuNzcyLTAuMzE2LDEuMzI2LTEuMDY2LDEuMzI5LTEuOTA0di0zLjgzbDI3LjQ5MywwLjAzNWMwLjU0NywwLDEuMDcyLTAuMjE2LDEuNDU5LTAuNjAyczAuNjA1LTAuOTEsMC42MDctMS40NTZMNDQuMiwyOS45Nw0KCQkJQzQ0LjIwMywyOC44Myw0My4yODQsMjcuOTAzLDQyLjE0NiwyNy45MDF6Ii8+DQoJPC9nPg0KPC9nPg0KPC9zdmc+",
  20. infinitecraft: null,
  21. autocraftButton: null,
  22. anticheat: true,
  23. isCrafting: false,
  24. popupHTML: `
  25. <style>
  26. body {
  27. margin: 0;
  28. font-family: Arial, sans-serif;
  29. background-color: #1e1e1e;
  30. color: #f0f0f0;
  31. display: flex;
  32. flex-direction: column;
  33. align-items: center;
  34. justify-content: center;
  35. height: 100%;
  36. }
  37. textarea {
  38. width: 90%;
  39. height: 100px;
  40. margin-bottom: 10px;
  41. background-color: #2d2d2d;
  42. color: #f0f0f0;
  43. border: 1px solid #555;
  44. border-radius: 5px;
  45. padding: 10px;
  46. }
  47. label {
  48. font-size: 14px;
  49. }
  50. input[type="checkbox"] {
  51. margin-right: 5px;
  52. }
  53. hr {
  54. width: 90%;
  55. border: none;
  56. border-top: 1px solid #555;
  57. margin: 15px 0;
  58. }
  59. .highlight {
  60. font-weight: bold;
  61. color: #ffffff; /* Plain white */
  62. margin-bottom: 20px; /* Increased spacing */
  63. }
  64. button {
  65. color: #ffffff; /* White text */
  66. font-weight: bold;
  67. text-shadow: 1px 1px 2px #000000; /* Black outline for text */
  68. border: none;
  69. border-radius: 5px;
  70. padding: 10px 20px;
  71. cursor: pointer;
  72. font-size: 16px;
  73. margin-top: 20px; /* Increased spacing */
  74. }
  75. button#submitButton {
  76. background-color: #4caf50;
  77. }
  78. button#submitButton:hover {
  79. filter: brightness(0.9);
  80. }
  81. button#autoCraftButton {
  82. background-color: #d4b106; /* Less vibrant yellow */
  83. }
  84. button#autoCraftButton:hover {
  85. filter: brightness(0.9);
  86. }
  87. </style>
  88. <textarea id="userInput" placeholder="Enter your lineage..."></textarea>
  89. <button id="submitButton">Craft</button>
  90. <hr>
  91. <div class="highlight">Cheating section:</div>
  92. <label>
  93. <input type="checkbox" id="anticheatToggle" checked> Enable Anti-Cheat
  94. </label>
  95. <button id="autoCraftButton"></button>`,
  96. processLineage: async function () {
  97. const userInput = await this.getUserInput();
  98. console.log(userInput);
  99. if (typeof userInput.autoCraft === "boolean"){
  100. console.log("Auto craft started/stopped", this.isCrafting);
  101. this.craftSomething();
  102. return;
  103. }
  104. const { lineage, anticheatEnabled } = userInput;
  105. this.anticheat = anticheatEnabled; // Update anticheat option
  106. const recipes = this.parseRecipes(lineage);
  107. console.log(recipes);
  108.  
  109. for (let i = 0; i < recipes.length; i++) {
  110. const [string1, string2] = recipes[i];
  111. // Anti cheat
  112. const element1Exists = this.infinitecraft.elements.some(el => el.text?.toLowerCase() === string1?.toLowerCase());
  113. const element2Exists = this.infinitecraft.elements.some(el => el.text?.toLowerCase() === string2?.toLowerCase());
  114. if (!this.anticheat || (element1Exists && element2Exists)) {
  115. await this.infinitecraft.craft({text: string1}, {text: string2});
  116. this.infinitecraft.instances.pop();
  117. } else {
  118. await this.showToast(`Skipping craft: You don"t have one of these elements: "${string1}", "${string2}"`);
  119. }
  120. }
  121. },
  122. parseRecipes: function (lineage) {
  123. const recipes = [];
  124. const lines = lineage.split("\n").map(line => line.trim());
  125. const isNumberedLineage = lines[0].match(/^\d+\.\s*/);
  126.  
  127. lines.forEach(line => {
  128. if (!line || !line.includes(" = ")) return;
  129.  
  130. if (isNumberedLineage) {
  131. line = line.replace(/^\d+\.\s*/, ""); // Account for numbered lineages
  132. }
  133.  
  134. const [ingredients, result] = line.split(" = ");
  135. if (!ingredients || !result) return;
  136. const ingredientList = ingredients.trim().split(" + ");
  137. if (ingredientList.length < 2) return;
  138. recipes.push(ingredientList.map(ingredient => ingredient.trim()));
  139. });
  140.  
  141. return recipes;
  142. },
  143. craftSomething: async function () { // randomly craft 2 items
  144. while (this.isCrafting) {
  145. await this.infinitecraft.craft({
  146. text: this.infinitecraft.elements.at(this.infinitecraft.elements.length * Math.random()).text
  147. }, {
  148. text: this.infinitecraft.elements.at(this.infinitecraft.elements.length * Math.random()).text
  149. });
  150. this.infinitecraft.instances = [];
  151. // new Promise(resolve => setTimeout(resolve, 200));
  152. }
  153. },
  154. getUserInput: async function () {
  155. return new Promise((resolve) => {
  156. const screenWidth = window.screen.width;
  157. const screenHeight = window.screen.height;
  158. const popupWidth = 400;
  159. const popupHeight = 350;
  160. const left = (screenWidth - popupWidth) / 2;
  161. const top = (screenHeight - popupHeight) / 2;
  162. let popup = window.open("", "", `width=${popupWidth},height=${popupHeight},top=${top},left=${left}`);
  163. popup.document.write(this.popupHTML); // Open popup
  164. const autoCraftButton = popup.document.getElementById("autoCraftButton");
  165. if (this.isCrafting) { // Set auto craft button
  166. autoCraftButton.textContent = "Stop Auto Craft";
  167. autoCraftButton.style.backgroundColor = "#ff0000";
  168. } else {
  169. autoCraftButton.textContent = "Start Auto Craft";
  170. autoCraftButton.style.backgroundColor = "#d4b106";
  171. }
  172. autoCraftButton.addEventListener("click", () => {
  173. this.isCrafting = !this.isCrafting;
  174. popup.close();
  175. resolve({ autoCraft: this.isCrafting });
  176. });
  177. popup.document.getElementById("submitButton").addEventListener("click", function () {
  178. let userInput = popup.document.getElementById("userInput").value;
  179. let anticheatEnabled = popup.document.getElementById("anticheatToggle").checked;
  180. popup.close();
  181. resolve({ lineage: userInput, anticheatEnabled: anticheatEnabled });
  182. });
  183. });
  184. },
  185. showToast: function(message) {
  186. const toast = document.createElement("div");
  187. toast.textContent = message;
  188. Object.assign(toast.style, {
  189. position: "fixed",
  190. left: "50%",
  191. transform: "translateX(-50%)",
  192. padding: "10px 20px",
  193. backgroundColor: "#333",
  194. color: "#fff",
  195. borderRadius: "5px",
  196. fontSize: "16px",
  197. opacity: "0",
  198. transition: "opacity 0.5s ease, bottom 0.3s ease",
  199. marginTop: "10px"
  200. });
  201. const existingToasts = document.querySelectorAll(".toast");
  202. const offset = existingToasts.length * (toast.offsetHeight + 40);
  203. toast.style.bottom = `${30 + offset}px`;
  204. toast.classList.add("toast");
  205. document.body.appendChild(toast);
  206. (async () => {
  207. await new Promise(resolve => setTimeout(resolve, 10));
  208. toast.style.opacity = "1";
  209. await new Promise(resolve => setTimeout(resolve, 3000));
  210. toast.style.opacity = "0";
  211. await new Promise(resolve => setTimeout(resolve, 500));
  212. toast.remove();
  213. const remainingToasts = document.querySelectorAll(".toast");
  214. remainingToasts.forEach((t, index) => {
  215. t.style.bottom = `${30 + index * (toast.offsetHeight + 40)}px`;
  216. });
  217. })();
  218. return new Promise(resolve => setTimeout(resolve, 50)); // 0.05 delay
  219. },
  220. addUiOption: function () {
  221. this.autocraftButton = document.createElement("div");
  222. this.autocraftButton.classList.add("setting");
  223. this.autocraftButton.textContent = "Autocrafter";
  224. const img = document.createElement("img");
  225. img.src = this.iconthing;
  226. this.autocraftButton.appendChild(img);
  227. this.autocraftButton.onclick = function () {
  228. window.AT.autocrafterdata.processLineage();
  229. };
  230.  
  231. document.querySelector(".settings-content").appendChild(this.autocraftButton);
  232. return true;
  233. },
  234. start: function () {
  235. if (document.querySelector(".settings-content")) { // Wait for IC Helper
  236. this.infinitecraft = document.querySelector(".container").__vue__;
  237. this.addUiOption();
  238. } else {
  239. setTimeout(this.start.bind(this), 200);
  240. }
  241. }
  242. };
  243. window.AT.autocrafterdata.start();
  244.  
  245. })();