Skip to content
This repository was archived by the owner on Jul 1, 2024. It is now read-only.

Commit 3bbdfc8

Browse files
committed
Add a change set for entities
1 parent 3cfac8f commit 3bbdfc8

File tree

5 files changed

+33
-19
lines changed

5 files changed

+33
-19
lines changed

minecraft-server/src/entities/mod.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,13 @@ impl<T> Handler<T> where AnyEntity: TryAsEntityRef<T> {
111111
self.world.observe_entity(self.eid, observer).await
112112
}
113113

114-
pub async fn mutate<R>(&self, mutator: impl FnOnce(&mut T) -> (R, EntityChanges)) -> Option<R> {
114+
pub async fn mutate<R>(&self, mutator: impl FnOnce(&mut T) -> R) -> Option<R> {
115115
self.world.mutate_entity(self.eid, move |entity| {
116116
mutator(entity.try_as_entity_mut().expect("Called mutate on the wrong entity"))
117117
}).await
118118
}
119119

120-
pub async fn mutate_any<R>(&self, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option<R> {
120+
pub async fn mutate_any<R>(&self, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option<R> {
121121
self.world.mutate_entity(self.eid, mutator).await
122122
}
123123
}

minecraft-server/src/entities/player.rs

+5-5
Original file line numberDiff line numberDiff line change
@@ -93,7 +93,7 @@ impl Handler<Player> {
9393
let old_center_chunk = player.center_chunk.clone();
9494
let new_center_chunk = player.get_entity().position.chunk();
9595
player.center_chunk = new_center_chunk.clone();
96-
((old_center_chunk, new_center_chunk, player.render_distance), EntityChanges::other())
96+
(old_center_chunk, new_center_chunk, player.render_distance)
9797
}).await else {return};
9898

9999
// Tell the client which chunk he is in
@@ -113,7 +113,7 @@ impl Handler<Player> {
113113

114114
// Select chunks to load (max 50) and unload
115115
let Some((loaded_chunks_after, newly_loaded_chunks, unloaded_chunks, uuid)) = self.mutate(|player| {
116-
if loaded_chunks_after == player.loaded_chunks { return (None, EntityChanges::nothing()) };
116+
if loaded_chunks_after == player.loaded_chunks { return None };
117117
let mut newly_loaded_chunks: Vec<_> = loaded_chunks_after.difference(&player.loaded_chunks).cloned().collect();
118118
let unloaded_chunks: Vec<_> = player.loaded_chunks.difference(&loaded_chunks_after).cloned().collect();
119119
for skipped in newly_loaded_chunks.iter().skip(50) {
@@ -122,7 +122,7 @@ impl Handler<Player> {
122122
newly_loaded_chunks.truncate(50);
123123
let uuid = player.info.uuid;
124124
player.loaded_chunks = loaded_chunks_after.clone();
125-
(Some((loaded_chunks_after, newly_loaded_chunks, unloaded_chunks, uuid)), EntityChanges::other())
125+
Some((loaded_chunks_after, newly_loaded_chunks, unloaded_chunks, uuid))
126126
}).await.flatten() else { return };
127127

128128
// Tell the world about the changes
@@ -177,7 +177,7 @@ impl Handler<Player> {
177177
let packet = packet.serialize_minecraft_packet().unwrap();
178178
let packets_sent = self.mutate(|player| {
179179
player.packets_sent += 1;
180-
(player.packets_sent, EntityChanges::other())
180+
player.packets_sent
181181
}).await.unwrap_or(0);
182182
if packets_sent > 500 {
183183
warn!("Many packets sent ({packets_sent})");
@@ -234,7 +234,7 @@ impl Handler<Player> {
234234
},
235235
WorldChange::EntityMetadata { eid, metadata } => todo!(),
236236
WorldChange::EntityPosition { eid, position } => {
237-
let Some(prev_position) = self.mutate(|player| ((player.entity_prev_positions.insert(eid, position.clone())), EntityChanges::other())).await else {return};
237+
let Some(prev_position) = self.mutate(|player| player.entity_prev_positions.insert(eid, position.clone())).await else {return};
238238
match prev_position {
239239
Some(prev_position) => {
240240
self.send_packet(PlayClientbound::UpdateEntityPosition {

minecraft-server/src/world/change.rs

+9-6
Original file line numberDiff line numberDiff line change
@@ -38,13 +38,10 @@ pub enum WorldChange {
3838
},
3939
}
4040

41+
#[derive(Clone, Copy)]
4142
pub struct EntityChanges(u8);
4243

4344
impl EntityChanges {
44-
pub const fn other() -> EntityChanges {
45-
EntityChanges(0)
46-
}
47-
4845
pub const fn nothing() -> EntityChanges {
4946
EntityChanges(0)
5047
}
@@ -61,7 +58,7 @@ impl EntityChanges {
6158
EntityChanges(1 << 2)
6259
}
6360

64-
pub const fn metadata() -> EntityChanges {
61+
pub const fn other() -> EntityChanges {
6562
EntityChanges(1 << 3)
6663
}
6764

@@ -81,7 +78,7 @@ impl EntityChanges {
8178
self.0 & (1 << 2) != 0
8279
}
8380

84-
pub const fn metadata_changed(&self) -> bool {
81+
pub const fn other_changed(&self) -> bool {
8582
self.0 & (1 << 3) != 0
8683
}
8784
}
@@ -99,3 +96,9 @@ impl std::ops::AddAssign<EntityChanges> for EntityChanges {
9996
self.0 |= rhs.0;
10097
}
10198
}
99+
100+
impl Default for EntityChanges {
101+
fn default() -> EntityChanges {
102+
EntityChanges::nothing()
103+
}
104+
}

minecraft-server/src/world/ecs.rs

+16-2
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ pub struct Entities {
88
uuid_counter: std::sync::atomic::AtomicU64,
99
tasks: RwLock<HashMap<Eid, EntityTask>>,
1010
entities: RwLock<HashMap<Eid, AnyEntity>>,
11+
change_set: RwLock<HashMap<Eid, EntityChanges>>,
1112

1213
/// A hashmap of chunk positions to get a list of entities in a chunk
1314
chunks: RwLock<HashMap<ChunkColumnPosition, HashSet<Eid>>>,
@@ -21,6 +22,7 @@ impl Entities {
2122
uuid_counter: std::sync::atomic::AtomicU64::new(0),
2223
tasks: RwLock::new(HashMap::new()),
2324
entities: RwLock::new(HashMap::new()),
25+
change_set: RwLock::new(HashMap::new()),
2426
chunks: RwLock::new(HashMap::new()),
2527
uuids: RwLock::new(HashMap::new()),
2628
}
@@ -48,22 +50,34 @@ impl Entities {
4850
results
4951
}
5052

53+
// TODO don't return [EntityChanges]
5154
/// Mutate an entity through a closure
52-
pub(super) async fn mutate_entity<R>(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option<(R, EntityChanges)> {
55+
pub(super) async fn mutate_entity<R>(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option<(R, EntityChanges)> {
5356
let mut entities = self.entities.write().await;
5457

5558
if let Some(entity) = entities.get_mut(&eid) {
5659
let prev_position = entity.as_entity().position.clone();
60+
let prev_velocity = entity.as_entity().velocity.clone();
61+
let prev_pitch = entity.as_entity().pitch;
5762
let r = mutator(entity);
63+
let mut changes = EntityChanges::other();
64+
if prev_velocity != entity.as_entity().velocity {
65+
changes += EntityChanges::velocity();
66+
}
67+
if prev_pitch != entity.as_entity().pitch { // TODO: detect yaw changes
68+
changes += EntityChanges::pitch();
69+
}
5870
if prev_position != entity.as_entity().position {
71+
changes += EntityChanges::position();
5972
let old_chunk = prev_position.chunk_column();
6073
let new_chunk = entity.as_entity().position.chunk_column();
6174
drop(entities);
6275
let mut chunks = self.chunks.write().await;
6376
chunks.entry(old_chunk).and_modify(|set| { set.remove(&eid); }); // TODO: ensure it gets removed
6477
chunks.entry(new_chunk).or_insert(HashSet::new()).insert(eid);
6578
}
66-
Some(r)
79+
*self.change_set.write().await.entry(eid).or_default() += changes;
80+
Some((r, changes))
6781
} else {
6882
None
6983
}

minecraft-server/src/world/mod.rs

+1-4
Original file line numberDiff line numberDiff line change
@@ -111,7 +111,7 @@ impl World {
111111
}
112112

113113
// TODO: add version that doesn't notify modified entity
114-
pub async fn mutate_entity<R>(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> (R, EntityChanges)) -> Option<R> {
114+
pub async fn mutate_entity<R>(&self, eid: Eid, mutator: impl FnOnce(&mut AnyEntity) -> R) -> Option<R> {
115115
// TODO: change events
116116
match self.entities.mutate_entity(eid, mutator).await {
117117
Some((r, changes)) => {
@@ -139,9 +139,6 @@ impl World {
139139
head_yaw,
140140
}).await;
141141
}
142-
if changes.metadata_changed() {
143-
todo!()
144-
}
145142
Some(r)
146143
},
147144
None => None,

0 commit comments

Comments
 (0)