- Java 63.4%
- HTML 36.6%
| .gradle | ||
| build | ||
| gradle/wrapper | ||
| run | ||
| runs | ||
| src/main | ||
| TACZ-source@957ef55546 | ||
| build.gradle | ||
| gradle.properties | ||
| gradlew | ||
| gradlew.bat | ||
| hs_err_pid9752.log | ||
| hs_err_pid30376.log | ||
| README.md | ||
| settings.gradle | ||
Meccha Chameleon — мод-режим «прятки с маскировкой» для Minecraft 1.21.1 (NeoForge)
Полностью рабочий командный режим прятков, вдохновлённый игрой MECCHA CHAMELEON (прячущиеся раскрашивают свои белые модели, чтобы слиться с окружением, а охотники ищут их за отведённое время). Реализован «с нуля» на Java для NeoForge.
На сервере одновременно идёт ровно один матч, в котором участвуют все игроки.
1. Требования
| Компонент | Версия |
|---|---|
| Minecraft | 1.21.1 |
| NeoForge | 21.1.220 и новее (скомпилировано против 21.1.233) |
| Java | 21 (JDK) |
| TaCZ (Timeless and Classics Zero) | опционально — определяется автоматически |
Мод нужен и на сервере, и на клиенте (это сетевой режим с собственными пакетами, клавишами и интерфейсом).
2. Установка (готовый мод)
- Соберите или возьмите готовый
mecchachameleon-1.0.0.jar(см. раздел 3). - Скопируйте
.jarв папкуmods/:- на сервере — в
mods/; - на каждом клиенте — в
mods/.
- на сервере — в
- Запустите сервер и подключайтесь. Если в
configвключёнautoStart(по умолчаниюtrue), матч начнётся автоматически, как только онлайн достигнетminPlayers(по умолчанию 2). В любой момент оператор может запустить матч вручную:/mc start.
Готовый jar после сборки лежит в build/libs/mecchachameleon-1.0.0.jar.
3. Сборка из исходников
Требуется установленный JDK 21. Wrapper Gradle уже включён.
# Windows PowerShell
$env:JAVA_HOME = 'C:\Path\To\jdk-21'
.\gradlew.bat build
# Linux / macOS
export JAVA_HOME=/path/to/jdk-21
./gradlew build
Результат: build/libs/mecchachameleon-1.0.0.jar.
4. Локальное тестирование (сервер + 2 клиента)
В build.gradle уже настроены три конфигурации запуска:
.\gradlew.bat runServer # выделенный сервер (--nogui)
.\gradlew.bat runClient # первый клиент
.\gradlew.bat runClient2 # второй клиент (имя HiderDev, отдельная папка runs/client2)
Запустите сервер, затем оба клиента, подключитесь к localhost. Минимум для матча — 2 игрока:
один станет охотником, другой — прячущимся (роли можно выбрать вручную).
Примечание о тестировании в этой среде: мод проверен компиляцией против целевой платформы (NeoForge 21.1.233 / MC 1.21.1) и успешным запуском выделенного сервера — в логах есть
Meccha Chameleon initialised (dist=DEDICATED_SERVER)иDone!без ошибок и без сбоев миксинов. Полноценный прогон двух графических клиентов нужно выполнить на машине с GPU/дисплеем командами выше — именно там исполняется клиентский код (миксины скина/поз, GUI палитры).
5. Управление и команды
Клавиши
| Действие | Клавиша (по умолчанию) |
|---|---|
| Заморозка на месте (прячущийся) | ПКМ |
| Разморозка (прячущийся) | ЛКМ |
| Сменить позу (прячущийся) | R |
| Открыть палитру рисования (только когда заморожен) | F |
| Закрыть палитру | любая клавиша движения W/A/S/D |
Клавиши
RиFнастраиваются вНастройки → Управление → Meccha Chameleon.Fпо умолчанию совпадает со «сменой руки» — при необходимости переназначьте.
Команды
| Команда | Право | Описание |
|---|---|---|
/mc start |
OP (2) | Принудительно начать матч |
/mc stop |
OP (2) | Прервать матч и всё очистить |
/mc status |
все | Текущая фаза/таймер/счётчики команд |
/mc role hunter |
все | Выбрать роль охотника (в фазе выбора) |
/mc role hider |
все | Выбрать роль прячущегося (в фазе выбора) |
6. Конфигурация
Файл config/mecchachameleon-common.toml (создаётся при первом запуске). Основные параметры:
[match]
roleSelectSeconds = 25 # фаза выбора роли
hunterPrepSeconds = 35 # охотники ждут, прячущиеся прячутся
matchSeconds = 300 # активный раунд (5 минут)
minPlayers = 2
autoStart = true
autoStartCountdownSeconds = 10
[teams]
maxHunters = 4
maxHiders = 16
minHunters = 1
minHiders = 1
[hunter]
hunterMaxHp = 100.0 # 100 HP = 50 сердец
missPenalty = 10.0 # урон охотнику за промах
hitHeal = 20.0 # лечение охотнику за попадание
arrowCount = 30 # стрелы (когда TaCZ не установлен)
taczAmmoCount = 30 # tacz:ammo (когда TaCZ установлен)
[hider]
hiderScale = 0.5 # модель и хитбокс 50%
hiderSpeedBonus = 0.15 # +15% к скорости относительно охотника
honkRadius = 20.0 # радиус слышимости «Гудка»
honkCooldownSeconds = 20 # перезарядка «Гудка»
7. Объяснение ключевых систем
7.1 Командная конфигурация и выбор роли
- В начале матча наступает фаза
ROLE_SELECTION(25 c). Каждому игроку автоматически открывается экран выбора (RoleSelectScreen) либо можно использовать/mc role …. - Размеры и минимумы команд берутся из
[teams]. По окончании фазыGameManager.assignRoles()распределяет неопределившихся: сначала добивает доminHunters/minHiders, затем балансирует с учётом максимумов (избыток уходит в прячущихся — это «большая» команда). Для крошечных лобби есть гарантированный сплит (минимум 1 vs 1).
7.2 Таймеры матча и досрочное завершение
Конечный автомат GamePhase: IDLE → (LOBBY_COUNTDOWN) → ROLE_SELECTION(25c) → HUNTER_PREP(35c) → ACTIVE(300c) → ENDING(5c) → IDLE.
- Тик считается на сервере (
GameManager.onServerTick), каждую секунду рассылаются пакеты состояния и обновляется action-bar с таймером. - Досрочное завершение: на каждом тике фазы
ACTIVEпроверяются счётчики живых. ЕслиhidersAlive == 0— побеждают охотники; еслиhuntersAlive == 0— прячущиеся. - Во время
HUNTER_PREPохотники «укоренены» (модификатор скорости ×0 + слепота), чтобы не охотиться раньше времени; прячущиеся свободно прячутся/красятся.
7.3 Урон, лечение и счёт охотника
- При входе в матч охотнику ставится модификатор
MAX_HEALTHдо 100 HP и здоровье до максимума. - Промах (стрела в блок/воздух/мимо хитбокса, в т.ч. мимо замороженного прячущегося)
→
-10 HP(onHunterMiss). ПриHP ≤ 0— стандартная смерть и спектатор. - Попадание в хитбокс прячущегося → охотнику
+20 HPи+1 очко, прячущийся устраняется (onHunterHitHider). Штрафа при попадании нет. Засчитывается независимо от заморозки. - HP/счёт отправляются клиенту (
S2CSelfState) и показываются в HUD.
7.4 Различие «попадание в хитбокс» vs «промах»
- Лук (по умолчанию): через
ProjectileImpactEvent(см.GameEvents). Каждая стрела разрешается один раз:HitResult.ENTITYс прячущимся → попадание; всё остальное (BLOCK/MISS/не-прячущийся) → промах. Поскольку у замороженного прячущегося хитбокс сохраняется, прямое попадание = попадание, а стрела мимо уходит в блок = промах. - TaCZ (если установлен): урон-событие
LivingIncomingDamageEventконвертируется в попадание (хитскан-оружие наносит урон напрямую). См. ограничение в разделе 9.
7.5 Условная выдача оружия (детекция мода)
TaczCompat.giveWeapon:
- если загружен
taczи найден предметtacz:modern_kinetic_gun→ выдаётся он +tacz:ammo(30 шт.) с попыткой проставитьGunIdв custom-data; - иначе → лук + 30 стрел.
TaCZ определяется через
ModListи не требуется для компиляции/запуска.
7.6 Прячущийся: масштаб, хитбокс, скорость, «Гудок»
- Масштаб/хитбокс 50% — через ванильный атрибут
minecraft:generic.scale(масштабирует и модель, и bounding box → реально сложнее попасть). - Скорость +15% — модификатор
MOVEMENT_SPEED(ADD_MULTIPLIED_BASE 0.15) относительно стандартной скорости охотника. - «Гудок» (
HonkerItem) — ПКМ проигрывает громкий звук с радиусом слышимостиhonkRadiusблоков (черезvolume = radius/16, ванильное затухание), перезарядкаhonkCooldownSeconds.
7.7 Позы (R)
5 поз + стойка: «свёрнут в квадрат», «T-поза», «лёжа на боку», «лёжа пластом», «сидя».
- Клиент по
Rциклит позу и шлётC2SSetPose; сервер хранит и рассылаетS2CHiderVisualвсем. - Углы конечностей/головы применяются в
PlayerModelMixin#setupAnim(после ванильной анимации); «лежачие» позы дополнительно поворачивают всю модель вClientEventsчерезPoseStack.
7.8 Заморозка/разморозка без видимой анимации
- ПКМ →
C2SFreeze(true, …): сервер фиксирует позицию/углы, обнуляет скорость, ставитnoGravity(можно замёрзнуть в воздухе) и каждый тик «возвращает» игрока на место (бэкстоп против рассинхрона). Клиент локально блокирует мышь и движение (MovementInputUpdateEvent+ жёсткая фиксация углов вClientTickEvent). - Видимость для охотников: в
PlayerModelMixinприfrozenобнуляются все колебания конечностей и повороты головы — модель абсолютно статична, без анимаций. - ЛКМ → разморозка и обычное движение. Время заморозки не ограничено.
7.9 Рисование по скину (палитра, F)
- Палитра (
PaintPaletteScreen) открывается только при активной заморозке и закрывается при нажатии W/A/S/D (если фокус не в hex-поле). Не закрывает обзор игры — затемняется только сама панель (renderBackgroundпереопределён). - Инструменты: цветовой круг (HSV), 30 пресет-цветов, слайдеры R/G/B/A и H/S/V, ввод hex sRGB (RRGGBBAA), слайдеры металличности/шероховатости, слайдер размера кисти, 3D-пипетка (берёт цвет блока по лучу взгляда), режим текстурной кисти (рисует с лёгкой вариацией цвета).
- Холст показывает скин 64×64 в увеличении; мазки кистью напрямую меняют пиксели.
- Синхронизация: клиент мгновенно применяет мазок локально и шлёт
C2SPaintStroke; сервер валидирует (заморожен, прячущийся, фаза prep/active), пишет в авторитетную копию и рассылаетS2CSkinStrokeвсем → охотники видят каждый мазок в реальном времени. Технически скин подменяется на лету черезPlayerRendererMixin#getTextureLocationна динамическую текстуру (ClientSkinManager). - Сброс каждый раунд: в начале матча всем прячущимся выдаётся чистый белый скин
(
S2CSkinFull), а при завершении —S2CClearSkins.
7.10 Система видимости
Подчиняется стандартным правилам Minecraft: мод не добавляет свечения/просвечивания. Охотник видит прячущегося, только если тот в поле зрения; за углом/стеной/в пещере модель скрыта обычными непрозрачными блоками. Маскировка достигается малым размером, позами, заморозкой и раскраской.
7.11 Стандартная смерть → спектатор
И прячущийся (при попадании), и охотник (при HP≤0) устраняются через настоящую ванильную
смерть (hurt(... , MAX)): падение, звук смерти, частицы — это видят все. Дроп предметов
гасится (LivingDropsEvent), а на PlayerRespawnEvent игрок переводится в режим спектатора
на месте гибели. Инвентарь сохраняется при входе в матч и восстанавливается при его завершении.
7.12 Единственный матч на сервере
Всё состояние держит синглтон GameManager (одна карта UUID → PlayerState). Игроки,
зашедшие посреди матча, становятся спектаторами и получают актуальные скины/позы.
8. Архитектура (кратко)
Сервер (авторитет) Клиент (отображение/ввод)
GameManager ── S2CPhase ─────────────► ClientGameState ──► HUD
── S2CSelfState ─────────►
── S2CHiderVisual ───────► PlayerModelMixin (позы/заморозка)
── S2CSkinFull/Stroke ───► ClientSkinManager ─► PlayerRendererMixin (скин)
── S2CClearSkins ────────►
ServerNetHandler ◄─ C2SSelectRole / C2SSetPose / C2SFreeze / C2SPaintStroke ◄─ ClientEvents/GUI
- Сетевые пакеты:
network/Payloads.java(+ регистрация вregistry/ModNetwork.java). - Серверная логика: пакет
game/(GameManager,GameEvents,GameCommands,ServerNetHandler). - Клиент: пакет
client/(ClientEvents,ClientNetHandler,KeyMappings,gui/,skin/). - Миксины:
mixin/PlayerRendererMixin(подмена скина),mixin/PlayerModelMixin(позы/заморозка). - Совместимость:
compat/TaczCompat.
9. Известные ограничения и заметки
- Штраф за промах с TaCZ. Для лука реализована полная экономика «попадание/промах». Для хитскан-оружия TaCZ детектируется попадание (через урон-событие), но штраф за промах требует подписки на событие выстрела TaCZ — без публичного API TaCZ (мы намеренно не линкуемся с ним) это не реализуется «вслепую». Базовый лук обеспечивает требуемую механику штрафа полностью.
- Слайдеры металличности/шероховатости хранятся и синхронизируются по смыслу, но в ванильном рендере нет PBR, поэтому визуально это косметика (значения готовы для шейдер-паков/будущего PBR).
- Визуал поз (особенно «лёжа») задаётся приблизительными углами/поворотами
PoseStackи легко подстраивается вPlayerModelMixin/ClientEvents. - Экран смерти. Чтобы показать настоящую ванильную анимацию смерти, используется реальная
смерть с последующим переводом в спектатор на
PlayerRespawnEvent— выбывший игрок один раз нажимает «Возродиться». - Звук «Гудка» использует ванильный
note_block.didgeridoo(чтобы не тянуть бинарный.ogg). Легко заменить на свой звук, добавивsounds.jsonи.ogg. image.pngв рабочей папке отсутствовал, поэтому раскладка палитры собрана строго по текстовому ТЗ (круг + 30 свотчей + RGBA/HSV + hex + материалы + размер кисти + пипетка + текстурная кисть). Координаты легко поправить вPaintPaletteScreen.- Папки
build/иrun/— генерируемые (сборка и тестовый мир сервера).
10. Структура проекта
build.gradle / settings.gradle / gradle.properties — сборка (ModDevGradle 2.0.141)
src/main/templates/META-INF/neoforge.mods.toml — метаданные (подстановка из gradle.properties)
src/main/resources/
mecchachameleon.mixins.json — конфиг миксинов
pack.mcmeta
assets/mecchachameleon/lang/{en_us,ru_ru}.json
assets/mecchachameleon/models/item/honker.json
assets/mecchachameleon/textures/item/honker.png
src/main/java/com/mecchachameleon/
MecchaChameleon.java, Config.java
registry/ ModItems, ModNetwork
game/ GameManager, GameEvents, GameCommands, ServerNetHandler,
PlayerState, Role, GamePhase, Pose, SkinData, Util
items/ HonkerItem
compat/ TaczCompat
network/ Payloads
client/ ClientSetup, ClientEvents, ClientNetHandler, ClientNet,
ClientGameState, KeyMappings
client/skin/ ClientSkinManager
client/gui/ RoleSelectScreen, PaintPaletteScreen, PaletteSlider, ColorUtil
mixin/ PlayerRendererMixin, PlayerModelMixin
Приятной игры! 🦎