Compare commits
14 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 7aaa4245c8 | |||
| 4e21fdba4e | |||
| 00bd14bac1 | |||
| e9a6814ebb | |||
| 452694ff32 | |||
| ae0eba134a | |||
| 14ce58f303 | |||
| c03be07eab | |||
| ac1e3550db | |||
| 0fbb6988b0 | |||
| cb77ff3abb | |||
| 3e379d03a3 | |||
| be685b888a | |||
| 4623e0175c |
@@ -3,6 +3,7 @@ services:
|
||||
image: umputun/reproxy:master
|
||||
container_name: reproxy
|
||||
hostname: reproxy
|
||||
restart: unless-stopped
|
||||
ports:
|
||||
- "80:8080"
|
||||
- "443:8443"
|
||||
@@ -15,16 +16,18 @@ services:
|
||||
environment:
|
||||
- TZ=Asia/Novosibirsk
|
||||
- DOCKER_ENABLED=true
|
||||
- STATIC_ENABLED=true
|
||||
- STATIC_RULES=crabs-games.art,^/minecraft/api/readme$,https://git.3crabs.space/api/v1/repos/user-penguin/gmancraft/contents/README.md?ref=main;crabs-games.art,^/minecraft/api/status$,https://api.mcsrvstat.us/3/90.189.218.191:25565
|
||||
- ASSETS_LOCATION=/web
|
||||
- DEBUG=true
|
||||
- SSL_TYPE=auto
|
||||
- SSL_ACME_FQDN=crabs-games.art
|
||||
- SSL_ACME_FQDN=crabs-games.art,mail.crabs-games.art,evening-detective-api.crabs-games.art,evening-detective.crabs-games.art
|
||||
- SSL_ACME_EMAIL=admin@crabs-games.art
|
||||
- SSL_ACME_LOCATION=/srv/var/ssl
|
||||
- MAX_SIZE=150M
|
||||
- HEADER=
|
||||
X-Frame-Options:SAMEORIGIN,
|
||||
X-XSS-Protection:1; mode=block;,
|
||||
Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://evening-detective-api.crabs-games.art; img-src 'self' https://evening-detective-files.crabs-games.art;
|
||||
- MAX_SIZE=1G
|
||||
- TIMEOUT_WRITE=1800s
|
||||
- TIMEOUT_RESP_HEADER=1800s
|
||||
- HEADER= X-Frame-Options:SAMEORIGIN, X-XSS-Protection:1; mode=block;, Content-Security-Policy:default-src 'self'; style-src 'self' 'unsafe-inline'; connect-src 'self' https://evening-detective-api.crabs-games.art; img-src 'self' https://evening-detective-api.crabs-games.art; media-src 'self' https://evening-detective-api.crabs-games.art;
|
||||
|
||||
networks:
|
||||
crabs-network:
|
||||
|
||||
|
After Width: | Height: | Size: 318 KiB |
@@ -0,0 +1,64 @@
|
||||
const repository = 'https://git.3crabs.space/user-penguin/gmancraft';
|
||||
|
||||
function parseLatestBuild(readme) {
|
||||
// shortcut: формат строки актуальной версии README, при его смене нужен явный manifest.
|
||||
const line = readme.split('\n').find(line => line.startsWith('Актуальная версия'));
|
||||
const match = line?.match(/^Актуальная версия\s*—\s*\*\*(\d+\.\d+\.\d+)\*\*:\s*\[Скачать \1\]\((dist\/minecraft-lab-neoforge-spike-\1\/minecraft-lab-neoforge-spike-\1\.mrpack)\)/);
|
||||
if (!match) throw new Error('Не найдена актуальная сборка');
|
||||
return { version: match[1], url: `${repository}/raw/branch/main/${match[2]}` };
|
||||
}
|
||||
|
||||
async function loadLatestBuild() {
|
||||
const statuses = document.querySelectorAll('.build-status');
|
||||
const downloads = document.querySelectorAll('.build-download');
|
||||
try {
|
||||
const response = await fetch('/minecraft/api/readme', {
|
||||
cache: 'no-store',
|
||||
signal: AbortSignal.timeout(10000),
|
||||
});
|
||||
if (!response.ok) throw new Error('README недоступен');
|
||||
const data = await response.json();
|
||||
if (data.encoding !== 'base64' || typeof data.content !== 'string') {
|
||||
throw new Error('Неизвестный формат README');
|
||||
}
|
||||
const readme = new TextDecoder().decode(Uint8Array.from(atob(data.content), char => char.charCodeAt(0)));
|
||||
const build = parseLatestBuild(readme);
|
||||
for (const status of statuses) {
|
||||
status.textContent = `Актуальная версия — ${build.version}`;
|
||||
}
|
||||
for (const download of downloads) {
|
||||
download.href = build.url;
|
||||
download.textContent = `Скачать сборку ${build.version}`;
|
||||
download.hidden = false;
|
||||
}
|
||||
} catch {
|
||||
for (const status of statuses) {
|
||||
status.textContent = 'Не удалось определить актуальную версию. Кнопка откроет репозиторий — выбери актуальную сборку в README.';
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async function loadServerStatus() {
|
||||
const status = document.getElementById('server-status');
|
||||
try {
|
||||
const response = await fetch('/minecraft/api/status', {
|
||||
cache: 'no-store',
|
||||
signal: AbortSignal.timeout(10000),
|
||||
});
|
||||
if (!response.ok) throw new Error('Статус недоступен');
|
||||
const data = await response.json();
|
||||
if (data?.online === false) {
|
||||
status.textContent = 'Сервер недоступен';
|
||||
} else if (data?.online === true && Number.isSafeInteger(data.players?.online) && data.players.online >= 0) {
|
||||
status.textContent = `Игроков онлайн: ${data.players.online}`;
|
||||
} else {
|
||||
throw new Error('Неизвестный формат статуса');
|
||||
}
|
||||
} catch {
|
||||
status.textContent = 'Не удалось получить онлайн';
|
||||
}
|
||||
}
|
||||
|
||||
loadLatestBuild();
|
||||
loadServerStatus();
|
||||
setInterval(loadServerStatus, 5 * 60 * 1000);
|
||||
|
After Width: | Height: | Size: 294 KiB |
@@ -0,0 +1,93 @@
|
||||
Copyright 2012 The Press Start 2P Project Authors (cody@zone38.net), with Reserved Font Name "Press Start 2P".
|
||||
|
||||
This Font Software is licensed under the SIL Open Font License, Version 1.1.
|
||||
This license is copied below, and is also available with a FAQ at:
|
||||
http://scripts.sil.org/OFL
|
||||
|
||||
|
||||
-----------------------------------------------------------
|
||||
SIL OPEN FONT LICENSE Version 1.1 - 26 February 2007
|
||||
-----------------------------------------------------------
|
||||
|
||||
PREAMBLE
|
||||
The goals of the Open Font License (OFL) are to stimulate worldwide
|
||||
development of collaborative font projects, to support the font creation
|
||||
efforts of academic and linguistic communities, and to provide a free and
|
||||
open framework in which fonts may be shared and improved in partnership
|
||||
with others.
|
||||
|
||||
The OFL allows the licensed fonts to be used, studied, modified and
|
||||
redistributed freely as long as they are not sold by themselves. The
|
||||
fonts, including any derivative works, can be bundled, embedded,
|
||||
redistributed and/or sold with any software provided that any reserved
|
||||
names are not used by derivative works. The fonts and derivatives,
|
||||
however, cannot be released under any other type of license. The
|
||||
requirement for fonts to remain under this license does not apply
|
||||
to any document created using the fonts or their derivatives.
|
||||
|
||||
DEFINITIONS
|
||||
"Font Software" refers to the set of files released by the Copyright
|
||||
Holder(s) under this license and clearly marked as such. This may
|
||||
include source files, build scripts and documentation.
|
||||
|
||||
"Reserved Font Name" refers to any names specified as such after the
|
||||
copyright statement(s).
|
||||
|
||||
"Original Version" refers to the collection of Font Software components as
|
||||
distributed by the Copyright Holder(s).
|
||||
|
||||
"Modified Version" refers to any derivative made by adding to, deleting,
|
||||
or substituting -- in part or in whole -- any of the components of the
|
||||
Original Version, by changing formats or by porting the Font Software to a
|
||||
new environment.
|
||||
|
||||
"Author" refers to any designer, engineer, programmer, technical
|
||||
writer or other person who contributed to the Font Software.
|
||||
|
||||
PERMISSION & CONDITIONS
|
||||
Permission is hereby granted, free of charge, to any person obtaining
|
||||
a copy of the Font Software, to use, study, copy, merge, embed, modify,
|
||||
redistribute, and sell modified and unmodified copies of the Font
|
||||
Software, subject to the following conditions:
|
||||
|
||||
1) Neither the Font Software nor any of its individual components,
|
||||
in Original or Modified Versions, may be sold by itself.
|
||||
|
||||
2) Original or Modified Versions of the Font Software may be bundled,
|
||||
redistributed and/or sold with any software, provided that each copy
|
||||
contains the above copyright notice and this license. These can be
|
||||
included either as stand-alone text files, human-readable headers or
|
||||
in the appropriate machine-readable metadata fields within text or
|
||||
binary files as long as those fields can be easily viewed by the user.
|
||||
|
||||
3) No Modified Version of the Font Software may use the Reserved Font
|
||||
Name(s) unless explicit written permission is granted by the corresponding
|
||||
Copyright Holder. This restriction only applies to the primary font name as
|
||||
presented to the users.
|
||||
|
||||
4) The name(s) of the Copyright Holder(s) or the Author(s) of the Font
|
||||
Software shall not be used to promote, endorse or advertise any
|
||||
Modified Version, except to acknowledge the contribution(s) of the
|
||||
Copyright Holder(s) and the Author(s) or with their explicit written
|
||||
permission.
|
||||
|
||||
5) The Font Software, modified or unmodified, in part or in whole,
|
||||
must be distributed entirely under this license, and must not be
|
||||
distributed under any other license. The requirement for fonts to
|
||||
remain under this license does not apply to any document created
|
||||
using the Font Software.
|
||||
|
||||
TERMINATION
|
||||
This license becomes null and void if any of the above conditions are
|
||||
not met.
|
||||
|
||||
DISCLAIMER
|
||||
THE FONT SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
||||
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO ANY WARRANTIES OF
|
||||
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT
|
||||
OF COPYRIGHT, PATENT, TRADEMARK, OR OTHER RIGHT. IN NO EVENT SHALL THE
|
||||
COPYRIGHT HOLDER BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
INCLUDING ANY GENERAL, SPECIAL, INDIRECT, INCIDENTAL, OR CONSEQUENTIAL
|
||||
DAMAGES, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
|
||||
FROM, OUT OF THE USE OR INABILITY TO USE THE FONT SOFTWARE OR FROM
|
||||
OTHER DEALINGS IN THE FONT SOFTWARE.
|
||||
@@ -0,0 +1,112 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="ru">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta name="description" content="gman-world — уютная техническая сборка Minecraft: механизмы Create, аэронавтика и виноделие.">
|
||||
<title>gman-world — Minecraft</title>
|
||||
<link rel="stylesheet" href="/minecraft/style.css?v=20261020-equal-cards">
|
||||
<script src="/minecraft/app.js?v=20261020-download-visible" defer></script>
|
||||
<script src="/minecraft/motion.js?v=20261017-steam" defer></script>
|
||||
</head>
|
||||
<body>
|
||||
<svg class="machine-definitions" aria-hidden="true" xmlns="http://www.w3.org/2000/svg"><defs>
|
||||
<g id="cog"><path d="M42 2h16l3 12 11 5 12-6 11 11-6 12 5 11 12 3v16l-12 3-5 11 6 12-11 11-12-6-11 5-3 12H42l-3-12-11-5-12 6L5 92l6-12-5-11-12-3V50l12-3 5-11-6-12 11-11 12 6 11-5z" transform="translate(6 -6) scale(.9)" fill="#ae693a" stroke="#e2b878" stroke-width="3"/><circle cx="50" cy="50" r="27" fill="#302b23" stroke="#d3a361" stroke-width="7"/><path d="M50 24v52M24 50h52M32 32l36 36M32 68l36-36" stroke="#b67b44" stroke-width="8"/><circle cx="50" cy="50" r="10" fill="#e2b878" stroke="#634126" stroke-width="3"/></g>
|
||||
<g id="wheel"><circle cx="50" cy="50" r="42" fill="#30281c" stroke="#c98b47" stroke-width="7"/><circle cx="50" cy="50" r="30" fill="none" stroke="#875b32" stroke-width="5"/><path d="M50 8v84M8 50h84M20 20l60 60M20 80l60-60" stroke="#c58b4b" stroke-width="6"/><path d="M38 4h24v10H38zM86 38h10v24H86zM38 86h24v10H38zM4 38h10v24H4zM13 13h20v12H13zM75 13h12v20H75zM67 75h20v12H67zM13 67h12v20H13z" fill="#815332" stroke="#dda25d" stroke-width="2"/><circle cx="50" cy="50" r="9" fill="#e6bb77" stroke="#563822" stroke-width="4"/></g>
|
||||
<g id="propeller"><path d="M46 45C10 37 5 19 18 15c15-5 27 14 32 29C58 9 77 4 82 18c4 14-13 26-31 32 36 9 41 27 27 32-14 4-26-13-29-31-9 36-27 41-31 27-5-14 12-26 27-29z" fill="#cfb37a" stroke="#785232" stroke-width="3"/><circle cx="50" cy="50" r="9" fill="#b5703e" stroke="#f0c589" stroke-width="3"/></g>
|
||||
</defs></svg>
|
||||
<main>
|
||||
<div class="side-machine side-machine-left" aria-hidden="true"><div class="chain-drive"></div><svg class="rotor side-cog" viewBox="0 0 100 100"><use href="#cog"/></svg><svg class="rotor reverse side-cog-small" viewBox="0 0 100 100"><use href="#cog"/></svg><div class="gauge"><i class="needle"></i></div></div>
|
||||
<div class="side-machine side-machine-right" aria-hidden="true"><div class="pipe vertical-pipe"></div><div class="valve"></div><div class="gauge"><i class="needle"></i></div><div class="steam"><i></i><i></i><i></i></div></div>
|
||||
<nav class="topbar" aria-label="Главная навигация">
|
||||
<a class="brand" href="/">CRABS GAMES<span> / </span>GMAN-WORLD</a>
|
||||
<div class="nav-actions"><a class="nav-link" href="#installation">Как зайти?</a><button id="motion-toggle" class="button" type="button" aria-pressed="false" hidden>Остановить механизмы</button></div>
|
||||
</nav>
|
||||
|
||||
<header class="hero">
|
||||
<div class="hero-machine" aria-hidden="true"><div class="pipe machine-pipe"></div><div class="gauge"><i class="needle"></i></div><svg class="rotor waterwheel" viewBox="0 0 100 100"><use href="#wheel"/></svg><svg class="rotor hero-cog" viewBox="0 0 100 100"><use href="#cog"/></svg><svg class="rotor reverse hero-cog-small" viewBox="0 0 100 100"><use href="#cog"/></svg><div class="steam"><i></i><i></i><i></i></div><span class="machine-caption">ВОДЯНОЙ ПРИВОД / CREATE</span></div>
|
||||
<div class="hero-copy">
|
||||
<p class="eyebrow">ТВОЯ МАСТЕРСКАЯ В MINECRAFT</p>
|
||||
<h1>GMAN-WORLD</h1>
|
||||
<p class="intro">Шестерёнки крутятся. Дирижабли взлетают. Виноград растёт. Залетай!</p>
|
||||
<div class="join-panel">
|
||||
<p class="server"><span>АДРЕС СЕРВЕРА</span><code>90.189.218.191:25565</code></p>
|
||||
<p id="server-status" role="status">Проверяем онлайн…</p>
|
||||
<a id="build-download" class="button build-download" href="https://git.3crabs.space/user-penguin/gmancraft">Скачать сборку</a>
|
||||
<p id="build-status" class="hint build-status" role="status">Проверяем актуальную версию…</p>
|
||||
<a class="button telemost" href="https://telemost.yandex.ru/j/76726739040099?skip_app=1" target="_blank" rel="noopener noreferrer">Зайти в Телемост</a>
|
||||
<noscript><p>Без JavaScript кнопка скачивания откроет репозиторий. Выбери актуальную сборку в README.</p></noscript>
|
||||
</div>
|
||||
</div>
|
||||
</header>
|
||||
|
||||
<div class="pipe pipe-bridge" aria-hidden="true"><span class="valve"></span><span class="pipe-joint"></span><div class="steam"><i></i><i></i><i></i></div></div>
|
||||
<section class="world" aria-labelledby="world-title">
|
||||
<div class="section-heading"><p class="eyebrow">ЗАШЁЛ НА ПЯТЬ МИНУТ</p><h2 id="world-title">Вот какой здесь вайб</h2></div>
|
||||
<p class="world-intro">Механизмы Create, полёты и виноделье — повод собраться. А дальше у каждого найдётся своё «сейчас ещё одну штуку доделаю».</p>
|
||||
<div class="world-grid">
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-workshop.webp" width="1280" height="1169" loading="lazy" decoding="async" alt="Мастер в цехе склонился над чертежами механизмов."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">ПРИДУМЫВАЕМ</p><h3>По чертежу. Почти</h3><p>Зашёл поставить пару шестерёнок. Теперь у тебя цех, три схемы переделки и уверенность, что следующий конвейер точно будет последним.</p></div>
|
||||
</article>
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-waterwheel.webp" width="1280" height="1169" loading="lazy" decoding="async" alt="Мастер налаживает деревянное водяное колесо у реки."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">КРУТИМ</p><h3>Крутится — значит, работает</h3><p>Вода шумит, колесо вращается, мастерская оживает. Можно просто постоять и посмотреть. Но ты уже присматриваешь место для второго колеса.</p></div>
|
||||
</article>
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-building.webp" width="1280" height="1169" loading="lazy" decoding="async" alt="Улыбающийся строитель укладывает каменный блок на фоне храма и гор."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">СТРОИМ</p><h3>Ещё один блок — и домой</h3><p>С друзьями даже укладка камня превращается в приключение. Особенно когда строили сарай, а получился храм.</p></div>
|
||||
</article>
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-mine.webp" width="1280" height="861" loading="lazy" decoding="async" alt="Два шахтёра с фонарями на касках в тёмном подземном проходе."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">КОПАЕМ</p><h3>За углём точно алмазы</h3><p>Факелы взяли, кирки взяли, дорогу назад вроде запомнили. Наверху уже утро, но эту жилу надо докопать.</p></div>
|
||||
</article>
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-drilling.webp" width="1129" height="1280" loading="lazy" decoding="async" alt="Бурильщик стоит рядом с большой буровой установкой под открытым небом."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">МАСШТАБИРУЕМ</p><h3>Кирка ушла на пенсию</h3><p>Когда копать руками надоело, начинается инженерия. Бур побольше, склад пошире — теперь главное успевать за собственной машиной.</p></div>
|
||||
</article>
|
||||
<article class="theme">
|
||||
<div class="scene"><img src="/minecraft/world-friendship.webp" width="800" height="800" loading="lazy" decoding="async" alt="Девушка гладит волка на фоне замка и поезда в мире Minecraft."></div>
|
||||
<div class="theme-copy"><p class="eyebrow">ПРИРУЧАЕМ</p><h3>Зашёл за ресурсами — нашёл друга</h3><p>Пока механизмы работают, можно выдохнуть и погладить волка. Большие приключения подождут.</p></div>
|
||||
</article>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<div class="pipe pipe-bridge lower-pipe" aria-hidden="true"><span class="valve"></span><span class="pipe-joint"></span></div>
|
||||
<div id="installation" class="downloads">
|
||||
<section aria-labelledby="build-title">
|
||||
<p class="eyebrow">НОВЫЙ ИГРОК</p>
|
||||
<h2 id="build-title">Первый заход</h2>
|
||||
<p class="hint">Файл .mrpack · импорт через Prism Launcher</p>
|
||||
<a id="installation-build-download" class="button build-download" href="https://git.3crabs.space/user-penguin/gmancraft">Скачать сборку</a>
|
||||
<p id="installation-build-status" class="hint build-status" role="status">Проверяем актуальную версию…</p>
|
||||
<ol>
|
||||
<li>Скачай и установи <a href="https://github.com/Diegiwg/PrismLauncher-Cracked" target="_blank" rel="noopener noreferrer">Prism Launcher</a>.</li>
|
||||
<li>Скачай актуальную сборку.</li>
|
||||
<li>В Prism Launcher выбери <strong>Add Instance → Import</strong> и укажи скачанный .mrpack.</li>
|
||||
<li>Дождись загрузки модов и запусти Minecraft.</li>
|
||||
</ol>
|
||||
</section>
|
||||
|
||||
<section aria-labelledby="transfer-title">
|
||||
<p class="eyebrow">СОХРАНЯЕМ СВОЁ</p>
|
||||
<h2 id="transfer-title">Обновляешь сборку?</h2>
|
||||
<p>Карта и метки Xaero, закладки рецептов JEI — из старой сборки в новую.</p>
|
||||
<a class="button secondary" href="https://git.3crabs.space/user-penguin/gmancraft/raw/branch/main/XaeroMapTransfer.exe">Скачать трансфер</a>
|
||||
<p class="hint">XaeroMapTransfer.exe · Windows 10/11 · <a href="https://git.3crabs.space/user-penguin/gmancraft/raw/branch/main/XaeroMapTransfer.exe.sha256">SHA-256</a></p>
|
||||
<ol>
|
||||
<li>Закрой Minecraft и запусти утилиту.</li>
|
||||
<li>Укажи старую папку игры слева, новую — справа.</li>
|
||||
<li>Нажми <strong>«Перенести данные»</strong> и дождись завершения.</li>
|
||||
</ol>
|
||||
<p class="notice">После пересоздания серверного мира старую карту переносить не следует. Перед переносом проверь изменения версии в репозитории.</p>
|
||||
</section>
|
||||
</div>
|
||||
|
||||
<footer>
|
||||
<a href="https://git.3crabs.space/user-penguin/gmancraft">Что нового? Репозиторий и инструкции ↗</a>
|
||||
<span>gman-world / crabs-games</span>
|
||||
</footer>
|
||||
</main>
|
||||
</body>
|
||||
</html>
|
||||
|
After Width: | Height: | Size: 347 KiB |
@@ -0,0 +1,15 @@
|
||||
const motionToggle = document.getElementById('motion-toggle');
|
||||
const reducedMotion = window.matchMedia('(prefers-reduced-motion: reduce)');
|
||||
|
||||
function setMotionPaused(isPaused) {
|
||||
document.documentElement.classList.toggle('motion-running', !isPaused);
|
||||
motionToggle.setAttribute('aria-pressed', String(isPaused));
|
||||
motionToggle.textContent = isPaused ? 'Запустить механизмы' : 'Остановить механизмы';
|
||||
}
|
||||
|
||||
setMotionPaused(reducedMotion.matches);
|
||||
motionToggle.hidden = false;
|
||||
motionToggle.addEventListener('click', () => {
|
||||
setMotionPaused(document.documentElement.classList.contains('motion-running'));
|
||||
});
|
||||
reducedMotion.addEventListener('change', event => setMotionPaused(event.matches));
|
||||
|
After Width: | Height: | Size: 291 KiB |
@@ -0,0 +1,182 @@
|
||||
@font-face {
|
||||
font-family: 'Press Start 2P';
|
||||
src: url('/minecraft/fonts/PressStart2P-Regular.ttf') format('truetype');
|
||||
font-display: swap;
|
||||
font-style: normal;
|
||||
font-weight: 400;
|
||||
}
|
||||
|
||||
:root {
|
||||
color-scheme: dark;
|
||||
font-family: system-ui, sans-serif;
|
||||
color: #f6ecd4;
|
||||
background: #26231e;
|
||||
line-height: 1.65;
|
||||
--pixel: 'Press Start 2P', monospace;
|
||||
--muted: #ded3bd;
|
||||
--copper: #e2ac69;
|
||||
--edge: #191612;
|
||||
}
|
||||
|
||||
* { box-sizing: border-box; }
|
||||
html { scroll-padding-top: 24px; }
|
||||
body { margin: 0; background-image: repeating-linear-gradient(0deg, #0000 0 31px, #0003 31px 34px), repeating-linear-gradient(90deg, #0000 0 63px, #ffffff04 63px 66px); }
|
||||
main { max-width: 1440px; margin: auto; padding: 18px 16px 28px; }
|
||||
a { color: #ffe3a0; text-underline-offset: 4px; }
|
||||
a:hover { color: #fff; }
|
||||
a:focus-visible { outline: 3px solid #ffdf61; outline-offset: 5px; }
|
||||
.topbar { display: flex; align-items: center; justify-content: space-between; flex-wrap: wrap; gap: 18px; padding: 16px; background: repeating-linear-gradient(0deg, #0000 0 14px, #0002 14px 17px), #68482e; border: 4px solid var(--edge); box-shadow: inset 3px 3px #987048, inset -3px -3px #3d2a1b, 0 5px #0005; }
|
||||
.brand { color: #fff0c8; font: 400 9px/1.8 var(--pixel); text-decoration: none; text-shadow: 2px 2px #302214; }
|
||||
.brand span { color: #dba16b; padding: 0 6px; }
|
||||
.nav-link { font: 400 10px/1.8 var(--pixel); }
|
||||
.hero { position: relative; isolation: isolate; display: flex; align-items: center; min-height: 670px; margin: 20px 0 44px; padding: 32px 20px; border: 4px solid #191612; box-shadow: inset 0 0 0 3px #ba8b50, 6px 6px #0005; background: #3b4934 url('/minecraft/world-waterwheel.webp') 65% center / cover no-repeat; }
|
||||
.hero::before { content: ''; position: absolute; inset: 0; z-index: -1; background: linear-gradient(90deg, #171a16ed, #171a16bb 45%, #171a1633); }
|
||||
.hero-copy { width: 100%; max-width: 600px; }
|
||||
.eyebrow { color: #f1bf73; font: 400 9px/1.9 var(--pixel); }
|
||||
h1 { color: #f4e8cb; font: 400 clamp(23px, 4vw, 48px)/1.4 var(--pixel); letter-spacing: -1px; text-shadow: 3px 3px #5b422b, 6px 6px #181711; margin: 24px 0; }
|
||||
h2 { font: 400 clamp(15px, 2vw, 22px)/1.7 var(--pixel); margin: 16px 0 24px; text-shadow: 2px 2px #0008; }
|
||||
h3 { font: 400 14px/1.8 var(--pixel); margin: 14px 0; text-shadow: 2px 2px #0008; }
|
||||
.intro { max-width: 460px; color: #fff3d9; font-size: 18px; margin-bottom: 24px; text-shadow: 1px 2px #111; }
|
||||
.join-panel { max-width: 430px; background: #494b43f5; border: 4px solid #1c211b; padding: 20px 16px; box-shadow: inset 3px 3px #92927b, inset -3px -3px #30352b, 5px 5px #0005; }
|
||||
.server { margin: 0; padding: 12px; border: 3px solid #252a22; background: #24291f; box-shadow: inset 2px 2px #10170f, inset -2px -2px #6d725e; }
|
||||
.server span { display: block; color: #cabd9e; font: 400 8px/1.8 var(--pixel); margin-bottom: 7px; }
|
||||
code { font: 600 17px/1.6 monospace; color: #fff3ca; overflow-wrap: anywhere; }
|
||||
#server-status { color: #d2f2b0; font: 600 14px/1.6 monospace; margin: 12px 0 16px; }
|
||||
.button, .nav-link, footer a { display: inline-block; color: #fff8e7; text-decoration: none; text-align: center; background: #72716a; border: 3px solid #191a16; padding: 13px 16px; box-shadow: inset 3px 3px #b9b7a7, inset -3px -3px #48483e, 3px 3px #0005; text-shadow: 2px 2px #222; }
|
||||
.button { font: 400 10px/1.9 var(--pixel); }
|
||||
.button:hover, .nav-link:hover, footer a:hover { background-color: #858b70; color: #ffffbf; box-shadow: inset 3px 3px #d4dab1, inset -3px -3px #535d43, 3px 3px #0005; }
|
||||
.button:active, .nav-link:active, footer a:active { box-shadow: inset 3px 3px #414535, inset -2px -2px #a0ab83; transform: translate(2px, 2px); }
|
||||
.button[hidden] { display: none; }
|
||||
.build-download { display: block; background-color: #526f36; box-shadow: inset 3px 3px #8eac60, inset -3px -3px #2e4924, 3px 3px #0005; }
|
||||
.build-download[hidden] { display: none; }
|
||||
.build-download:hover { background-color: #657f42; }
|
||||
.build-download:active { box-shadow: inset 3px 3px #2e4924, inset -2px -2px #8eac60; }
|
||||
.telemost { display: block; }
|
||||
.hint { font-size: 12px; color: var(--muted); overflow-wrap: anywhere; }
|
||||
.build-status { margin: 12px 0; }
|
||||
.world { margin-bottom: 34px; }
|
||||
.world-intro { max-width: 740px; margin: 0 auto 28px; color: var(--muted); text-align: center; }
|
||||
.section-heading { width: fit-content; max-width: 100%; margin: 0 auto 24px; padding: 16px 24px; text-align: center; border: 4px solid #241b13; background: repeating-linear-gradient(0deg, #0000 0 17px, #0002 17px 20px), #63462e; box-shadow: inset 3px 3px #9b7046, inset -3px -3px #39291d, 5px 5px #0004; }
|
||||
.section-heading h2 { margin-bottom: 4px; }
|
||||
.world-grid { display: grid; grid-auto-rows: 1fr; gap: 20px; }
|
||||
.theme { min-width: 0; padding: 24px; border: 4px solid #33261b; background: #4d493d; box-shadow: inset 3px 3px #a48d67, inset -3px -3px #29271f, 4px 4px #0005; }
|
||||
.theme-symbol { display: grid; width: 74px; height: 74px; place-items: center; border: 4px solid #25251f; background: #97917c; box-shadow: inset 3px 3px #5b5c4d, inset -3px -3px #c7bca0; }
|
||||
.theme-symbol svg { image-rendering: pixelated; filter: drop-shadow(3px 3px #0005); }
|
||||
.theme .eyebrow { margin-top: 24px; }
|
||||
.theme p:last-child { color: #e7dfc9; font-size: 15px; margin-bottom: 0; }
|
||||
.aviation { background: #3e4c46; }
|
||||
.winery { background: #514044; }
|
||||
.downloads { display: grid; gap: 24px; }
|
||||
.downloads section { min-width: 0; border: 4px solid #1c1d19; background: repeating-linear-gradient(0deg, #ffffff03 0 3px, #0000 3px 8px), #53554d; padding: 24px 20px; box-shadow: inset 4px 4px #97998a, inset -4px -4px #30332c, 5px 5px #0005; }
|
||||
.downloads section > p { color: var(--muted); }
|
||||
.downloads section > .eyebrow { color: #f1bf73; }
|
||||
ol { padding-left: 22px; margin-top: 24px; }
|
||||
li { padding-left: 4px; margin-bottom: 14px; }
|
||||
li::marker { color: #f5c982; font-weight: 800; }
|
||||
.notice { font-size: 13px; border-left: 4px solid #e7b05f; background: #272b23; padding: 14px; margin-top: 26px; }
|
||||
footer { display: flex; justify-content: space-between; align-items: center; flex-wrap: wrap; gap: 20px; font-size: 12px; padding: 24px 0 4px; margin-top: 16px; }
|
||||
footer span { color: #c5c1ac; font-family: monospace; }
|
||||
|
||||
@media (min-width: 700px) {
|
||||
main { padding: 24px 32px 32px; }
|
||||
.brand { font-size: 12px; }
|
||||
.hero { padding: 48px; }
|
||||
.world-grid { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.downloads { grid-template-columns: repeat(2, minmax(0, 1fr)); }
|
||||
.downloads section { padding: 28px; }
|
||||
}
|
||||
|
||||
@media (min-width: 1100px) {
|
||||
.hero { min-height: 720px; padding: 56px; }
|
||||
.hero::before { background: linear-gradient(90deg, #151a14e8, #151a14a3 43%, #151a140d 75%); }
|
||||
}
|
||||
|
||||
/* Copper fittings and moving machinery are decorative layers, clear of controls. */
|
||||
.machine-definitions { position: absolute; width: 0; height: 0; overflow: hidden; }
|
||||
main { position: relative; }
|
||||
body { background-color: #201d19; }
|
||||
.nav-actions { display: flex; flex-wrap: wrap; align-items: center; gap: 12px; }
|
||||
button { cursor: pointer; }
|
||||
#motion-toggle { font-size: 8px; padding: 12px; }
|
||||
.topbar, .join-panel, .theme, .downloads section { position: relative; border-color: #3e281a; box-shadow: inset 3px 3px #bc8c56, inset -3px -3px #573820, 5px 5px #0007; }
|
||||
.topbar::after, .join-panel::after, .theme::after, .downloads section::after { content: ''; position: absolute; inset: 7px; pointer-events: none; background: radial-gradient(circle at 4px 4px, #ffe0a4 0 1px, #a66a3c 2px 3px, #302116 4px, transparent 5px) top left / 10px 10px no-repeat, radial-gradient(circle at 4px 4px, #ffe0a4 0 1px, #a66a3c 2px 3px, #302116 4px, transparent 5px) top right / 10px 10px no-repeat, radial-gradient(circle at 4px 4px, #e5bd79 0 1px, #8a512d 2px 3px, #302116 4px, transparent 5px) bottom left / 10px 10px no-repeat, radial-gradient(circle at 4px 4px, #e5bd79 0 1px, #8a512d 2px 3px, #302116 4px, transparent 5px) bottom right / 10px 10px no-repeat; }
|
||||
.hero { overflow: hidden; }
|
||||
.hero-copy { position: relative; z-index: 2; }
|
||||
.join-panel { background: linear-gradient(125deg, #544536f5, #282e28fa); border-width: 6px; }
|
||||
.hero-machine { position: absolute; right: 3%; bottom: 24px; width: 350px; height: 300px; pointer-events: none; z-index: 1; background: linear-gradient(0deg, #141815cc, transparent); }
|
||||
.rotor { animation: machine-turn 28s linear infinite; transform-origin: center; transform-box: fill-box; filter: drop-shadow(4px 5px 2px #0009); }
|
||||
.reverse { animation-direction: reverse; }
|
||||
.waterwheel { position: absolute; width: 230px; height: 230px; right: 12px; bottom: 20px; animation-duration: 38s; }
|
||||
.hero-cog { position: absolute; width: 100px; height: 100px; left: 6px; bottom: 20px; }
|
||||
.hero-cog-small { position: absolute; width: 70px; height: 70px; left: 68px; bottom: 92px; animation-duration: 19.6s; }
|
||||
.machine-caption { position: absolute; right: 8px; bottom: 0; font: 8px/1.6 var(--pixel); color: #e9bd7a; text-shadow: 2px 2px #000; }
|
||||
.pipe { position: relative; height: 24px; border: 3px solid #492c1b; background: linear-gradient(#634124, #d5a067 24%, #a96538 50%, #5f3c26 85%, #9e6439); box-shadow: 0 5px #0005, inset 0 1px #f8cf96; pointer-events: none; }
|
||||
.pipe-bridge { margin: -20px 18px 32px; }
|
||||
.pipe-joint, .pipe::before, .pipe::after { content: ''; position: absolute; top: -8px; height: 34px; width: 14px; border: 3px solid #492e1d; background: linear-gradient(90deg, #9a6038, #e5b57d 50%, #6d4026); box-shadow: 2px 2px #0004; }
|
||||
.pipe::before { left: 12%; }
|
||||
.pipe::after { right: 12%; }
|
||||
.pipe-joint { left: 65%; }
|
||||
.valve { position: absolute; left: 32%; top: -20px; width: 44px; height: 44px; border: 6px solid #ae633c; border-radius: 50%; background: radial-gradient(circle, #d7a16a 0 4px, transparent 5px), linear-gradient(90deg, transparent 43%, #ae633c 43% 57%, transparent 57%), linear-gradient(transparent 43%, #ae633c 43% 57%, transparent 57%); box-shadow: 2px 3px #281a12; }
|
||||
.machine-pipe { position: absolute; left: 0; right: 0; top: 48px; }
|
||||
.gauge { position: relative; width: 70px; height: 70px; border: 7px solid #a57040; border-radius: 50%; background: repeating-conic-gradient(from -120deg, #5a4630 0deg 3deg, transparent 3deg 30deg), #ddcea6; box-shadow: inset 0 0 0 5px #eedcb4, 0 0 0 3px #35261b, 4px 5px #0005; }
|
||||
.gauge::after { content: ''; position: absolute; width: 10px; height: 10px; border-radius: 50%; background: #73432a; left: calc(50% - 5px); top: calc(50% - 5px); }
|
||||
.needle { position: absolute; width: 24px; height: 3px; left: 50%; top: calc(50% - 1px); background: #8a3429; transform-origin: left center; animation: pressure 7s ease-in-out infinite alternate; }
|
||||
.hero-machine > .gauge { position: absolute; top: 0; left: 95px; }
|
||||
.steam { position: absolute; width: 80px; height: 130px; bottom: 35px; right: 16px; pointer-events: none; }
|
||||
.steam i { position: absolute; width: 30px; height: 30px; left: 20px; bottom: 0; border-radius: 35%; background: #f0e7cd; opacity: 0; animation: steam-rise 5s ease-out infinite; }
|
||||
.steam i:nth-child(2) { animation-delay: -1.7s; left: 10px; }
|
||||
.steam i:nth-child(3) { animation-delay: -3.4s; left: 30px; }
|
||||
.hero-machine > .steam { top: -100px; left: 0; }
|
||||
.pipe-bridge > .steam { bottom: 10px; right: 22%; }
|
||||
.world-grid { gap: 24px; }
|
||||
.theme { padding: 18px; background-image: linear-gradient(135deg, #9c69451a, #0002); }
|
||||
.scene { position: relative; margin: -2px -2px 22px; border: 3px solid #291e15; box-shadow: 0 0 0 2px #ad794b; overflow: hidden; }
|
||||
.scene img { display: block; width: 100%; height: auto; aspect-ratio: 4 / 3; object-fit: cover; }
|
||||
.card-rotor { position: absolute; width: 72px; height: 72px; bottom: 8px; right: 10px; background: #29261caa; border: 3px solid #a77a44; border-radius: 50%; }
|
||||
.aviation .card-rotor { animation-duration: 4s; }
|
||||
.theme-symbol { width: 52px; height: 52px; border-width: 3px; float: right; margin: 0 0 10px 10px; }
|
||||
.theme-symbol svg { width: 36px; height: 36px; }
|
||||
.theme .eyebrow { margin-top: 0; padding-top: 12px; }
|
||||
.theme h3 { clear: both; }
|
||||
.lower-pipe { margin-top: 46px; margin-bottom: 40px; }
|
||||
.downloads section { background-color: #454b43; border-width: 6px; }
|
||||
.side-machine { display: none; position: absolute; top: 240px; width: 75px; height: 570px; pointer-events: none; }
|
||||
.side-machine-left { left: -64px; }
|
||||
.side-machine-right { right: -64px; }
|
||||
.side-cog { position: absolute; width: 85px; height: 85px; top: 80px; left: -12px; }
|
||||
.side-cog-small { position: absolute; width: 58px; height: 58px; top: 146px; left: 26px; animation-duration: 19s; }
|
||||
.side-machine-left > .gauge { position: absolute; top: 260px; left: 0; }
|
||||
.chain-drive { position: absolute; top: 0; left: 17px; height: 430px; width: 35px; border: 7px solid #82552f; border-radius: 22px; background: repeating-linear-gradient(#b8a07b 0 6px, #292821 6px 14px); background-size: 100% 14px; box-shadow: inset 0 0 0 5px #211b15, 3px 3px #0007; animation: chain-run 1.5s linear infinite; }
|
||||
.vertical-pipe { position: absolute; left: 20px; top: 30px; width: 24px; height: 500px; background: linear-gradient(90deg, #634124, #d5a067 24%, #a96538 50%, #5f3c26 85%, #9e6439); }
|
||||
.vertical-pipe::before, .vertical-pipe::after { width: 36px; height: 14px; left: -9px; }
|
||||
.vertical-pipe::before { top: 80px; }
|
||||
.vertical-pipe::after { top: 410px; }
|
||||
.side-machine-right > .valve { top: 100px; left: 10px; }
|
||||
.side-machine-right > .gauge { top: 210px; left: 0; }
|
||||
.side-machine-right > .steam { top: -90px; right: 0; }
|
||||
@keyframes machine-turn { to { transform: rotate(360deg); } }
|
||||
@keyframes pressure { from { transform: rotate(-130deg); } to { transform: rotate(-50deg); } }
|
||||
@keyframes steam-rise { 0% { opacity: 0; transform: translate(0, 0) scale(.4); } 15% { opacity: .4; } 100% { opacity: 0; transform: translate(15px, -120px) scale(2.2); } }
|
||||
@keyframes chain-run { to { background-position-y: -28px; } }
|
||||
.rotor, .needle, .steam i, .chain-drive { animation-play-state: paused; }
|
||||
html.motion-running .rotor, html.motion-running .needle, html.motion-running .steam i, html.motion-running .chain-drive { animation-play-state: running; }
|
||||
@media (max-width: 1099px) {
|
||||
.hero-machine { width: 180px; height: 170px; right: 12px; bottom: 8px; opacity: .85; }
|
||||
.waterwheel { width: 130px; height: 130px; right: 0; bottom: 15px; }
|
||||
.hero-cog { width: 54px; height: 54px; left: 0; bottom: 10px; }
|
||||
.hero-cog-small { width: 38px; height: 38px; left: 31px; bottom: 48px; }
|
||||
.hero-machine > .gauge, .hero-machine > .machine-pipe, .machine-caption { display: none; }
|
||||
.hero-machine > .steam { top: 0; }
|
||||
.hero { padding-bottom: 170px; }
|
||||
}
|
||||
@media (max-width: 699px) {
|
||||
.steam i:nth-child(3), .pipe-bridge > .steam { display: none; }
|
||||
.pipe-bridge { margin-left: 8px; margin-right: 8px; }
|
||||
.scene { margin-bottom: 18px; }
|
||||
#motion-toggle { font-size: 7px; }
|
||||
}
|
||||
@media (min-width: 1580px) { .side-machine { display: block; } }
|
||||
@media (prefers-reduced-motion: reduce) {
|
||||
html:not(.motion-running) .rotor, html:not(.motion-running) .needle, html:not(.motion-running) .steam i, html:not(.motion-running) .chain-drive { animation: none; }
|
||||
.needle { transform: rotate(-90deg); }
|
||||
}
|
||||
|
After Width: | Height: | Size: 485 KiB |
|
After Width: | Height: | Size: 185 KiB |
|
After Width: | Height: | Size: 208 KiB |
|
After Width: | Height: | Size: 123 KiB |
|
After Width: | Height: | Size: 62 KiB |
|
After Width: | Height: | Size: 240 KiB |
|
After Width: | Height: | Size: 144 KiB |