Skip to content

Saving players

Money, skin and position kept between visits, by name, in a JSON file. (Use a database for anything serious; the shape is the same.)

saving.ts
import { readFileSync, writeFileSync, existsSync } from "node:fs";
import type { Server, Player } from "@sagl/server";

interface Saved { money: number; skin: number; x: number; y: number; z: number; heading: number }

export function saving(server: Server, file = "players.json") {
  const db: Record<string, Saved> = existsSync(file) ? JSON.parse(readFileSync(file, "utf8")) : {};
  const flush = () => writeFileSync(file, JSON.stringify(db, null, 2));

  const save = (p: Player) => {
    const { x, y, z } = p.position;
    db[p.name] = { money: p.money, skin: p.skin, x, y, z, heading: p.heading };
  };

  server.on("playerJoin", (player) => {
    const saved = db[player.name];
    if (!saved) return;
    player.money = saved.money;
    player.skin = saved.skin;
    player.data.returning = saved;
  });

  // Put returning players back where they left, on their first spawn.
  server.on("playerSpawn", (player) => {
    const saved = player.data.returning as Saved | undefined;
    if (!saved) return;
    delete player.data.returning;
    player.setPosition({ x: saved.x, y: saved.y, z: saved.z }, saved.heading);
  });

  server.on("playerQuit", (player) => { save(player); flush(); });

  // And every minute, in case the server stops.
  setInterval(() => { server.players.forEach(save); flush(); }, 60_000);
}