74 lines
4.3 KiB
JavaScript
74 lines
4.3 KiB
JavaScript
/*
|
||
* Erfolge im Minecraft-Stil („Erfolg erzielt!“).
|
||
*
|
||
* Bewertet wird aus dem, was der Launcher ohnehin weiß (Instanzen, Spielzeit,
|
||
* Starts, Mods), plus ein paar Merkern für einzelne Aktionen (Umhang
|
||
* hochgeladen, Skin im Editor übernommen, Leistungs-Paket …). Freigeschaltete
|
||
* Erfolge landen mit Datum in userData/erfolge.json.
|
||
*/
|
||
const fs = require('fs');
|
||
const path = require('path');
|
||
|
||
const STUNDE = 3600;
|
||
const LISTE = [
|
||
{ id: 'erster-start', symbol: 'grass', titel: 'Los geht’s!', text: 'Starte zum ersten Mal ein Spiel mit AeroMC.', pruefe: (w) => w.starts >= 1 },
|
||
{ id: 'starts-10', symbol: 'pickaxe', titel: 'Stammgast', text: 'Starte 10-mal ein Spiel.', pruefe: (w) => w.starts >= 10 },
|
||
{ id: 'starts-100', symbol: 'gold', titel: 'Ohne mich geht nichts', text: 'Starte 100-mal ein Spiel.', pruefe: (w) => w.starts >= 100 },
|
||
{ id: 'zeit-1', symbol: 'map', titel: 'Erste Stunde', text: 'Spiele insgesamt eine Stunde.', pruefe: (w) => w.sekunden >= STUNDE },
|
||
{ id: 'zeit-10', symbol: 'sword', titel: 'Zeit vergeht wie im Flug', text: 'Spiele insgesamt 10 Stunden.', pruefe: (w) => w.sekunden >= 10 * STUNDE },
|
||
{ id: 'zeit-50', symbol: 'diamond', titel: 'Abenteurer', text: 'Spiele insgesamt 50 Stunden.', pruefe: (w) => w.sekunden >= 50 * STUNDE },
|
||
{ id: 'zeit-100', symbol: 'star', titel: 'Lebt in Minecraft', text: 'Spiele insgesamt 100 Stunden.', pruefe: (w) => w.sekunden >= 100 * STUNDE },
|
||
{ id: 'instanzen-5', symbol: 'chest', titel: 'Sammler', text: 'Lege 5 Instanzen an.', pruefe: (w) => w.instanzen >= 5 },
|
||
{ id: 'instanzen-10', symbol: 'book', titel: 'Archivar', text: 'Lege 10 Instanzen an.', pruefe: (w) => w.instanzen >= 10 },
|
||
{ id: 'versionen-3', symbol: 'end', titel: 'Zeitreisender', text: 'Spiele 3 verschiedene Minecraft-Versionen.', pruefe: (w) => w.versionen >= 3 },
|
||
{ id: 'erste-mod', symbol: 'redstone', titel: 'Bastler', text: 'Habe die erste Mod in einer Instanz.', pruefe: (w) => w.mods >= 1 },
|
||
{ id: 'mods-50', symbol: 'potion', titel: 'Mod-Meister', text: 'Habe 50 Mods in deinen Instanzen.', pruefe: (w) => w.mods >= 50 },
|
||
{ id: 'modpack', symbol: 'nether', titel: 'Das volle Paket', text: 'Installiere ein Modpack.', pruefe: (w) => w.modpacks >= 1 },
|
||
{ id: 'freund', symbol: 'creeper', titel: 'Gemeinsam statt einsam', text: 'Füge deinen ersten Freund hinzu.', pruefe: (w) => w.freunde >= 1 },
|
||
{ id: 'umhang', symbol: 'star', titel: 'Modeschöpfer', text: 'Lade einen eigenen AeroMC-Umhang hoch.', pruefe: (w) => w.merker.umhang },
|
||
{ id: 'skin-editor', symbol: 'map', titel: 'Pixelkünstler', text: 'Übernimm einen im Skin-Editor gemalten Skin.', pruefe: (w) => w.merker['skin-editor'] },
|
||
{ id: 'leistung', symbol: 'tnt', titel: 'Turbo', text: 'Installiere das Leistungs-Paket.', pruefe: (w) => w.merker.leistung },
|
||
];
|
||
|
||
let datei = null;
|
||
function init(userDataDir) { datei = path.join(userDataDir, 'erfolge.json'); }
|
||
|
||
function lies() {
|
||
try { return JSON.parse(fs.readFileSync(datei, 'utf8')); } catch { return null; }
|
||
}
|
||
function schreibe(stand) {
|
||
try { fs.writeFileSync(datei, JSON.stringify(stand, null, 1)); } catch { /* nicht schlimm */ }
|
||
}
|
||
|
||
/**
|
||
* werte: { starts, sekunden, instanzen, versionen, mods, modpacks, freunde }
|
||
* merker: zusätzliche Einzel-Aktionen ({ umhang: true } …)
|
||
* -> { neu: [Erfolge], ersteAuswertung }
|
||
*/
|
||
function pruefe(werte, merker = {}) {
|
||
const vorher = lies();
|
||
const stand = vorher || { freigeschaltet: {}, merker: {} };
|
||
Object.assign(stand.merker, merker);
|
||
const w = Object.assign({ starts: 0, sekunden: 0, instanzen: 0, versionen: 0, mods: 0, modpacks: 0, freunde: 0 }, werte, { merker: stand.merker });
|
||
const neu = [];
|
||
const jetzt = new Date().toISOString();
|
||
for (const e of LISTE) {
|
||
if (stand.freigeschaltet[e.id]) continue;
|
||
let erreicht = false;
|
||
try { erreicht = !!e.pruefe(w); } catch { /* Wert fehlt */ }
|
||
if (erreicht) { stand.freigeschaltet[e.id] = jetzt; neu.push(oeffentlich(e, jetzt)); }
|
||
}
|
||
if (neu.length || !vorher || Object.keys(merker).length) schreibe(stand);
|
||
return { neu, ersteAuswertung: !vorher };
|
||
}
|
||
|
||
const oeffentlich = (e, am) => ({ id: e.id, symbol: e.symbol, titel: e.titel, text: e.text, am: am || null });
|
||
|
||
/** Alle Erfolge mit Datum (null = noch offen). */
|
||
function liste() {
|
||
const stand = lies() || { freigeschaltet: {} };
|
||
return LISTE.map((e) => oeffentlich(e, stand.freigeschaltet[e.id] || null));
|
||
}
|
||
|
||
module.exports = { init, pruefe, liste };
|