Перейти к содержимому

MCCTP

Fabric-мод, который поднимает WebSocket-сервер в твоём клиенте Minecraft. Он стримит состояние игры каждый тик и принимает команды действий — позволяя любой программе на любом языке управлять игроком.

Fabric
Загрузчики
Fabric
Скачиваний на Modrinth
367
Подписчиков на Modrinth
2
версии
3
Обновлён
3 марта 20263 мар.
Опубликован
в 2026

Коротко о моде

Работает на Fabric
Для Minecraft 1.21.11
Ставится только в игру; на сервер ставить не нужно
Последняя версия — 1.2.0 от 3 марта 2026
Лицензия MIT — бесплатно
Где нужен
В игреобязателенНа серверене нужен

Ставится только в игру; на сервер ставить не нужно

Версии игры1.21.11
Описание переведено автоматическиПоказать оригинал (EN)

MCCTP - Minecraft Control Transfer Protocol

Мод для Fabric, который поднимает WebSocket-сервер на вашем клиенте Minecraft. Он стримит состояние игры каждый тик и принимает команды действий — позволяя любой программе на любом языке управлять игроком.

Возможности

  • WebSocket API — JSON поверх WebSocket, не зависит от языка
  • 13 типов действий — движение, бой, инвентарь, камера и другое
  • Состояние игры каждый тик — здоровье, позиция, предмет в руке, боевой контекст
  • Категоризация предметов — автоматическая классификация (SWORD, BOW, BLOCK, FOOD и т.д.)
  • Круговой оверлей хотбара — круговой HUD со всеми 9 слотами, управляется командами или клавишей V
  • Потокобезопасность — WebSocket работает в собственной группе потоков Netty, действия отправляются в игровой поток

Требования

  • Minecraft 1.21.11
  • Fabric Loader >= 0.18.0
  • Fabric API
  • Java 21+

Установка

./gradlew build

Скопируйте build/libs/mcctp-1.0.0.jar в папку .minecraft/mods/ (рядом с Fabric Loader + Fabric API).

Как это работает

Когда вы заходите в мир, мод запускает WebSocket-сервер на порту 8765. Любой клиент может подключиться к `ws://:8765/mcctp` и:

  1. Получать JSON состояния игры каждый тик (50мс по умолчанию)
  2. Отправлять команды действий в виде JSON для управления игроком

Сервер работает в собственной NioEventLoopGroup Netty, отдельно от сетевого стека Minecraft. Входящие действия отправляются в игровой поток через MinecraftClient.execute(), так что они безопасны и ведут себя идентично реальному вводу. Сервер останавливается, когда вы выходите из мира.

Протокол

Подключение

ws://<host>:8765/mcctp

Стандартное WebSocket-соединение. Без аутентификации. Несколько клиентов могут подключаться одновременно.

Состояние игры (Сервер → Клиент)

Транслируется всем подключённым клиентам каждый тик. Все поля присутствуют всегда.

{
  "type": "game_state",
  "timestamp": 1700000000000,
  "selectedSlot": 0,
  "heldItem": {
    "name": "minecraft:diamond_sword",
    "category": "SWORD",
    "stackCount": 1,
    "maxDurability": 1561,
    "currentDurability": 1500
  },
  "offhandItem": {
    "name": "minecraft:shield",
    "category": "SHIELD",
    "stackCount": 1,
    "maxDurability": 336,
    "currentDurability": 336
  },
  "playerState": {
    "health": 20.0,
    "maxHealth": 20.0,
    "hunger": 20,
    "saturation": 5.0,
    "x": 100.5,
    "y": 64.0,
    "z": -200.3,
    "yaw": 45.0,
    "pitch": -10.0,
    "onGround": true,
    "sprinting": false,
    "sneaking": false,
    "swimming": false,
    "flying": false,
    "inWater": false,
    "onFire": false
  },
  "combatContext": {
    "isUsingItem": false,
    "isBlocking": false,
    "activeHand": "MAIN_HAND",
    "crosshairTarget": "ENTITY",
    "crosshairEntityType": "minecraft:zombie",
    "crosshairBlockPos": null
  }
}
Поля состояния игры
ПолеТипОписание
typestringВсегда "game_state"
timestamplongUnix-миллисекунды
selectedSlotintАктивный слот хотбара (0-8)

heldItem / offhandItem:

ПолеТипОписание
namestringID в реестре, например "minecraft:diamond_sword"
categorystringСм. Категории предметов
stackCountintТекущий размер стака
maxDurabilityintМаксимальная прочность (0, если не имеет прочности)
currentDurabilityintОставшаяся прочность

playerState:

ПолеТипОписание
healthfloatТекущее здоровье (0-20)
maxHealthfloatМаксимальное здоровье
hungerintУровень еды (0-20)
saturationfloatУровень насыщения
x, y, zfloatПозиция в мире
yaw, pitchfloatПоворот камеры (в градусах)
onGroundboolСтоит на твёрдой земле
sprintingboolСейчас бежит
sneakingboolСейчас крадётся
swimmingboolСейчас плывёт
flyingboolПолёт в креативе/на элитрах
inWaterboolНаходится под водой
onFireboolГорит

combatContext:

ПолеТипОписание
isUsingItemboolУдерживается правая кнопка мыши (еда, натягивание лука и т.д.)
isBlockingboolБлокирование щитом
activeHandstring"MAIN_HAND" или "OFF_HAND"
crosshairTargetstring"ENTITY", "BLOCK" или "MISS"
crosshairEntityTypestring?ID сущности в реестре или null
crosshairBlockPosint[3]?Позиция блока [x, y, z] или null

Действия (клиент → сервер)

Отправьте JSON-сообщение с action и params:

{"action": "<action_name>", "params": {<params>}}
Справочник действий
ДействиеПараметрыОписание
movedirection: "forward" "backward" "left" "right", state: "start" "stop"Движение WASD. Удерживает клавишу, пока не отправите "stop".
lookyaw: float, pitch: float, relative: boolУправление камерой. relative: true прибавляет к текущим углам. relative: false задаёт абсолютные значения.
jump(нет)Одиночный прыжок.
attack(нет)Левый клик — взмах оружием, удар по сущности, начало ломания блока.
use_itemstate: "start" "stop"Удержание правого клика. Используйте "start", чтобы начать (натянуть лук, поесть, поднять щит), и "stop", чтобы отпустить.
throw_item(нет)Одиночный импульс правого клика — для снежков, эндер-жемчужин, выстрела из заряженного арбалета.
select_slotslot: int (0-8)Переключить активный слот хотбара.
sneakstate: "start" "stop"Присесть. Удерживается до остановки.
sprintstate: "start" "stop"Бег. Удерживается до остановки.
drop_itemfull_stack: boolВыбросить предмет из руки. true выбрасывает весь стак (Ctrl+Q).
swap_hands(нет)Поменять местами основную руку и вторую руку (клавиша F).
open_inventory(нет)Открыть/закрыть экран инвентаря (клавиша E).
toggle_wheel(нет)Переключить HUD-оверлей колеса хотбара.
Примеры действий
// Идти вперёд
{"action": "move", "params": {"direction": "forward", "state": "start"}}

// Остановиться
{"action": "move", "params": {"direction": "forward", "state": "stop"}}

// Повернуть на 90 градусов вправо
{"action": "look", "params": {"yaw": 90.0, "pitch": 0.0, "relative": true}}

// Смотреть на север, прямо перед собой
{"action": "look", "params": {"yaw": 180.0, "pitch": 0.0, "relative": false}}

// Натянуть и выстрелить из лука
{"action": "use_item", "params": {"state": "start"}}
// ... подождать ~1 секунду ...
{"action": "use_item", "params": {"state": "stop"}}

// Бросить снежок
{"action": "throw_item", "params": {}}

// Переключиться на слот 3 и атаковать
{"action": "select_slot", "params": {"slot": 3}}
{"action": "attack", "params": {}}

Категории предметов

Каждый предмет в руке относится к одной из этих категорий:

КатегорияПримеры
SWORDАлмазный меч, незеритовый меч
BOWЛук
CROSSBOWАрбалет
AXEЖелезный топор, деревянный топор
PICKAXEАлмазная кирка
SHOVELКаменная лопата
HOEНезеритовая мотыга
TRIDENTТрезубец
SHIELDЩит
FOODСтейк, золотое яблоко
BLOCKБулыжник, земля, доски
THROWABLEСнежок, яйцо, эндер-жемчужина
FISHING_RODУдочка
EMPTYПустая рука
OTHERВсё, что не подошло выше

Конфигурация

Файл конфигурации: .minecraft/config/mcctp.json (создаётся при первом запуске)

{
  "port": 8765,
  "tickInterval": 1
}
ПолеПо умолчаниюОписание
port8765Порт WebSocket-сервера
tickInterval1Рассылать состояние игры каждые N тиков (20 тиков = 1 секунда)

Архитектура

Любой клиент ←── WebSocket (JSON) ──→ Fabric Mod
                                       │
                                       ├── WebSocketServer (Netty, своя группа потоков)
                                       │     ├── WebSocketServerInitializer (HTTP → WS upgrade)
                                       │     ├── WebSocketFrameHandler (парсит входящий JSON)
                                       │     └── ConnectionManager (отслеживает каналы, рассылает)
                                       │
                                       ├── GameStateCollector (END_CLIENT_TICK → JSON)
                                       │     ├── GameStatePayload
                                       │     ├── HeldItemInfo + ItemCategorizer
                                       │     ├── PlayerStateInfo
                                       │     └── CombatContextInfo
                                       │
                                       ├── ActionDispatcher (JSON → ActionHandler)
                                       │     ├── MoveHandler, LookHandler, JumpHandler
                                       │     ├── AttackHandler, UseItemHandler, ThrowItemHandler
                                       │     ├── SelectSlotHandler, SneakHandler, SprintHandler
                                       │     ├── DropItemHandler, SwapHandsHandler
                                       │     ├── OpenInventoryHandler, ToggleWheelHandler
                                       │     └── KeyReleaseScheduler (timed key pulses)
                                       │
                                       └── HotbarWheelRenderer (HUD overlay)

Ключевые детали реализации:

  • WebSocket-сервер использует Netty NioEventLoopGroup, полностью отдельную от сетевого потока Minecraft
  • Все обработчики действий выполняются в игровом потоке через MinecraftClient.execute() — так же, как настоящий ввод игрока
  • Импульсные действия (прыжок, атака, бросок, смена рук, инвентарь) используют KeyReleaseScheduler, который удерживает клавишу 3 тика и увеличивает timesPressed, повторяя то, как Minecraft обрабатывает одиночные нажатия клавиш
  • Удерживаемые действия (движение, приседание, спринт, use_item) напрямую выставляют KeyBinding.pressed и остаются зажатыми до команды "stop"
  • Сбор состояния завязан на END_CLIENT_TICK и сериализуется через Gson
  • Мод использует Mixin-аксессор (KeyBindingAccessor) для доступа к KeyBinding.pressed и KeyBinding.timesPressed

Сборка из исходников

# Build
./gradlew build

# Output jar
build/libs/mcctp-1.0.0.jar

Сборка под Java 21. Протестировано с Gradle 9.2.0 и Fabric Loom 1.15.3.

Python-клиент

Референсный Python-клиент включён в python/. Установка:

cd python
pip install -e .

Предоставляет асинхронный и синхронный WebSocket-клиенты с типизированными датаклассами для состояния игры:

import time
from mcctp import SyncMCCTPClient, Actions

with SyncMCCTPClient("localhost", 8765) as client:
    client.on_state(lambda s: print(s.player_state.health))
    client.send(Actions.move("forward", "start"))
    time.sleep(2)
    client.send(Actions.move("forward", "stop"))

Также включает remote_play.py — проброс клавиатуры и мыши, позволяющий кому-то играть в вашем мире с другого компьютера.

Лицензия

MIT

Частые вопросы

Как установить MCCTP?

Установите Fabric под свою версию Minecraft, скачайте MCCTP под ту же версию и загрузчик, положите файл в папку mods и запустите игру с профилем загрузчика.

Для каких версий Minecraft есть MCCTP?

У MCCTP есть сборки для Minecraft 1.21.11.

Нужен ли MCCTP на сервере?

Ставится только в игру; на сервер ставить не нужно

Лицензия и источник
MIT Licenseможно свободно использовать и распространять с указанием автора
Оригинал — Modrinth↗Файлы — без изменений, проверены по SHA-512Это ваш мод? Правообладателям

Другие моды автора

MCSTP↓ 179

Часто нужны вместе

MCSTP↓ 179

Сайт использует cookie: необходимые — для входа и темы, а также счётчики посещений Яндекс Метрика и LiveInternet — по ним мы видим, как пользуются сайтом. Рекламных cookie у нас нет. Подробнее