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

Чтение данных игрока

Меняется. Следите: #158

Эта страница показывает, как плагин находит игроков, читает их данные, различает их идентификаторы и меняет их состояние. В Paper Player - объект с методами. В mcrs игрок - сущность внутри мира измерения, а его состояние хранится в наборе компонентов. Поэтому там, где код для Paper держал бы объект, вы пишете запрос.

Страница короткая, потому что набор компонентов растет вместе с проектом. Примеры взяты из файлов репозитория, и вне тестов репозитория мы их не запускали.

У каждой сущности игрока есть компонент-маркер Player. Система в мире измерения видит игроков только этого измерения, об этом рассказывает страница Измерения. Тестовое окружение находит игрока таким же запросом:

Найти сущность игрока по его сессии
pub fn player_in(&mut self, dim: Entity, anchor: Entity) -> Option<Entity> {
let session = self.session_of(anchor)?;
let world = self.world_in(dim);
world
.query_filtered::<(Entity, &Owner), With<Player>>()
.iter(world)
.find(|(_, owner)| owner.0 == session)
.map(|(player, _)| player)
}

crates/mcrs_minecraft_server/tests/it/host_app/mod.rs:374-382

В плагине запрос пишется как параметр системы, например Query<(&GameProfile, &PlayerGameMode), With<Player>>. Эта строка только иллюстрация, ее никто не компилировал. Имена типов в ней взяты из файлов следующего раздела.

GameProfile - профиль, с которым клиент вошел на сервер:

GameProfile
#[derive(Debug, Clone, Component)]
pub struct GameProfile {
pub id: uuid::Uuid,
pub username: String,
pub properties: Vec<Property<String>>,
}

crates/mcrs_minecraft_engine/src/game_profile.rs:8-13

Режим игры, состояние полета и уровень оператора лежат в одном файле:

PlayerGameMode и PlayerFlying
#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Deref, DerefMut)]
pub struct PlayerGameMode(pub GameMode);
impl Default for PlayerGameMode {
fn default() -> Self {
Self(GameMode::Survival)
}
}
/// Whether the player flies, as its client reports it and its game mode allows.
#[derive(Component, Debug, Clone, Copy, PartialEq, Eq, Deref, DerefMut, Default)]
pub struct PlayerFlying(pub bool);

crates/mcrs_minecraft_engine/src/ability.rs:12-23

PlayerOpLevel в том же файле хранит уровень оператора, от 0 для игрока без прав оператора до 4. Тестовое окружение читает режим игры так:

Прочитать PlayerGameMode игрока
pub fn game_mode(&mut self, anchor: Entity) -> GameMode {
let player = self.player(anchor);
self.world().get::<PlayerGameMode>(player).unwrap().0
}

crates/mcrs_minecraft_server/tests/it/host_app/mod.rs:389-392

Подставить один из них вместо другого нельзя.

Идентификатор Где Что это
GameProfile::id компонент игрока UUID профиля, как в Paper
PlayerSession компонент Owner игрока в мире измерения, а также на хосте имя одного соединения. Хост не выдает одно значение дважды, а при смене измерения оно сохраняется
Entity сущность игрока внутри одного мира измерения идентификатор Bevy, который существует только в одном мире. У хоста для того же игрока есть еще якорная сущность, и это другая сущность
PlayerSession
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub struct PlayerSession(pub u64);

crates/mcrs_minecraft_engine_world/src/session/sessions.rs:12-13

По сессии адресуйте игрока между мирами и отправляйте ему пакеты. UUID берите для всего, что должно пережить переподключение.

Внутри мира игрока его компоненты можно вставлять и править. Не меняйте игрока из системы, которая работает в другом мире. Изменение, которое пересекает границу миров, передается сообщением или эффектом. Ванильные команды gamemode и teleport делают это через эффекты команд, см. Добавить команду.

Метода player.sendMessage() в mcrs нет. Низкоуровневый способ - записать пакет в сессию. Плагин чата так и поступает с игроком, который скрыл чат:

Записать пакет системного чата в сессию игрока
if info.is_some_and(|info| info.chat_mode == ChatMode::Hidden) {
let disabled: Text = Text::translate("chat.disabled.options", vec![]).color(Color::RED);
if let Ok(disabled) = RawText::from_text(&disabled) {
packet_writer.write(bus::to(owner.0, system_chat(disabled)));
}
return;
}

crates/mcrs_minecraft_chat_server/src/chat_plugin.rs:56-62

Более удобного слоя для этого пока нет. Issue о нем мы не знаем, поэтому ничего не обещаем.

Сохранение данных игрока тоже не готово.2 Состояние сохранения показывает страница Статус.

Дальше: Тест плагина без клиента, где тест подключает фиктивного игрока и читает эти компоненты.

  1. В работе#158 Планирует сетевые идентификаторы сущностей, которые не зависят от мира-владельца. ↩ ↩2

  2. В работе#78 Отслеживает сохранение измененных чанков в файлы регионов. ↩

Источники и проверка

Проверено: 26.4-snapshot-7, 51d45c26a, 2026-11-09

Переведено с версии 51d45c26a

Следить: #158