mirror of
https://github.com/italicsjenga/valence.git
synced 2024-12-23 22:41:30 +11:00
Improve chunks API
This commit is contained in:
parent
e27144bc01
commit
55cb595740
|
@ -170,7 +170,7 @@ impl Config for Game {
|
|||
|
||||
// Generate chunk data for chunks created this tick.
|
||||
world.chunks.par_iter_mut().for_each(|(pos, chunk)| {
|
||||
if chunk.created_tick() != server.shared.current_tick() {
|
||||
if !chunk.created_this_tick() {
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
57
src/chunk.rs
57
src/chunk.rs
|
@ -22,7 +22,6 @@ use crate::protocol_inner::packets::s2c::play::{
|
|||
};
|
||||
use crate::protocol_inner::{Encode, Nbt, VarInt, VarLong};
|
||||
use crate::server::SharedServer;
|
||||
use crate::Ticks;
|
||||
|
||||
/// A container for all [`Chunks`]s in a [`World`](crate::world::World).
|
||||
pub struct Chunks<C: Config> {
|
||||
|
@ -32,10 +31,7 @@ pub struct Chunks<C: Config> {
|
|||
}
|
||||
|
||||
impl<C: Config> Chunks<C> {
|
||||
pub(crate) fn new(
|
||||
shared: SharedServer<C>,
|
||||
dimension: DimensionId,
|
||||
) -> Self {
|
||||
pub(crate) fn new(shared: SharedServer<C>, dimension: DimensionId) -> Self {
|
||||
Self {
|
||||
chunks: HashMap::new(),
|
||||
shared,
|
||||
|
@ -56,12 +52,7 @@ impl<C: Config> Chunks<C> {
|
|||
pub fn insert(&mut self, pos: impl Into<ChunkPos>, state: C::ChunkState) -> &mut Chunk<C> {
|
||||
let section_count = (self.shared.dimension(self.dimension).height / 16) as u32;
|
||||
let biome_registry_len = self.shared.biomes().len();
|
||||
let chunk = Chunk::new(
|
||||
section_count,
|
||||
self.shared.current_tick(),
|
||||
biome_registry_len,
|
||||
state,
|
||||
);
|
||||
let chunk = Chunk::new(section_count, biome_registry_len, state);
|
||||
|
||||
match self.chunks.entry(pos.into()) {
|
||||
Entry::Occupied(mut oe) => {
|
||||
|
@ -194,6 +185,27 @@ impl<C: Config> Chunks<C> {
|
|||
|
||||
false
|
||||
}
|
||||
|
||||
/// Apply chunk modifications to only the chunks that were created this
|
||||
/// tick.
|
||||
pub(crate) fn update_created_this_tick(&mut self) {
|
||||
let biome_registry_len = self.shared.biomes().len();
|
||||
self.chunks.par_iter_mut().for_each(|(_, chunk)| {
|
||||
if chunk.created_this_tick() {
|
||||
chunk.apply_modifications(biome_registry_len);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/// Apply chunk modifications to all chunks and clear the created_this_tick
|
||||
/// flag.
|
||||
pub(crate) fn update(&mut self) {
|
||||
let biome_registry_len = self.shared.biomes().len();
|
||||
self.chunks.par_iter_mut().for_each(|(_, chunk)| {
|
||||
chunk.apply_modifications(biome_registry_len);
|
||||
chunk.created_this_tick = false;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// A chunk is a 16x16-block segment of a world with a height determined by the
|
||||
|
@ -208,16 +220,11 @@ pub struct Chunk<C: Config> {
|
|||
// TODO block_entities: HashMap<u32, BlockEntity>,
|
||||
/// The MOTION_BLOCKING heightmap
|
||||
heightmap: Vec<i64>,
|
||||
created_tick: Ticks,
|
||||
created_this_tick: bool,
|
||||
}
|
||||
|
||||
impl<C: Config> Chunk<C> {
|
||||
pub(crate) fn new(
|
||||
section_count: u32,
|
||||
current_tick: Ticks,
|
||||
biome_registry_len: usize,
|
||||
data: C::ChunkState,
|
||||
) -> Self {
|
||||
fn new(section_count: u32, biome_registry_len: usize, data: C::ChunkState) -> Self {
|
||||
let sect = ChunkSection {
|
||||
blocks: [BlockState::AIR.to_raw(); 4096],
|
||||
modified_count: 1, // Must be >0 so the chunk is initialized.
|
||||
|
@ -229,15 +236,15 @@ impl<C: Config> Chunk<C> {
|
|||
state: data,
|
||||
sections: vec![sect; section_count as usize].into(),
|
||||
heightmap: Vec::new(),
|
||||
created_tick: current_tick,
|
||||
created_this_tick: true,
|
||||
};
|
||||
|
||||
chunk.apply_modifications(biome_registry_len);
|
||||
chunk
|
||||
}
|
||||
|
||||
pub fn created_tick(&self) -> Ticks {
|
||||
self.created_tick
|
||||
pub fn created_this_tick(&self) -> bool {
|
||||
self.created_this_tick
|
||||
}
|
||||
|
||||
pub fn height(&self) -> usize {
|
||||
|
@ -327,7 +334,7 @@ impl<C: Config> Chunk<C> {
|
|||
&self,
|
||||
pos: ChunkPos,
|
||||
min_y: i32,
|
||||
mut packet: impl FnMut(BlockChangePacket),
|
||||
mut push_packet: impl FnMut(BlockChangePacket),
|
||||
) {
|
||||
for (sect_y, sect) in self.sections.iter().enumerate() {
|
||||
if sect.modified_count == 1 {
|
||||
|
@ -342,7 +349,7 @@ impl<C: Config> Chunk<C> {
|
|||
let global_y = sect_y as i32 * 16 + (idx / (16 * 16)) as i32 + min_y;
|
||||
let global_z = pos.z * 16 + (idx / 16 % 16) as i32;
|
||||
|
||||
packet(BlockChangePacket::Single(BlockUpdate {
|
||||
push_packet(BlockChangePacket::Single(BlockUpdate {
|
||||
location: BlockPos::new(global_x, global_y, global_z),
|
||||
block_id: VarInt((block & BLOCK_STATE_MASK).into()),
|
||||
}));
|
||||
|
@ -368,7 +375,7 @@ impl<C: Config> Chunk<C> {
|
|||
| (pos.z as i64 & 0x3fffff) << 20
|
||||
| (sect_y as i64 + min_y.div_euclid(16) as i64) & 0xfffff;
|
||||
|
||||
packet(BlockChangePacket::Multi(ChunkSectionUpdate {
|
||||
push_packet(BlockChangePacket::Multi(ChunkSectionUpdate {
|
||||
chunk_section_position,
|
||||
invert_trust_edges: false,
|
||||
blocks,
|
||||
|
@ -377,7 +384,7 @@ impl<C: Config> Chunk<C> {
|
|||
}
|
||||
}
|
||||
|
||||
pub(crate) fn apply_modifications(&mut self, biome_registry_len: usize) {
|
||||
fn apply_modifications(&mut self, biome_registry_len: usize) {
|
||||
let mut any_modified = false;
|
||||
|
||||
for sect in self.sections.iter_mut() {
|
||||
|
|
|
@ -1064,8 +1064,6 @@ impl<C: Config> Client<C> {
|
|||
}
|
||||
}
|
||||
|
||||
let view_dist = self.view_distance();
|
||||
|
||||
let center = ChunkPos::at(self.position.x, self.position.z);
|
||||
|
||||
// Send the update view position packet if the client changes the chunk section
|
||||
|
@ -1092,8 +1090,8 @@ impl<C: Config> Client<C> {
|
|||
let cache = 2;
|
||||
|
||||
if let Some(chunk) = world.chunks.get(pos) {
|
||||
if is_chunk_in_view_distance(center, pos, view_dist + cache)
|
||||
&& chunk.created_tick() != current_tick
|
||||
if is_chunk_in_view_distance(center, pos, self.view_distance + cache)
|
||||
&& !chunk.created_this_tick()
|
||||
{
|
||||
chunk.block_change_packets(pos, dimension.min_y, |pkt| {
|
||||
send_packet(&mut self.send, pkt)
|
||||
|
@ -1113,7 +1111,7 @@ impl<C: Config> Client<C> {
|
|||
});
|
||||
|
||||
// Load new chunks within the view distance
|
||||
for pos in chunks_in_view_distance(center, view_dist) {
|
||||
for pos in chunks_in_view_distance(center, self.view_distance) {
|
||||
if let Some(chunk) = world.chunks.get(pos) {
|
||||
if self.loaded_chunks.insert(pos) {
|
||||
self.send_packet(chunk.chunk_data_packet(pos));
|
||||
|
@ -1188,7 +1186,7 @@ impl<C: Config> Client<C> {
|
|||
self.loaded_entities.retain(|&id| {
|
||||
if let Some(entity) = entities.get(id) {
|
||||
debug_assert!(entity.kind() != EntityKind::Marker);
|
||||
if self.position.distance(entity.position()) <= view_dist as f64 * 16.0 {
|
||||
if self.position.distance(entity.position()) <= self.view_distance as f64 * 16.0 {
|
||||
if let Some(meta) = entity.updated_tracked_data_packet(id) {
|
||||
send_packet(&mut self.send, meta);
|
||||
}
|
||||
|
@ -1300,6 +1298,7 @@ impl<C: Config> Client<C> {
|
|||
|
||||
// Spawn new entities within the view distance.
|
||||
let pos = self.position();
|
||||
let view_dist = self.view_distance;
|
||||
world.spatial_index.query::<_, _, ()>(
|
||||
|bb| bb.projected_point(pos).distance(pos) <= view_dist as f64 * 16.0,
|
||||
|id, _| {
|
||||
|
|
|
@ -436,14 +436,11 @@ fn do_update_loop<C: Config>(server: &mut Server<C>) -> ShutdownResult {
|
|||
shared.config().update(server);
|
||||
|
||||
server.worlds.par_iter_mut().for_each(|(id, world)| {
|
||||
world.chunks.par_iter_mut().for_each(|(_, chunk)| {
|
||||
if chunk.created_tick() == shared.current_tick() {
|
||||
// Chunks created this tick can have their changes applied immediately because
|
||||
// they have not been observed by clients yet. Clients will not have to be sent
|
||||
// the block change packet in this case.
|
||||
chunk.apply_modifications(server.shared.biomes().len());
|
||||
}
|
||||
});
|
||||
// Chunks created this tick can have their changes applied immediately because
|
||||
// they have not been observed by clients yet. Clients will not have to be sent
|
||||
// the block change packet in this case, since the changes are applied before we
|
||||
// update clients.
|
||||
world.chunks.update_created_this_tick();
|
||||
|
||||
world.spatial_index.update(&server.entities, id);
|
||||
});
|
||||
|
@ -460,9 +457,7 @@ fn do_update_loop<C: Config>(server: &mut Server<C>) -> ShutdownResult {
|
|||
server.entities.update();
|
||||
|
||||
server.worlds.par_iter_mut().for_each(|(_, world)| {
|
||||
world.chunks.par_iter_mut().for_each(|(_, chunk)| {
|
||||
chunk.apply_modifications(server.shared.biomes().len());
|
||||
});
|
||||
world.chunks.update();
|
||||
});
|
||||
|
||||
server.player_lists.update();
|
||||
|
|
Loading…
Reference in a new issue