UNPKG

@haelp/teto

Version:

A typescript-based controllable TETR.IO client.

268 lines (267 loc) 10.5 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); Object.defineProperty(exports, "ReplayManager", { enumerable: true, get: function() { return ReplayManager; } }); const _game = require("../game"); class ReplayManager { #replay; constructor(readyPlayers, roomPlayers){ this.#replay = { gamemode: null, id: null, ts: new Date().toString(), version: 1, users: readyPlayers.map((p)=>roomPlayers.find((pl)=>pl._id === p.userid)).map((p)=>({ id: p._id, username: p.username, avatar_revision: 0, banner_revision: 0, flags: 0, country: p.country })), replay: { leaderboard: readyPlayers.map((p)=>({ id: p.userid, username: p.options.username, wins: 0, active: true, shadowedBy: [ null, null ], shadows: [], naturalorder: p.naturalorder, stats: { apm: 0, pps: 0, vsscore: 0, garbagesent: 0, garbagereceived: 0, kills: 0, altitude: 0, rank: 0, targetingfactor: 0, targetinggrace: 0, btb: 0, revives: 0, escapeartist: null, blockrationing_app: null, blockrationing_final: null } })), rounds: [] } }; } addRound(players) { this.#replay.replay.rounds.push(players.map((p)=>({ active: true, alive: true, naturalorder: p.naturalorder, id: p.userid, lifetime: 0, shadows: [], shadowedBy: [ null, null ], stats: { apm: 0, pps: 0, vsscore: 0, garbagesent: 0, garbagereceived: 0, kills: 0, altitude: 0, rank: 0, targetingfactor: 0, targetinggrace: 0, btb: 0, revives: 0 }, replay: { frames: 0, events: [], options: { ...p.options, gameid: p.gameid }, results: { aggregatestats: { apm: 0, pps: 0, vsscore: 0 }, stats: { lines: 0, level_lines: 0, level_lines_needed: 0, inputs: 0, holds: 0, score: 0, zenlevel: 0, zenprogress: 0, level: 0, combo: 0, topcombo: 0, combopower: 0, btb: 0, topbtb: 0, btbpower: 0, tspins: 0, piecesplaced: 0, clears: { singles: 0, doubles: 0, triples: 0, quads: 0, pentas: 0, realtspins: 0, minitspins: 0, minitspinsingles: 0, tspinsingles: 0, minitspindoubles: 0, tspindoubles: 0, minitspintriples: 0, tspintriples: 0, minitspinquads: 0, tspinquads: 0, tspinpentas: 0, allclear: 0 }, garbage: { sent: 0, sent_nomult: 0, maxspike: 0, maxspike_nomult: 0, received: 0, attack: 0, cleared: 0 }, kills: 0, finesse: { combo: 0, faults: 0, perfectpieces: 0 }, zenith: { altitude: 0, rank: 0, peakrank: 0, avgrankpts: 0, floor: 0, targetingfactor: 0, targetinggrace: 0, totalbonus: 0, revives: 0, revivesTotal: 0, revivesMaxOfBoth: 0, speedrun: false, speedrun_seen: false, splits: [ 0, 0, 0, 0, 0, 0, 0, 0, 0 ] }, finaltime: 0 }, gameoverreason: "x" } } }))); } pipe({ gameid, frames }) { const p = this.#replay.replay.rounds.at(-1).find((p)=>p.replay.options.gameid === gameid); if (!p) return; p.replay.frames = frames.reduce((acc, frame)=>Math.max(acc, frame.frame), p.replay.frames); p.replay.events.push(...frames); } die({ gameid, data, game }) { const p = this.#replay.replay.rounds.at(-1).find((p)=>p.replay.options.gameid === gameid); if (p && p.replay.results.gameoverreason === "x") { p.replay.results.gameoverreason = data?.gameoverreason ?? "winner"; p.alive = (data?.gameoverreason ?? "winner") === "winner"; p.active = true; p.lifetime = p.replay.frames * 1000 / _game.Game.fps; if (game) { const e = game.players.find((p)=>p.gameid === gameid)?.engine; if (e) { p.stats.apm = e.dynamicStats.apm; p.stats.pps = e.dynamicStats.pps; p.stats.vsscore = e.dynamicStats.vs; p.stats.garbagesent = e.stats.garbage.sent; p.stats.garbagereceived = e.stats.garbage.receive; p.replay.results.aggregatestats = { apm: e.dynamicStats.apm, pps: e.dynamicStats.pps, vsscore: e.dynamicStats.vs }; } } if (!p.replay.events.find((f)=>f.type === "end")) { p.replay.events.push({ type: "end", frame: p.replay.frames, // TODO: put real data here data: {} }); } } } endRound({ game }) { if (!game) return; for (const p of game.players){ this.die({ gameid: p.gameid, game }); } } end({ self }) { this.#replay.ts = new Date().toString(); this.#replay.replay.leaderboard.forEach((user)=>{ const rounds = this.#replay.replay.rounds.map((r)=>r.find((p)=>p.id === user.id)).filter((r)=>r); user.stats.apm = rounds.reduce((acc, r)=>acc + r.stats.apm, 0) / rounds.length; user.stats.pps = rounds.reduce((acc, r)=>acc + r.stats.pps, 0) / rounds.length; user.stats.vsscore = rounds.reduce((acc, r)=>acc + r.stats.vsscore, 0) / rounds.length; user.stats.garbagesent = rounds.reduce((acc, r)=>acc + r.stats.garbagesent, 0); user.stats.garbagereceived = rounds.reduce((acc, r)=>acc + r.stats.garbagereceived, 0); user.stats.kills = rounds.reduce((acc, r)=>acc + r.stats.kills, 0); user.wins = rounds.reduce((acc, r)=>acc + (r.alive ? 1 : 0), 0); }); // sort: self uesr id needs first in naturalorder this.#replay.replay.leaderboard = this.#replay.replay.leaderboard.toSorted((a, b)=>{ if (a.id === self) return -1; if (b.id === self) return 1; return a.naturalorder - b.naturalorder; }).map((user, i)=>{ user.naturalorder = i; return user; }); this.#replay.replay.rounds = this.#replay.replay.rounds.map((round)=>round.toSorted((a, b)=>{ if (a.id === self) return -1; if (b.id === self) return 1; return a.naturalorder - b.naturalorder; }).map((user, i)=>{ user.naturalorder = i; return user; })); } export() { return this.#replay; } } //# sourceMappingURL=replayManager.js.map