From 3866c171691bfd308e7d9bf47096662b8905e2a7 Mon Sep 17 00:00:00 2001 From: Andercou Alexandru Date: Sat, 21 Mar 2026 11:44:05 +0200 Subject: [PATCH 1/3] discoveries are blue --- .../DiscoveriesAreBlue/README.md | 5 ++ .../DiscoveriesAreBlue/index.user.js | 81 +++++++++++++++++++ 2 files changed, 86 insertions(+) create mode 100644 userscripts/24sandualexandru/DiscoveriesAreBlue/README.md create mode 100644 userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js diff --git a/userscripts/24sandualexandru/DiscoveriesAreBlue/README.md b/userscripts/24sandualexandru/DiscoveriesAreBlue/README.md new file mode 100644 index 0000000..ef161d7 --- /dev/null +++ b/userscripts/24sandualexandru/DiscoveriesAreBlue/README.md @@ -0,0 +1,5 @@ +# Discoveries are blue [Install](https://raw.githubusercontent.com/InfiniteCraftCommunity/userscripts/master/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js) + +Script highlights discovered items in the sidebar + +### by [Alexander_Andercou](https://github.com/24sanduAlexandru) diff --git a/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js b/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js new file mode 100644 index 0000000..3374dbe --- /dev/null +++ b/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js @@ -0,0 +1,81 @@ +// ==UserScript== +// @name Discoveries are blue +// @namespace http://tampermonkey.net/ +// @version 2026-03-21 +// @description try to take over the world! +// @author You +// @match https://neal.fun/infinite-craft/ +// @icon https://www.google.com/s2/favicons?sz=64&domain=neal.fun +// @grant none +// ==/UserScript== + +(function() { + 'use strict'; + + function injectDeadElementStyles() { + const css = ` + .discovered-element { + border-radius: 8px !important;; + padding: 8px 12px !important;; + color: var(--color,#fff); + --color:#bbf; + transition: box-shadow 0.25s ease, transform 0.25s ease; + } + + .discovered-element:hover { + box-shadow: 0 0 18px var(--color) !important;; + transform: translateY(-2px) !important; + } + `; + + const style = document.createElement("style"); + style.textContent = css; + document.head.appendChild(style); +} + 'use strict'; + + async function doStuffOnItem(node) { + node.classList.add("discovered-element"); + + } + async function doStuffOnItemMutation(mutations) { + for (const mutation of mutations) { + if (mutation.addedNodes.length > 0) { + for (const node of mutation.addedNodes) { + console.log("ITEM CHECK",node) + + if (node.classList && node.classList.contains("item-wrapper")) { + let itemNode=node.querySelector(".item-discovery"); + if(itemNode) + doStuffOnItem(itemNode); + } + } + } + } + } + window.addEventListener("load", async() => { + injectDeadElementStyles() ; + + const itemObserver = new MutationObserver((mutations) => { + + + doStuffOnItemMutation(mutations); + + + }); + + itemObserver.observe(document.querySelector(".items"), { + childList: true, + subtree: true, + + }); + + var items = document.querySelectorAll(".item-discovery"); + for (let item of items) + doStuffOnItem(item,true); + + + + }); + +})(); \ No newline at end of file From 3be363b6b8dc4e801d17e57af1c7bf9e39a8dc0b Mon Sep 17 00:00:00 2001 From: Andercou Alexandru Date: Sat, 21 Mar 2026 15:55:14 +0200 Subject: [PATCH 2/3] many updates, fix for helper after IC update --- .../DiscoveriesAreBlue/index.user.js | 30 +++++- .../TemporaryFixForHelper/README.md | 3 + .../TemporaryFixForHelper/index.user.js | 99 +++++++++++++++++++ 3 files changed, 131 insertions(+), 1 deletion(-) create mode 100644 userscripts/24sandualexandru/TemporaryFixForHelper/README.md create mode 100644 userscripts/24sandualexandru/TemporaryFixForHelper/index.user.js diff --git a/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js b/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js index 3374dbe..d3664c4 100644 --- a/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js +++ b/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js @@ -42,7 +42,6 @@ for (const mutation of mutations) { if (mutation.addedNodes.length > 0) { for (const node of mutation.addedNodes) { - console.log("ITEM CHECK",node) if (node.classList && node.classList.contains("item-wrapper")) { let itemNode=node.querySelector(".item-discovery"); @@ -52,6 +51,19 @@ } } } + } + async function doStuffOnInstancesMutation(mutations) { + for (const mutation of mutations) { + if (mutation.addedNodes.length > 0) { + for (const node of mutation.addedNodes) { + + if (node.id!="instance-0" && node.classList.contains("instance-discovery") && node.querySelector(".instance-emoji")) { + + doStuffOnItem(node); + } + } + } + } } window.addEventListener("load", async() => { injectDeadElementStyles() ; @@ -74,7 +86,23 @@ for (let item of items) doStuffOnItem(item,true); + const instanceObserver = new MutationObserver((mutations) => { + + + doStuffOnInstancesMutation(mutations); + + + }); + + instanceObserver.observe(document.querySelector("#instances"), { + childList: true, + subtree: true, + + }); + var instances = document.querySelectorAll(".instance-discovery"); + for (let inst of instances) + doStuffOnItem(inst,true); }); diff --git a/userscripts/24sandualexandru/TemporaryFixForHelper/README.md b/userscripts/24sandualexandru/TemporaryFixForHelper/README.md new file mode 100644 index 0000000..2f61e06 --- /dev/null +++ b/userscripts/24sandualexandru/TemporaryFixForHelper/README.md @@ -0,0 +1,3 @@ +# Helper patch by Alex| [Install](https://raw.githubusercontent.com/InfiniteCraftCommunity/userscripts/master/userscripts/24sandualexandru/TemporaryFixForHelper/index.user.js) +Temporary fix for helper after latest Neal update from 03.2026 , to be deprecated after Natasquare fixes his helper +### by [Alexander_Andercou](https://github.com/24sanduAlexandru) diff --git a/userscripts/24sandualexandru/TemporaryFixForHelper/index.user.js b/userscripts/24sandualexandru/TemporaryFixForHelper/index.user.js new file mode 100644 index 0000000..6a70cec --- /dev/null +++ b/userscripts/24sandualexandru/TemporaryFixForHelper/index.user.js @@ -0,0 +1,99 @@ +// ==UserScript== +// @name Helper patch by Alex +// @namespace http://tampermonkey.net/ +// @version 2026-03-21 +// @description try to take over the world! +// @author Alexander_sandu +// @match https://neal.fun/infinite-craft/ +// @icon https://www.google.com/s2/favicons?sz=64&domain=neal.fun +// @grant unsafeWindow +// ==/UserScript== + +(function() { + 'use strict'; + + //need a sleep method + function sleep(ms) { + return new Promise(resolve => setTimeout(resolve, ms)); +} + function injectItemsMoveLower() { + const css = ` + .items-inner { + top:20px !important; + } + .items-inner + div { + top:20px !important; + } + `; + + const style = document.createElement("style"); + style.textContent = css; + document.head.appendChild(style); +} + async function doStuffOnItem(node) { + let itemNode=node.querySelector(".item"); + itemNode.addEventListener("contextmenu",async ()=>{ + let contextMenu=document.querySelector(".item-context-menu"); + if(contextMenu) + { contextMenu.remove(); + } + + }); + + } + async function doStuffOnItemMutation(mutations) { + for (const mutation of mutations) { + if (mutation.addedNodes.length > 0) { + for (const node of mutation.addedNodes) { + console.log("ITEM CHECK",node) + + if (node.classList && node.classList.contains("item-wrapper")) + doStuffOnItem(node); + } + } + } + } + + window.addEventListener("load", async() => { + + injectItemsMoveLower(); + const itemObserver = new MutationObserver((mutations) => { + + + doStuffOnItemMutation(mutations); + + + }); + + itemObserver.observe(document.querySelector(".items"), { + childList: true, + subtree: true, + + }); + + if (unsafeWindow?.ICHelper?.recipeModalTabs) unsafeWindow.ICHelper.recipeModalTabs.set("hideItem", { + renderBody: function(container, item) { + let wrappers= Array.from(document.querySelectorAll(".item-wrapper")); + let wrappersVues=wrappers.map(x=>x.__vue__); + let myVueObject=wrappersVues.find(x=>x.element==item); + myVueObject?.$emit("hideItem",item,!item.hide); + let span=document.createElement("span"); + span.style.padding=" 20px 24px"; + span.textContent=`${item.emoji} ${item.text} was ${(item.hide)?"Hidden":"Unhidden"}` + container.appendChild(span); + //change text of button + let footers= Array.from(document.querySelectorAll(".recipe-modal-footer-tab")); + let myFooter=footers.find(x=>x.textContent.trim()=="Hide Item" || x.textContent.trim()=="Unhide Item"); + myFooter.textContent=`${(item.hide)?"Hidden":"Unhidden"}` + }, + renderFooter: function(container, item) { + + container.appendChild(document.createTextNode((!item.hide)?"Hide Item":"Unhide Item")); + } + + + }) + + }); + +})(); \ No newline at end of file From d423c8cd35d0b771ebcda641bc5571f65846d65b Mon Sep 17 00:00:00 2001 From: Andercou Alexandru Date: Tue, 24 Mar 2026 20:33:42 +0200 Subject: [PATCH 3/3] add special character search --- .../CollectableIsGreen/README.md | 5 + .../CollectableIsGreen/index.user.js | 130 +++++++++ .../SpecialCharactersFilter/README.md | 3 + .../SpecialCharactersFilter/index.user.js | 252 ++++++++++++++++++ 4 files changed, 390 insertions(+) create mode 100644 userscripts/24sandualexandru/CollectableIsGreen/README.md create mode 100644 userscripts/24sandualexandru/CollectableIsGreen/index.user.js create mode 100644 userscripts/24sandualexandru/SpecialCharactersFilter/README.md create mode 100644 userscripts/24sandualexandru/SpecialCharactersFilter/index.user.js diff --git a/userscripts/24sandualexandru/CollectableIsGreen/README.md b/userscripts/24sandualexandru/CollectableIsGreen/README.md new file mode 100644 index 0000000..564d64f --- /dev/null +++ b/userscripts/24sandualexandru/CollectableIsGreen/README.md @@ -0,0 +1,5 @@ +# Collectable is green | [Install](https://raw.githubusercontent.com/InfiniteCraftCommunity/userscripts/master/userscripts/24sandualexandru/CollectableIsGreen/index.user.js) + +This script highlights all collectable items and instances by detecting them through the achievement tracker’s reverse index. Any element identified as collectable is styled with a green theme for quick visual recognition. + +### by [Alexander_Andercou](https://github.com/24sanduAlexandru) \ No newline at end of file diff --git a/userscripts/24sandualexandru/CollectableIsGreen/index.user.js b/userscripts/24sandualexandru/CollectableIsGreen/index.user.js new file mode 100644 index 0000000..f60664a --- /dev/null +++ b/userscripts/24sandualexandru/CollectableIsGreen/index.user.js @@ -0,0 +1,130 @@ +// ==UserScript== +// @name Collectable is green +// @namespace http://tampermonkey.net/ +// @version 2026-03-21 +// @description try to take over the world! +// @author You +// @match https://neal.fun/infinite-craft/ +// @icon https://www.google.com/s2/favicons?sz=64&domain=neal.fun +// @grant none +// ==/UserScript== + +(async function() { + 'use strict'; + function sleep(ms = 0) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + await new Promise((r,e)=> + {while(document.querySelector(".container")==null) + sleep(300); + r(); + }) + function injectDeadElementStyles() { + const css = ` + .collection-element { + border-radius: 8px !important; + border: 3px solid var(--border-strong) !important; + padding: 8px 12px !important; + background: var(--green-main-soft) !important; + color: var(--green-main,#fff); + --green-main: #22c55e; + --green-main-soft: #22c55e33; /* same green, 20% opacity */ + --border-strong: #4ade80; + transition: box-shadow 0.25s ease, transform 0.25s ease; + } + + .collection-element:hover { + box-shadow: 0 0 18px var(--green-main-soft) !important;; + transform: translateY(-2px) !important; + } + `; + + const style = document.createElement("style"); + style.textContent = css; + document.head.appendChild(style); +} + 'use strict'; + + async function doStuffOnItem(node,text="") { + //search for text in reverseMap + let reverseMap= document.querySelector(".container").__vue__._data.achievementTracker.reverseIndex.get(text.toLowerCase()) + if(reverseMap && reverseMap.length>0) + { + node.classList.add("collection-element"); + } + + } + async function doStuffOnItemMutation(mutations) { + for (const mutation of mutations) { + if (mutation.addedNodes.length > 0) { + for (const node of mutation.addedNodes) { + + if (node.classList && node.classList.contains("item-wrapper")) { + let itemNode=node.querySelector(".item"); + let text=node.__vue__.element.text; + doStuffOnItem(itemNode,text); + } + } + } + } + } + async function doStuffOnInstancesMutation(mutations) { + for (const mutation of mutations) { + if (mutation.addedNodes.length > 0) { + for (const node of mutation.addedNodes) { + + if (node.id!="instance-0" && node.classList.contains("instance") && node.querySelector(".instance-emoji")) { + let text=node.querySelector(".instance-text").textContent; + + doStuffOnItem(node,text); + } + } + } + } + } + + injectDeadElementStyles() ; + // you have to wait for container + + + const itemObserver = new MutationObserver((mutations) => { + + + doStuffOnItemMutation(mutations); + + + }); + + itemObserver.observe(document.querySelector(".items"), { + childList: true, + subtree: true, + + }); + + var items = document.querySelectorAll(".item"); + for (let item of items) + doStuffOnItem(item,item.parentNode.__vue__.element.text); + + const instanceObserver = new MutationObserver((mutations) => { + + + doStuffOnInstancesMutation(mutations); + + + }); + + instanceObserver.observe(document.querySelector("#instances"), { + childList: true, + subtree: true, + + }); + + var instances = document.querySelectorAll(".instance"); + for (let inst of instances) + { + doStuffOnItem(inst,inst.querySelector(".instance-text").textContent); + } + + + +})(); \ No newline at end of file diff --git a/userscripts/24sandualexandru/SpecialCharactersFilter/README.md b/userscripts/24sandualexandru/SpecialCharactersFilter/README.md new file mode 100644 index 0000000..d4c7be2 --- /dev/null +++ b/userscripts/24sandualexandru/SpecialCharactersFilter/README.md @@ -0,0 +1,3 @@ +# RegexSearch | [Install](https://raw.githubusercontent.com/InfiniteCraftCommunity/userscripts/master/userscripts/24sandualexandru/RegexSearch/index.user.js) +Click on checkbox under searchbar to allow searching using regex in IC (case insensitive) +### by [Alexander_Andercou](https://github.com/24sanduAlexandru) diff --git a/userscripts/24sandualexandru/SpecialCharactersFilter/index.user.js b/userscripts/24sandualexandru/SpecialCharactersFilter/index.user.js new file mode 100644 index 0000000..f639ebc --- /dev/null +++ b/userscripts/24sandualexandru/SpecialCharactersFilter/index.user.js @@ -0,0 +1,252 @@ +// ==UserScript== +// @name Regex Special Character Search +// @namespace http://tampermonkey.net/ +// @version 2026-03-23 +// @description Search items by selecting special characters extracted from item texts on demand, with scrollable modal and sticky header +// @author You +// @match https://neal.fun/infinite-craft/ +// @icon https://www.google.com/s2/favicons?sz=64&domain=neal.fun +// @grant none +// ==/UserScript== + +(async function () { + "use strict"; + + function sleep(ms = 0) { + return new Promise((resolve) => setTimeout(resolve, ms)); + } + + // Wait for Vue to load + await new Promise((r) => { + const check = () => { + if (document.querySelector(".container") && + document.querySelector("#sidebar") && + document.querySelector("#sidebar").__vue__) r(); + else setTimeout(check, 300); + }; + check(); + }); + + let v_sidebar = document.querySelector("#sidebar").__vue__; + const oldFiltered = v_sidebar._computedWatchers.filteredElements.getter; + + // ------------------------------------------------------- + // Filtering logic + // ------------------------------------------------------- + function applyRegexSearch() { + const spans = [...document.querySelectorAll("span")] + .filter(s => s.textContent.trim() === "Regex search"); + + const label = spans.find(s => { + const prev = s.previousElementSibling; + return prev && prev.tagName === "INPUT" && prev.type === "checkbox"; + }); + + if (label) { + const checkbox = label.previousElementSibling; + + if (checkbox && checkbox.tagName === "INPUT" && checkbox.type === "checkbox") { + checkbox.checked = false; + checkbox.click(); + } + } + + v_sidebar._computedWatchers.filteredElements.getter = function () { + let query = v_sidebar.searchQuery; + v_sidebar.searchQuery = ""; + let filtered = oldFiltered.apply(this); + const regex = new RegExp(query, "i"); + return filtered.filter(x => regex.test(x.text)); + }; + } + + // ------------------------------------------------------- + // Lazy modal creation + // ------------------------------------------------------- + let modalCreated = false; + + function createModal() { + + let modal = document.querySelector("#regex-modal"); + if (modal) { + modal.innerHTML = ""; + } else { + modal = document.createElement("div"); + document.body.appendChild(modal); + } + + // Extract special characters dynamically + let items = document.querySelector(".container").__vue__._data.items; + let allText = items.map(i => i.text).join(""); + let specialChars = [...new Set(allText.replace(/[A-Za-z0-9 ]/g, ""))]; + specialChars.sort(); + + // Modal wrapper + modal.id = "regex-modal"; + modal.style.cssText = ` + position: fixed; + inset: 0; + background: rgba(0,0,0,0.6); + display: none; + justify-content: center; + align-items: center; + z-index: 99999; + `; + + // Modal box (scrollable) + const modalBox = document.createElement("div"); + modalBox.style.cssText = ` + background: #1e1e1e; + padding: 0; + border-radius: 10px; + width: 340px; + max-height: 50vh; + color: white; + display: flex; + flex-direction: column; + overflow: hidden; + box-shadow: 0 0 20px rgba(0,0,0,0.5); + `; + + modal.appendChild(modalBox); + + // ------------------------------------------------------- + // NEW: Close modal when clicking outside modalBox + // ------------------------------------------------------- + modal.addEventListener("click", (e) => { + if (e.target === modal) { + modal.style.display = "none"; + } + }); + + // Sticky header + const header = document.createElement("div"); + header.style.cssText = ` + position: sticky; + top: 0; + background: #222; + padding: 12px; + border-bottom: 1px solid #444; + z-index: 2; + `; + header.innerHTML = ` +
Selected:
+ + `; + modalBox.appendChild(header); + + const selectedDisplay = header.querySelector("#selected-chars"); + + // Scrollable content + const scrollArea = document.createElement("div"); + scrollArea.style.cssText = ` + overflow-y: auto; + padding: 12px; + flex: 1; + `; + + scrollArea.addEventListener("wheel", e => e.stopPropagation(), { passive: true }); + + modalBox.appendChild(scrollArea); + + // Character list container + const charList = document.createElement("div"); + charList.style.cssText = ` + display:flex; flex-wrap:wrap; gap:6px; + `; + scrollArea.appendChild(charList); + + // Build character buttons dynamically + specialChars.forEach(ch => { + const btn = document.createElement("button"); + btn.textContent = ch; + btn.style.cssText = ` + width:32px; height:32px; border-radius:6px; + background:#333; color:white; border:1px solid #555; + cursor:pointer; font-size:16px; + `; + btn.dataset.selected = "false"; + + btn.onclick = () => { + if (btn.dataset.selected === "false") { + btn.style.background = "#4caf50"; + btn.dataset.selected = "true"; + } else { + btn.style.background = "#333"; + btn.dataset.selected = "false"; + } + + let selected = [...charList.children] + .filter(b => b.dataset.selected === "true") + .map(b => b.textContent) + .join(" "); + + selectedDisplay.textContent = selected; + }; + + charList.appendChild(btn); + }); + + // Search button + header.querySelector("#regex-search-btn").onclick = () => { + const selected = [...charList.children] + .filter(btn => btn.dataset.selected === "true") + .map(btn => btn.textContent); + + if (selected.length === 0) { + modal.style.display = "none"; + return; + } + + const regex = new RegExp("[" + selected.join("") + "]", "i"); + + applyRegexSearch(); + v_sidebar.searchQuery = ""; + document.querySelector(".sidebar-input").value = regex.source; + v_sidebar.searchQuery = regex.source; + + modal.style.display = "none"; + }; + + createModal.modal = modal; + } + + // ------------------------------------------------------- + // Sidebar button + // ------------------------------------------------------- + const bar = document.querySelector(".sidebar-sorting"); + const btn = document.createElement("button"); + const fakeDiv = document.createElement("div"); + btn.textContent = "Special Character Search"; + btn.style.cssText = ` + margin-left:10px; + padding:6px 12px; + background:#4caf50; + color:white; + border:none; + border-radius:6px; + cursor:pointer; + font-weight:bold; + `; + + btn.onclick = () => { + createModal(); + createModal.modal.style.display = "flex"; + }; + + if (bar.children.length % 3 == 2) { + bar.appendChild(fakeDiv); + bar.appendChild(btn); + } else if (bar.children.length % 3 == 0) { + const fakeDiv2 = document.createElement("div"); + bar.appendChild(btn); + bar.appendChild(fakeDiv); + bar.appendChild(fakeDiv2); + } else { + bar.appendChild(btn); + bar.appendChild(fakeDiv); + } +})(); \ No newline at end of file