«Работает» — только после строки о готовности сервера
CI / test (push) Successful in 23s
Release / release (push) Successful in 30s

Регистрацию в Steam сервер печатает задолго до того, как мир загружен, и по
ней панель показывала «Работает» на сервере, который ещё никого не пустит.
Теперь готовность распознаётся только по «*** SERVER STARTED ****», а пока
идёт загрузка, состояние остаётся «Запускается» с пояснением под ним и
счётчиком времени загрузки.

Если строки о готовности так и не будет (своя версия, свои моды), через
пятнадцать минут менеджер сочтёт сервер запущенным и скажет об этом в
консоли: иначе панель навсегда осталась бы без опроса игроков.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-06 14:15:54 +03:00
co-authored by Claude Opus 5
parent 9a224bc070
commit 1e659678b9
8 changed files with 87 additions and 7 deletions
+12 -3
View File
@@ -68,7 +68,9 @@ function formatBytes(bytes) {
return `${value.toFixed(value < 10 && unit > 0 ? 1 : 0)} ${units[unit]}`;
}
function formatUptime(seconds) {
// key разделяет два смысла одного счётчика: сервер либо уже работает, либо
// всё ещё загружается.
function formatUptime(seconds, key = "overview.uptime") {
if (!seconds) return "";
const days = Math.floor(seconds / 86400);
const hours = Math.floor((seconds % 86400) / 3600);
@@ -77,7 +79,7 @@ function formatUptime(seconds) {
if (days) parts.push(t("unit.days", { value: days }));
if (hours) parts.push(t("unit.hours", { value: hours }));
parts.push(t("unit.minutes", { value: minutes }));
return t("overview.uptime", { value: parts.join(" ") });
return t(key, { value: parts.join(" ") });
}
function formatDate(unixSeconds) {
@@ -253,7 +255,14 @@ function renderStatus(status) {
$("#ov-profile").textContent = status.profile_title
? t("overview.profile", { title: status.profile_title })
: "";
$("#ov-uptime").textContent = formatUptime(status.uptime_sec);
// Процесс уже запущен, но мир грузится минутами, и всё это время сервер
// никого не пустит: пишем об этом прямо, иначе «Работает» вводит в
// заблуждение.
const starting = status.state === "starting";
$("#ov-note").textContent = starting ? t("overview.starting") : "";
$("#status-pill").title = starting ? t("overview.starting") : "";
$("#ov-uptime").textContent =
formatUptime(status.uptime_sec, starting ? "overview.loading" : "overview.uptime");
$("#ov-pid").textContent = status.pid ? `PID ${status.pid}` : "";
$("#ov-lastexit").textContent =
status.state === "stopped" && status.last_exit
+4
View File
@@ -133,6 +133,8 @@ const STRINGS = {
"overview.load": "Load average",
"overview.diskFree": "Диск свободно",
"overview.uptime": "Работает: {value}",
"overview.loading": "Загружается: {value}",
"overview.starting": "Мир загружается — сервер ещё не принимает подключения",
"overview.profile": "Профиль: {title}",
"overview.lastExit": "Последнее завершение: {reason}",
"overview.memoryOf": "{free} из {total}",
@@ -428,6 +430,8 @@ const STRINGS = {
"overview.load": "Load average",
"overview.diskFree": "Disk free",
"overview.uptime": "Uptime: {value}",
"overview.loading": "Loading: {value}",
"overview.starting": "The world is loading — the server does not accept connections yet",
"overview.profile": "Profile: {title}",
"overview.lastExit": "Last exit: {reason}",
"overview.memoryOf": "{free} of {total}",
+1
View File
@@ -101,6 +101,7 @@
<div class="card">
<h3 data-i18n="overview.stateCard"></h3>
<div class="stat" id="ov-state"></div>
<div class="starting-note" id="ov-note"></div>
<div class="muted" id="ov-profile"></div>
<div class="muted" id="ov-uptime"></div>
<div class="muted" id="ov-pid"></div>
+4
View File
@@ -109,6 +109,10 @@ code {
}
.dot.running { background: var(--accent); box-shadow: 0 0 8px var(--accent); }
.dot.starting, .dot.stopping, .dot.restarting { background: var(--warn); animation: pulse 1.2s infinite; }
/* Пояснение под состоянием — тем же цветом, что и пульсирующий индикатор:
пока он мигает, сервер ещё не принимает игроков. */
.starting-note { color: var(--warn); }
.dot.stopped { background: #5b636f; }
@keyframes pulse { 50% { opacity: .35; } }