27 KiB
RustNotMC — данные оригинала, решения и план работ
Файл для перечитывания: после сброса контекста, при передаче работы другому агенту или при возврате к проекту через месяц. Здесь лежит всё, что нужно знать, чтобы продолжить, не выясняя заново.
Порядок работы: сначала этот файл, потом код.
0. Где мы сейчас
| модуль | что в нём | состояние |
|---|---|---|
rsx-protocol |
формат провода: кадрирование, буфер, рукопожатие, игровые пакеты | рабочий, 22 теста |
rsx-auth |
свои аккаунты сервера (PBKDF2, токены, троттлинг) | рабочий, используется только когда лаунчер не настроен |
rsx-server-core |
тик-луп, мир (чанки, генерация, сохранение), сессии, вход через лаунчер | рабочий, 49 тестов |
rsx-client |
загрузчик модов, API модов, хуки в клиент | рабочий, 128 тестов |
game-fork |
форк Minecraft 1.12.2: свой сетевой слой, свой экран входа, свой HUD | собирается чисто, 3275 классов |
Уже работает целиком: клиент заходит на сервер по токену лаунчера → сервер спрашивает лаунчер «этот ваш?» → клиент получает мир → чанки приходят и рисуются → игрок ходит и ломает блоки.
Не сделано: предметы, инвентарь, крафт, верстаки, изучение чертежей, узлы-ресурсы (деревья/камни/руда как разрушаемые объекты), постройка баз, нормальная генерация мира, транспорт на NIO, дальний вид (DistantView).
1. Данные оригинала (Rust)
Источники: вики Rust (rust.fandom.com), локальный референс G:\decompiled-rustex
(Rust-клон на MC 1.8, обфусцирован), Paper API (jd.papermc.io).
1.1 Камень (Rock) — стартовый предмет
«the most basic resource gathering and fighting tool» — инструмент сбора и оружие.
- Выдаётся первым предметом в тулбаре при спавне. Крафтится из 10 камня.
- Прочность ограниченная, предмет изнашивается.
- Собирает дерево и камень; ломает бочки; бьёт постройки.
- Урон по постройкам: лоза (twig) — 9, дерево/камень — 0.2, металл — 0.1, бронированные — 0.1. То есть обычным камнем постройку не сносят.
Таблица сбора (сколько снимает один удар, сколько нужно ударов, сколько урона):
| ресурс | доля прочности за удар | ударов до разрушения | урон за удар |
|---|---|---|---|
| дерево | 0.3 | 2 | 10 |
| руда | 0.3 | 2 | 5 |
| животное | 0.0 | 2 | 10 |
1.2 Верстак (Workbench) — 3 уровня
- Разворачиваемый предмет: надо стоять рядом, чтобы крафтить.
- Открывает тех-дерево: рецепты своего уровня и ниже.
- Уровень выше → время крафта короче: −50% на один уровень выше, максимум −75% на два уровня выше.
- Рецепты, открытые верстаком, нельзя передать другому игроку (в отличие от чертежей со стола исследований).
Стоимость и время изготовления:
| уровень | ingredients | время | где крафтится |
|---|---|---|---|
| 1 | 500 дерева, 100 металла, 50 скрапа | 60 с | — |
| 2 | 500 металла, 20 ХМ, 500 скрапа | 60 с | верстак 1 |
| 3 | 1000 металла, 100 ХМ, 1250 скрапа | 60 с | верстак 2 |
Что открывает каждый уровень (выборочно, полный список — в вики):
- L1: постройки (пол, решётка, ворота, сетка-фенси, гаражные ворота, мешки с песком, бойницы, ставни, лестница, окна, калитка), предметы (торговый автомат, верстак для ремонта, кровать, лампа, стул, холодильник, мишень, стол исследований, верстак 2), ресурсы (порох), одежда (футболка, штаны, лонгслив, шахтёрская каска, куртка, рубашка, каска, ведро, резиновая каска), инструменты: Salvaged Hammer, Hatchet, Pick Axe (топор, кирка), оружие (пистолеты, револьвер, лом, гвоздомёт, дробовик, пистолет-пулемёт, M16, огнемёт, F1, гранната, мачете, глушитель, фонарь, прицел, коллиматор, 8-кратник), патроны (пистолетная, высокоскоростная стрела), ловушки (капкан, огнемёт, мина).
- L2: бетонный баррикад, клетка, водосборник, металл-баррикад, люк; предметы (большая печь, дроп-бокс, шкаф, нефтезаводка, прожектор, верстак 3); одежда (тяжёлая броня); инструменты (Salvaged Axe, Salvaged Icepick); оружие (пистолет-пулемёт Python, огнемёт, дробовик, Thompson, тесак, дульный тормоз, глушитель, длинный меч), патроны (5.56, 12 калибра), ловушки (автотурель).
- L3: каменные врата, бронированные двери, укреплённые окна; взрывчатка; тяжёлая броня; оружие (штурмовая винтовка, bolt action, rocket launcher, MP5A4); боеприпасы; детали (шестерни, труба, маслёнка, пружина, набор для шитья).
1.3 Стол исследований (Research Table) и чертежи (Blueprints)
- «to create Blueprints by using Scrap and the item to make the blueprint of, which means one has to find the desired item first».
- Процедура: кладёшь один нужный предмет в верхний слот → показывается требуемый скрап (в нижний слот) → кнопка «Research» → 10 секунд → в верхнем слоте появляется чертёж, предмет уничтожается.
- Прочность предмета на результат не влияет (если предмет не сломан — иначе не работает).
- Исследование продолжается, если закрыть интерфейс стола. Звук слышно рядом.
- Скрап: 20 / 75 / 125 / 500 по тирам предмета.
- Сам стол: 200 металла + 20 скрапа, крафтится на верстаке 1, 60 с.
- Столы есть на монументах (аэродром, электростанция, спутниковая тарелка, супермаркет, аванпост) — то есть это вещь, за которой надо сходить.
- Эксперимент на верстаке: ломаешь 75 / 300 / 1000 скрапа → получаешь случайный ещё неизвестный чертёж уровня этого верстака. Отличие от стола: случайный результат.
1.4 Скрап (Scrap)
- Выпадает при разрушении постройек игроков, а не из ресурсных узлов.
- Тратится на исследование и на крафт верстаков.
1.5 Постройка баз (Rust)
Как ставится. Строительный план (Building Plan, 20 дерева) — разворачиваемый предмет: кладёшь в хотбар, выбираешь, видишь «призрак» объекта; ПКМ + движение мышью перебирает варианты объекта, ЛКМ ставит.
Два слоя объектов:
- Строительные (то, из чего база): фундамент (квадратный/треугольный), пол (квадратный/ треугольный), стена, полустена, низкая стена, дверной проём, окно, настенная рамка, рамка пола, лестница, крыша, столб.
- Внутренние (то, что внутри): двери, верстаки, печи, сундуки, торговый автомат, шкаф, инструментальный шкаф, замки.
Ставятся свободно, не по сетке мира. Снаппятся внутренние к уже поставленным строительным: стены — к краю фундамента, полы — к верхней кромке стены, двери — внутрь дверного проёма. Правило из вики дословно: «To place walls, select them and aim at the edge of a foundation. Floors must be placed at the top edge of a wall, and doors must be placed inside door frames.»
Проёмы двух видов:
- малый (дверной проём) — влезает только одиночная дверь;
- большой — влезают двойные двери и гаражные, но не одиночные.
Уровни (tiers) и прочность:
| уровень | прочность | как получить | цена (пример) |
|---|---|---|---|
| Twig (лоза) | 10 | только строительным планом, напрямую | дерево: фундамент 50, стена 50, проём 35, окно 35, пол 25, рамка 25, лестница 50, крыша 50 |
| Wood (дерево) | 250 | улучшение из лозы молотком | дерево ×4 |
| Stone (камень) | 500 | улучшение молотком | камень |
| Sheet Metal (лист) | — | улучшение молотком | металл (вдвое дешевле камня, но нужна переплавка) |
| Armored (броня) | 2000 | улучшение молотком | High Quality Metal |
Двери: деревянная 200 HP, листовая 250 HP, бронедверь 800 HP. Понизить уровень нельзя.
Куда можно строить: почти везде; крутые склоны и неровная земля мешают, фундамент ставят и под водой.
Прочность конструкции (stability): у постройки есть запас прочности; если он упал в ноль — объект ломается сразу при установке. Столбы ставят до стен, под столбом должен быть фундамент, и на втором этаже столбы должны быть и снизу.
Инструментальный шкаф (Tool Cupboard): разблокирует постройку в радиусе 50 м от любого фундамента базы, в которой он стоит. «Twig floors can be built, regardless of the building privileges» — лозу строить можно всегда, улучшать — нельзя.
Замки: ключевой (дерево) и кодовый (100 металла, 4 цифры). Ставятся на двери, на контейнеры (сундуки, торговый автомат) и на инструментальный шкаф.
Гниение (decay): лоза и дерево теряют здоровье через несколько часов и разваливаются, камень/металл/броня — через дни. Открытие/закрытие двери с замком сбрасывает таймер гниения.
1.6 Что из этого берём мы
- Строительные объекты — наши кастомные предметы (не блоки мира).
- Ставятся свободно, внутренние снаппятся к поставленным (сокеты на объектах).
- Два вида проёмов: малый (только одиночная дверь) и большой (двойные/гаражные, но не одиночные).
- Уровни (tier) и прочность — как в Rust, плюс тег
admin(см. п. 2.2) для объектов, которые нельзя ставить обычному игроку. - Столб/устойчивость и гниение — позже, по необходимости.
2. Решения по проекту
2.1 Кто такой админ
Админ — свойство конкретного сервера, а не проекта. Проект коммьюнити-френдли:
в разных серверах разные роли и разные права. Роль приходит из лаунчера
(у лаунчера есть server/roles.py и роли ROLE_USER / ROLE_PASS_HOLDER / ROLE_MODERATOR / ROLE_ELDER / ROLE_CREATOR).
2.2 Кто что может ставить и ломать
Правило на блоке/предмете (тег admin):
тег admin |
кто может ставить/ломать/менять |
|---|---|
| нет | кто угодно, включая обычных игроков |
| есть | только админы сервера |
- Тег
adminесть, например, у «тестблока» и у всего, что не добавлено в крафт/изучение/дроп. - Режим креатива не даёт прав. Даже игрок в креативе без админки не может поставить
или сломать блок с тегом
admin. - Проверка — на сервере. Клиент только показывает или не показывает курсор.
2.3 Ванильные блоки игры
Мир (карта, монолиты, рельеф) — не ломается и не строится обычными игроками: это работа админов. Игроки строят нашими кастомными предметами через наш API.
2.4 Предметы
- Все предметы игрока — кастомные, через наш код и наше API (не ванильные
ItemStack). - У предмета: прочность, урон, значение bench.
bench = 0— крафтится сразу.bench = 1— изначально недоступен для крафта, его надо изучить на верстаке (или получить чертёж через стол исследований).
- У предмета есть класс инструмента (NONE / PICKAXE / AXE / SWORD / …) и класс ресурса, который он добывает.
2.5 Крафт
- Как в Rust: верстаки трёх уровней (разворачиваемый предмет, надо стоять рядом), чертежи (стол исследований: нужен найденный предмет + скрап), эксперименты на верстаке (случайный чертёж за скрап).
- Знание рецепта — состояние игрока, а не свойство предмета.
- Время крафта, множитель от уровня верстака, стоимость скрапа — как в Rust.
2.6 Структуры вместо блоков мира
Руда, деревья и камни — не блоки мира, а разрушаемые объекты (как узлы в Rust): у них есть прочность, они бьются инструментом и дают дроп. Мир меняют только админы.
2.7 Текстуры
- Текстуры предметов пока временные, взяты из ремейка как заглушки.
- Пометка: заменить на свои (см. п. 6).
3. Архитектура
3.1 Модули
| модуль | про что | лицензия |
|---|---|---|
rsx-client |
загрузчик модов, API модов, хуки в клиент | MIT |
rsx-protocol |
формат провода, общий словарь (блоки, формат чанка) | MIT |
rsx-plugin-api |
API серверного контента: события, реестр предметов, рецепты, роли | MIT (пустой, следующий) |
rsx-server-core |
тик-луп, мир, сущности, масштабирование | proprietary |
rsx-auth |
свои аккаунты сервера (когда лаунчер не настроен) | proprietary |
3.2 Провод
- Кадр:
magic "RSX1", версия, id пакета, длина, тело. - Рукопожатие:
Hello → HelloAck → Auth|LauncherAuth → AuthAck → Login → LoginAck. - Вход через лаунчер: клиент отдаёт токен лаунчера, сервер спрашивает лаунчер
POST /auth/validate(у лаунчера такой эндпоинт есть, он же проверяет бан) → если «свой» — выдаёт свой игровой токен. - Игровая фаза:
JoinWorld → WorldJoin,ChunkData,BlockChange,PlayerMove,EntitySpawn/Move/Remove,BreakProgress,SetGameMode,Inventory,Ping/Pong.
3.3 Мир
- Чанк 16×16×256, палитра по секциям (4 бита на блок) — плоский массив не годится: 62 500 чанков × 64 КБ = 4 ГБ.
- Лежат регионами на диске (32×32 чанка в файле), в памяти — LRU-кэш.
- Генерация — чистая функция от зерна и координат (детерминизм обязателен: чанк может прийти через месяц после соседнего).
- Сгенерированный чанк не пишется на диск: террейн восстанавливается генератором. На диск уходит только то, во что построили.
3.4 Что взято из Paper/Bukkit (как образец)
| у Paper | зачем нам | у нас |
|---|---|---|
BlockBreakEvent (cancellable, setDropItems) |
сервер решает, ломается ли блок и что падает | BreakEvent: cancelled, drops |
BlockPlaceEvent, PlayerInteractEvent |
кто что нажал | InteractEvent (левая/правая), PlaceEvent |
ItemMeta + PersistentDataContainer |
свои данные на предмете | ItemStack + ItemData (ключ→значение) |
PlayerInventory / InventoryClickEvent |
инвентарь, хотбар, защита от дюпа | свой Inventory + проверки на сервере |
Permissible / роли |
«мир только для админов» | роли сервера, тег admin у блоков |
ShapedRecipe / ShapelessRecipe |
рецепты | свой реестр с гейтом по чертежу и верстаку (в Paper такого нет) |
Чего у Paper нет, а нужно нам: гейт крафта по изученности, прочность/урон/сбор по классам ресурсов, структуры вместо блоков мира.
4. План работ
Каждый шаг — законченный кусок, который можно проверить. Порядок важен.
Шаг A. Фундамент предметов и инвентаря (следующий)
ItemType: id, имя, класс инструмента, класс ресурса, прочность, урон по частям тела, скорость сбора,bench, рецепт.ItemStack: тип + количество + прочность +ItemData(свой ключ→значение).Inventory: слоты, хотбар, что в руках. Сервер — источник истины.- Реестр предметов + протокол
Inventory/InventorySlot. - Клиент: свой реестр + свои текстуры + свой рендер предмета в руке и в слоте
(наши предметы не ванильные
IItem). - Текстуры предметов — временные (взяты из ремейка как заглушки). ПОМЕТКА: заменить на свои.
- Стартовый набор: камень (как в Rust — выдаётся первым).
Критерий готовности: игрок заходит, получает камень в руку, видит его в хотбаре и в руке; сервер знает, что у него в руках.
Шаг B. Ломание и установка — решает сервер
- Протокол:
Dig(START/STOP, позиция, грань) вместо «клиент присылает результат»;BreakProgress(0..9) — трещины у всех. - Сервер: состояние ломания по образцу
PlayerInteractionManager(PlayerInteractionManager.java:79 updateBlockRemoving,:124 onBlockClicked,:216 tryHarvestBlock): прогресс по твёрдости блока и скорости инструмента, рассылка прогресса, досягаемость, роль/тегadmin. - Правило из ваниллы: меч в креативе блок не ломает
(
PlayerInteractionManager.java:217). - Клиент ничего не решает: 4 патча (
Minecraft.clickMouse→ свойDig,Minecraft.sendClickBlockToController→ состояние кнопки,PlayerControllerMP.clickBlock→ клиент не ломает сам,EntityRenderer.isDrawBlockOutline→ контур только там, где можно).
Критерий готовности: зажатая кнопка ломает один блок; блок с тегом admin обычному
игроку не ломается ни в выживании, ни в креативе; у остальных — ломается инструментом
того класса, который нужен.
Шаг C. Структуры, узлы, постройка
StructureTemplate(блоки + AABB + меш + HP + дроп),StructureInstance,StructureWorld. Деревья/камни/руда — узлы, не блоки мира.- Сбор: попадание инструментом → урон по классу ресурса → разрушение → дроп.
- Постройка: игрок ставит наши кастомные предметы-конструкции (не блоки мира). Снаппинг — см. п. 1.5.
- Растительность и руда в генерации — через шаблоны структур.
Шаг D. Мир один раз, конфиг, барьер
- Конфиг:
world.size(сторона карты в блоках),world.gamemode,world.seed,world.generate,barrier.distance. - Мир генерится один раз и отдаётся; изменения игроков — отдельным слоем.
- Барьер: сервер не пускает; клиент рисует (прозрачность → 0.5 у границы, блендинг с блоком под игроком в ±5 блоках, дальше размытие в невидимую стену).
Шаг E. Транспорт на NIO (независим, можно раньше)
Selector+ неблокирующиеSocketChannel,ClientSession→ конечный автомат, блокирующие места (HTTP к лаунчеру) — в пул потоков.- Проверка: 49 существующих тестов идут по сокету и должны пройти без правок; + 100 одновременных соединений.
Шаг F. DistantView
- Сервер шлёт LOD (высоты + цвет) по регионам; клиент кэширует архивом и досылает недостающее.
- Рендер: квадродерево, Hi-Z отсечение (пирамида глубины),
uCamOffset(float не хватает на ±2000), зажим UV по мипам, свой шейдер GLSL 330.
5. Открытые вопросы
- Роли приходят из лаунчера или живут на сервере? Лаунчер знает роли
(
ROLE_USER … ROLE_CREATOR), но сервер может держать свои. - Эксперимент на верстаке делаем? (случайный чертёж за скрап) — в Rust есть.
- Урон по частям тела (голова/грудь/руки/ноги) — сразу или один общий урон?
6. Что дописать
- Полные таблицы предмет→требуемый верстак и предмет→скрап (из вики).
- Точная таблица сбора по классам ресурсов (дерево/руда/животное/лоза/камень/металл).
- Список строительных объектов и их сокеты (что куда снаппится) — по п. 1.5.