[![TypeScript](https://img.shields.io/badge/TypeScript-5.5-3178C6?logo=typescript&logoColor=white)](https://www.typescriptlang.org/) [![Node.js](https://img.shields.io/badge/Node.js-ESM-339933?logo=nodedotjs&logoColor=white)](https://nodejs.org/) [![Three.js](https://img.shields.io/badge/Three.js-r165-000000?logo=threedotjs&logoColor=white)](https://threejs.org/) [![Vite](https://img.shields.io/badge/Vite-8-646CFF?logo=vite&logoColor=white)](https://vite.dev/) [![Vitest](https://img.shields.io/badge/Vitest-4.1-6E9F18?logo=vitest&logoColor=white)](https://vitest.dev/) [![PostgreSQL](https://img.shields.io/badge/PostgreSQL-16-4169E1?logo=postgresql&logoColor=white)](https://www.postgresql.org/) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](../../LICENSE) [![Version](https://img.shields.io/badge/version-0.6.0-blue)](../../package.json) [![Discord](https://img.shields.io/badge/Discord-join-5865F2?logo=discord&logoColor=white)](https://discord.gg/GjhnUsBtw) [English](../../README.md) · [Español](README.es.md) · [Español (España)](README.es_ES.md) · [Français](README.fr_FR.md) · [Français (Canada)](README.fr_CA.md) · [Italiano](README.it_IT.md) · [Deutsch](README.de_DE.md) · [简体中文](README.zh_CN.md) · [繁體中文](README.zh_TW.md) · [한국어](README.ko_KR.md) · [日本語](README.ja_JP.md) · [Português (Brasil)](README.pt_BR.md) · **Русский**
# World of ClaudeCraft — MMO в классическом стиле [Присоединяйтесь к сообществу в Discord](https://discord.gg/GjhnUsBtw) ![Заставка World of ClaudeCraft](../../docs/screenshots/title-screen.jpg) Микро-MMO в духе классических MMO эпохи, которую вы можете хостить и в которую можете играть: 1. **Играйте онлайн** — настоящая клиент-серверная игра с учётными записями, персонажами, сохраняемыми в Postgres, и другими игроками в мире рядом с вами. 2. **Играйте офлайн** в браузере, чтобы сразу окунуться в мир. Оба режима используют **одно и то же детерминированное ядро симуляции** (`src/sim/`), поэтому офлайн-мир ведёт себя точно так же, как авторитетный многопользовательский сервер запускает для всех онлайн. ## Скриншоты ![Группа собирается у аптеки в Eastbrook](../../docs/screenshots/party-questing.jpg) | | | |:---:|:---:| | ![Сумерки у костра в Eastbrook](../../docs/screenshots/eastbrook-dusk.jpg)
*Сумерки у костра в Eastbrook* | ![Пуллы элитных мобов в Hollow Crypt](../../docs/screenshots/hollow-crypt.jpg)
*Пуллы элитных мобов при свете факелов в The Hollow Crypt* | | ![Беспокойные мертвецы у разрушенной часовни](../../docs/screenshots/restless-dead.jpg)
*Беспокойные мертвецы у разрушенной часовни* | ![Стычка с Vale Bandits](../../docs/screenshots/vale-bandits.jpg)
*В меньшинстве у лагеря бандитов* | | ![Old Greyjaw, загнанный на северной дороге](../../docs/screenshots/old-greyjaw.jpg)
*Old Greyjaw, редкий спавн, загнан на северной дороге* | ![Интерфейс торговца и сумок](../../docs/screenshots/vendor-and-bags.jpg)
*Экипировка у Smith Haldren — подсказки, сумки, монеты* | ![World of Claude](../../worldofclaude.png) ![Сообщество World of ClaudeCraft](../../woc_community.png) --- ## Хостинг (одна команда) ```bash cp .env.example .env # отредактируйте .env и задайте длинный случайный POSTGRES_PASSWORD docker compose up -d --build # postgres + игровой сервер, полностью собранные # откройте http://localhost:8787 — учётные записи, персонажи, весь мир ``` Для **удалённого хостинга**: разверните compose-стек на любом VPS, задайте реальный `POSTGRES_PASSWORD` в окружении и поставьте перед портом 8787 обратный прокси с TLS (с Caddy это две строки — `your.domain { reverse_proxy localhost:8787 }`); WebSocket-соединения проксируются автоматически, и клиент сам выбирает `wss://` на https-страницах. Эндпоинты аутентификации ограничены по частоте на каждый IP; пароли хешируются через scrypt; токены истекают через 7 дней. Никогда не задавайте `ALLOW_DEV_COMMANDS=1` в продакшене (это включает читы на уровень/телепорт, используемые тестовыми ботами). ## Разработка онлайн (горячая перезагрузка) ```bash npm install cp .env.example .env # отредактируйте .env и задайте одинаковый пароль в POSTGRES_PASSWORD и DATABASE_URL npm run db:up # postgres 16 в docker (порт 5433, с сохранением на томе) npm run server # авторитетный игровой сервер на :8787 (REST + WebSocket) npm run dev # клиентский dev-сервер на :5173 (проксирует /api и /ws) ``` Откройте http://localhost:5173 → **Play Online** → создайте учётную запись → создайте персонажа → Enter World. Откройте второй браузер/вкладку и войдите снова — вы увидите друг друга в городе. `Enter` открывает чат. - **Учётные записи**: пароли, хешированные scrypt, 7-дневные bearer-токены (`auth_tokens`). - **Персонажи**: до 10 на учётную запись; уровень/экипировка/сумки/квесты/позиция/деньги сохраняются как JSONB в Postgres — каждые 30 с, при выходе и при остановке сервера. Имена глобально уникальны, только буквы, в классическом стиле. - **Сервер авторитетен**: клиенты передают намерение о движении + команды с частотой 20 Hz; сервер запускает мир (один общий `Sim`) и рассылает снимки, ограниченные областью интереса (~120 yd), плюс события, маршрутизируемые по игрокам. Вся боевая математика, броски на лут, зачёт квестов и сделки с торговцами происходят на стороне сервера; клиент — лишь рендерер. - **Группы** (до 5): правый клик по игроку → *Invite to Party*. Рамки группы слева, участники делят права на добычу, зачёт квестов за убийства и делят опыт с настоящими ванильными групповыми бонусами (1.166/1.3/1.43 для 3/4/5). Чат группы через `/p message`. Синие метки участников на миникарте. - **Торговля**: правый клик по игроку → *Trade*. Обе стороны выставляют предметы + деньги, оба должны подтвердить, и обмен атомарен и проверяется сервером (квестовые предметы нельзя передать). Если разойтись, обмен отменяется. - **Дуэли**: правый клик → *Challenge to a Duel*. Обратный отсчёт 3 секунды, бой до тех пор, пока у одной из сторон не останется 1 hp — никто не умирает, победитель объявляется по всей зоне. Отбежав на 60 ярдов, вы сдаётесь. - **The Ashen Coliseum** (рейтинговая арена 1 на 1): нажмите `G` (или кнопку ⚔), чтобы открыть панель арены и *Enter the Queue*. Подбор пары сводит вас с ближайшим по рейтингу соперником онлайн, затем телепортирует вас обоих на приватную, освещённую факелами боевую арену. Обратный отсчёт 5 секунд лечит и сбрасывает обоих бойцов для честного старта; бой заканчивается, когда один сдаётся при 1 hp (никто не умирает). Победы и поражения изменяют постоянный **рейтинг Elo** (все начинают с 1500), и вы возвращаетесь ровно туда, откуда встали в очередь. Панель показывает ваше положение, актуальную онлайн-лестницу и таблицу лидеров за всё время (`GET /api/arena/leaderboard`). - **Правила мультиплеера**: классические права на добычу (первый игрок, нанёсший урон мобу, владеет его лутом/опытом/зачётом квеста — остальные получают "You don't have permission to loot that."), мобы переключаются на следующего атакующего, когда их жертва умирает (без бесплатных сбросов), объявления о входе/выходе, чат в стиле `/say`. ## The Hollow Crypt — элитное подземелье на 5 игроков Сюжетная линия Brother Aldric продолжается после *The Restless Dead*: **Whispers Below** (найти печать Gravecaller у разрушенной часовни) → **The Binding Rite** (собрать Blessed Tallow на раскопках кобольдов и Ghostly Essence у беспокойных мертвецов) → **Into the Hollow** (*рекомендуемое число игроков: 5*) — убить Morthen the Gravecaller на дне склепа под часовней. - Дверь склепа у Fallen Chapel телепортирует вашу **группу в её собственную приватную копию подземелья** (6 слотов; экземпляры сбрасываются после 5 минут пустоты). - Внутри: освещённые факелами залы, парные паки **элитного** трэша (ванильное масштабирование элиты: ~2.3× здоровья, ~1.5× урона, двойной опыт), минибосс Sexton Marrow и Morthen — элитный босс 10 уровня с AoE **Shadow Pulse** каждые 10 секунд. Трэш подземелья не возрождается, пока экземпляр не сбросится. - Награды: редкое (синее) оружие под каждый классовый архетип, 1 золотой, 1500 опыта. - Подземелье по-настоящему рассчитано на 5: наш автоматический рейд из 5 ботов (warrior, paladin, priest, mage, hunter с фокус-фаером + ИИ-хилером) проходит его примерно за 5 минут с ~10 смертями (`node scripts/crypt_raid.mjs`, требует ALLOW_DEV_COMMANDS=1). ``` docker compose ps # eastbrook-db (postgres:16-alpine, healthcheck) node scripts/mp_integration.mjs # набор из 26 проверок API/WS/персистентности node scripts/mp_browser.mjs # два реальных браузерных клиента видят друг друга ``` ## The Sunken Bastion и Gravewyrm Sanctum Заговор не заканчивается на Morthen. **The Sunken Bastion** (5 игроков, ~уровень 13, юго-восток Mirefen) укрывает Vael the Mistcaller — он призывает волны Drowned Thralls при 60% и 30% здоровья. Финал — **Gravewyrm Sanctum** (5 игроков, уровень 20, под Thornpeak): три зала элитной костяной стражи и драконидов, Korgath the Bound (впадает в ярость ниже 30%), Grand Necromancer Velkhar (новые волны адов) и **Korzul the Gravewyrm** — здесь падает эпическое оружие, а подводящая квестовая цепочка проходима в одиночку, так что никто не остаётся за бортом сюжета. ## Играйте офлайн ```bash npm run dev # откройте http://localhost:5173 -> Play Offline ``` Назовите своего персонажа, выберите любой из девяти классов — и вы в **Eastbrook Vale** (уровни 1-7): рыночный городок, окружённый шестью хабами — волчьи тропы на севере, кабаньи луга на востоке, the Webwood на западе, Mirror Lake на северо-западе, медные раскопки кобольдов на юго-западе, разрушенная часовня с беспокойными мертвецами на северо-востоке и лагерь бандитов Gorrak на юго-востоке. Дорога на север поднимается через горный перевал в **Mirefen Marsh** (6-13, хаб: Fenbridge) и дальше вверх к **Thornpeak Heights** (13-20, хаб: Highwatch) — три зоны, ~60 квестов и одна сюжетная линия: заговор Gravecaller, от первых беспокойных костей за Eastbrook до **Korzul the Gravewyrm** под пиками. У каждого хаба есть торговцы (включая оружейников и бронников, продающих честное белое снаряжение), кладбище, своя музыка и карта зоны. ### Управление (классическая раскладка) | Ввод | Действие | |---|---| | `W`/`S` | бег / шаг назад — `A`/`D` поворот (стрейф при зажатой правой кнопке мыши), `Q`/`E` стрейф | | right-drag / left-drag | обзор мышью / орбита камеры  ·  колесо приближает · `Space` прыжок | | `Tab` | переключение по ближайшим врагам · левый клик — выбор цели · правый клик — атака/добыча/разговор | | `1`–`9`, `0`, `-`, `=` | панель действий | | `F` | взаимодействие (обыскать труп / подобрать объект / поговорить) | | `C` `P` `L` `M` `B` `G` | персонаж · книга заклинаний · журнал квестов · карта мира · сумки · арена (Ashen Coliseum) | | `V` / `R` / `Esc` | имена над головой · автобег · закрыть окна / сбросить цель | ### Чек-лист соответствия классике **Формулы (настоящие ванильные)** - Конвертация ярости `c = 0.0091L² + 3.23L + 4.27`; прирост `7.5·d/c` при нанесении, `2.5·d/c` при получении - Таблица попадания заклинаний с обрывом на +3 уровня (96/95/94/83%); промах/уклонение в ближнем бою относительно уровня - Снижение урона бронёй `armor/(armor + 85·AttackerLevel + 400)` - Правила характеристик HP/маны: первые 20 выносливости → по 1 hp каждая, остальные → 10; первые 20 интеллекта → по 1 мане, остальные → 15 - Кривая опыта 400/900/1400/… до 20 уровня; опыт за моба `45 + 5·L` с настоящими серыми диапазонами при нулевой разнице - GCD 1.5 с (1.0 с для разбойников), таймеры взмаха оружия, правило 5 секунд для маны **Все девять ванильных классов (уровни изучения и значения рангов как в ванили, 1–20 — заклинания получают ранги по мере роста уровня: Lightning Bolt R2 на 8, R3 на 14, R4 на 20, плюс новые способности высоких диапазонов вроде Execute, Kidney Shot, Flash Heal, Stormstrike и Starfire)** - *Warrior*: ярость, Heroic Strike (на следующий взмах, вне GCD), Battle Shout, Charge, Rend, Thunder Clap, Hamstring, Bloodrage, Overpower (прок от уклонения) - *Paladin*: Seal of Righteousness (имбью оружия), высвобождаемое через **Judgement**, Holy Light, Devotion Aura, Blessing of Might, Divine Protection (поглощение), Hammer of Justice (оглушение), Lay on Hands - *Hunter*: **дальний Auto Shot** (8–35 yd с классической мёртвой зоной), Raptor Strike, Aspect of the Hawk, Serpent Sting, Arcane Shot, Concussive Shot, Mongoose Bite (прок от уклонения), Wing Clip - *Rogue*: энергия + **комбо-очки**, Sinister Strike, Eviscerate, Backstab (со спины + кинжал), Gouge, Evasion, Slice and Dice, Sprint - *Priest*: Smite, Lesser Heal, Power Word: Fortitude, Shadow Word: Pain, **Power Word: Shield** (поглощение), **Renew** (HoT), Mind Blast - *Shaman*: Lightning Bolt, **Rockbiter Weapon** (имбью), Healing Wave, Earth Shock, **Lightning Shield** (шипы), Flame Shock - *Mage*: Fireball, Frost Armor, Arcane Intellect, Frostbolt, Conjure Water, Fire Blast, Arcane Missiles (поддерживаемое), **Polymorph**, Frost Nova - *Warlock*: Shadow Bolt, Demon Skin, Immolate, Corruption, **Life Tap**, Curse of Agony, **Drain Life** (поддерживаемая кража здоровья) - *Druid*: Wrath, Healing Touch, Mark of the Wild, Moonfire, Rejuvenation, Thorns, Entangling Roots, **Bear Form** (переключаемое превращение на 10) - Лечения можно направлять на участников группы (кликните по рамке группы, затем лечите); баффы можно накладывать на дружественных игроков; лечение бьёт критами; щиты-поглотители впитывают урон раньше здоровья. **Мир и системы** - Еда/питьё: садитесь, восстановление за 18 с, прерывается уроном или вставанием — и да, можно есть и пить одновременно - Торговец: покупайте еду/воду, продавайте свой серый хлам; отображение монет в g/s/c - Наземные квестовые объекты с искрами (украдите назад ящики с припасами бандитов) - ИИ мобов: блуждание, агро по близости в зависимости от разницы уровней, социальные пуллы (мурлоки тянут издалека — берите друзей), погоня, leash-уход-сброс, обыск трупов, возрождение; редкий спавн (Old Greyjaw) на длинном таймере - Смерть → отпустите дух → кладбище; урон от падения; плавание замедляет вас - Журнал квестов с возможностью отказа, диалоги с приветствиями, награды по классу **Презентация** - Процедурно всё: фахверковые дома, черепичные крыши, часовня, рыночный прилавок, шатры, костры с мерцающим светом, портал шахты, разрушенные колонны, рыбацкий причал, грязевые хижины мурлоков, дороги, нанесённые на ландшафт, пучки травы, сосны и дубы, озеро с анимированной водой, плывущие облака, тени в реальном времени - Двенадцать оснащённых скелетом семейств существ (wolf/boar/spider/murloc/kobold/skeleton/ humanoid/troll/ogre/elemental/dragonkin/sheep) с анимациями ходьбы/атаки/каста/сидения/ смерти - Нарисованные процедурные иконки для каждого заклинания, предмета и баффа — рисуются на canvas во время выполнения, без файлов ресурсов - Классический UI: портретные рамки юнитов, полосы баффов/дебаффов с длительностями, панель действий с разворотами перезарядки + раскраской дальности/ресурса, полоса каста/поддержания, книга заклинаний, кукла персонажа, журнал квестов, карта мира, окна торговца + добычи, подсказки с золотой каймой, всплывающий боевой текст, боевой лог, сегментированная полоса опыта, миникарта с метками и полная карта зоны - Процедурный звук WebAudio: удары в ближнем бою/заклинаниями, фанфара уровня, перезвон квестов, звон монет, мелодия смерти — без аудиофайлов ## Разработка ```bash npm test # набор vitest: формулы, бой, ИИ, квесты, все 9 классов, # группы, дуэли, обмены, элиты, склеп npm run build # продакшен-сборка для веба node scripts/smoke_browser.mjs # E2E для warrior (требует запущенного `npm run dev`) node scripts/smoke_mage.mjs # mage: касты, polymorph, conjure+drink, смерть/отпускание духа node scripts/smoke_rogue.mjs # rogue: комбо-очки, eviscerate, торговец, еда node scripts/visual_tour.mjs # скриншот-тур по зоне + UI в tmp/ node scripts/mp_integration.mjs # набор из 26 проверок API/WS/персистентности (сервер запущен) node scripts/social_e2e.mjs # обмен + дуэль по сети (ALLOW_DEV_COMMANDS=1) node scripts/arena_visual.mjs # два клиента встают в очередь + бьются в рейтинговом 1 на 1 в the Ashen Coliseum node scripts/crypt_raid.mjs # пять ботов проходят the Hollow Crypt (ALLOW_DEV_COMMANDS=1) ``` Браузерные агенты могут управлять движением через `window.__game.controller` вместо имитации зажатых клавиш. Используйте `controller.move({ forward: true }, facingRadians)` или компактные websocket-флаги вроде `{ f: 1, sr: 1 }`; вызовите `controller.face(facingRadians)`, чтобы обновить направление взгляда без изменения движения, и `controller.stop()`, чтобы вернуться к реальному вводу с клавиатуры. Онлайн-игра отправляет тот же кадр ввода на сервер, который принимает только булевы/`1` флаги движения и конечные значения направления взгляда. Структура: ``` src/sim/ детерминированное N-игроковое игровое ядро (без DOM-импортов) — общее для всех целей src/render/ рендерер Three.js: models.ts (риги), props.ts, textures.ts (процедурные) src/game/ ввод + камера + WebAudio-синтез src/ui/ классический HUD: рамки, окна, подсказки, карта, FCT src/net/ онлайн-клиент: REST-аутентификация + зеркало мира по WebSocket (ClientWorld) src/world_api.ts интерфейс IWorld, которому удовлетворяют и Sim, и ClientWorld server/ игровой сервер: main.ts (HTTP+WS), game.ts (цикл мира), db.ts, auth.ts docker-compose.yml postgres:16-alpine tests/ набор vitest scripts/ браузерные E2E + скриншот-тур + интеграционные тесты мультиплеера ``` Имена, квесты и зоны оригинальны; формулы и механики следуют ванили. Сид мира зафиксирован в `src/main.ts`, поэтому мир — это одно и то же место при каждом посещении. ## Участие в разработке Мы рады любому вкладу: коду, переводам, сообщениям об ошибках и документации. Начните с [CONTRIBUTING.ru_RU.md](CONTRIBUTING.ru_RU.md), где описаны настройка и рекомендации, и, пожалуйста, соблюдайте наш [Кодекс поведения](../../CODE_OF_CONDUCT.md). Впервые здесь? Посмотрите задачи с меткой [`good first issue`](https://github.com/levy-street/world-of-claudecraft/labels/good%20first%20issue), откройте [задачу](https://github.com/levy-street/world-of-claudecraft/issues/new/choose) или поздоровайтесь в [Discord](https://discord.gg/GjhnUsBtw). ## Лицензия Код [лицензирован под MIT](../../LICENSE) — форкайте его, ремиксируйте, хостите свой собственный мир. Включённые сторонние художественные ресурсы (модели, текстуры, HDRI) остаются под своими собственными лицензиями — все CC0 в общественном достоянии, кроме нормал-карт воды под MIT, как задокументировано по каждому паку в [CREDITS.md](../../CREDITS.md).