Skip to content

Commit ac6ac18

Browse files
feat: metadata overhall (#603)
1 parent da94465 commit ac6ac18

File tree

18 files changed

+701
-349
lines changed

18 files changed

+701
-349
lines changed

Cargo.lock

Lines changed: 1 addition & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ fastrand = '2.1.0'
5858
futures-util = '0.3.31'
5959
glam = '0.29.0'
6060
heapless = '0.8.0'
61+
heck = "0.5.0"
6162
heed = '0.20.5'
6263
hex = '0.4.3'
6364
itertools = '0.13.0'

crates/hyperion/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@ base64 = {workspace = true}
2424
geometry = {workspace = true}
2525
bitfield-struct = {workspace = true}
2626
bitvec = {workspace = true}
27+
heck = {workspace = true}
2728
papaya = {workspace = true}
2829
bumpalo = {workspace = true}
2930
bvh-region = {workspace = true}

crates/hyperion/src/egress/player_join/mod.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@ use crate::{
3333
simulation::{
3434
Comms, Name, Position, Uuid, Yaw,
3535
command::{Command, ROOT_COMMAND, get_command_packet},
36-
metadata::{EntityFlags, MetadataBuilder},
36+
metadata::{MetadataChanges, entity::EntityFlags},
3737
skin::PlayerSkin,
3838
util::registry_codec_raw,
3939
},
@@ -239,7 +239,7 @@ pub fn player_join_world(
239239
// todo: could also be helped by denoting some packets as infallible for serialization
240240
let mut query_errors = Vec::new();
241241

242-
let mut metadata = MetadataBuilder::default();
242+
let mut metadata = MetadataChanges::default();
243243

244244
query
245245
.iter_stage(world)

crates/hyperion/src/egress/sync_entity_state.rs

Lines changed: 88 additions & 102 deletions
Original file line numberDiff line numberDiff line change
@@ -1,28 +1,23 @@
1-
use std::{borrow::Cow, cell::UnsafeCell};
1+
use std::borrow::Cow;
22

33
use anyhow::Context;
44
use flecs_ecs::prelude::*;
55
use glam::Vec3;
66
use hyperion_inventory::PlayerInventory;
77
use hyperion_utils::EntityExt;
88
use tracing::{error, info_span};
9-
use valence_ident::ident;
109
use valence_protocol::{
11-
ByteAngle, GameMode, RawBytes, VarInt, Velocity,
12-
game_mode::OptGameMode,
10+
ByteAngle, RawBytes, VarInt, Velocity,
1311
packets::{play, play::entity_equipment_update_s2c::EquipmentEntry},
1412
};
1513

1614
use crate::{
1715
Prev,
18-
egress::metadata::show_all,
19-
net::{Compose, NetworkStreamRef, agnostic},
16+
net::{Compose, NetworkStreamRef},
2017
simulation::{
21-
EntityReaction, Health, Pitch, Position, Xp, Yaw,
22-
animation::ActiveAnimation,
23-
metadata::{EntityFlags, MetadataBuilder, Pose},
18+
EntityReaction, Pitch, Position, Xp, Yaw, animation::ActiveAnimation,
19+
metadata::MetadataChanges,
2420
},
25-
storage::ThreadLocal,
2621
system_registry::{SYNC_ENTITY_POSITION, SystemId},
2722
util::TracingExt,
2823
};
@@ -34,13 +29,11 @@ impl Module for EntityStateSyncModule {
3429
fn module(world: &World) {
3530
let system_id = SYNC_ENTITY_POSITION;
3631

37-
let metadata: ThreadLocal<UnsafeCell<MetadataBuilder>> = ThreadLocal::new_defaults();
38-
3932
world
4033
.system_named::<(
4134
&Compose, // (0)
4235
&NetworkStreamRef, // (1)
43-
&mut Prev<Xp>, // (2)
36+
&mut (Prev, Xp), // (2)
4437
&mut Xp, // (3)
4538
)>("entity_xp_sync")
4639
.term_at(0u32)
@@ -62,7 +55,7 @@ impl Module for EntityStateSyncModule {
6255
let net = table.field_unchecked::<NetworkStreamRef>(1);
6356
let net = net.get(..).unwrap();
6457

65-
let mut prev_xp = table.field_unchecked::<Prev<Xp>>(2);
58+
let mut prev_xp = table.field_unchecked::<Xp>(2);
6659
let prev_xp = prev_xp.get_mut(..).unwrap();
6760
let prev_xp: &mut [u16] =
6861
core::slice::from_raw_parts_mut(prev_xp.as_mut_ptr().cast(), count);
@@ -104,6 +97,29 @@ impl Module for EntityStateSyncModule {
10497
}
10598
});
10699

100+
system!("entity_metadata_sync", world, &Compose($), &mut MetadataChanges)
101+
.multi_threaded()
102+
.kind::<flecs::pipeline::OnStore>()
103+
.tracing_each_entity(
104+
info_span!("entity_metadata_sync"),
105+
move |entity, (compose, metadata_changes)| {
106+
let world = entity.world();
107+
let entity_id = VarInt(entity.minecraft_id());
108+
109+
let metadata = metadata_changes.get_and_clear();
110+
111+
if let Some(view) = metadata {
112+
let pkt = play::EntityTrackerUpdateS2c {
113+
entity_id,
114+
tracked_values: RawBytes(&view),
115+
};
116+
117+
// todo(perf): do so locally
118+
compose.broadcast(&pkt, system_id).send(&world).unwrap();
119+
}
120+
},
121+
);
122+
107123
system!(
108124
"entity_state_sync",
109125
world,
@@ -115,12 +131,6 @@ impl Module for EntityStateSyncModule {
115131
&mut ActiveAnimation,
116132
&mut PlayerInventory,
117133
&mut EntityReaction,
118-
&mut Health,
119-
&mut Prev<Health>,
120-
&mut EntityFlags,
121-
&mut Prev<EntityFlags>,
122-
&mut Pose,
123-
&mut Prev<Pose>
124134
)
125135
.multi_threaded()
126136
.kind::<flecs::pipeline::OnStore>()
@@ -136,12 +146,6 @@ impl Module for EntityStateSyncModule {
136146
animation,
137147
inventory,
138148
reaction,
139-
health,
140-
Prev(prev_health),
141-
entity_flags,
142-
Prev(prev_entity_flags),
143-
pose,
144-
Prev(prev_pose),
145149
)| {
146150
let mut run = || {
147151
let entity_id = VarInt(entity.minecraft_id());
@@ -150,75 +154,67 @@ impl Module for EntityStateSyncModule {
150154
let io = *io;
151155

152156
let world = entity.world();
153-
let observer = unsafe { &mut *metadata.get(&world).get() };
154157

155158
let chunk_pos = position.to_chunk();
156159

157-
let pose_updated = *prev_pose != *pose;
158-
159-
if pose_updated {
160-
observer.encode(*pose);
161-
*prev_pose = *pose;
162-
}
163-
164-
let health_updated = *prev_health != *health;
165-
166-
if health_updated {
167-
let to = *health;
168-
let from = *prev_health;
169-
170-
observer.encode(*health);
171-
*prev_health = *health;
172-
173-
if to < from {
174-
let pkt = play::EntityDamageS2c {
175-
entity_id,
176-
source_type_id: VarInt::default(),
177-
source_cause_id: VarInt::default(),
178-
source_direct_id: VarInt::default(),
179-
source_pos: None,
180-
};
181-
182-
compose.broadcast_local(&pkt, chunk_pos, system_id).send(&world)?;
183-
184-
let packet = agnostic::sound(
185-
ident!("minecraft:entity.player.hurt"),
186-
**position,
187-
).build();
188-
189-
compose.broadcast_local(&packet, chunk_pos, system_id).send(&world)?;
190-
}
191-
192-
if *to == 0.0 {
193-
// send respawn packet
194-
let pkt = play::PlayerRespawnS2c {
195-
dimension_type_name: ident!("minecraft:overworld").into(),
196-
dimension_name: ident!("minecraft:overworld").into(),
197-
hashed_seed: 0,
198-
game_mode: GameMode::Survival,
199-
previous_game_mode: OptGameMode::default(),
200-
is_debug: false,
201-
is_flat: false,
202-
copy_metadata: false,
203-
last_death_location: None,
204-
portal_cooldown: VarInt::default(),
205-
};
206-
// position.position = PLAYER_SPAWN_POSITION;
207-
compose.unicast(&pkt, io, system_id, &world)?;
208-
209-
**health = 20.0;
210-
211-
let show_all = show_all(entity.minecraft_id());
212-
compose.unicast(show_all.borrow_packet(), io, system_id, &world)?;
213-
}
214-
}
215-
216-
let entity_flags_updated = *prev_entity_flags != *entity_flags;
217-
218-
if entity_flags_updated {
219-
observer.encode(*entity_flags);
220-
*prev_entity_flags = *entity_flags;
221-
}
160+
// let health_updated = *prev_health != *health;
161+
//
162+
// if health_updated {
163+
// let to = *health;
164+
// let from = *prev_health;
165+
//
166+
// observer.encode(*health);
167+
// *prev_health = *health;
168+
//
169+
// if to < from {
170+
// let pkt = play::EntityDamageS2c {
171+
// entity_id,
172+
// source_type_id: VarInt::default(),
173+
// source_cause_id: VarInt::default(),
174+
// source_direct_id: VarInt::default(),
175+
// source_pos: None,
176+
// };
177+
//
178+
// compose.broadcast_local(&pkt, chunk_pos, system_id).send(&world)?;
179+
//
180+
// let packet = agnostic::sound(
181+
// ident!("minecraft:entity.player.hurt"),
182+
// **position,
183+
// ).build();
184+
//
185+
// compose.broadcast_local(&packet, chunk_pos, system_id).send(&world)?;
186+
// }
187+
//
188+
// if *to == 0.0 {
189+
// // send respawn packet
190+
// let pkt = play::PlayerRespawnS2c {
191+
// dimension_type_name: ident!("minecraft:overworld").into(),
192+
// dimension_name: ident!("minecraft:overworld").into(),
193+
// hashed_seed: 0,
194+
// game_mode: GameMode::Survival,
195+
// previous_game_mode: OptGameMode::default(),
196+
// is_debug: false,
197+
// is_flat: false,
198+
// copy_metadata: false,
199+
// last_death_location: None,
200+
// portal_cooldown: VarInt::default(),
201+
// };
202+
// // position.position = PLAYER_SPAWN_POSITION;
203+
// compose.unicast(&pkt, io, system_id, &world)?;
204+
//
205+
// **health = 20.0;
206+
//
207+
// let show_all = show_all(entity.minecraft_id());
208+
// compose.unicast(show_all.borrow_packet(), io, system_id, &world)?;
209+
// }
210+
// }
211+
212+
// let entity_flags_updated = *prev_entity_flags != *entity_flags;
213+
214+
// if entity_flags_updated {
215+
// observer.encode(*entity_flags);
216+
// *prev_entity_flags = *entity_flags;
217+
// }
222218

223219
let pkt = play::EntityPositionS2c {
224220
entity_id,
@@ -269,16 +265,6 @@ impl Module for EntityStateSyncModule {
269265
reaction.velocity = Vec3::ZERO;
270266
}
271267

272-
273-
if let Some(view) = observer.get_and_clear() {
274-
let pkt = play::EntityTrackerUpdateS2c {
275-
entity_id,
276-
tracked_values: RawBytes(&view),
277-
};
278-
279-
compose.broadcast_local(&pkt, chunk_pos, system_id).send(&world)?;
280-
}
281-
282268
for pkt in animation.packets(entity_id) {
283269
compose
284270
.broadcast_local(&pkt, chunk_pos, system_id)

crates/hyperion/src/ingress/mod.rs

Lines changed: 19 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -25,12 +25,12 @@ use crate::{
2525
runtime::AsyncRuntime,
2626
simulation::{
2727
AiTargetable, ChunkPosition, Comms, ConfirmBlockSequences, EntityReaction, EntitySize,
28-
Health, IgnMap, ImmuneStatus, Name, PacketState, Pitch, Player, Position, StreamLookup,
29-
Uuid, Xp, Yaw,
28+
IgnMap, ImmuneStatus, Name, PacketState, Pitch, Player, Position, StreamLookup, Uuid, Xp,
29+
Yaw,
3030
animation::ActiveAnimation,
3131
blocks::Blocks,
3232
handlers::PacketSwitchQuery,
33-
metadata::{EntityFlags, Pose},
33+
metadata::{MetadataPrefabs, Pose},
3434
skin::PlayerSkin,
3535
},
3636
storage::{Events, GlobalEventHandlers, PlayerJoinServer, SkinHandler},
@@ -160,23 +160,22 @@ fn process_login(
160160

161161
ign_map.insert(username.clone(), entity.id(), world);
162162

163-
entity
164-
.set(Name::from(username))
165-
.add::<AiTargetable>()
166-
.set(ImmuneStatus::default())
167-
.set(Uuid::from(uuid))
168-
.set(Prev(Health::default()))
169-
.add::<Health>()
170-
.set(Prev(Xp::default()))
171-
.add::<Xp>()
172-
.set(Prev(EntityFlags::default()))
173-
.set(EntityFlags::default())
174-
.set(Prev(Pose::default()))
175-
.add::<Pose>()
176-
.add::<ChunkSendQueue>()
177-
.add::<EntityReaction>()
178-
.set(ChunkPosition::null())
179-
.set(EntityReaction::default());
163+
world.get::<&MetadataPrefabs>(|prefabs| {
164+
entity
165+
.is_a_id(prefabs.player_base)
166+
.set(Name::from(username))
167+
.add::<AiTargetable>()
168+
.set(ImmuneStatus::default())
169+
.set(Uuid::from(uuid))
170+
.add::<Xp>()
171+
.add::<Pose>()
172+
.set_pair::<Prev, _>(Xp::default())
173+
.set_pair::<Prev, _>(Pose::default())
174+
.add::<ChunkSendQueue>()
175+
.add::<EntityReaction>()
176+
.set(ChunkPosition::null())
177+
.set(EntityReaction::default());
178+
});
180179

181180
compose.io_buf().set_receive_broadcasts(stream_id, world);
182181

0 commit comments

Comments
 (0)