Под капотом
Здесь без маркетинга: как эта штука устроена и почему именно так.
Сервер
C++20, один процесс на мир. Всё игровое состояние живёт в одном потоке — без мьютексов, потому что владелец один. Второй поток занимается только сокетами: опрашивает их, читает и пишет, а прикладной код не трогает.
Между потоками две очереди: входящая будит логику, исходящая — ввод-вывод через self-pipe. Пока логика ждёт базу, сокеты продолжают жить на другом ядре.
Тик — 20 раз в секунду. Клиент присылает намерение, сервер решает.
Хранилище
PostgreSQL. Важное свойство: ревизии мира дописываются и никогда не меняются.
Триггеры в схеме физически запрещают UPDATE и DELETE на них — не «мы так
договорились», а «база не даст».
Переход A→B живёт по правилам, знакомым всем, кто писал распределённые вещи:
- аренда на переход — чтобы два процесса не двигали один мир;
- токен ограждения растёт монотонно — опоздавший писатель отсекается;
- CAS на голове — коммит проходит, только если голова там же, где была;
- исходящий ящик пишется той же транзакцией, что и ревизия.
Отсюда следует то самое проверяемое свойство: переход переживает рестарт сервера на полпути. Не «обычно переживает» — это в регрессионных тестах.
Горячий путь
Сутки становления — это 20 тиков в секунду, и каждый из них когда-то ходил в базу. Сейчас на горячем пути записей в базу нет:
- базовая ревизия декодируется один раз и лежит в кэше — она неизменяемая;
- аренда продлевается не каждый тик, а когда истекла треть срока;
- часы мира пишутся не каждый тик, а когда набежала секунда.
При падении мир доигрывает не больше секунды назад — детерминированно и идемпотентно.
Крипта
Своя, без TLS: X25519 для рукопожатия, ChaCha20-Poly1305 для кадров, HKDF-SHA256 для ключей. Ключ сервера закреплён в клиенте — сертификаты и удостоверяющие центры не нужны.
Это проверено между тремя реализациями: C++ на сервере, CryptoKit в клиенте на Swift и Python в тестах. Все три договариваются об одних и тех же ключах.
Клиент
macOS, Swift и Metal. Клиент держит каркас кадра — проходы, тени, HDR. Форма
мира приходит с сервера, клиент её не выдумывает: пока не пришёл WorldSpec,
строить нечего.
Рельеф считается по одному и тому же алгоритму на C++, Swift и Python и сверен бит-в-бит. Иначе игрок и сервер видели бы разные горы.
Сборка и выкладка
Монорепозиторий. Сервер собирается в контейнере той же Ubuntu, что стоит на боевой машине — иначе бинарь не запустится. На боевой машине не собирается ничего: два ядра и живой игровой цикл, компиляция дёргала бы тик.
После выкладки идёт проба: настоящее шифрованное рукопожатие и вход. Если она не прошла — бинарь откатывается на предыдущий, автоматически.
Чего здесь нет
Ни трекеров, ни куки, ни аналитики, ни внешних запросов. Этот сайт не знает, что ты его читаешь.