|
| 1 | +use flecs_ecs::{core::World, prelude::*}; |
| 2 | +use hyperion::{ |
| 3 | + net::{Compose, ConnectionId}, |
| 4 | + simulation::{Uuid, metadata::entity::EntityFlags}, |
| 5 | +}; |
| 6 | +use valence_protocol::packets::play::{self, player_list_s2c::PlayerListActions}; |
| 7 | +use valence_server::GameMode; |
| 8 | + |
| 9 | +#[derive(Component)] |
| 10 | +pub struct VanishModule; |
| 11 | + |
| 12 | +#[derive(Default, Component, Debug)] |
| 13 | +pub struct Vanished(pub bool); |
| 14 | + |
| 15 | +impl Vanished { |
| 16 | + #[must_use] |
| 17 | + pub const fn new(is_vanished: bool) -> Self { |
| 18 | + Self(is_vanished) |
| 19 | + } |
| 20 | + |
| 21 | + #[must_use] |
| 22 | + pub const fn is_vanished(&self) -> bool { |
| 23 | + self.0 |
| 24 | + } |
| 25 | +} |
| 26 | + |
| 27 | +impl Module for VanishModule { |
| 28 | + fn module(world: &World) { |
| 29 | + world.component::<Vanished>(); |
| 30 | + |
| 31 | + system!( |
| 32 | + "vanish_sync", |
| 33 | + world, |
| 34 | + &Compose($), |
| 35 | + &ConnectionId, |
| 36 | + &Vanished, |
| 37 | + &Uuid, |
| 38 | + ) |
| 39 | + .multi_threaded() |
| 40 | + .kind::<flecs::pipeline::PreStore>() |
| 41 | + .each_iter(move |it, row, (compose, _connection_id, vanished, uuid)| { |
| 42 | + let entity = it.entity(row); |
| 43 | + let system = it.system(); |
| 44 | + let world = it.world(); |
| 45 | + |
| 46 | + if vanished.is_vanished() { |
| 47 | + // Remove from player list and make them invisible |
| 48 | + let remove_packet = play::PlayerListS2c { |
| 49 | + actions: PlayerListActions::new() |
| 50 | + .with_update_listed(true) |
| 51 | + .with_update_game_mode(true), |
| 52 | + entries: vec![play::player_list_s2c::PlayerListEntry { |
| 53 | + player_uuid: uuid.0, |
| 54 | + listed: false, |
| 55 | + game_mode: GameMode::Survival, |
| 56 | + ..Default::default() |
| 57 | + }] |
| 58 | + .into(), |
| 59 | + }; |
| 60 | + compose.broadcast(&remove_packet, system).send().unwrap(); |
| 61 | + |
| 62 | + // Set entity flags to make them invisible |
| 63 | + let flags = EntityFlags::INVISIBLE; |
| 64 | + entity.entity_view(world).set(flags); |
| 65 | + } else { |
| 66 | + // Add back to player list and make them visible |
| 67 | + let add_packet = play::PlayerListS2c { |
| 68 | + actions: PlayerListActions::new() |
| 69 | + .with_update_listed(true) |
| 70 | + .with_update_game_mode(true), |
| 71 | + entries: vec![play::player_list_s2c::PlayerListEntry { |
| 72 | + player_uuid: uuid.0, |
| 73 | + listed: true, |
| 74 | + game_mode: GameMode::Survival, |
| 75 | + ..Default::default() |
| 76 | + }] |
| 77 | + .into(), |
| 78 | + }; |
| 79 | + compose.broadcast(&add_packet, system).send().unwrap(); |
| 80 | + |
| 81 | + // Clear invisible flag |
| 82 | + let flags = EntityFlags::default(); |
| 83 | + entity.entity_view(world).set(flags); |
| 84 | + } |
| 85 | + }); |
| 86 | + } |
| 87 | +} |
0 commit comments