### Install and Run Noitool Console Search CLI Source: https://github.com/twoabove/noita-tools/blob/develop/README.md Steps to install and run the Noitool console search as a compute node via the command line. This involves cloning the repository, installing dependencies, and running the search command. ```bash git clone https://github.com/TwoAbove/noita-tools.git cd noita-tools git checkout master # for https://www.noitool.com # git checkout develop # for https://dev.noitool.com npm install --frozen-lockfile npm run console-build npm run console-search --userId ``` -------------------------------- ### Install npm dependencies Source: https://github.com/twoabove/noita-tools/blob/develop/README.md Run this command after installing Emscripten to install project dependencies. ```bash npm i ``` -------------------------------- ### Setup Noita Data Symlinks for Development Source: https://github.com/twoabove/noita-tools/blob/develop/README.md Commands to create symbolic links for Noita data files required for development. Ensure you have unpacked Noita data and adjust paths as necessary. ```bash ln -s ~/.steam/debian-installation/steamapps/compatdata/881100/pfx/drive_c/users/steamuser/AppData/LocalLow/Nolla_Games_Noita/data dataScripts/noita-data/data ln -s ~/.steam/debian-installation/steamapps/common/Noita/data/translations dataScripts/noita-data/translations ln -s ~/.steam/debian-installation/steamapps/common/Noita/data/fonts dataScripts/noita-data/fonts ``` -------------------------------- ### Initialize Session using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Start a new session with the Noitool API. This action sets a session cookie. ```bash # Initialize session (sets cookie) curl https://www.noitool.com/api/session # Response: "ok" ``` -------------------------------- ### Run Noitool Console Search with Docker Source: https://github.com/twoabove/noita-tools/blob/develop/README.md Use this command to spin up a Noitool compute node using Docker. Ensure you have Docker installed. ```bash docker run -it -e ghcr.io/twoabove/noitool-console-search:latest ``` -------------------------------- ### Initialize and Use OCRHandler for Live Seed Detection Source: https://context7.com/twoabove/noita-tools/llms.txt Instantiate OCRHandler, wait for readiness, listen for detected seeds, and start screen capture. Alternatively, process a single image. Ensure browser permissions are handled for screen capture. ```typescript import OCRHandler from "./src/components/LiveSeedStats/OCRHandler"; // Create OCR handler const ocrHandler = new OCRHandler({ onUpdate: () => console.log("OCR state updated") }); // Wait for initialization while (!ocrHandler.ready) { await new Promise(r => setTimeout(r, 100)); } // Listen for detected seeds ocrHandler.addEventListener("seed", (event: CustomEvent) => { const detectedSeed = event.detail.seed; console.log(`Detected seed: ${detectedSeed}`); // Use the seed to fetch game info }); // Start screen capture (triggers browser permission dialog) await ocrHandler.startCapture({ video: { displaySurface: "window" } }); // Or process a single image const imageBlob = await fetch("screenshot.png").then(r => r.blob()); await ocrHandler.doSingleDetect(imageBlob); // Stop capture await ocrHandler.stopCapture(); ``` -------------------------------- ### Check API Version using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Query the Noitool API to get version information and check for updates. ```bash # Get version info curl https://www.noitool.com/api/version # Response: {"outdated":false,"version":"34.2.0"} ``` -------------------------------- ### Define Complex Search Rules in TypeScript Source: https://context7.com/twoabove/noita-tools/llms.txt Construct nested search rules using AND, OR, and NOT logic with specific validators for perks, alchemy, shops, weather, and starting flasks. Ensure correct `RuleType` and `type` are used for each condition. ```typescript import { RuleType, ILogicRules, IRule } from "./src/services/SeedInfo/infoHandler/IRule"; // Complex nested rule example const searchRules: ILogicRules = { id: "root", type: RuleType.AND, rules: [ // Must have specific first perk { id: "perk-1", type: "perk", val: [{ level: 0, // First Holy Mountain repikeNumber: 0, // No rerolls perks: [["EXTRA_MONEY", "EXTRA_HP"]] // Either perk }] }, // OR condition for alchemy { id: "alchemy-or", type: RuleType.OR, rules: [ { id: "lc-water", type: "alchemy", val: { lc: { material: "water" } } }, { id: "lc-blood", type: "alchemy", val: { lc: { material: "blood" } } } ] }, // NOT condition - exclude certain shops { id: "no-wand-shop", type: RuleType.NOT, rules: [{ id: "shop-type", type: "shop", val: [{ type: 1 }] // type 1 = wand shop }] }, // Weather conditions { id: "weather", type: "weather", val: { rain_material: "blood" // Blood rain seed } }, // Starting setup { id: "start-flask", type: "startingFlask", val: "slime" } ] }; ``` -------------------------------- ### Initialize and Use GameInfoProvider Source: https://context7.com/twoabove/noita-tools/llms.txt Initializes the GameInfoProvider with a seed and configuration, then updates the seed and retrieves all game information for the current seed. Ensure the randoms module is loaded and ready before initializing GameInfoProvider. ```typescript import GameInfoProvider from "./src/services/SeedInfo/infoHandler"; import loadRandom from "./src/services/SeedInfo/random"; // Initialize the game info provider const randoms = await loadRandom(); const gameInfo = new GameInfoProvider( { seed: 786433405 }, [], // unlocked spells array undefined, // i18n instance randoms, true // dispatch events ); // Wait for all providers to be ready await gameInfo.ready(); // Update the seed gameInfo.updateConfig({ seed: 123456789 }); // Get all information for the current seed const allInfo = await gameInfo.provideAll(); console.log(allInfo); ``` -------------------------------- ### Generate Holy Mountain Shop Contents Source: https://context7.com/twoabove/noita-tools/llms.txt Use ShopInfoProvider to generate shop contents for Holy Mountains based on world seed. Requires wand and spell providers. Call `ready()` before providing shops. ```typescript import ShopInfoProvider, { IShopType } from "./src/services/SeedInfo/infoHandler/InfoProviders/Shop"; // Shop provider requires wand and spell providers const shopProvider = new ShopInfoProvider(randoms, wandProvider, spellProvider); await shopProvider.ready(); // Set the world seed randoms.SetWorldSeed(786433405); // Get all shop contents (7 Holy Mountains) const pickedPerks = new Map(); // perks affect shop contents const worldOffset = 0; // parallel world offset const allShops = shopProvider.provide(pickedPerks, worldOffset); // Get specific shop level (0-indexed) const firstShop = shopProvider.provideLevel(0, pickedPerks, worldOffset); console.log(firstShop); // Output for wand shop: // { // type: IShopType.wand, // items: [ // { gun: { deck_capacity: 6, actions_per_round: 2, ... }, ui: { file: "wand_0004.png" }, cards: { cards: ["LIGHT_BULLET", ...] } }, // ... // ] // } // Output for item shop: // { // type: IShopType.item, // items: [ // { spell: { id: "BLACK_HOLE", price: 500 }, price: 150 }, // ... // ] // } ``` -------------------------------- ### Run development build script Source: https://github.com/twoabove/noita-tools/blob/develop/README.md Executes a build script that monitors C++ files for changes and recompiles WASM files. ```bash npm run dev ``` -------------------------------- ### Deploy Noitool to Multiple Machines Source: https://github.com/twoabove/noita-tools/blob/develop/README.md This script automates the deployment of Noitool to several machines. It requires a `.servers` file to configure SSH access and user IDs for each server. ```bash user@server1,,main_user_id user@server2,dev_user_id, ``` -------------------------------- ### Generate Wand Statistics and Spells Source: https://context7.com/twoabove/noita-tools/llms.txt Use WandInfoProvider to generate wand statistics and spell loadouts. Call `ready()` after instantiation. Seed must be set before providing wands. ```typescript import WandInfoProvider from "./src/services/SeedInfo/infoHandler/InfoProviders/Wand"; const wandProvider = new WandInfoProvider(randoms); await wandProvider.ready(); randoms.SetWorldSeed(786433405); // Generate a wand at specific coordinates const wand = wandProvider.provide( 100, // x coordinate 200, // y coordinate 60, // cost budget 3, // level (1-6) false, // force_unshuffle false // unshufflePerk active ); console.log(wand); // Output: // { // gun: { // deck_capacity: 8, // actions_per_round: 2, // reload_time: 45, // shuffle_deck_when_empty: 1, // fire_rate_wait: 12, // spread_degrees: 3.5, // mana_max: 250, // mana_charge_speed: 120, // cost: 0 // }, // ui: { file: "wand_0023.png", name: "Wand" }, // cards: { // cards: ["LIGHT_BULLET", "LIGHT_BULLET", "DAMAGE"], // permanentCard: "HOMING" // always-cast spell (optional) // } // } ``` -------------------------------- ### Host and Join Live Seed Rooms via Socket.IO Source: https://context7.com/twoabove/noita-tools/llms.txt Connect to the Socket.IO server to host a new live seed room or join an existing one. Broadcast or receive seeds in real-time. ```typescript import { io } from "socket.io-client"; const socket = io("https://www.noitool.com/"); // === Live Seed Sharing === // Host a live seed room socket.emit("host", null); // or pass custom room ID socket.on("set_room", (roomNumber) => { console.log(`Hosting room: ${roomNumber}`); }); // Broadcast seed to room viewers socket.emit("seed", "786433405"); // Join existing room socket.emit("join", roomNumber); socket.on("seed", (seed) => { console.log(`Received seed: ${seed}`); }); ``` -------------------------------- ### Configure and Run SeedSearcher Source: https://context7.com/twoabove/noita-tools/llms.txt Sets up and runs the SeedSearcher to find seeds matching specific criteria defined by ILogicRules. The searcher can be configured to stop at the first match or find all matches. Callbacks are available for progress and found seeds. ```typescript import { SeedSearcher, ISeedSearcherConfig } from "./src/services/seedSearcher"; import { RuleType, ILogicRules } from "./src/services/SeedInfo/infoHandler/IRule"; // Create a seed searcher instance const searcher = new SeedSearcher(); await searcher.ready(); // Define search rules - find seeds with specific perks const rules: ILogicRules = { id: "root", type: RuleType.AND, rules: [ { id: "perk-rule", type: "perk", val: [ { perks: [["EXTRA_MONEY"]], repikeNumber: 0, level: 0 } ] }, { id: "alchemy-rule", type: "alchemy", val: { lc: { material: "water" }, ap: { material: "gold" } } } ] }; // Configure the search await searcher.update({ currentSeed: 1, seedEnd: 1000000, rules: rules, findAll: false // stop at first match }); // Set up callbacks searcher.onInfo((info) => { console.log(`Checked: ${info.count}, Current: ${info.currentSeed}`); }); searcher.onFound((info) => { console.log(`Found matching seed: ${info.foundSeed}`); }); // Start searching await searcher.start(); ``` -------------------------------- ### WandInfoProvider - Wand Generation Source: https://context7.com/twoabove/noita-tools/llms.txt Generates wand statistics and spell loadouts based on position and level parameters. ```APIDOC ## WandInfoProvider - Wand Generation ### Description Generates wand statistics and spell loadouts based on position and level parameters. ### Method N/A (This is a class usage example) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import WandInfoProvider from "./src/services/SeedInfo/infoHandler/InfoProviders/Wand"; const wandProvider = new WandInfoProvider(randoms); await wandProvider.ready(); randoms.SetWorldSeed(786433405); // Generate a wand at specific coordinates const wand = wandProvider.provide( 100, // x coordinate 200, // y coordinate 60, // cost budget 3, // level (1-6) false, // force_unshuffle false // unshufflePerk active ); console.log(wand); ``` ### Response #### Success Response (200) N/A (This is a class usage example) #### Response Example ```json { "gun": { "deck_capacity": 8, "actions_per_round": 2, "reload_time": 45, "shuffle_deck_when_empty": 1, "fire_rate_wait": 12, "spread_degrees": 3.5, "mana_max": 250, "mana_charge_speed": 120, "cost": 0 }, "ui": { "file": "wand_0023.png", "name": "Wand" }, "cards": { "cards": ["LIGHT_BULLET", "LIGHT_BULLET", "DAMAGE"], "permanentCard": "HOMING" // always-cast spell (optional) } } ``` ``` -------------------------------- ### Upload Database Dump using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Send a database dump file to the Noitool API for sharing. Requires a POST request with the file attached. ```bash # Upload database dump for sharing curl -X POST https://www.noitool.com/api/db_dump/ \ -F "file=@database.db" # Response: {"id":12345} ``` -------------------------------- ### Run Noitool Console Search Dev with Docker Source: https://github.com/twoabove/noita-tools/blob/develop/README.md This command runs the development version of the Noitool console search with Docker. It allows you to specify a different URL for the Noitool instance. ```bash docker run -it -e NOITOOL_URL=https://dev.noitool.com/ ghcr.io/twoabove/noitool-console-search:latest-dev ``` -------------------------------- ### Predict Weather Conditions Source: https://context7.com/twoabove/noita-tools/llms.txt Use WeatherInfoProvider to determine rain/snow conditions based on date and world seed. The `provide()` method returns current weather, while `test()` checks against specific rules. ```typescript import WeatherInfoProvider, { RAIN_TYPE_NONE, RAIN_TYPE_SNOW, RAIN_TYPE_LIQUID } from "./src/services/SeedInfo/infoHandler/InfoProviders/Weather"; const weatherProvider = new WeatherInfoProvider(randoms); randoms.SetWorldSeed(786433405); const weather = weatherProvider.provide(); console.log(weather); // Output: // { // rain_type: 2, // RAIN_TYPE_LIQUID // rain_material: "water", // or "blood", "acid", "slime", "snow", "slush" // rain_particles: 6, // rain_duration: 14400, // seconds // fog: 0.65, // 0-1 // clouds: 0.8, // 0-1 // hour: 14, // day: 15 // } // Test weather conditions in search const rule = { type: "weather", val: { rain_material: "blood", fog: [0.5, 1.0], // min, max range clouds: [0.7, 1.0] } }; const matches = weatherProvider.test(rule); ``` -------------------------------- ### ShopInfoProvider - Holy Mountain Shop Generation Source: https://context7.com/twoabove/noita-tools/llms.txt Generates shop contents for each Holy Mountain based on the world seed, including wand and spell shops. ```APIDOC ## ShopInfoProvider - Holy Mountain Shop Generation ### Description Generates shop contents for each Holy Mountain based on the world seed, including wand and spell shops. ### Method N/A (This is a class usage example) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import ShopInfoProvider, { IShopType } from "./src/services/SeedInfo/infoHandler/InfoProviders/Shop"; // Shop provider requires wand and spell providers const shopProvider = new ShopInfoProvider(randoms, wandProvider, spellProvider); await shopProvider.ready(); // Set the world seed randoms.SetWorldSeed(786433405); // Get all shop contents (7 Holy Mountains) const pickedPerks = new Map(); // perks affect shop contents const worldOffset = 0; // parallel world offset const allShops = shopProvider.provide(pickedPerks, worldOffset); // Get specific shop level (0-indexed) const firstShop = shopProvider.provideLevel(0, pickedPerks, worldOffset); console.log(firstShop); ``` ### Response #### Success Response (200) N/A (This is a class usage example) #### Response Example ```json // Output for wand shop: { "type": "wand", "items": [ { "gun": { "deck_capacity": 6, "actions_per_round": 2, ... }, "ui": { "file": "wand_0004.png" }, "cards": { "cards": ["LIGHT_BULLET", ...] } }, ... ] } // Output for item shop: { "type": "item", "items": [ { "spell": { "id": "BLACK_HOLE", "price": 500 }, "price": 150 }, ... ] } ``` ``` -------------------------------- ### Download Shared Database using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Retrieve a shared database file from the Noitool API using its ID. ```bash # Download shared database curl https://www.noitool.com/api/db_dump/12345 # Response: binary database file ``` -------------------------------- ### WeatherInfoProvider - Weather Prediction Source: https://context7.com/twoabove/noita-tools/llms.txt Determines rain/snow conditions based on real-world date and world seed. ```APIDOC ## WeatherInfoProvider - Weather Prediction ### Description Determines rain/snow conditions based on real-world date and world seed. ### Method N/A (This is a class usage example) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import WeatherInfoProvider, { RAIN_TYPE_NONE, RAIN_TYPE_SNOW, RAIN_TYPE_LIQUID } from "./src/services/SeedInfo/infoHandler/InfoProviders/Weather"; const weatherProvider = new WeatherInfoProvider(randoms); randoms.SetWorldSeed(786433405); const weather = weatherProvider.provide(); console.log(weather); // Test weather conditions in search const rule = { "type": "weather", "val": { "rain_material": "blood", "fog": [0.5, 1.0], // min, max range "clouds": [0.7, 1.0] } }; const matches = weatherProvider.test(rule); ``` ### Response #### Success Response (200) N/A (This is a class usage example) #### Response Example ```json { "rain_type": 2, // RAIN_TYPE_LIQUID "rain_material": "water", // or "blood", "acid", "slime", "snow", "slush" "rain_particles": 6, "rain_duration": 14400, // seconds "fog": 0.65, // 0-1 "clouds": 0.8, // 0-1 "hour": 14, "day": 15 } ``` ``` -------------------------------- ### OCRHandler - Live Seed Detection Source: https://context7.com/twoabove/noita-tools/llms.txt Utilizes Tesseract OCR to detect game seeds from screen captures in real-time. ```APIDOC ## OCRHandler - Live Seed Detection Uses Tesseract OCR to read the game seed from screen captures, enabling real-time seed information during gameplay. ### Initialization ```typescript const ocrHandler = new OCRHandler({ onUpdate: () => console.log("OCR state updated") }); // Wait for initialization while (!ocrHandler.ready) { await new Promise(r => setTimeout(r, 100)); } ``` ### Event Listener Listens for detected seeds. ```typescript ocrHandler.addEventListener("seed", (event: CustomEvent) => { const detectedSeed = event.detail.seed; console.log(`Detected seed: ${detectedSeed}`); }); ``` ### Starting Capture Starts screen capture, which will trigger a browser permission dialog. ```typescript await ocrHandler.startCapture({ video: { displaySurface: "window" } }); ``` ### Single Image Detection Processes a single image file for seed detection. ```typescript const imageBlob = await fetch("screenshot.png").then(r => r.blob()); await ocrHandler.doSingleDetect(imageBlob); ``` ### Stopping Capture Stops the screen capture process. ```typescript await ocrHandler.stopCapture(); ``` ``` -------------------------------- ### Fetch Daily Seed using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Retrieve the daily seed from the Noitool API. The seed changes at UTC midnight. ```bash # Get daily seed (changes at UTC midnight) curl https://www.noitool.com/api/daily-seed # Response: {"seed":"123456789"} ``` -------------------------------- ### Console Seed Searcher Entrypoint Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md The entrypoint for the console-based seed searcher, which is bundled into the docket container and can be run independently. ```typescript src/consoleSearch.ts ``` -------------------------------- ### REST API - Server Endpoints Source: https://context7.com/twoabove/noita-tools/llms.txt Exposes REST endpoints for fetching game data and managing sessions. ```APIDOC ## REST API - Server Endpoints The Noitool server exposes several REST endpoints for fetching game data and managing sessions. ### GET /api/daily-seed Retrieves the daily seed, which changes at UTC midnight. **Method:** GET **Endpoint:** `https://www.noitool.com/api/daily-seed` **Response Example:** ```json { "seed": "123456789" } ``` ### GET /api/version Fetches version information for the tool. **Method:** GET **Endpoint:** `https://www.noitool.com/api/version` **Response Example:** ```json { "outdated": false, "version": "34.2.0" } ``` ### POST /api/session Initializes a session and sets a cookie. **Method:** POST **Endpoint:** `https://www.noitool.com/api/session` **Response Example:** ``` "ok" ``` ### POST /api/db_dump/ Uploads a database dump for sharing. **Method:** POST **Endpoint:** `https://www.noitool.com/api/db_dump/` **Parameters:** #### Form Data - **file** (blob) - Required - The database file to upload. **Response Example:** ```json { "id": 12345 } ``` ### GET /api/db_dump/{id} Downloads a shared database dump. **Method:** GET **Endpoint:** `https://www.noitool.com/api/db_dump/{id}` **Parameters:** #### Path Parameters - **id** (integer) - Required - The ID of the database dump to download. **Response Example:** ``` [binary database file] ``` ### POST /api/stats Submits search statistics for analytics. **Method:** POST **Endpoint:** `https://www.noitool.com/api/stats` **Headers:** - **Content-Type**: application/json **Request Body:** ```json { "searchRules": { "type": "and", "rules": [] } } ``` ``` -------------------------------- ### Load and Use WebAssembly Random Module Source: https://context7.com/twoabove/noita-tools/llms.txt Loads the WebAssembly random number generation module and demonstrates its various functions for generating random numbers, setting seeds, and picking items. Ensure the WASM module is loaded before calling any RNG functions. ```typescript import loadRandom, { IRandom } from "./src/services/SeedInfo/random"; // Load the WASM module const randoms: IRandom = await loadRandom(); // Set the world seed (required before any operations) randoms.SetWorldSeed(786433405); // Set random seed for specific x,y coordinates randoms.SetRandomSeed(100, 200); // Generate random numbers const randomInt = randoms.Random(0, 100); // Integer between 0-100 const randomFloat = randoms.Randomf(); // Float between 0-1 // Procedural random (deterministic based on x,y,min,max) const proceduralInt = randoms.ProceduralRandomi(x, y, 0, 100); const proceduralFloat = randoms.ProceduralRandomf(x, y, 0.0, 1.0); // Distribution-based random const distributed = randoms.RandomDistribution(min, max, mean, sharpness); // Get random spell action const spell = randoms.GetRandomAction(x, y, level, index); const spellByType = randoms.GetRandomActionWithType(x, y, level, ACTION_TYPE.PROJECTILE, index); // Helper functions const rnd = randoms.random_create(x, y); const nextVal = randoms.random_next(rnd, 0.0, 1.0); const item = randoms.randomFromArray(items); const picked = randoms.pick_random_from_table_weighted(rnd, weightedTable); ``` -------------------------------- ### Seed Searcher Implementation Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md The base component for performing seed searches. It loads a GameInfoProvider, takes a seed range and ruleset as input, iterates through the seeds, and checks for matches against the ruleset. Matching seeds are collected and sent to the main thread. ```typescript src/services/seedSearcher.ts ``` -------------------------------- ### Connect to Noitool Compute Network Source: https://context7.com/twoabove/noita-tools/llms.txt Use ComputeSocket to connect as a worker to process seed search chunks. Requires a SeedSolver instance and session token. Handles version mismatches and provides job updates. ```typescript import { ComputeSocket } from "./src/services/compute/ComputeSocket"; import SeedSolver from "./src/services/seedSolverHandler.node"; // Create a seed solver with multiple cores const seedSolver = new SeedSolver(os.cpus().length, false); // Connect to the compute network const computeSocket = new ComputeSocket({ url: "https://www.noitool.com/", version: "34.2.0", sessionToken: "your-session-token", seedSolver: seedSolver, onUpdate: () => { console.log({ connected: computeSocket.connected, running: computeSocket.running, jobName: computeSocket.jobName, chunkFrom: computeSocket.chunkFrom, chunkTo: computeSocket.chunkTo }); }, onDone: () => { console.log("No more jobs available"); } }); // Handle version mismatch computeSocket.on("compute:version_mismatch", ({ serverVersion, clientVersion }) => { console.log(`Version mismatch: server ${serverVersion}, client ${clientVersion}`); computeSocket.terminate(); }); // Start processing jobs await computeSocket.start(); // Graceful shutdown process.on("SIGINT", () => { computeSocket.terminate(); }); ``` -------------------------------- ### Frontend Seed Search Management Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md Component demonstrating how seed searching is managed within the frontend application. It is suggested that this could be refactored into a stateful class for better management. ```typescript src/components/SearchSeeds/SearchContext.tsx ``` -------------------------------- ### Register Compute Worker and Request Jobs via Socket.IO Source: https://context7.com/twoabove/noita-tools/llms.txt Register a compute worker with the cluster, specifying version and capacity. Request jobs and report completion. ```typescript import { io } from "socket.io-client"; const socket = io("https://www.noitool.com/"); // === Compute Cluster === // Register as a compute worker socket.emit("compute:worker:register", { version: "34.2.0", appetite: 4 // number of cores available }, (response) => { console.log("Registered:", response); }); // Request work from the cluster socket.emit("compute:need_job", 4, (job) => { if (!job || job.done) { console.log("No jobs available"); return; } const { from, to, rules, hostId, chunkId } = job; console.log(`Processing seeds ${from} to ${to}`); // Process the chunk and report results const results = processChunk(from, to, rules); socket.emit("compute:done", { hostId, result: results, chunkId }); }); // Get cluster statistics socket.emit("compute:workers", (count) => { console.log(`Active workers: ${count}`); }); ``` -------------------------------- ### Socket.IO Events - Real-time Communication Source: https://context7.com/twoabove/noita-tools/llms.txt Handles live seed sharing, compute job distribution, and cluster coordination via WebSocket. ```APIDOC ## Socket.IO Events - Real-time Communication The WebSocket interface handles live seed sharing, compute job distribution, and cluster coordination. ### Connection Establish a connection to the server. ```typescript import { io } from "socket.io-client"; const socket = io("https://www.noitool.com/"); ``` ### Live Seed Sharing #### Hosting a Room Emits an event to host a live seed room. Optionally pass a custom room ID. ```typescript socket.emit("host", null); // or pass custom room ID socket.on("set_room", (roomNumber) => { console.log(`Hosting room: ${roomNumber}`); }); ``` #### Broadcasting a Seed Emits a seed to all viewers in the current room. ```typescript socket.emit("seed", "786433405"); ``` #### Joining a Room Emits an event to join an existing room. ```typescript socket.emit("join", roomNumber); socket.on("seed", (seed) => { console.log(`Received seed: ${seed}`); }); ``` ### Compute Cluster #### Registering as a Worker Registers the client as a compute worker with specified version and appetite (cores). ```typescript socket.emit("compute:worker:register", { version: "34.2.0", appetite: 4 // number of cores available }, (response) => { console.log("Registered:", response); }); ``` #### Requesting Work Requests a job chunk from the cluster. Processes the chunk and reports results. ```typescript socket.emit("compute:need_job", 4, (job) => { if (!job || job.done) { console.log("No jobs available"); return; } const { from, to, rules, hostId, chunkId } = job; console.log(`Processing seeds ${from} to ${to}`); // Process the chunk and report results const results = processChunk(from, to, rules); socket.emit("compute:done", { hostId, result: results, chunkId }); }); ``` #### Getting Worker Count Retrieves the number of active workers in the cluster. ```typescript socket.emit("compute:workers", (count) => { console.log(`Active workers: ${count}`); }); ``` ``` -------------------------------- ### Submit Search Statistics using curl Source: https://context7.com/twoabove/noita-tools/llms.txt Send search statistics to the Noitool API for analytics. Requires a POST request with a JSON payload. ```bash # Submit search stats (for analytics) curl -X POST https://www.noitool.com/api/stats \ -H "Content-Type: application/json" \ -d '{"searchRules":{"type":"and","rules":[]}}' ``` -------------------------------- ### Map Generation Biome Classes Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md Directory containing biome generation classes for map generation. These classes are transpiled from Lua code to TypeScript. The conversion process is currently half-manual, with AST conversion being a possibility. ```typescript src/services/SeedInfo/infoHandler/InfoProviders/Map ``` -------------------------------- ### Map Data Conversion Script Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md Scripts used for converting map data from Lua to an object format in TypeScript. This illustrates the process of generating map implementations. ```typescript dataScripts/src/mapsToObj/generateMaps.ts ``` ```typescript dataScripts/src/mapsToObj/generateMapImpls.ts ``` -------------------------------- ### Noita Random Number Generation Interface Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md This module provides the interface for pseudorandom number generation used in Noita. It involves setting a seed and then calling various random functions. ```typescript SetRandomSeed(x, y); Random(); RandomFloat(); RandomRange(min, max); RandomRangeInt(min, max); ``` -------------------------------- ### ComputeSocket - Distributed Computing Client Source: https://context7.com/twoabove/noita-tools/llms.txt Connects to the Noitool server as a compute worker to process seed search chunks for other users. ```APIDOC ## ComputeSocket - Distributed Computing Client ### Description Connects to the Noitool server as a compute worker to process seed search chunks for other users. ### Method N/A (This is a class usage example) ### Endpoint N/A ### Parameters N/A ### Request Example ```typescript import { ComputeSocket } from "./src/services/compute/ComputeSocket"; import SeedSolver from "./src/services/seedSolverHandler.node"; // Create a seed solver with multiple cores const seedSolver = new SeedSolver(os.cpus().length, false); // Connect to the compute network const computeSocket = new ComputeSocket({ url: "https://www.noitool.com/", version: "34.2.0", sessionToken: "your-session-token", seedSolver: seedSolver, onUpdate: () => { console.log({ connected: computeSocket.connected, running: computeSocket.running, jobName: computeSocket.jobName, chunkFrom: computeSocket.chunkFrom, chunkTo: computeSocket.chunkTo }); }, onDone: () => { console.log("No more jobs available"); } }); // Handle version mismatch computeSocket.on("compute:version_mismatch", ({ serverVersion, clientVersion }) => { console.log(`Version mismatch: server ${serverVersion}, client ${clientVersion}`); computeSocket.terminate(); }); // Start processing jobs await computeSocket.start(); // Graceful shutdown process.on("SIGINT", () => { computeSocket.terminate(); }); ``` ### Response #### Success Response (200) N/A (This is a class usage example) #### Response Example ```json { "connected": true, "running": true, "jobName": "example_job", "chunkFrom": 1000, "chunkTo": 2000 } ``` ``` -------------------------------- ### Firefox FOUC Fix Initialization Source: https://github.com/twoabove/noita-tools/blob/develop/index.html This JavaScript code is intended to prevent Flash of Unstyled Content (FOUC) in Firefox. It must be placed at the beginning of the script execution. ```javascript Noitool /* to prevent Firefox FOUC, this must be here */ 0; let FF_FOUC_FIX; ``` -------------------------------- ### Search Rules - Rule Definition System Source: https://context7.com/twoabove/noita-tools/llms.txt Defines complex search criteria using nested AND/OR/NOT rules with typed validators. ```APIDOC ## Search Rules - Rule Definition System Define complex search criteria using nested AND/OR/NOT rules with typed validators for each game aspect. ### Rule Structure Rules can be nested using `RuleType.AND`, `RuleType.OR`, and `RuleType.NOT`. ```typescript import { RuleType, ILogicRules, IRule } from "./src/services/SeedInfo/infoHandler/IRule"; // Complex nested rule example const searchRules: ILogicRules = { id: "root", type: RuleType.AND, rules: [ // Rule examples... ] }; ``` ### Example Rules #### Perk Rule Requires specific perks from the first Holy Mountain. ```typescript { id: "perk-1", type: "perk", val: [{ level: 0, // First Holy Mountain repikeNumber: 0, // No rerolls perks: [["EXTRA_MONEY", "EXTRA_HP"]] // Either perk }] } ``` #### Alchemy Rule (OR) Specifies an OR condition for alchemy materials. ```typescript { id: "alchemy-or", type: RuleType.OR, rules: [ { id: "lc-water", type: "alchemy", val: { lc: { material: "water" } } }, { id: "lc-blood", type: "alchemy", val: { lc: { material: "blood" } } } ] } ``` #### Shop Rule (NOT) Excludes specific shop types using a NOT condition. ```typescript { id: "no-wand-shop", type: RuleType.NOT, rules: [{ id: "shop-type", type: "shop", val: [{ type: 1 }] // type 1 = wand shop }] } ``` #### Weather Rule Specifies weather conditions, such as blood rain. ```typescript { id: "weather", type: "weather", val: { rain_material: "blood" // Blood rain seed } } ``` #### Starting Flask Rule Defines the starting flask type. ```typescript { id: "start-flask", type: "startingFlask", val: "slime" } ``` ``` -------------------------------- ### C++ WASM Interface for Noita Random Source: https://github.com/twoabove/noita-tools/blob/develop/ARCHITECTURE.md The C++ WASM code used for Noita's random number and map generation. This is the underlying implementation called by the TypeScript interface. ```cpp #include "random.h" int main() { // Example usage: SetRandomSeed(100, 200); int randomNumber = Random(); // ... more random calls return 0; } ``` === COMPLETE CONTENT === This response contains all available snippets from this library. No additional content exists. Do not make further requests.