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

saddle

Saddle: датапак-отладчик для редактирования в реальном времени

Fabric
Загрузчики
Fabric
Скачиваний на Modrinth
132
Подписчиков на Modrinth
5
версии
3
Обновлён
19 сентября 202619 сент.
Опубликован
в 2026

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

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

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

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

Saddle

Saddle: A Datapack Debugger for Live Editing Мод для Fabric, который встраивает в Minecraft сервер Debug Adapter Protocol, чтобы файлы датапаков .mcfunction можно было отлаживать из VS Code (или любого DAP-клиента) — точки останова, пошаговое выполнение, путешествие во времени и живой просмотр и редактирование состояния игры, с которым работают ваши функции. В Minecraft седло — это то, что позволяет взять в руки поводья чего-то, что иначе бежит само по себе. Этот мод надевает седло на выполнение датапаков: остановите его там, где нужно (точки останова), откатите назад (путешествие во времени) и управляйте им (живые правки) — вместо того чтобы смотреть, как оно проносится мимо.

Скачать

МодModrinth · CurseForge · GitHub Releases
Расширение для VS CodeVisual Studio Marketplace (или найдите "Saddle" в разделе расширений)
Исходники и проблемыgithub.com/d1n-0/saddle · Issues

Требования

  • Minecraft 26.2 – 26.3, Fabric Loader ≥ 0.19.0, Fabric API, Java 25
  • Мод на той стороне, которая запускает мир: клиент для одиночной игры, сервер для многопользовательской
  • DAP-эндпоинт: 127.0.0.1:16352 — переопределяется через -Dsaddle.host / -Dsaddle.port. Привязка к не-loopback адресам отклоняется, если не задано -Dsaddle.allowRemote=true: порт отладки допускает выполнение команд без аутентификации, поэтому открывайте его только в доверенных сетях или через туннель

Быстрый старт

  1. Установите мод (вместе с Fabric API) и запустите мир или сервер.
  2. Установите расширение для VS Code.
  3. Откройте папку датапака в VS Code, поставьте точки останова в файлах .mcfunction и запустите Attach to Minecraft (Saddle) (или нажмите F5). Консоль отладки и игровой чат сообщат, к какому миру вы подключились.
  4. Вызовите функцию в игре — из tick-функции или консоли отладки — либо нажмите Ctrl+Alt+Enter (Cmd+Alt+Enter на macOS) / ▶ в редакторе .mcfunction, чтобы выполнить функцию этого файла.
  5. По желанию: включите saddle.reloadOnSave (или нажмите Reload on Save в строке состояния), чтобы выполнять /reload при сохранении файла датапака. Остальная часть этого README описывает мод и его протокол; обзор возможностей со стороны редактора см. в vscode-extension/README.md.

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

  • Миксин в CommandFunction.fromLines оборачивает каждую разобранную команду декоратором, несущим её происхождение (function id, source line), и записывает исходный текст функции. Строки макросов ($...) помечаются во время разбора и оборачиваются, когда MacroFunction их создаёт, так что они тоже отлаживаются. Когда клиент отладки не подключён, накладные расходы на команду — одно volatile-чтение.
  • При срабатывании точки останова/шага/паузы поток сервера останавливается внутри выполнения команды — игра замирает посреди функции с нетронутым состоянием ванильного выполнения. Пока поток приостановлен, он обслуживает очередь задач, так что DAP-запросы, которым нужно состояние игры (переменные, evaluate, интроспекция), всё равно безопасно выполняются в потоке сервера.
  • Пути точек останова сопоставляются с id функций по сегменту `data//function/.mcfunction` в пути к файлу, так что любая структура рабочего пространства работает без настройки. Точки останова, запрошенные на комментариях или пустых строках, сдвигаются вниз к следующей исполняемой строке.

Поддержка DAP

ОбластьЗапросы
Жизненный циклinitialize, launch/attach, configurationDone, disconnect
Точки остановаsetBreakpoints, breakpointLocations — обычные команды и строки макросов; строки комментариев/пустые сдвигаются к следующей исполняемой строке
Выполнениеcontinue, next, stepIn, stepOut, pause
Состояниеthreads, stackTrace, scopes, variables, setVariable, source
Консольevaluate — выполняет любую команду, отвечая асинхронно, так что команда, попавшая на точку останова, никогда не задерживает вид стека; пока выполнение приостановлено, она исполняется в изолированном ExecutionContext. completions отдаёт подсказки Brigadier, так что консоль отладки автодополняется как игровой чат
Наведениеevaluate(context: hover) разрешает аргументы макросов ($(name)), селекторы сущностей (@e[...]) и тройки координат (~ ~2 ~) без выполнения команд
Выводигровой чат зеркалится клиенту как события output: системные объявления (/say, смерти, входы в игру), чат игроков и сообщения отдельным игрокам (/tellraw, /msg)
Путешествие во времениstepBack / reverseContinue перемещаются по записи выполненных команд (кольцевой буфер, -Dsaddle.ttd.steps, по умолчанию 20k). Находясь в прошлом, стек, исполнитель, аргументы макросов и восстановленное состояние scoreboard/storage показываются для того момента — области сохраняют свои живые имена, так что раскрытые строки переживают перемещение между настоящим и историей, а область Executor несёт метку (time travel). Шаг вперёд воспроизводит запись обратно к настоящему; continue за пределами записи возобновляет живое выполнение. saddle/trace возвращает недавнюю трассировку выполнения

Переменные ("регистры и память")

Каждый кадр стека предоставляет живые области, все читающие состояние игры во время остановки:

  • Executor — сводка источника команды (исполнитель, позиция, поворот, измерение) плюс лениво раскрываемое, редактируемое NBT-дерево исполняющей сущности.
  • Macro Arguments — значения $(...) текущего кадра макроса.
  • Command — команда, которая вот-вот выполнится, со всеми селекторами сущностей, разрешёнными в сущности, которым они сейчас соответствуют (каждая раскрывается в живой NBT), и всеми тройками координат, разрешёнными в блок, на который они указывают.
  • Watched — закреплённые пользователем выражения (см. ниже), заново разрешаемые вживую при каждом запросе.
  • Scoreboard — каждая цель с её очками; значения очков редактируются через setVariable.
  • Хранилище — каждое хранилище команд в виде редактируемого NBT-дерева; листовые значения принимают SNBT через setVariable. Предпросмотр контейнеров основан на размере ({400 entries}), поэтому просмотр больших хранилищ остаётся быстрым; правки отправляют событие invalidated, и клиент заново запрашивает устаревшие строки. Наведение на $(name), @e[...] или 1 2 3/~ ~2 ~ в файле .mcfunction во время остановки показывает те же данные прямо в строке (через расширение VS Code).

Отслеживание и закрепление выражений

Панель WATCH в VS Code, закреплённая область "Watched" (saddle/pin, saddle/unpin, saddle/pins) и вид Saddle Watch принимают:

  • @e[type=pig] — совпавшие сущности, раскрываются в живой NBT
  • `storage [path]/entity [path]/block [path]— живой (редактируемый) NBT по цели;— всё, что принимает/data get entity: имя игрока, UUID или селектор одиночной сущности (@s` — исполнитель выбранного кадра)
  • `score [holder]` — один счёт или вся цель (редактируемая), если holder опущен
  • scoreboard / storage — каждая цель / каждое хранилище
  • $(name) — аргумент макроса выбранного кадра; голые тройки координат разрешаются в блок, на который они указывают

Saddle Watch (реальное время + редактирование, точка останова не нужна)

Расширение добавляет вид Saddle Watch в боковую панель Run and Debug — одна панель отслеживания, которая делает то, что WATCH и Variables делают вместе, без необходимости в точке останова:

  • Реальное время: закреплённые выражения обновляются по таймеру (saddle.liveWatchRefreshInterval, по умолчанию 1 с) через не сохраняющий состояние запрос saddle/live {expression, path}, который читает состояние игры в потоке сервера независимо от того, запущена игра или приостановлена — счётчики тикают вживую, позиции сущностей двигаются, хранилище обновляется по мере записи вашими функциями.
  • Редактирование: строки, опирающиеся на счёты или NBT, показывают встроенный карандаш; правки идут через saddle/liveSet {expression, path, name, value} и применяются к живой игре немедленно. Закрепления, называющие одно значение — `score или NBT-путь вродеstorage /entity (например, добавленные через **Add to Saddle Watch**) — тоже редактируемы:saddle/liveSetбезname` задаёт собственное значение выражения.
  • Отслеживание вложенного узла: щёлкните правой кнопкой по раскрытой дочерней строке (ключ NBT или элемент списка, цель, держатель счёта, id хранилища, совпавшая сущность) и выберите Add to Saddle Watch, чтобы закрепить её как отдельную запись — например, storage mypack:store players.list[0], entity Steve Inventory[0] или score kills Steve. Игроки закрепляются по имени; другие сущности — по UUID, единственной ссылке, которая продолжает указывать на ту же сущность. Каждая переменная, имеющая живой автономный эквивалент, сообщает его как свой DAP evaluateName, что также включает встроенную в VS Code функцию Add to Watch в виде Variables. У записанных (time-travel) значений и NBT блоков его нет: выражение отслеживания не может назвать измерение блока.
  • Отображаемые имена: щёлкните правой кнопкой по закреплению и выберите Rename (или выберите его и нажмите F2), чтобы показать его под своим именем, например pig inventory вместо entity 1a2b…-… Inventory. Меняется только отображаемое имя — закреплённое выражение остаётся тем же и показывается во всплывающей подсказке. Имена хранятся для каждого рабочего пространства, поэтому закрепление получает своё имя обратно, когда его закрепляют снова в следующей сессии; очистка имени восстанавливает выражение.

Интеграция с редактором: запуск из файла и перезагрузка при сохранении

  • Run Function From File (saddle/runFunction {path, arguments?, executor?}): запускает функцию, определённую файлом .mcfunction. Путь разрешается точно так же, как путь точки останова (`data//function/.mcfunction), поэтому подходит любая структура рабочего пространства. arguments— SNBT-компаунд для макрофункций — расширение запрашивает его, когда файл содержит строки с$, и запоминает последнее значение для каждого файла. executor(настройкаsaddle.runFunctionExecutor, например @p) оборачивает вызов в execute as at @s run`; пустой запускает его от имени сервера, как Debug Console. Ответ асинхронный, поэтому функция, останавливающаяся на точке останова, ведёт себя точно так же, как запущенная из консоли. Несохранённые изменения сначала сохраняются, а при перезагрузке при сохранении запуск ждёт завершения этой перезагрузки.
  • Reload on save (saddle/reload): эквивалент /reload (текущие паки плюс вновь обнаруженные, не отключённые), отвечает, когда новые ресурсы вступают в силу. Расширение объединяет сохранения файлов датапака — pack.mcmeta и всего, что находится под data/ в папке, которая также содержит pack.mcmeta — поэтому "Save All" вызывает одну перезагрузку и сообщает результат в строке состояния; Debug Console пишет Saddle: datapacks reloaded. Перезагрузка отклоняется, пока выполнение остановлено на точке останова, потому что приостановленная функция иначе выполнялась бы против подменённой библиотеки функций — сначала продолжите. Saddle: Reload Datapacks перезагружает по требованию.

/deploy — выпуск карты

/deploy (уровень разрешений 4) сохраняет мир как распространяемую карту: постройки и командные блоки (файлы регионов), сущности, точки интереса, сохранённые данные (счётчики, хранилище команд, карты, …), датапаки и настройки мира (level.dat) сохраняются; данные игроков — папка players/ (инвентари, позиции, достижения, статистика; также устаревшие папки playerdata/, advancements/, stats/) и владелец одиночного мира и время последней игры (singleplayer_uuid, устаревшие Player, LastPlayed), записанные в level.dat/level.dat_old — удаляются. Пока развёрнутый мир не открыт впервые, список одиночных миров не показывает осмысленную дату последней игры для него. Запущенный игроком, /deploy открывает диалог с полем назначения и двумя вариантами:

  • Create Copy (/deploy copy [path]): сбрасывает мир на диск и записывает очищенную копию в path. Относительные пути создаются рядом с папкой мира (в одиночной игре это папка saves, так что копия появляется в списке миров); по умолчанию — `-deploy`. Папка назначения должна находиться вне мира и либо отсутствовать, либо быть пустой; при неудачном копировании всё записанное удаляется. Работающий мир не изменяется. Копирование выполняется в потоке сервера, поэтому во время копирования в мир ничего не может записаться — игра приостанавливается на всё время копирования.
  • Apply to This World (/deploy apply): очищает сам этот мир. Поскольку при завершении работы игра заново записывает данные всех игроков онлайн, мир сначала закрывается (в одиночной игре происходит возврат в главное меню; выделенный сервер останавливается), а очистка выполняется после финального сохранения. Копировать по произвольному пути могут только консоль сервера (включая rcon и Debug Console) и владелец одиночного мира; остальные операторы — например, гости по LAN с включёнными читами — ограничены папками внутри папки, содержащей мир, а в одиночном/LAN-мире применять на месте может только владелец. Оба действия отклоняются, пока выполнение остановлено на точке останова. Без игрока (консоль сервера, rcon, Debug Console) /deploy выводит две подкоманды вместо диалога. Кнопки диалога срабатывают сразу, без обычного для Minecraft запроса «выполнить эту команду?»: они отправляют пользовательские действия клика (saddle:deploy/copy, saddle:deploy/apply), которые сервер сам проверяет на уровень разрешений 4.

Пользовательские запросы

  • minecraft/getScoreboard, minecraft/setScore {objective, holder, value}
  • minecraft/getStorage {id?, path?}, minecraft/listEntities {selector}, minecraft/getEntity {uuid} (включая NBT)
  • minecraft/getData / minecraft/setData {type: storage|entity|block, target, path, value} — доступ в стиле ванильного /data; цели-блоки задаются как "x y z [dimension]"
  • minecraft/getBlock {pos, dimension?} — состояние блока плюс NBT блок-сущности
  • saddle/runFunction {path, arguments?, executor?}, saddle/reload — см. Интеграция с редактором

Сборка

./gradlew build                     # jar мода в build/libs/

cd vscode-extension                 # расширение .vsix
npx --yes @vscode/vsce package
code --install-extension saddle-debug-*.vsix

Minecraft 26.x не обфусцирован, поэтому в сборочном скрипте используется плагин net.fabricmc.fabric-loom без ремапа. Мод собирается под 26.2 (gradle.properties); передайте `-Pminecraft_version=26.3 -Pfabric_api_version=, чтобы собрать или запустить runServer` под другой поддерживаемой версией.

Тестирование

# только в первый раз: примите EULA и отключите tick watchdog
mkdir -p run
printf 'eula=true\n' > run/eula.txt
printf 'max-tick-time=-1\nonline-mode=false\npause-when-empty-seconds=0\n' > run/server.properties

./gradlew runServer                 # терминал 1
python3 scripts/dap_smoke_test.py   # терминал 2

Скрипт устанавливает scripts/test-datapack в мир, выполняет /reload и прогоняет весь цикл отладки от начала до конца (141 проверка): точки останова, пошаговое выполнение, путешествие во времени (шаг назад / обратное продолжение / восстановление исторического состояния), макро-точки останова и значения макро-аргументов, сдвиг строк комментариев, чтение/запись переменных в реальном времени (scoreboard, NBT хранилища, NBT сущности), разрешение селекторов/координат, вычисление при наведении, автодополнение консоли, зеркалирование вывода чата, запросы данных сущностей/блоков, evaluate и pause, reload и запуск из файла, а также /deploy copy. CI прогоняет тот же набор на настоящем выделенном сервере для каждой поддерживаемой версии Minecraft (26.2 и 26.3), а при пуше тега v* jar и vsix публикуются как GitHub Release.

Примечания

  • Держите мод и расширение VS Code на совпадающих версиях: при подключении мод отправляет событие saddle/version, и расширение предупреждает, когда версии расходятся (major.minor).
  • На выделенных серверах установите max-tick-time=-1: приостановка на точке останова останавливает поток сервера, что иначе вызвало бы срабатывание watchdog.
  • В одиночной игре внутренний клиент может отключиться, если игра остаётся приостановленной слишком долго.
  • Шаг за конец всех поставленных в очередь команд оставляет сессию в состоянии выполнения до следующего попадания в точку останова/паузу (например, до следующей команды tick-функции).

Решение проблем

  • Правки будто не применяются / data get показывает старые значения. Сначала проверьте объявление о подключении: при подключении Saddle выводит Saddle: debugger attached to world '…' в Debug Console и [Saddle] Debugger attached в чат игры. Если сообщение в чате не появляется в вашем мире, значит порт занят другим экземпляром Minecraft с Saddle (в его логе будет Failed to bind DAP server), и ваши правки уходят в тот экземпляр — закройте его или используйте -Dsaddle.port, чтобы их разделить. Также учтите, что tick-функция, перезаписывающая scoreboard/хранилище каждый тик, перезапишет ручные правки, как только вы возобновите выполнение.
  • Области Watched/Storage редактируют только живые данные. Во время путешествия во времени одноимённые области показывают записанные значения и доступны только для чтения — строка (time travel) в области Executor подсказывает, на какой режим вы смотрите.

Лицензия

MIT

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

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

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

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

У saddle есть сборки для Minecraft 26.2–26.3.

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

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

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

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