Убрать и заменить ванильные части
На этой странице показано, как собрать собственный сервер из тех же плагинов, что и штатный, как убрать один из них и как передать плагинам настройки.
В Paper вы берете готовый сервер и добавляете к нему плагины. В mcrs вы берете группу плагинов и убираете из нее лишнее, поэтому лобби может работать без генерации мира, а тест - без освещения. Примеры взяты из файлов репозитория, вне репозиторных тестов мы их не запускали.
Сервер - это группа плагинов
Заголовок раздела «Сервер - это группа плагинов»MinecraftServerPlugins - это PluginGroup из Bevy, то есть набор плагинов, который добавляют в приложение одним значением. Четыре ее поля - это части, которые принимают настройки:
pub struct MinecraftServerPlugins { pub core: ServerCorePlugin, pub worlds: DimensionWorldsPlugin, pub world_gen: WorldGenPlugin, pub network: ServerNetworkPlugin,}crates/mcrs_minecraft_server/src/lib.rs:22-27
Остальной ванильный сервер добавляет build(). Члены группы в том порядке, в каком build() их добавляет: ядро сервера, реестры генерации мира, ванильный набор команд, ванильные команды, команды мира, миры измерений, чат, физика сущностей, мозги мобов, генерация мира, освещение и сеть.1
impl PluginGroup for MinecraftServerPlugins { fn build(self) -> PluginGroupBuilder { PluginGroupBuilder::start::<Self>() .add(self.core) .add(WorldgenRegistriesPlugin) .add(CommandPlugin::<VanillaCommands>::new()) .add(VanillaCommandsPlugin) .add(WorldCommandsPlugin) .add(self.worlds) .add(VanillaChatPlugin) .add(VanillaEntityPhysicsPlugin) .add(VanillaMobBrainPlugin) .add(self.world_gen) .add(LightingPlugin) .add(self.network) }}crates/mcrs_minecraft_server/src/lib.rs:61-77
Любого члена группы можно отключить или заменить, не трогая крейт сервера. Если члену нужен другой плагин, а его нет, группа паникует при сборке и называет недостающий плагин. Ошибку вы получаете на старте, и вам не приходится разбираться с отсутствующим ресурсом на первом тике.
Ванильный геймплей живет в плагинах над движком. Каждый из них можно убрать отдельно, а в каждый мир измерения они попадают через add_dimension_plugin.2
Члена группы отключает disable
Заголовок раздела «Члена группы отключает disable»Бинарник выключает ИИ мобов так:
if !settings.mob_ai { server = server.disable::<VanillaMobBrainPlugin>();}disable::<T>() - метод билдера группы плагинов Bevy, а T - плагин, который вы убираете. Тест из репозитория тем же методом запускает сервер без генерации мира и освещения:
fn a_client_without_an_app_joins_the_embedded_server_offline() { let mut plugins = MinecraftServerPlugins::embedded(); plugins.core.asset_path = Some(ASSETS.to_owned()); plugins.network.announce_on_lan = false; let mut app = App::new(); app.add_plugins( plugins .build() .disable::<WorldGenPlugin>() .disable::<LightingPlugin>(), ); let stop = StopOnDrop(Arc::new(AtomicBool::new(false)));crates/mcrs_minecraft_server/tests/it/client_join.rs:31-42
Этот тест вызывает еще и MinecraftServerPlugins::embedded(). Он дает сервер, который работает внутри другого процесса. Такой сервер слушает только loopback, берет порт, который назначит ОС, и оставляет пулы задач приложению-хозяину.
impl MinecraftServerPlugins { /// A server running inside another process: loopback only, an OS-assigned /// port, and the task pools left to the host app. pub fn embedded() -> Self { let defaults = Self::default(); Self { core: ServerCorePlugin { owns_task_pools: false, ..defaults.core }, network: ServerNetworkPlugin::embedded(), ..defaults } }}crates/mcrs_minecraft_server/src/lib.rs:45-59
Настройки - это поля плагинов
Заголовок раздела «Настройки - это поля плагинов»Бинарник читает настройки из окружения и превращает их в поля плагинов в src/main.rs:
let settings = ServerSettings::read( |name| std::env::var(format!("MCRS_{name}")).ok(), |error| bevy_log::warn!("{error}"),);let mut server = MinecraftServerPlugins { core: ServerCorePlugin { compute_threads: settings.compute_threads, ..MinecraftServerPlugins::default().core }, worlds: DimensionWorldsPlugin { world: world_folder(), ops, seed: settings.world_seed, preset: settings.world_preset.clone(), default_game_mode: settings.default_game_mode, ..Default::default() }, world_gen: WorldGenPlugin, network: network(&settings),}.build();Так делает только бинарник. Библиотечный крейт не читает ради своих настроек ни переменные окружения, ни файлы, и каждая настройка - поле того плагина, который ее использует.3
Переменные окружения бинарника соответствуют полям ServerSettings. Имя переменной - это имя поля с префиксом MCRS_. Полный список лежит в исходном файле.
В собственной программе обойдитесь без ServerSettings и заполните поля плагинов сами. Тогда встроенный сервер в тесте стартует с явными настройками, что бы ни экспортировал шелл.
Свои чанки серверу пока передать нельзя
Заголовок раздела «Свои чанки серверу пока передать нельзя»Дальше: Добавить команду.
Footnotes
Заголовок раздела «Footnotes»-
Работает#279 Делит плагин сервера на группу плагинов, которые можно убрать. ↩
-
Работает#282 Переносит ванильный геймплей из крейта сервера в убираемые плагины. ↩
-
Работает#278 Сервер настраивается только через свой плагин. ↩
-
В работе#281 Планирует источник чанков как заменяемую точку расширения с пустым и плоским источниками. ↩
-
В работе#78 Отслеживает сохранение измененных чанков в файлы регионов. ↩
Источники и проверка
Проверено: 26.4-snapshot-7, 51d45c26a, 2026-11-09
Переведено с версии 51d45c26a