Added chunk deletion

Former-commit-id: 63c29e43c4dc28097aaf4e0ff72977c7db5cc28f
This commit is contained in:
Joshua Barretto 2019-04-25 20:08:26 +01:00
parent f136a63f69
commit 5e38eee8d4
3 changed files with 71 additions and 22 deletions

View File

@ -146,10 +146,8 @@ impl Client {
// Handle new messages from the server
frontend_events.append(&mut self.handle_new_messages()?);
self.state.terrain().iter().for_each(|(k, _)| {
//println!("Chunk at {:?}", k);
});
// Pass character control from frontend input to the player's entity
// TODO: Only do this if the entity already has a Control component!
self.state.write_component(
self.entity,
comp::Control {
@ -186,16 +184,28 @@ impl Client {
}
}
// Request chunks from the server
if let Some(pos) = self
let pos = self
.state
.read_storage::<comp::phys::Pos>()
.get(self.entity)
{
.cloned();
if let Some(pos) = pos {
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
for i in chunk_pos.x - 1..chunk_pos.x + 1 {
for j in chunk_pos.y - 1..chunk_pos.y + 1 {
// Remove chunks that are too far from the player
let mut chunks_to_remove = Vec::new();
self.state.terrain().iter().for_each(|(k, _)| {
if (chunk_pos - k).map(|e| e.abs()).reduce_max() > 3 {
chunks_to_remove.push(k);
}
});
for key in chunks_to_remove {
self.state.remove_chunk(key);
}
// Request chunks from the server
for i in chunk_pos.x - 1..chunk_pos.x + 2 {
for j in chunk_pos.y - 1..chunk_pos.y + 2 {
for k in 0..2 {
let key = Vec3::new(i, j, k);
if self.state.terrain().get_key(key).is_none()

View File

@ -183,6 +183,17 @@ impl State {
}
}
/// Remove the chunk with the given key from this state's terrain, if it exists
pub fn remove_chunk(&mut self, key: Vec3<i32>) {
if self.ecs
.write_resource::<TerrainMap>()
.remove(key)
.is_some()
{
self.changes.removed_chunks.insert(key);
}
}
/// Execute a single tick, simulating the game state by the given duration.
pub fn tick(&mut self, dt: Duration) {
// Change the time accordingly

View File

@ -8,10 +8,20 @@ pub mod input;
// Reexports
pub use crate::{error::Error, input::Input};
use crate::{
client::{Client, Clients},
cmd::CHAT_COMMANDS,
use std::{
collections::HashSet,
net::SocketAddr,
sync::mpsc,
time::Duration,
i32,
};
use specs::{
join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
Entity as EcsEntity,
};
use threadpool::ThreadPool;
use vek::*;
use world::World;
use common::{
comp,
comp::character::Animation,
@ -20,14 +30,10 @@ use common::{
state::{State, Uid},
terrain::TerrainChunk,
};
use specs::{
join::Join, saveload::MarkedBuilder, world::EntityBuilder as EcsEntityBuilder, Builder,
Entity as EcsEntity,
use crate::{
client::{Client, Clients},
cmd::CHAT_COMMANDS,
};
use std::{collections::HashSet, net::SocketAddr, sync::mpsc, time::Duration};
use threadpool::ThreadPool;
use vek::*;
use world::World;
const CLIENT_TIMEOUT: f64 = 20.0; // Seconds
@ -187,9 +193,7 @@ impl Server {
&self.state.ecs().entities(),
&self.state.ecs().read_storage::<comp::Player>(),
&self.state.ecs().read_storage::<comp::phys::Pos>(),
)
.join()
{
).join() {
// TODO: Distance check
// if self.state.terrain().key_pos(key)
@ -200,6 +204,30 @@ impl Server {
}
self.state.insert_chunk(key, chunk);
self.pending_chunks.remove(&key);
}
// Remove chunks that are too far from players
let mut chunks_to_remove = Vec::new();
self.state.terrain().iter().for_each(|(k, _)| {
let mut min_dist = i32::MAX;
// For each player with a position, calculate the distance
for (_, pos) in (
&self.state.ecs().read_storage::<comp::Player>(),
&self.state.ecs().read_storage::<comp::phys::Pos>(),
).join() {
let chunk_pos = self.state.terrain().pos_key(pos.0.map(|e| e as i32));
let dist = (chunk_pos - k).map(|e| e.abs()).reduce_max();
min_dist = min_dist.min(dist);
}
if min_dist > 3 {
chunks_to_remove.push(k);
}
});
for key in chunks_to_remove {
self.state.remove_chunk(key);
}
// Synchronise clients with the new state of the world