Files
Emil c7e86663d8
MVP checks / mvp (push) Waiting to run
Expand voxel gameplay, lighting, full-height streaming and world imports
Add shared Rust/WASM physics, worker meshing and diagnostics, 64-chunk full-height streaming, atlas texture support, and baseline world import. Document the current implementation and include the supplied in-game lobby screenshot.
2026-09-17 02:10:53 +03:00

203 lines
10 KiB
HTML
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
<!doctype html>
<html lang="ru">
<head>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width,initial-scale=1" />
<meta name="color-scheme" content="dark" />
<title>Shacraft · Мир</title>
<link
rel="icon"
href="data:image/svg+xml,%3Csvg xmlns=%27http://www.w3.org/2000/svg%27 viewBox=%270 0 32 32%27%3E%3Cpath fill=%27%2394ae81%27 d=%27M16 1 30 9v15L16 32 2 24V9z%27/%3E%3C/svg%3E"
/>
<link rel="stylesheet" href="/style.css" />
</head>
<body>
<canvas
id="world-canvas"
tabindex="0"
aria-label="Трёхмерный мир Shacraft. WASD — движение, пробел — прыжок, Ctrl — бег, Shift — присесть, мышь — обзор."
></canvas>
<div id="labels" aria-hidden="true"></div>
<header class="topbar">
<div class="identity">
<svg viewBox="0 0 28 32" width="27" height="30" aria-hidden="true">
<path d="M14 1 27 8.5 14 16 1 8.5Z" fill="#c0d3a9" />
<path d="M1 8.5 14 16v15L1 23.5Z" fill="#6d8560" />
<path d="m14 16 13-7.5v15L14 31Z" fill="#94ae81" />
</svg>
<div>
<strong>Shacraft</strong
><button id="world-button" class="world-name" title="Выбрать мир">
Подключение… ▾
</button>
</div>
<span id="connection" role="status">Загрузка</span>
</div>
<nav aria-label="Игровое меню">
<button id="library-button">Блоки <kbd>E</kbd></button
><button id="diagnostics-button" title="Открыть диагностику">
Диагностика <kbd>F3</kbd></button
><button id="menu-button" aria-label="Меню игры"></button>
</nav>
</header>
<div id="crosshair" aria-hidden="true"></div>
<div id="target-label"></div>
<div id="match" hidden></div>
<div id="toast" role="status" hidden></div>
<div class="bottom-left">
<div id="chat-log" aria-live="polite"></div>
<form id="chat-form" hidden>
<input
id="chat-input"
autocomplete="off"
maxlength="240"
aria-label="Сообщение в чат"
placeholder="Сообщение · Enter — отправить, Esc — закрыть"
/>
</form>
<div id="hints">
<span><kbd>W A S D</kbd> движение</span
><span><kbd>Пробел</kbd> прыжок</span
><span><kbd>Ctrl / Shift</kbd> бег / присесть</span
><span><kbd>ЛКМ / ПКМ</kbd> убрать / поставить</span
><span><kbd>T</kbd> чат</span>
</div>
</div>
<footer>
<div id="selected-name"></div>
<div id="hotbar" role="toolbar" aria-label="Быстрый выбор блоков"></div>
<div id="play-hint">
Нажмите на мир для управления · без захвата мыши: удерживайте и двигайте
</div>
</footer>
<div id="fatal" hidden role="alert"></div>
<aside id="menu" class="panel" hidden aria-label="Меню игры">
<div class="panel-head">
<h1>Меню игры</h1>
<button data-close="menu" aria-label="Закрыть меню">×</button>
</div>
<label for="player-name">Имя игрока</label>
<div class="inline">
<input id="player-name" maxlength="24" autocomplete="off" /><button
id="rename-button"
>
Применить
</button>
</div>
<button id="resume-button" class="primary wide">Вернуться в мир</button
><button id="respawn-button" class="wide">
Вернуться к точке появления</button
><button id="spleef-button" class="wide">Начать Spleef</button>
<p class="muted">
В Spleef убирайте снег под соперником. Последний игрок на арене
побеждает.
</p>
<div class="rule"></div>
<button id="time-button" class="wide" title="Переключить день / ночь">Освещение: ночь</button>
<button id="mouse-mode" class="wide" title="Переключить захват мыши и обзор перетаскиванием">Мышь: захват</button>
<label for="view-distance">Дальность прорисовки</label>
<div class="inline">
<select id="view-distance" aria-describedby="view-distance-info">
<option value="2">2 чанка · 32 блока</option>
<option value="3" selected>3 чанка · 48 блоков</option>
<option value="4">4 чанка · 64 блока</option>
<option value="5">5 чанков · 80 блоков</option>
<option value="6">6 чанков · 96 блоков</option>
<option value="7">7 чанков · 112 блоков</option>
<option value="8">8 чанков · 128 блоков</option>
<option value="12">12 чанков · 192 блока</option>
<option value="16">16 чанков · 256 блоков</option>
<option value="24">24 чанка · 384 блока</option>
<option value="32">32 чанка · 512 блоков</option>
<option value="48">48 чанков · 768 блоков</option>
<option value="64">64 чанка · 1 024 блока</option>
</select>
<button id="view-distance-apply" aria-label="Применить дальность" disabled>Применить</button>
</div>
<p id="view-distance-info" class="muted">Радиус вокруг игрока. Большая дальность увеличивает нагрузку на память и видеокарту.</p>
<p id="view-distance-status" class="muted" role="status"></p>
<label for="sensitivity">Чувствительность мыши</label
><input
type="range"
id="sensitivity"
min="0.0008"
max="0.006"
step="0.0002"
value="0.0024"
/>
<p class="muted">
Esc освобождает мышь. Перетаскивание работает и без захвата. Средняя
кнопка выбирает блок под прицелом. Ctrl — бег, Shift — присесть и
удержаться у края. Двойной пробел или F включает полёт, если он разрешён
в мире; пробел / Shift — вверх / вниз.
</p>
<button id="reconnect-button" class="wide">Переподключиться</button>
</aside>
<aside id="worlds" class="panel" hidden aria-label="Выбор мира">
<div class="panel-head">
<h1>Миры</h1>
<button data-close="worlds" aria-label="Закрыть миры">×</button>
</div>
<p class="muted">Изменения каждого экземпляра сохраняются независимо.</p>
<div id="world-list"></div>
</aside>
<aside
id="library"
class="panel library"
hidden
aria-label="Каталог блоков"
>
<div class="panel-head">
<div>
<h1>Библиотека блоков</h1>
<p id="catalog-count" class="muted">Каталог сервера</p>
</div>
<button data-close="library" aria-label="Закрыть библиотеку">×</button>
</div>
<input
id="catalog-search"
type="search"
placeholder="Поиск: oak, stairs, glass…"
aria-label="Поиск по каталогу"
/>
<p class="muted">
Выберите блок для текущей ячейки. Свойства состояний показаны под
названием.
</p>
<div id="catalog-list"></div>
<button id="catalog-more" class="wide">Показать ещё</button>
</aside>
<aside
id="diagnostics"
class="panel diagnostics"
hidden
aria-label="Диагностика"
>
<div class="panel-head">
<h1>Диагностика</h1>
<button data-close="diagnostics" aria-label="Закрыть диагностику">
×
</button>
</div>
<p class="muted">F3 — скрыть панель. Нажмите на мир, чтобы играть с открытой диагностикой.</p>
<div class="dynamics-tools">
<label for="dynamics-scenario">Диагностика движения</label>
<select id="dynamics-scenario"><option value="record">Запись ручного движения</option><option value="flight">Автополёт через чанки</option><option value="run">Автопробег</option><option value="turns">Полёт с поворотами</option></select>
<div class="inline"><button id="dynamics-start">Записать 30 секунд</button><button id="dynamics-stop">Стоп</button><button id="dynamics-export" disabled>Скачать JSON</button></div>
<p id="dynamics-status" role="status">Готов к записи. Автомаршрут использует обычное управление игроком.</p>
<canvas id="dynamics-chart" width="480" height="120" aria-label="Время кадров, физики и отрисовки" style="width:100%;height:120px"></canvas>
<p class="muted">Жёлтый — кадр · зелёный — отрисовка · синий — физика.</p>
<pre id="dynamics-result" style="white-space:pre-wrap;max-height:240px;overflow:auto" hidden></pre>
</div>
<dl id="debug-values"></dl>
<div id="package-status" class="muted">Пакеты ещё не загружены</div>
<button id="resync-button" class="wide">Сверить снимок мира</button>
<p class="muted">
Сервер подтверждает движение и правки. RAM процесса и полезные данные
кэша — разные измерения.
</p>
</aside>
<script type="module" src="/app.js?v=live-diagnostics-2"></script>
</body>
</html>