panel.innerHTML = ` <div style="display: flex; justify-content: space-between; align-items: center; margin-bottom: 8px;"> <strong>🔧 Infinite Craft Tools</strong> <button id="ic-toggle-recipes" style="background:#2a2a2a; border:none; color:white; border-radius:6px; padding:2px 8px; cursor:pointer;">📖 Recipes</button> </div> <div id="ic-recipes-panel" style="display: none; overflow-y: auto; max-height: 300px; margin-top: 8px; border-top: 1px solid #333; padding-top: 8px;"> <div style="font-size:12px; color:#aaa;">Click any recipe to auto-fill and craft</div> <div id="ic-recipe-list"></div> </div> <div style="margin-top: 8px; display: flex; gap: 8px;"> <button id="ic-auto-learn" style="flex:1; background:#1e4a2f; border:none; color:white; border-radius:6px; padding:6px; cursor:pointer;">⚡ Auto-learn new</button> <button id="ic-clear-panel" style="flex:1; background:#4a2f2f; border:none; color:white; border-radius:6px; padding:6px; cursor:pointer;">🗑️ Reset panel</button> </div> `;
function escapeHtml(str) return str.replace(/[&<>]/g, function(m) if (m === '&') return '&'; if (m === '<') return '<'; if (m === '>') return '>'; return m; );
// Hook into game's combine function if possible const origCombine = window.combine; if (origCombine) window.combine = function(left, right) const result = origCombine(left, right); if (result && result.name) addRecipeFromCombine(left.name, right.name, result.name); return result; ; infinite craft userscript
// Update the recipe book UI function updateRecipeBook() if (!recipeListDiv) return; if (recipes.size === 0) recipeListDiv.innerHTML = '<div style="color:#888; padding:8px;">No recipes yet. Combine elements to learn!</div>'; return;
toggleBtn.addEventListener('click', () => recipesPanel.style.display = recipesPanel.style.display === 'none' ? 'block' : 'none'; ); panel.innerHTML = ` <
// Hook into the game's internal events if possible (monkeypatch) let originalAddElement = null; if (window.addElement) originalAddElement = window.addElement; window.addElement = function(element, ...args) if (element && element.name) return originalAddElement.apply(this, [element, ...args]); ;
// Auto-learn: repeatedly combine the newest discovered with everything async function autoLearn() autoLearnBtn.disabled = true; autoLearnBtn.textContent = '⏳ Learning...'; div style="display: flex
let html = '<table style="width:100%; border-collapse: collapse;">'; for (let [result, [left, right]] of recipes.entries()) html += ` <tr class="ic-recipe-row" data-left="$escapeHtml(left)" data-right="$escapeHtml(right)" style="border-bottom:1px solid #333; cursor:pointer;"> <td style="padding:6px 4px;">$escapeHtml(left)</td> <td style="padding:6px 4px;">+</td> <td style="padding:6px 4px;">$escapeHtml(right)</td> <td style="padding:6px 4px; color:#4caf50;">→ $escapeHtml(result)</td> </tr> `; html += '</table>'; recipeListDiv.innerHTML = html;