No description
  • Java 63.4%
  • HTML 36.6%
Find a file
2026-06-25 22:11:09 +03:00
.gradle first commit 2026-06-25 22:11:09 +03:00
build first commit 2026-06-25 22:11:09 +03:00
gradle/wrapper first commit 2026-06-25 22:11:09 +03:00
run first commit 2026-06-25 22:11:09 +03:00
runs first commit 2026-06-25 22:11:09 +03:00
src/main first commit 2026-06-25 22:11:09 +03:00
TACZ-source@957ef55546 first commit 2026-06-25 22:11:09 +03:00
build.gradle first commit 2026-06-25 22:11:09 +03:00
gradle.properties first commit 2026-06-25 22:11:09 +03:00
gradlew first commit 2026-06-25 22:11:09 +03:00
gradlew.bat first commit 2026-06-25 22:11:09 +03:00
hs_err_pid9752.log first commit 2026-06-25 22:11:09 +03:00
hs_err_pid30376.log first commit 2026-06-25 22:11:09 +03:00
README.md first commit 2026-06-25 22:11:09 +03:00
settings.gradle first commit 2026-06-25 22:11:09 +03:00

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. Установка (готовый мод)

  1. Соберите или возьмите готовый mecchachameleon-1.0.0.jar (см. раздел 3).
  2. Скопируйте .jar в папку mods/:
    • на сервере — в mods/;
    • на каждом клиенте — в mods/.
  3. Запустите сервер и подключайтесь. Если в 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

Приятной игры! 🦎