Skip to content

Chat

A Chat page in the pause menu: the last messages, a text box (Enter sends), and /commands the gamemode handles.

client/scripts/chat.js
const lines = [];

const chat = sagl.ui.pauseMenu.addPage("Chat", `
  <h2 class="first">Chat</h2>
  <div id="log" style="display: block; height: 260dp; overflow-y: auto;"></div>
  <input class="text" type="text" id="msg" maxlength="128" placeholder="Say something, or /help"/>
  <button id="send">Send</button>`);

function send() {
  const text = chat.getValue("msg").trim();
  if (text) sagl.emit("chat", text);
  chat.setValue("msg", "");
}

chat.on("click", "send", send);
chat.on("change", "msg", (e) => { if (e.enter) send(); });  // Enter in the text box
chat.onShow(() => chat.focus("msg"));

const escape = (s) => s.replace(/&/g, "&amp;").replace(/</g, "&lt;");

sagl.on("chat", ({ from, text, colour }) => {
  lines.push(`<div><span style="color: ${colour ?? "#accbf1"}">${escape(from)}:</span> ${escape(text)}</div>`);
  if (lines.length > 50) lines.shift();
  chat.setHtml("log", lines.join(""));
});

The gamemode broadcasts messages and runs commands:

chat.ts
import type { Server, Player } from "@sagl/server";

export type Command = (player: Player, args: string[]) => void;

export function chat(server: Server) {
  const channel = server.channel("chat");
  const commands = new Map<string, Command>();

  const say = (from: string, text: string, colour?: string) => channel.broadcast({ from, text, colour });
  const tell = (player: Player, text: string) => channel.send(player, { from: "Server", text, colour: "#e1c063" });

  commands.set("help", (p) => tell(p, `Commands: ${[...commands.keys()].map((c) => "/" + c).join(" ")}`));
  commands.set("me", (p, args) => say(p.name, `* ${args.join(" ")}`, "#c0a0ff"));

  channel.on((player, data) => {
    const text = String(data).slice(0, 128).trim();
    if (!text) return;
    if (text.startsWith("/")) {
      const [name, ...args] = text.slice(1).split(/\s+/);
      const run = commands.get(name.toLowerCase());
      run ? run(player, args) : tell(player, `Unknown command /${name}`);
      return;
    }
    say(player.name, text);
  });

  server.on("playerJoin", (p) => say("Server", `${p.name} joined`, "#9aa3b2"));
  return { commands, say, tell };
}