Initial commit: Brass & Sigil monorepo
Self-hosted Minecraft modpack distribution + administration system.
- launcher/ Avalonia 12 desktop client; single-file win-x64 publish.
Microsoft auth via XboxAuthNet, manifest+SHA-1 mod sync,
portable install path, sidecar settings.
- server/ brass-sigil-server daemon (.NET 8, linux-x64). Wraps the
MC subprocess, embedded Kestrel admin panel with cookie
auth + rate limiting, RCON bridge, scheduled backups,
BlueMap CLI integration with player markers + skin proxy,
friend-side whitelist request flow, world wipe with seed
selection (keep current / random / custom).
- pack/ pack.lock.json (Modrinth + manual CurseForge entries),
data-only tweak source under tweaks/, build outputs in
overrides/ (gitignored).
- scripts/ Build-Pack / Build-Tweaks / Update-Pack / Check-Updates
plus Deploy-Brass.ps1 unified one-shot deploy with
version-bump pre-flight and daemon-state detection.
This commit is contained in:
@@ -0,0 +1,76 @@
|
||||
// Live log streaming via Server-Sent Events + command-input wiring.
|
||||
// EventSource gives us instant push (no 1-second polling lag) and reconnects
|
||||
// automatically if the connection drops.
|
||||
"use strict";
|
||||
|
||||
import { api, apiJson, escapeHtml } from "./api.js";
|
||||
import { state } from "./state.js";
|
||||
|
||||
const consoleEl = () => document.getElementById("console");
|
||||
|
||||
export function setupConsole() {
|
||||
consoleEl().textContent = "Connecting to server log…";
|
||||
|
||||
const es = new EventSource("/api/logs/stream");
|
||||
let firstEvent = true;
|
||||
es.addEventListener("log", e => {
|
||||
if (firstEvent) { consoleEl().textContent = ""; firstEvent = false; }
|
||||
try {
|
||||
const d = JSON.parse(e.data);
|
||||
const ts = new Date(d.t).toLocaleTimeString();
|
||||
const div = document.createElement("div");
|
||||
if (d.e) div.className = "err";
|
||||
div.textContent = `[${ts}] ${d.m}`;
|
||||
consoleEl().appendChild(div);
|
||||
consoleEl().scrollTop = consoleEl().scrollHeight;
|
||||
// Trim very old lines so the DOM doesn't grow unbounded
|
||||
while (consoleEl().childNodes.length > 5000) {
|
||||
consoleEl().removeChild(consoleEl().firstChild);
|
||||
}
|
||||
// Re-broadcast so other modules (e.g. pregen) can react to log lines
|
||||
// without opening a second SSE connection.
|
||||
document.dispatchEvent(new CustomEvent("serverlog", { detail: d }));
|
||||
} catch {}
|
||||
});
|
||||
es.onerror = () => {
|
||||
// EventSource will retry automatically.
|
||||
};
|
||||
|
||||
// Command input
|
||||
const cmdInput = document.getElementById("cmdInput");
|
||||
document.getElementById("cmdSend").addEventListener("click", sendCommand);
|
||||
cmdInput.addEventListener("keydown", onCmdKeyDown);
|
||||
}
|
||||
|
||||
async function sendCommand() {
|
||||
const cmdInput = document.getElementById("cmdInput");
|
||||
const v = cmdInput.value.trim();
|
||||
if (!v) return;
|
||||
try {
|
||||
await apiJson("/api/command", { command: v });
|
||||
state.cmdHistory.push(v);
|
||||
state.cmdHistoryIdx = state.cmdHistory.length;
|
||||
cmdInput.value = "";
|
||||
cmdInput.dispatchEvent(new Event("input")); // refresh ghost text
|
||||
} catch (e) { alert(e.message); }
|
||||
}
|
||||
|
||||
function onCmdKeyDown(e) {
|
||||
const cmdInput = document.getElementById("cmdInput");
|
||||
if (e.key === "Enter") {
|
||||
sendCommand();
|
||||
} else if (e.key === "ArrowUp") {
|
||||
if (state.cmdHistory.length === 0) return;
|
||||
e.preventDefault();
|
||||
state.cmdHistoryIdx = Math.max(0, state.cmdHistoryIdx - 1);
|
||||
cmdInput.value = state.cmdHistory[state.cmdHistoryIdx] || "";
|
||||
cmdInput.dispatchEvent(new Event("input"));
|
||||
} else if (e.key === "ArrowDown") {
|
||||
if (state.cmdHistory.length === 0) return;
|
||||
e.preventDefault();
|
||||
state.cmdHistoryIdx = Math.min(state.cmdHistory.length, state.cmdHistoryIdx + 1);
|
||||
cmdInput.value = state.cmdHistory[state.cmdHistoryIdx] || "";
|
||||
cmdInput.dispatchEvent(new Event("input"));
|
||||
}
|
||||
// Note: Tab is handled by the autocomplete module's keydown listener.
|
||||
}
|
||||
Reference in New Issue
Block a user