Actually fix region removal panic, update fuzzy chunk location, sync entity removal when unloading chunks, region size constant tweak

This commit is contained in:
Imbris 2019-10-06 21:00:47 -04:00 committed by Imbris
parent ab7740f378
commit 53ddbec527
3 changed files with 24 additions and 19 deletions

View File

@ -503,7 +503,9 @@ impl Client {
}
ServerMsg::DeleteEntity(entity) => {
if let Some(entity) = self.state.ecs().entity_from_uid(entity) {
let _ = self.state.ecs_mut().delete_entity(entity);
if entity != self.entity {
let _ = self.state.ecs_mut().delete_entity(entity);
}
}
}
ServerMsg::EntityPos { entity, pos } => {

View File

@ -54,11 +54,10 @@ impl Region {
/// In units of blocks (i.e. world pos)
/// Used to prevent rapid switching of entities between regions
pub const TETHER_LENGTH: u32 = 16;
/// Region Size in blocks
pub const REGION_SIZE: u32 = 16 * 32;
/// Shift between region to world pos
/// TODO: don't use this :P
/// Bitshift between region and world pos, i.e. log2(REGION_SIZE)
const REGION_LOG2: u8 = 9;
/// Region Size in blocks
pub const REGION_SIZE: u32 = 1 << REGION_LOG2;
/// Offsets to iterate though neighbors
/// Counter-clockwise order
const NEIGHBOR_OFFSETS: [Vec2<i32>; 8] = [
@ -166,14 +165,9 @@ impl RegionMap {
// Remove region if it is empty
// TODO: distribute this betweeen ticks
if self
.regions
.get_index(i)
.map(|(_, v)| v)
.unwrap()
.removable()
{
regions_to_remove.push(i);
let (key, region) = self.regions.get_index(i).unwrap();
if region.removable() {
regions_to_remove.push(*key);
}
}
@ -193,12 +187,11 @@ impl RegionMap {
.remove(id, None);
self.tracked_entities.remove(id);
}
for index in regions_to_remove {
let (k, r) = self.regions.get_index(index).unwrap();
for key in regions_to_remove.into_iter() {
// Check that the region is still removable
if r.removable() {
if self.regions.get(&key).unwrap().removable() {
// Note we have to use key's here since the index can change when others are removed
self.remove(*k);
self.remove(key);
}
}
}

View File

@ -1456,6 +1456,8 @@ impl Server {
{
let chunk = (Vec2::<f32>::from(pos.0))
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32);
// Only update regions when moving to a new chunk
// uses a fuzzy border to prevent rapid triggering when moving along chunk boundaries
if chunk != subscription.fuzzy_chunk
&& (subscription
.fuzzy_chunk
@ -1468,8 +1470,14 @@ impl Server {
})
.reduce_or()
{
// Update current chunk
subscription.fuzzy_chunk = (Vec2::<f32>::from(pos.0))
.map2(TerrainChunkSize::RECT_SIZE, |e, sz| e as i32 / sz as i32);
// Use the largest side length as our chunk size
let chunk_size = TerrainChunkSize::RECT_SIZE.reduce_max() as f32;
// Iterate through currently subscribed regions
for key in &subscription.regions {
// Check if the region is not within range anymore
if !region_in_vd(
*key,
pos.0,
@ -1477,15 +1485,17 @@ impl Server {
+ (client::CHUNK_FUZZ as f32 + client::REGION_FUZZ as f32 + chunk_size)
* 2.0f32.sqrt(),
) {
// Add to the list of regions to remove
regions_to_remove.push(*key);
}
}
let mut client = clients.get_mut(&entity);
// Iterate through regions to remove
for key in regions_to_remove.drain(..) {
// Remove region from this clients set of subscribed regions
subscription.regions.remove(&key);
// Inform the client to delete these entities
// Tell the client to delete the entities in that region if it exists in the RegionMap
if let (Some(ref mut client), Some(region)) =
(&mut client, ecs.read_resource::<RegionMap>().get(key))
{