mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Added entity simulation to rtsim, reification, assimilation
This commit is contained in:
parent
2b5e09e32e
commit
99a881f349
2
Cargo.lock
generated
2
Cargo.lock
generated
@ -5402,10 +5402,12 @@ dependencies = [
|
||||
"portpicker",
|
||||
"prometheus",
|
||||
"rand 0.7.3",
|
||||
"rand_chacha 0.2.2",
|
||||
"ron",
|
||||
"scan_fmt",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"slab",
|
||||
"specs",
|
||||
"specs-idvs",
|
||||
"tiny_http",
|
||||
|
@ -179,12 +179,12 @@ void main() {
|
||||
// float reflected_light_point = /*length*/(diffuse_light_point.r) + f_light * point_shadow;
|
||||
// reflected_light += k_d * (diffuse_light_point + f_light * point_shadow * shade_frac) + specular_light_point;
|
||||
|
||||
float passthrough = /*pow(*/dot(cam_norm, -cam_to_frag/*view_dir*/)/*, 0.5)*/;
|
||||
float passthrough = clamp(dot(cam_norm, -cam_to_frag) * 1.0 - 0.2, 0, 1);
|
||||
float min_refl = min(emitted_light.r, min(emitted_light.g, emitted_light.b));
|
||||
|
||||
vec3 surf_color = illuminate(max_light, view_dir, water_color * /* fog_color * */emitted_light, /*surf_color * */water_color * reflected_light);
|
||||
// vec4 color = vec4(surf_color, passthrough * 1.0 / (1.0 + min_refl));// * (1.0 - /*log(1.0 + cam_attenuation)*//*cam_attenuation*/1.0 / (2.0 - log_cam)));
|
||||
vec4 color = mix(vec4(surf_color, 1.0), vec4(surf_color, 1.0 / (1.0 + /*diffuse_light*//*(f_light * point_shadow + point_light)*//*4.0 * reflected_light_point*/min_refl/* * 0.25*/)), passthrough);
|
||||
vec4 color = vec4(surf_color, (1.0 - passthrough) * 1.0 / (1.0 + min_refl));
|
||||
|
||||
tgt_color = color;
|
||||
}
|
||||
|
@ -1,4 +1,11 @@
|
||||
use crate::{character::CharacterId, comp, sync::Uid, util::Dir, Explosion};
|
||||
use crate::{
|
||||
character::CharacterId,
|
||||
sync::Uid,
|
||||
util::Dir,
|
||||
comp,
|
||||
Explosion,
|
||||
rtsim::RtSimEntity,
|
||||
};
|
||||
use comp::{
|
||||
item::{Item, Reagent},
|
||||
Ori, Pos,
|
||||
@ -96,6 +103,7 @@ pub enum ServerEvent {
|
||||
ExitIngame {
|
||||
entity: EcsEntity,
|
||||
},
|
||||
// TODO: to avoid breakage when adding new fields, perhaps have an `NpcBuilder` type?
|
||||
CreateNpc {
|
||||
pos: comp::Pos,
|
||||
stats: comp::Stats,
|
||||
@ -107,6 +115,7 @@ pub enum ServerEvent {
|
||||
scale: comp::Scale,
|
||||
home_chunk: Option<comp::HomeChunk>,
|
||||
drop_item: Option<Item>,
|
||||
rtsim_entity: Option<RtSimEntity>,
|
||||
},
|
||||
CreateWaypoint(Vec3<f32>),
|
||||
ClientDisconnect(EcsEntity),
|
||||
|
@ -40,6 +40,7 @@ pub mod path;
|
||||
pub mod ray;
|
||||
pub mod recipe;
|
||||
pub mod region;
|
||||
pub mod rtsim;
|
||||
pub mod spiral;
|
||||
pub mod state;
|
||||
pub mod states;
|
||||
|
15
common/src/rtsim.rs
Normal file
15
common/src/rtsim.rs
Normal file
@ -0,0 +1,15 @@
|
||||
// We'd like to not have this file in `common`, but sadly there are
|
||||
// things in `common` that require it (currently, `ServerEvent`). When
|
||||
// possible, this should be moved to the `rtsim` module in `server`.
|
||||
|
||||
use specs_idvs::IdvStorage;
|
||||
use specs::Component;
|
||||
|
||||
pub type RtSimId = usize;
|
||||
|
||||
#[derive(Copy, Clone, Debug)]
|
||||
pub struct RtSimEntity(pub RtSimId);
|
||||
|
||||
impl Component for RtSimEntity {
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
@ -18,7 +18,10 @@ pub use self::{
|
||||
use roots::find_roots_cubic;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
use crate::{vol::RectVolSize, volumes::vol_grid_2d::VolGrid2d};
|
||||
use crate::{
|
||||
vol::{RectVolSize, ReadVol},
|
||||
volumes::vol_grid_2d::VolGrid2d,
|
||||
};
|
||||
use vek::*;
|
||||
|
||||
// TerrainChunkSize
|
||||
@ -106,6 +109,27 @@ impl TerrainChunkMeta {
|
||||
pub type TerrainChunk = chonk::Chonk<Block, TerrainChunkSize, TerrainChunkMeta>;
|
||||
pub type TerrainGrid = VolGrid2d<TerrainChunk>;
|
||||
|
||||
impl TerrainGrid {
|
||||
/// Find a location suitable for spawning an entity near the given
|
||||
/// position (but in the same chunk).
|
||||
pub fn find_space(&self, pos: Vec3<i32>) -> Vec3<i32> {
|
||||
let mut z_diff = 0;
|
||||
for _ in 0..128 {
|
||||
let test_pos = pos + Vec3::unit_z() * z_diff;
|
||||
if (0..2)
|
||||
.all(|z| self
|
||||
.get(test_pos + Vec3::unit_z() * z)
|
||||
.map(|b| !b.is_solid())
|
||||
.unwrap_or(true))
|
||||
{
|
||||
return test_pos;
|
||||
}
|
||||
z_diff = -z_diff + if z_diff <= 0 { 1 } else { 0 };
|
||||
}
|
||||
pos
|
||||
}
|
||||
}
|
||||
|
||||
// Terrain helper functions used across multiple crates.
|
||||
|
||||
/// Computes the position Vec2 of a SimChunk from an index, where the index was
|
||||
|
@ -43,3 +43,5 @@ libsqlite3-sys = { version = "0.18", features = ["bundled"] }
|
||||
diesel = { version = "1.4.3", features = ["sqlite"] }
|
||||
diesel_migrations = "1.4.0"
|
||||
dotenv = "0.15.0"
|
||||
slab = "0.4"
|
||||
rand_chacha = "0.2"
|
||||
|
@ -7,6 +7,7 @@ use common::{
|
||||
},
|
||||
outcome::Outcome,
|
||||
util::Dir,
|
||||
rtsim::RtSimEntity,
|
||||
};
|
||||
use comp::group;
|
||||
use specs::{Builder, Entity as EcsEntity, WorldExt};
|
||||
@ -50,6 +51,7 @@ pub fn handle_create_npc(
|
||||
scale: Scale,
|
||||
drop_item: Option<Item>,
|
||||
home_chunk: Option<HomeChunk>,
|
||||
rtsim_entity: Option<RtSimEntity>,
|
||||
) {
|
||||
let group = match alignment {
|
||||
Alignment::Wild => None,
|
||||
@ -90,6 +92,12 @@ pub fn handle_create_npc(
|
||||
entity
|
||||
};
|
||||
|
||||
let entity = if let Some(rtsim_entity) = rtsim_entity {
|
||||
entity.with(rtsim_entity)
|
||||
} else {
|
||||
entity
|
||||
};
|
||||
|
||||
entity.build();
|
||||
}
|
||||
|
||||
|
@ -2,6 +2,7 @@ use crate::{
|
||||
client::Client,
|
||||
comp::{biped_large, quadruped_medium, quadruped_small, PhysicsState},
|
||||
Server, SpawnPoint, StateExt,
|
||||
rtsim::RtSim,
|
||||
};
|
||||
use common::{
|
||||
assets::Asset,
|
||||
@ -20,6 +21,7 @@ use common::{
|
||||
terrain::{Block, TerrainGrid},
|
||||
vol::ReadVol,
|
||||
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
|
||||
rtsim::RtSimEntity,
|
||||
};
|
||||
use comp::item::Reagent;
|
||||
use rand::prelude::*;
|
||||
@ -308,7 +310,7 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
}
|
||||
})();
|
||||
|
||||
if state
|
||||
let should_delete = if state
|
||||
.ecs()
|
||||
.write_storage::<Client>()
|
||||
.get_mut(entity)
|
||||
@ -339,6 +341,8 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
.ecs()
|
||||
.write_storage::<comp::CharacterState>()
|
||||
.insert(entity, comp::CharacterState::default());
|
||||
|
||||
false
|
||||
} else if state.ecs().read_storage::<comp::Agent>().contains(entity) {
|
||||
use specs::Builder;
|
||||
|
||||
@ -452,10 +456,16 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
|
||||
)
|
||||
}
|
||||
|
||||
let _ = state
|
||||
.delete_entity_recorded(entity)
|
||||
.map_err(|e| error!(?e, ?entity, "Failed to delete destroyed entity"));
|
||||
true
|
||||
} else {
|
||||
true
|
||||
};
|
||||
|
||||
if should_delete {
|
||||
if let Some(rtsim_entity) = state.ecs().read_storage::<RtSimEntity>().get(entity).copied() {
|
||||
state.ecs().write_resource::<RtSim>().destroy_entity(rtsim_entity.0);
|
||||
}
|
||||
|
||||
let _ = state
|
||||
.delete_entity_recorded(entity)
|
||||
.map_err(|e| error!(?e, ?entity, "Failed to delete destroyed entity"));
|
||||
|
@ -118,9 +118,10 @@ impl Server {
|
||||
scale,
|
||||
home_chunk,
|
||||
drop_item,
|
||||
rtsim_entity,
|
||||
} => handle_create_npc(
|
||||
self, pos, stats, health, loadout, body, agent, alignment, scale, drop_item,
|
||||
home_chunk,
|
||||
home_chunk, rtsim_entity,
|
||||
),
|
||||
ServerEvent::CreateWaypoint(pos) => handle_create_waypoint(self, pos),
|
||||
ServerEvent::ClientDisconnect(entity) => {
|
||||
|
@ -44,6 +44,7 @@ use crate::{
|
||||
presence::{Presence, RegionSubscription},
|
||||
state_ext::StateExt,
|
||||
sys::sentinel::{DeletedEntities, TrackedComps},
|
||||
rtsim::RtSim,
|
||||
};
|
||||
use common::{
|
||||
assets::Asset,
|
||||
@ -58,7 +59,8 @@ use common::{
|
||||
state::{State, TimeOfDay},
|
||||
sync::WorldSyncExt,
|
||||
terrain::TerrainChunkSize,
|
||||
vol::RectVolSize,
|
||||
vol::{ReadVol, RectVolSize},
|
||||
rtsim::RtSimEntity,
|
||||
};
|
||||
use futures_executor::block_on;
|
||||
use metrics::{PhysicsMetrics, ServerMetrics, StateTickMetrics, TickMetrics};
|
||||
@ -321,6 +323,10 @@ impl Server {
|
||||
// set the spawn point we calculated above
|
||||
state.ecs_mut().insert(SpawnPoint(spawn_point));
|
||||
|
||||
// Insert the world into the ECS (todo: Maybe not an Arc?)
|
||||
let world = Arc::new(world);
|
||||
state.ecs_mut().insert(world.clone());
|
||||
|
||||
// Set starting time for the server.
|
||||
state.ecs_mut().write_resource::<TimeOfDay>().0 = settings.start_time;
|
||||
|
||||
@ -359,7 +365,7 @@ impl Server {
|
||||
|
||||
let this = Self {
|
||||
state,
|
||||
world: Arc::new(world),
|
||||
world,
|
||||
index,
|
||||
map,
|
||||
|
||||
@ -550,6 +556,11 @@ impl Server {
|
||||
};
|
||||
|
||||
for entity in to_delete {
|
||||
// Assimilate entities that are part of the real-time world simulation
|
||||
if let Some(rtsim_entity) = self.state.ecs().read_storage::<RtSimEntity>().get(entity).copied() {
|
||||
self.state.ecs().write_resource::<RtSim>().assimilate_entity(rtsim_entity.0);
|
||||
}
|
||||
|
||||
if let Err(e) = self.state.delete_entity_recorded(entity) {
|
||||
error!(?e, "Failed to delete agent outside the terrain");
|
||||
}
|
||||
|
@ -10,7 +10,7 @@ impl<'a> System<'a> for Sys {
|
||||
);
|
||||
|
||||
fn run(&mut self, (server_event_bus, mut rtsim): Self::SystemData) {
|
||||
for chunk in std::mem::take(&mut rtsim.chunks_to_load) {
|
||||
for chunk in std::mem::take(&mut rtsim.world.chunks_to_load) {
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
|
@ -1,55 +1,86 @@
|
||||
mod load_chunks;
|
||||
mod unload_chunks;
|
||||
mod tick;
|
||||
|
||||
use vek::*;
|
||||
use world::util::Grid;
|
||||
use common::state::State;
|
||||
use specs::{DispatcherBuilder, Component, WorldExt};
|
||||
use common::{
|
||||
state::State,
|
||||
terrain::TerrainChunk,
|
||||
rtsim::{RtSimEntity, RtSimId},
|
||||
vol::RectRasterableVol,
|
||||
};
|
||||
use specs::{DispatcherBuilder, WorldExt};
|
||||
use specs_idvs::IdvStorage;
|
||||
|
||||
type EntityId = u64;
|
||||
use slab::Slab;
|
||||
use rand::prelude::*;
|
||||
|
||||
pub struct RtSim {
|
||||
chunks: Grid<Chunk>,
|
||||
chunks_to_load: Vec<Vec2<i32>>,
|
||||
chunks_to_unload: Vec<Vec2<i32>>,
|
||||
world: RtWorld,
|
||||
entities: Slab<Entity>,
|
||||
}
|
||||
|
||||
impl RtSim {
|
||||
pub fn new(world_chunk_size: Vec2<u32>) -> Self {
|
||||
Self {
|
||||
chunks: Grid::populate_from(world_chunk_size.map(|e| e as i32), |_| Chunk {
|
||||
is_loaded: false,
|
||||
}),
|
||||
chunks_to_load: Vec::new(),
|
||||
chunks_to_unload: Vec::new(),
|
||||
world: RtWorld {
|
||||
chunks: Grid::populate_from(world_chunk_size.map(|e| e as i32), |_| Chunk {
|
||||
is_loaded: false,
|
||||
}),
|
||||
chunks_to_load: Vec::new(),
|
||||
chunks_to_unload: Vec::new(),
|
||||
},
|
||||
entities: Slab::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hook_load_chunk(&mut self, key: Vec2<i32>) {
|
||||
if let Some(chunk) = self.chunks.get_mut(key) {
|
||||
if let Some(chunk) = self.world.chunks.get_mut(key) {
|
||||
if !chunk.is_loaded {
|
||||
chunk.is_loaded = true;
|
||||
self.chunks_to_load.push(key);
|
||||
self.world.chunks_to_load.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn hook_unload_chunk(&mut self, key: Vec2<i32>) {
|
||||
if let Some(chunk) = self.chunks.get_mut(key) {
|
||||
if let Some(chunk) = self.world.chunks.get_mut(key) {
|
||||
if chunk.is_loaded {
|
||||
chunk.is_loaded = false;
|
||||
self.chunks_to_unload.push(key);
|
||||
self.world.chunks_to_unload.push(key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn assimilate_entity(&mut self, entity: EntityId) {
|
||||
// TODO
|
||||
pub fn assimilate_entity(&mut self, entity: RtSimId) {
|
||||
tracing::info!("Assimilated rtsim entity {}", entity);
|
||||
self.entities.get_mut(entity).map(|e| e.is_loaded = false);
|
||||
}
|
||||
|
||||
pub fn update_entity(&mut self, entity: EntityId, pos: Vec3<f32>) {
|
||||
// TODO
|
||||
pub fn reify_entity(&mut self, entity: RtSimId) {
|
||||
tracing::info!("Reified rtsim entity {}", entity);
|
||||
self.entities.get_mut(entity).map(|e| e.is_loaded = true);
|
||||
}
|
||||
|
||||
pub fn update_entity(&mut self, entity: RtSimId, pos: Vec3<f32>) {
|
||||
self.entities.get_mut(entity).map(|e| e.pos = pos);
|
||||
}
|
||||
|
||||
pub fn destroy_entity(&mut self, entity: RtSimId) {
|
||||
tracing::info!("Destroyed rtsim entity {}", entity);
|
||||
self.entities.remove(entity);
|
||||
}
|
||||
}
|
||||
|
||||
pub struct RtWorld {
|
||||
chunks: Grid<Chunk>,
|
||||
chunks_to_load: Vec<Vec2<i32>>,
|
||||
chunks_to_unload: Vec<Vec2<i32>>,
|
||||
}
|
||||
|
||||
impl RtWorld {
|
||||
pub fn chunk_at(&self, pos: Vec2<f32>) -> Option<&Chunk> {
|
||||
self.chunks.get(pos.map2(TerrainChunk::RECT_SIZE, |e, sz| (e.floor() as i32).div_euclid(sz as i32)))
|
||||
}
|
||||
}
|
||||
|
||||
@ -57,22 +88,41 @@ pub struct Chunk {
|
||||
is_loaded: bool,
|
||||
}
|
||||
|
||||
pub struct RtSimEntity(EntityId);
|
||||
|
||||
impl Component for RtSimEntity {
|
||||
type Storage = IdvStorage<Self>;
|
||||
pub struct Entity {
|
||||
is_loaded: bool,
|
||||
pos: Vec3<f32>,
|
||||
seed: u32,
|
||||
}
|
||||
|
||||
const LOAD_CHUNK_SYS: &str = "rtsim_load_chunk_sys";
|
||||
const UNLOAD_CHUNK_SYS: &str = "rtsim_unload_chunk_sys";
|
||||
const TICK_SYS: &str = "rtsim_tick_sys";
|
||||
|
||||
pub fn add_server_systems(dispatch_builder: &mut DispatcherBuilder) {
|
||||
dispatch_builder.add(load_chunks::Sys, LOAD_CHUNK_SYS, &[]);
|
||||
dispatch_builder.add(unload_chunks::Sys, UNLOAD_CHUNK_SYS, &[]);
|
||||
dispatch_builder.add(load_chunks::Sys, LOAD_CHUNK_SYS, &[UNLOAD_CHUNK_SYS]);
|
||||
dispatch_builder.add(tick::Sys, TICK_SYS, &[LOAD_CHUNK_SYS, UNLOAD_CHUNK_SYS]);
|
||||
}
|
||||
|
||||
pub fn init(state: &mut State, world: &world::World) {
|
||||
state.ecs_mut().insert(RtSim::new(world.sim().get_size()));
|
||||
let mut rtsim = RtSim::new(world.sim().get_size());
|
||||
|
||||
for _ in 0..10 {
|
||||
let pos = Vec2::new(
|
||||
thread_rng().gen_range(0, rtsim.world.chunks.size().x * TerrainChunk::RECT_SIZE.x as i32),
|
||||
thread_rng().gen_range(0, rtsim.world.chunks.size().y * TerrainChunk::RECT_SIZE.y as i32),
|
||||
);
|
||||
|
||||
let id = rtsim.entities.insert(Entity {
|
||||
is_loaded: false,
|
||||
pos: Vec3::from(pos.map(|e| e as f32)),
|
||||
seed: thread_rng().gen(),
|
||||
});
|
||||
|
||||
tracing::info!("Spawned rtsim NPC {} at {:?}", id, pos);
|
||||
}
|
||||
|
||||
state.ecs_mut().insert(rtsim);
|
||||
state.ecs_mut().register::<RtSimEntity>();
|
||||
tracing::info!("Initiated real-time world simulation");
|
||||
}
|
||||
|
76
server/src/rtsim/tick.rs
Normal file
76
server/src/rtsim/tick.rs
Normal file
@ -0,0 +1,76 @@
|
||||
use super::*;
|
||||
use common::{
|
||||
event::{EventBus, ServerEvent},
|
||||
terrain::TerrainGrid,
|
||||
comp,
|
||||
};
|
||||
use specs::{Join, Read, ReadStorage, System, Write, WriteExpect, ReadExpect};
|
||||
use rand_chacha::ChaChaRng;
|
||||
use std::sync::Arc;
|
||||
|
||||
pub struct Sys;
|
||||
impl<'a> System<'a> for Sys {
|
||||
type SystemData = (
|
||||
Read<'a, EventBus<ServerEvent>>,
|
||||
WriteExpect<'a, RtSim>,
|
||||
ReadExpect<'a, TerrainGrid>,
|
||||
ReadExpect<'a, Arc<world::World>>,
|
||||
);
|
||||
|
||||
fn run(
|
||||
&mut self,
|
||||
(
|
||||
server_event_bus,
|
||||
mut rtsim,
|
||||
terrain,
|
||||
world,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let rtsim = &mut *rtsim;
|
||||
|
||||
// TODO: don't update all of them each tick
|
||||
let mut to_reify = Vec::new();
|
||||
for (id, entity) in rtsim.entities.iter_mut() {
|
||||
if entity.is_loaded {
|
||||
continue;
|
||||
} else if rtsim.world.chunk_at(entity.pos.xy()).map(|c| c.is_loaded).unwrap_or(false) {
|
||||
to_reify.push(id);
|
||||
}
|
||||
|
||||
if let Some(chunk) = world.sim().get_wpos(entity.pos.xy().map(|e| e.floor() as i32)) {
|
||||
entity.pos.z = chunk.alt;
|
||||
}
|
||||
}
|
||||
|
||||
let mut server_emitter = server_event_bus.emitter();
|
||||
for id in to_reify {
|
||||
rtsim.reify_entity(id);
|
||||
let entity = &rtsim.entities[id];
|
||||
let mut rng = ChaChaRng::from_seed([
|
||||
entity.seed.to_le_bytes()[0],
|
||||
entity.seed.to_le_bytes()[1],
|
||||
entity.seed.to_le_bytes()[2],
|
||||
entity.seed.to_le_bytes()[3],
|
||||
0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0,
|
||||
]);
|
||||
let species = *(&comp::humanoid::ALL_SPECIES).choose(&mut rng).unwrap();
|
||||
let body = comp::humanoid::Body::random_with(&mut rng, &species).into();
|
||||
server_emitter.emit(ServerEvent::CreateNpc {
|
||||
pos: comp::Pos(terrain.find_space(entity.pos.map(|e| e.floor() as i32)).map(|e| e as f32) + Vec3::new(0.5, 0.5, 0.0)),
|
||||
stats: comp::Stats::new("Rtsim Entity".to_string(), body),
|
||||
health: comp::Health::new(body, 10),
|
||||
loadout: comp::Loadout::default(),
|
||||
body,
|
||||
agent: None,
|
||||
alignment: comp::Alignment::Npc,
|
||||
scale: comp::Scale(1.0),
|
||||
drop_item: None,
|
||||
home_chunk: None,
|
||||
rtsim_entity: Some(RtSimEntity(id)),
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
@ -28,27 +28,10 @@ impl<'a> System<'a> for Sys {
|
||||
positions,
|
||||
): Self::SystemData,
|
||||
) {
|
||||
let chunks = std::mem::take(&mut rtsim.chunks_to_unload);
|
||||
|
||||
for (entity, rtsim_entity, pos) in (
|
||||
&entities,
|
||||
&rtsim_entities,
|
||||
&positions,
|
||||
).join() {
|
||||
let key = terrain_grid.pos_key(pos.0.map(|e| e.floor() as i32));
|
||||
|
||||
if terrain_grid.get_key(key).is_some() {
|
||||
break;
|
||||
} else if chunks.contains(&key) {
|
||||
// Assimilate the entity back into the simulation
|
||||
rtsim.assimilate_entity(rtsim_entity.0);
|
||||
}
|
||||
|
||||
rtsim.update_entity(rtsim_entity.0, pos.0);
|
||||
}
|
||||
let chunks = std::mem::take(&mut rtsim.world.chunks_to_unload);
|
||||
|
||||
for chunk in chunks {
|
||||
|
||||
// TODO
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -198,6 +198,7 @@ impl<'a> System<'a> for Sys {
|
||||
scale: comp::Scale(scale),
|
||||
home_chunk: Some(comp::HomeChunk(key)),
|
||||
drop_item: entity.loot_drop,
|
||||
rtsim_entity: None,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user