aetheris_client_wasm/
world_state.rs1use crate::shared_world::SabSlot;
7use aetheris_protocol::error::WorldError;
8use aetheris_protocol::events::{ComponentUpdate, ReplicationEvent};
9use aetheris_protocol::traits::WorldState;
10use aetheris_protocol::types::{
11 ClientId, ComponentKind, LocalId, NetworkId, ShipClass, ShipStats, Transform,
12};
13use std::collections::BTreeMap;
14
15#[derive(Debug)]
17pub struct ClientWorld {
18 pub entities: BTreeMap<NetworkId, SabSlot>,
20 pub latest_tick: u64,
22}
23
24impl Default for ClientWorld {
25 fn default() -> Self {
26 Self::new()
27 }
28}
29
30impl ClientWorld {
31 #[must_use]
33 pub fn new() -> Self {
34 Self {
35 entities: BTreeMap::new(),
36 latest_tick: 0,
37 }
38 }
39}
40
41impl WorldState for ClientWorld {
42 fn get_local_id(&self, network_id: NetworkId) -> Option<LocalId> {
43 Some(LocalId(network_id.0))
44 }
45
46 fn get_network_id(&self, local_id: LocalId) -> Option<NetworkId> {
47 Some(NetworkId(local_id.0))
48 }
49
50 fn extract_deltas(&mut self) -> Vec<ReplicationEvent> {
51 Vec::new()
52 }
53
54 fn apply_updates(&mut self, updates: &[(ClientId, ComponentUpdate)]) {
55 for (_, update) in updates {
56 if update.tick > self.latest_tick {
57 self.latest_tick = update.tick;
58 }
59
60 let is_new = !self.entities.contains_key(&update.network_id);
62 if is_new {
63 tracing::debug!(
64 network_id = update.network_id.0,
65 kind = update.component_kind.0,
66 "New entity from server"
67 );
68 }
69 self.entities.entry(update.network_id).or_insert(SabSlot {
70 network_id: update.network_id.0,
71 x: 0.0,
72 y: 0.0,
73 z: 0.0,
74 rotation: 0.0,
75 dx: 0.0,
76 dy: 0.0,
77 dz: 0.0,
78 hp: 100,
79 shield: 0,
80 entity_type: 0,
81 flags: 1,
82 padding: [0; 5],
83 });
84
85 match update.component_kind {
86 ComponentKind(1) => match rmp_serde::from_slice::<Transform>(&update.payload) {
88 Ok(transform) => {
89 if let Some(entry) = self.entities.get_mut(&update.network_id) {
90 entry.x = transform.x;
91 entry.y = transform.y;
92 entry.z = transform.z;
93 entry.rotation = transform.rotation;
94 if transform.entity_type != 0 {
95 entry.entity_type = transform.entity_type;
96 }
97 }
98 }
99 Err(e) => {
100 tracing::warn!(network_id = update.network_id.0, error = ?e, "Failed to decode Transform");
101 }
102 },
103 ComponentKind(5) => match rmp_serde::from_slice::<ShipClass>(&update.payload) {
105 Ok(ship_class) => {
106 if let Some(entry) = self.entities.get_mut(&update.network_id) {
107 entry.entity_type = match ship_class {
108 ShipClass::Interceptor => 1,
109 ShipClass::Dreadnought => 3,
110 ShipClass::Hauler => 4,
111 };
112 }
113 }
114 Err(e) => {
115 tracing::warn!(network_id = update.network_id.0, error = ?e, "Failed to decode ShipClass");
116 }
117 },
118 ComponentKind(6) => match rmp_serde::from_slice::<ShipStats>(&update.payload) {
120 Ok(stats) => {
121 if let Some(entry) = self.entities.get_mut(&update.network_id) {
122 entry.hp = stats.hp;
123 entry.shield = stats.shield;
124 }
125 }
126 Err(e) => {
127 tracing::warn!(network_id = update.network_id.0, error = ?e, "Failed to decode ShipStats");
128 }
129 },
130 kind => {
131 tracing::debug!(
132 network_id = update.network_id.0,
133 kind = kind.0,
134 "Unhandled component kind"
135 );
136 }
137 }
138 }
139 }
140
141 fn simulate(&mut self) {}
142
143 fn spawn_networked(&mut self) -> NetworkId {
144 NetworkId(0)
145 }
146
147 fn spawn_networked_for(&mut self, _client_id: ClientId) -> NetworkId {
148 self.spawn_networked()
149 }
150
151 fn despawn_networked(&mut self, network_id: NetworkId) -> Result<(), WorldError> {
152 self.entities
153 .remove(&network_id)
154 .map(|_| ())
155 .ok_or(WorldError::EntityNotFound(network_id))
156 }
157
158 fn stress_test(&mut self, _count: u16, _rotate: bool) {}
159
160 fn spawn_kind(&mut self, _kind: u16, _x: f32, _y: f32, _rot: f32) -> NetworkId {
161 NetworkId(1)
162 }
163
164 fn clear_world(&mut self) {
165 self.entities.clear();
166 }
167}