Режим GM
Режим GM — это способ проверить вашу игру на вашем работающем сервере.
Когда сервер становится авторитетным, приёмы, которыми вы пользовались офлайн, перестают работать. Нельзя выдать себе монстра 40-го уровня, отредакт ировав файл сохранения, потому что файл сохранения больше не место, где живёт истина, — ею стал сервер. Задайте уровень локально, и следующая синхронизация команды его перезапишет, а то и не перезапишет, и вы потратите день на погоню за ошибкой, которая существует только на вашей машине.
В этом вся причина его существования. Отладочный инструмент, который пишет в локальное сохранение, пока авторитет у сервера, — не инструмент, а генератор призрачных ошибок. Поэтому каждое действие GM — это RPC сервера, разрешаемое сервером, сохраняемое сервером и видимое каждому клиенту, который спросит.
Режим GM предназначен для человека, который управляет сервером: вас, во время разработки, и того, кто ведёт вашу игру после запуска. Это не функция для игроков и не меню читов, которое поставляется включённым. См. Защита.
Два способа входа
Одни и те же восемь RPC доступны из двух мест, потому что они нужны для двух разных задач.
| Панель в игре | Вкладка GM в Hub | |
|---|---|---|
| Где | В запущенной игре, F9 | Tools → MCE → OpenMon Hub → GM |
| Для | Тестирования во время игры | Управления без запуска игры |
| Требуется | Онлайн-сессия с выполненным входом | Собственный вход по почте и паролю |
Панель в игре (F9)
Горячая клавиша устанавливается сама — ничего не нужно перетаскивать в сцену, и это намеренно: инструмент оператора до лжен работать в любой сцене, включая те, которые вы создаёте после покупки движка, а сцена, настроенная вручную, в следующей сцене забывается.
Так было не всегда. GmModeHotkey поставлялся как компонент с нулём ссылок — ни
префаб, ни сцена, ни ассет не упоминали его, поэтому его никто не создавал, и F9 не мог
работать ни в одной игре. Это обнаружили, управляя игрой, а не читая код: нажатие F9 в живой онлайн-сессии
под настоящим гейм-мастером вообще не отправляло gamemaster_status на сервер.

Это па нель поверх живого онлайн-мира, открытая клавишей F9 под аккаунтом, который сервер
распознаёт. Строка внизу — "10 verbos disponibles" — не подпись, написанная
клиентом: это собственный ответ сервера на gamemaster_status, поэтому аккаунт
без разрешения видит, что панель отказывается открываться, а не открывается пустой.
F9 выбрана по умолчанию, потому что она вне диапазона, который MCE использует для игры:
клавиши движения, Z/X и привязки меню не затронуты, так что панель
не может перехватить ввод, нужный игре. Привязка находится в GmModeHotkey.cs
и представляет собой обычное поле Key, так что её можно изменить.
Панель появляется только для аккаунта, который сервер считает гейм-мастером. Она
спрашивает, а не предполагает. При открытии она вызывает gamemaster_status, и ответ
касается вызывающего: нет способа спросить «является ли тот аккаунт GM»,
поэтому этот RPC нельзя использовать, чтобы перечислить, у кого на вашем сервере есть власть.
Вкладка GM в Hub

Вкладка Hub входит по почте и паролю, точно как игрок, и получает настоящий токен сессии. Это сознательный выбор, и его стоит объяснить, потому что остальной Hub работает не так.
Каждая другая панель Hub, которая обращается к серверу, — в первую очередь засев, — общается
от сервера к серверу с помощью http_key рантайма Nakama. У этого ключа нет привязанного
пользователя. А все семь действующих глаголов требуют ctx.userId, потому что каждый
из них записывает строку с указанием, кто это сделал.
Мы могли бы добавить варианты глаголов с http_key. Мы отказались, и причина укладывается в
одно предложение: строка аудита сказала бы «это сделал http_key», и журнал
потерял бы подлежащее — единственное, о чём кто-либо когда-либо спрашивает журнал администратора.
http_key — не гейм-мастерЭто два разных учётных данных с двумя разными значениями. Обладание ключом засева позволяет писать в хранилище от сервера к серверу. Оно не делает вас гейм-мастером и никогда не даёт глагол GM. Не путайте их и не помещайте ни тот, ни другой в свой репозиторий.
Вкладка также различает четыре состояния, а не сводит их к одной ошибке. «Вы не вошли», «вы вошли, но не GM», «вы GM, но на этом сервере включён аварийный выключатель» и «готово» отправляют вас в четыре разных места. Единственное «не удалось подключиться» заставило бы вас проверять учётные данные, когда на самом деле нужно разрешение, или засевать право, которое у вас уже есть, когда нужно поговорить с тем, кто управляет сервером.
Вкладка не запоминает ваш пароль между сессиями редактора. Хост, порт, ключ сервера и почта сохраняются; пароль — нет.
Восемь глаголов
Один задаёт вопрос. Семь действуют.
| RPC | Что делает |
|---|---|
gamemaster_status | Я гейм-мастер? Включён ли здесь режим GM? Какие глаголы существуют? |
gamemaster_mint_monster | Создаёт монстра заданного вида на сервере с идентификатором, назначенным сервером |
gamemaster_set_level | Меняет уровень монстра |
gamemaster_set_hp | Задаёт текущее HP — в том числе вплоть до нуля, чтобы добраться до путей потери сознания |
gamemaster_heal_party | Полностью восстанавливает команду |
gamemaster_force_encounter | Принудительно вызывает следующую дикую встречу |
gamemaster_set_dex | Отмечает вид как увиденный или пойманный |
gamemaster_set_variable | Записывает игровую переменную |
gamemaster_mint_monster заслуживает замечания. Он создаёт монстра на
сервере, и идентификатор назначает сервер. Нет пути клиента, который мог бы создать
монстра: исходящий канал может обновлять семь полей, которые игрок меняет в процессе игры, и
это всё, что он может. Если вам нужно, чтобы монстр существовал, это единственная дверь.
Почему это лучше, чем переигрывать контент
gamemaster_set_level существует потому, что проверка анимации эволюции раньше
стоила 126 сражений. Функция, которую он заменил, не была обходным путём вокруг тестирования;
это была разница между тестом, который запускают, и тестом, который не запускают.
Защита
Три независимых условия должны выполняться все сразу, прежде чем глагол выполнится. Любого одного достаточно, чтобы его остановить.
1. Таблица гейм-мастеров. Аккаунт является GM, только если он есть в этой таблице. Таблица начинается пустой, и пустая означает никто — не «все», не «первый аккаунт», не «тот, у кого есть ключ». У свежего сервера вообще нет гейм-мастеров.
2. Аварийный выключатель. Установка переменной окружения
MCE_GM_MODE_DISABLED=true отключает все глаголы, не трогая таблицу. Используйте
его на продакшен-узле: разрешения остаются ровно как есть, и ничего нельзя
вызвать. Повторное отключение восстанавливает то, что у вас уже было, так что вам никогда не придётся
восстанавливать таблицу по памяти во время инцидента.
3. Проверка на каждый глагол. requireGameMasterVerb выполняется при каждом вызове, включая
gamemaster_status. Отклонённый вызов тоже записывается.
Два журнала аудита — намеренно
Каждое действие GM записывает две записи, и они существуют для двух разных читателей.
gm_audit — журнал оператора. Он принадлежит системе, называет гейм-мастера, глагол и цель
и записывается для каждого вызова, включая те, что были отклонены. Отказ — это ровно то событие, для которого
существует журнал администратора.
Вторая запись попадает под собственный аккаунт целевого игрока и читаема этим игроком. Это та половина, которую легко пропустить и которая важна с этической точки зрения: игрок всегда может узнать, что кто-то с властью тронул его данные. Состояние «их тронули и ничего не сказали» — не то, что эта система может представить: видимая игроку строка едет в той же записи хранилища, что и сам эффект, поэтому нет окна, в котором одно дошло, а другое — нет.