chunkedge_server/
passenger.rs1use std::borrow::Cow;
8
9use bevy_app::prelude::*;
10use bevy_ecs::prelude::*;
11use bevy_ecs::relationship::RelationshipTarget;
12use chunkedge_entity::{EntityId, EntityLayerId, Position};
13use derive_more::Deref;
14
15use crate::client::{
16 Client, FlushPacketsSet, LoadEntityForClientMessage, ViewDistance, VisibleEntityLayers,
17};
18use crate::layer::UpdateLayersPreClientSet;
19use crate::protocol::packets::play::SetPassengersS2c;
20use crate::protocol::{VarInt, WritePacket};
21use crate::{ChunkView, EntityLayer, Layer};
22
23pub struct PassengerPlugin;
24
25impl Plugin for PassengerPlugin {
26 fn build(&self, app: &mut App) {
27 app.add_systems(
28 PostUpdate,
29 (
30 (send_passengers, send_empty_passengers_on_removal)
31 .before(UpdateLayersPreClientSet),
32 send_passengers_on_entity_load.before(FlushPacketsSet),
33 ),
34 );
35 }
36}
37
38#[derive(Component, Copy, Clone, PartialEq, Eq, Debug, Deref)]
44#[relationship(relationship_target = Passengers)]
45pub struct Riding(pub Entity);
46
47#[derive(Component, Debug)]
54#[relationship_target(relationship = Riding)]
55pub struct Passengers(Vec<Entity>);
56
57fn send_passengers(
58 vehicles: Query<(&EntityId, &Passengers, &EntityLayerId, &Position), Changed<Passengers>>,
59 entity_ids: Query<&EntityId>,
60 mut clients: Query<(
61 &mut Client,
62 &EntityId,
63 &Position,
64 &ViewDistance,
65 &VisibleEntityLayers,
66 )>,
67) {
68 for (vehicle_id, passengers, layer_id, vehicle_pos) in &vehicles {
69 for (mut client, client_id, client_pos, view_distance, visible_layers) in &mut clients {
70 if !visible_layers.0.contains(&layer_id.0) {
71 continue;
72 }
73
74 let view = ChunkView::new(client_pos.0.into(), view_distance.get());
75 if !view.contains(vehicle_pos.0.into()) {
76 continue;
77 }
78
79 client.write_packet(&packet_for_viewer(
80 client_id.get(),
81 vehicle_id.get(),
82 passengers,
83 &entity_ids,
84 ));
85 }
86 }
87}
88
89fn send_empty_passengers_on_removal(
90 mut removed: RemovedComponents<Passengers>,
91 vehicles: Query<(&EntityId, &EntityLayerId, &Position), Without<Passengers>>,
92 mut entity_layers: Query<&mut EntityLayer>,
93) {
94 for entity in removed.read() {
95 let Ok((vehicle_id, layer_id, pos)) = vehicles.get(entity) else {
96 continue;
97 };
98 let Ok(mut entity_layer) = entity_layers.get_mut(layer_id.0) else {
99 continue;
100 };
101
102 let packet = SetPassengersS2c {
103 entity_id: VarInt(vehicle_id.get()),
104 passengers: Cow::Borrowed(&[]),
105 };
106
107 entity_layer.view_writer(pos.0).write_packet(&packet);
108 }
109}
110
111fn send_passengers_on_entity_load(
112 mut messages: MessageReader<LoadEntityForClientMessage>,
113 mut clients: Query<(&mut Client, &EntityId)>,
114 vehicles: Query<(&EntityId, &Passengers)>,
115 entity_ids: Query<&EntityId>,
116) {
117 for message in messages.read() {
118 let Ok((vehicle_id, passengers)) = vehicles.get(message.entity_loaded) else {
119 continue;
120 };
121 let Ok((mut client, client_id)) = clients.get_mut(message.client) else {
122 continue;
123 };
124
125 client.write_packet(&packet_for_viewer(
126 client_id.get(),
127 vehicle_id.get(),
128 passengers,
129 &entity_ids,
130 ));
131 }
132}
133
134fn packet_for_viewer<'a>(
135 viewer_id: i32,
136 vehicle_id: i32,
137 passengers: &Passengers,
138 entity_ids: &Query<&EntityId>,
139) -> SetPassengersS2c<'a> {
140 let ids: Vec<VarInt> = passengers
141 .iter()
142 .filter_map(|passenger| entity_ids.get(passenger).ok())
143 .map(|id| VarInt(rewrite_self(id.get(), viewer_id)))
144 .collect();
145
146 SetPassengersS2c {
147 entity_id: VarInt(rewrite_self(vehicle_id, viewer_id)),
148 passengers: Cow::Owned(ids),
149 }
150}
151
152fn rewrite_self(id: i32, viewer_id: i32) -> i32 {
153 if id == viewer_id { 0 } else { id }
154}