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/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..d3664c4 --- /dev/null +++ b/userscripts/24sandualexandru/DiscoveriesAreBlue/index.user.js @@ -0,0 +1,109 @@ +// ==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) { + + if (node.classList && node.classList.contains("item-wrapper")) { + let itemNode=node.querySelector(".item-discovery"); + if(itemNode) + doStuffOnItem(itemNode); + } + } + } + } + } + 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() ; + + 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); + + 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); + + }); + +})(); \ 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 = ` +