fix ewext test and make some code nicer

This commit is contained in:
bgkillas 2025-08-30 16:55:47 -04:00
parent b39be102a7
commit f4f2020f87
2 changed files with 81 additions and 77 deletions

View file

@ -28,8 +28,8 @@ impl Module for WorldSync {
.filter_map(|i| { .filter_map(|i| {
let dx = i % 3; let dx = i % 3;
let dy = i / 3; let dy = i / 3;
let cx = x as i32 / CHUNK_SIZE as i32 - 1 + dx; let cx = (x as i32).div_euclid(CHUNK_SIZE as i32) - 1 + dx;
let cy = y as i32 / CHUNK_SIZE as i32 - 1 + dy; let cy = (y as i32).div_euclid(CHUNK_SIZE as i32) - 1 + dy;
let mut update = NoitaWorldUpdate { let mut update = NoitaWorldUpdate {
coord: ChunkCoord(cx, cy), coord: ChunkCoord(cx, cy),
pixels: std::array::from_fn(|_| Pixel::default()), pixels: std::array::from_fn(|_| Pixel::default()),
@ -271,39 +271,48 @@ pub fn test_world() {
.chunk_map .chunk_map
.insert(1, 1, chunk); .insert(1, 1, chunk);
} }
let mut data = [Pixel::default(); CHUNK_SIZE * CHUNK_SIZE]; let mut upd = NoitaWorldUpdate {
coord: ChunkCoord(5, 5),
pixels: [Pixel::default(); CHUNK_SIZE * CHUNK_SIZE],
};
unsafe { unsafe {
assert!(pws.encode_world(ChunkCoord(5, 5), &mut data).is_ok()); assert!(pws.encode_world(&mut upd).is_ok());
} }
assert_eq!( assert_eq!(
data[0..128].iter().map(|a| a.mat()).collect::<Vec<_>>(), upd.pixels[0..128]
.iter()
.map(|a| a.mat())
.collect::<Vec<_>>(),
vec![0; 128] vec![0; 128]
); );
let tmr = std::time::Instant::now(); let tmr = std::time::Instant::now();
upd.coord = ChunkCoord(0, 0);
unsafe { unsafe {
assert!(pws.encode_world(ChunkCoord(0, 0), &mut data).is_ok()); assert!(pws.encode_world(&mut upd).is_ok());
} }
println!("{}", tmr.elapsed().as_nanos()); println!("{}", tmr.elapsed().as_nanos());
assert_eq!( assert_eq!(
data[0..128].iter().map(|a| a.mat()).collect::<Vec<_>>(), upd.pixels[0..128]
.iter()
.map(|a| a.mat())
.collect::<Vec<_>>(),
list[0..128].iter().map(|a| *a as u16).collect::<Vec<_>>() list[0..128].iter().map(|a| *a as u16).collect::<Vec<_>>()
); );
let tmr = std::time::Instant::now(); let tmr = std::time::Instant::now();
upd.coord = ChunkCoord(5, 5);
unsafe { unsafe {
assert!( assert!(pws.decode_world(upd.clone()).is_ok());
pws.decode_world(NoitaWorldUpdate {
coord: ChunkCoord(5, 5),
pixels: data
})
.is_ok()
);
} }
println!("{}", tmr.elapsed().as_nanos()); println!("{}", tmr.elapsed().as_nanos());
upd.coord = ChunkCoord(0, 0);
unsafe { unsafe {
assert!(pws.encode_world(ChunkCoord(0, 0), &mut data).is_ok()); assert!(pws.encode_world(&mut upd).is_ok());
} }
assert_eq!( assert_eq!(
data[0..128].iter().map(|a| a.mat()).collect::<Vec<_>>(), upd.pixels[0..128]
.iter()
.map(|a| a.mat())
.collect::<Vec<_>>(),
list[0..128].iter().map(|a| *a as u16).collect::<Vec<_>>() list[0..128].iter().map(|a| *a as u16).collect::<Vec<_>>()
); );
} }

View file

@ -68,7 +68,7 @@ pub(crate) enum WorldNetMessage {
// Tell how to update a chunk storage // Tell how to update a chunk storage
UpdateStorage { UpdateStorage {
chunk: ChunkCoord, chunk: ChunkCoord,
chunk_data: Option<ChunkData>, chunk_data: ChunkData,
world_num: u8, world_num: u8,
priority: Option<u8>, priority: Option<u8>,
}, },
@ -318,13 +318,7 @@ impl WorldManager {
self.chunk_storage.clone() self.chunk_storage.clone()
} }
fn chunk_updated_locally( fn update_world_info(&mut self, pos: Option<(i32, i32, i32, i32, bool)>, world_num: u8) {
&mut self,
chunk: ChunkCoord,
priority: u8,
pos: Option<(i32, i32, i32, i32, bool)>,
world_num: u8,
) -> Vec<(OmniPeerId, u8)> {
if let Some((px, py, cx, cy, is_not)) = pos { if let Some((px, py, cx, cy, is_not)) = pos {
self.my_pos = (px, py); self.my_pos = (px, py);
self.cam_pos = (cx, cy); self.cam_pos = (cx, cy);
@ -337,6 +331,9 @@ impl WorldManager {
self.world_num = world_num; self.world_num = world_num;
self.reset(); self.reset();
} }
}
fn chunk_updated_locally(&mut self, chunk: ChunkCoord, priority: u8) -> Vec<(OmniPeerId, u8)> {
let entry = self.chunk_state.entry(chunk).or_insert_with(|| { let entry = self.chunk_state.entry(chunk).or_insert_with(|| {
debug!("Created entry for {chunk:?}"); debug!("Created entry for {chunk:?}");
ChunkState::RequestAuthority { ChunkState::RequestAuthority {
@ -400,9 +397,6 @@ impl WorldManager {
new_authority, new_authority,
stop_sending, stop_sending,
} => { } => {
let Some(delta) = self.outbound_model.get_chunk_delta(chunk, false) else {
return Vec::new();
};
if *pri != priority { if *pri != priority {
*pri = priority; *pri = priority;
emit_queue.push(( emit_queue.push((
@ -429,6 +423,11 @@ impl WorldManager {
new_auth_got = true new_auth_got = true
} }
if take_auth { if take_auth {
let Some(delta) = self.outbound_model.get_chunk_delta(chunk, false)
else {
return Vec::new();
};
emit_queue.retain(|(a, _)| matches!(a, Destination::Host));
emit_queue.push(( emit_queue.push((
Destination::Peer(listener), Destination::Peer(listener),
WorldNetMessage::ListenUpdate { WorldNetMessage::ListenUpdate {
@ -437,7 +436,8 @@ impl WorldManager {
take_auth, take_auth,
}, },
)); ));
chunks_to_send = Vec::new() chunks_to_send = Vec::new();
break;
} else { } else {
chunks_to_send.push((listener, priority)); chunks_to_send.push((listener, priority));
} }
@ -712,15 +712,19 @@ impl WorldManager {
} }
} }
} }
WorldNetMessage::GetChunk { chunk, priority } => self.emit_msg( WorldNetMessage::GetChunk { chunk, priority } => {
Destination::Host, if let Some(chunk_data) = self.outbound_model.get_chunk_data(chunk) {
WorldNetMessage::UpdateStorage { self.emit_msg(
chunk, Destination::Host,
chunk_data: self.outbound_model.get_chunk_data(chunk), WorldNetMessage::UpdateStorage {
world_num: self.world_num, chunk,
priority: Some(priority), chunk_data,
}, world_num: self.world_num,
), priority: Some(priority),
},
)
}
}
WorldNetMessage::AskForAuthority { chunk, priority } => { WorldNetMessage::AskForAuthority { chunk, priority } => {
self.emit_msg( self.emit_msg(
Destination::Host, Destination::Host,
@ -786,12 +790,12 @@ impl WorldManager {
if let Some(chunk_data) = chunk_data { if let Some(chunk_data) = chunk_data {
self.inbound_model.apply_chunk_data(chunk, &chunk_data); self.inbound_model.apply_chunk_data(chunk, &chunk_data);
self.outbound_model.apply_chunk_data(chunk, &chunk_data); self.outbound_model.apply_chunk_data(chunk, &chunk_data);
} else { } else if let Some(chunk_data) = self.outbound_model.get_chunk_data(chunk) {
self.emit_msg( self.emit_msg(
Destination::Host, Destination::Host,
WorldNetMessage::UpdateStorage { WorldNetMessage::UpdateStorage {
chunk, chunk,
chunk_data: self.outbound_model.get_chunk_data(chunk), chunk_data,
world_num: self.world_num, world_num: self.world_num,
priority: None, priority: None,
}, },
@ -811,15 +815,11 @@ impl WorldManager {
if world_num != self.world_num { if world_num != self.world_num {
return; return;
} }
if let Some(chunk_data) = chunk_data { let _ = self.tx.send((chunk, chunk_data.clone()));
let _ = self.tx.send((chunk, chunk_data.clone())); self.chunk_storage.insert(chunk, chunk_data);
self.chunk_storage.insert(chunk, chunk_data); if let Some(p) = priority {
if let Some(p) = priority { self.cut_through_world_explosion_chunk(chunk);
self.cut_through_world_explosion_chunk(chunk); self.emit_got_authority(chunk, source, p)
self.emit_got_authority(chunk, source, p)
}
} else if priority.is_some() {
warn!("{} sent give auth without chunk", source)
} }
} }
WorldNetMessage::RelinquishAuthority { WorldNetMessage::RelinquishAuthority {
@ -1040,16 +1040,17 @@ impl WorldManager {
}, },
); );
self.chunk_state.insert(chunk, ChunkState::UnloadPending); self.chunk_state.insert(chunk, ChunkState::UnloadPending);
let chunk_data = self.outbound_model.get_chunk_data(chunk); if let Some(chunk_data) = self.outbound_model.get_chunk_data(chunk) {
self.emit_msg( self.emit_msg(
Destination::Host, Destination::Host,
WorldNetMessage::UpdateStorage { WorldNetMessage::UpdateStorage {
chunk, chunk,
chunk_data, chunk_data,
world_num: self.world_num, world_num: self.world_num,
priority: None, priority: None,
}, },
); );
}
} else { } else {
self.emit_msg( self.emit_msg(
Destination::Peer(source), Destination::Peer(source),
@ -3344,36 +3345,30 @@ impl WorldManager {
} }
} }
WorldSyncToProxy::End(pos, priority, world_num) => { WorldSyncToProxy::End(pos, priority, world_num) => {
let updated_chunks = self let updated_chunks = self.outbound_model.updated_chunks().clone();
.outbound_model
.updated_chunks()
.iter()
.copied()
.collect::<Vec<_>>();
self.current_update += 1; self.current_update += 1;
let chunks_to_send: Vec<Vec<(OmniPeerId, u8)>> = updated_chunks
.iter()
.map(|chunk| self.chunk_updated_locally(*chunk, priority, pos, world_num))
.collect();
let mut chunk_packet: HashMap<OmniPeerId, Vec<(ChunkDelta, u8)>> = HashMap::new(); let mut chunk_packet: HashMap<OmniPeerId, Vec<(ChunkDelta, u8)>> = HashMap::new();
for (chunk, who_sending) in updated_chunks.iter().zip(chunks_to_send.iter()) { self.update_world_info(pos, world_num);
let Some(delta) = self.outbound_model.get_chunk_delta(*chunk, false) else { for chunk in updated_chunks {
// who sending may be better to be after the let some
// but im too lazy to figure out for sure
let who_sending = self.chunk_updated_locally(chunk, priority);
let Some(delta) = self.outbound_model.get_chunk_delta(chunk, false) else {
continue; continue;
}; };
for (peer, pri) in who_sending { for (peer, pri) in who_sending {
chunk_packet chunk_packet
.entry(*peer) .entry(peer)
.or_default() .or_default()
.push((delta.clone(), *pri)); .push((delta.clone(), pri));
} }
} }
let mut emit_queue = Vec::new(); let emit_queue = chunk_packet.into_iter().map(|(peer, chunkpacket)| {
for (peer, chunkpacket) in chunk_packet { (
emit_queue.push((
Destination::Peer(peer), Destination::Peer(peer),
WorldNetMessage::ChunkPacket { chunkpacket }, WorldNetMessage::ChunkPacket { chunkpacket },
)); )
} });
for (dst, msg) in emit_queue { for (dst, msg) in emit_queue {
self.emit_msg(dst, msg) self.emit_msg(dst, msg)
} }