'use strict'; /* * modschalter.js – Mods im laufenden Spiel an- und abschalten * ------------------------------------------------------------ * Im Pausemenü wird „Feedback geben“ zu „Mods verwalten“ (siehe * agent/ModsUmbau.java). Ein Klick ruft eine Adresse dieses kleinen, nur lokal * erreichbaren Empfängers auf; der Launcher öffnet daraufhin das Mod-Fenster * über dem Spiel. * * Solange Minecraft läuft, sind die Mod-Dateien gesperrt und geladene Mods * lassen sich ohnehin nicht entladen. Änderungen werden deshalb vorgemerkt * (instance.json -> modsAusstehend) und beim Beenden umgesetzt – das Spiel * läuft weiter, beim nächsten Start gilt der neue Stand. */ const http = require('http'); const crypto = require('crypto'); let server = null; let port = 0; const sitzungen = new Map(); // token -> { instanceId, pid } let beimKlick = null; // (sitzung) => void function starteServer() { if (server) return Promise.resolve(port); return new Promise((resolve, reject) => { server = http.createServer((req, res) => { const m = /^\/mods\/([a-f0-9]{32})$/.exec(req.url || ''); const s = m && sitzungen.get(m[1]); if (!s) { res.writeHead(404); res.end(); return; } res.writeHead(200, { 'Content-Type': 'text/plain' }); res.end('ok'); if (beimKlick) { try { beimKlick(s); } catch (err) { console.error('Mod-Schalter:', err); } } }); server.on('error', (err) => { server = null; reject(err); }); server.listen(0, '127.0.0.1', () => { port = server.address().port; resolve(port); }); }); } /** Neue Sitzung für einen Spielstart -> { token, adresse } (für das Agent-Argument) */ async function neueSitzung(instanceId) { await starteServer(); const token = crypto.randomBytes(16).toString('hex'); sitzungen.set(token, { instanceId, pid: null, token }); return { token, adresse: `http://127.0.0.1:${port}/mods/${token}` }; } function setzePid(token, pid) { const s = sitzungen.get(token); if (s) s.pid = pid; } function beende(token) { sitzungen.delete(token); } function sitzungFuer(instanceId) { for (const s of sitzungen.values()) if (s.instanceId === instanceId && s.pid) return s; return null; } function beiKlick(fn) { beimKlick = fn; } module.exports = { neueSitzung, setzePid, beende, sitzungFuer, beiKlick };