mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
add flag to clamp to ground for RepositionOnChunkLoad
This commit is contained in:
parent
6be4a2b33f
commit
0bb6fa7946
@ -137,7 +137,7 @@ impl Link for Mounting {
|
||||
let old_pos = pos.0.map(|e| e.floor() as i32);
|
||||
pos.0 = safe_pos
|
||||
.map(|p| p.0.map(|e| e.floor()))
|
||||
.unwrap_or_else(|| terrain.find_space(old_pos).map(|e| e as f32))
|
||||
.unwrap_or_else(|| terrain.find_ground(old_pos).map(|e| e as f32))
|
||||
+ Vec3::new(0.5, 0.5, 0.0);
|
||||
if let Some(force_update) = force_update.get_mut(rider) {
|
||||
force_update.update();
|
||||
|
@ -222,11 +222,13 @@ impl TerrainChunkMeta {
|
||||
pub type TerrainChunk = chonk::Chonk<Block, TerrainChunkSize, TerrainChunkMeta>;
|
||||
pub type TerrainGrid = VolGrid2d<TerrainChunk>;
|
||||
|
||||
const TERRAIN_GRID_SEARCH_DIST: i32 = 63;
|
||||
|
||||
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> {
|
||||
self.try_find_space(pos).unwrap_or(pos)
|
||||
pub fn find_ground(&self, pos: Vec3<i32>) -> Vec3<i32> {
|
||||
self.try_find_ground(pos).unwrap_or(pos)
|
||||
}
|
||||
|
||||
pub fn is_space(&self, pos: Vec3<i32>) -> bool {
|
||||
@ -237,8 +239,14 @@ impl TerrainGrid {
|
||||
}
|
||||
|
||||
pub fn try_find_space(&self, pos: Vec3<i32>) -> Option<Vec3<i32>> {
|
||||
const SEARCH_DIST: i32 = 63;
|
||||
(0..SEARCH_DIST * 2 + 1)
|
||||
(0..TERRAIN_GRID_SEARCH_DIST * 2 + 1)
|
||||
.map(|i| if i % 2 == 0 { i } else { -i } / 2)
|
||||
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
||||
.find(|pos| self.is_space(*pos))
|
||||
}
|
||||
|
||||
pub fn try_find_ground(&self, pos: Vec3<i32>) -> Option<Vec3<i32>> {
|
||||
(0..TERRAIN_GRID_SEARCH_DIST * 2 + 1)
|
||||
.map(|i| if i % 2 == 0 { i } else { -i } / 2)
|
||||
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
||||
.find(|pos| {
|
||||
|
@ -1,6 +1,6 @@
|
||||
use crate::{
|
||||
client::Client, events::player::handle_exit_ingame, persistence::PersistedComponents, sys,
|
||||
CharacterUpdater, Server, StateExt, presence::RepositionOnChunkLoad,
|
||||
client::Client, events::player::handle_exit_ingame, persistence::PersistedComponents,
|
||||
presence::RepositionOnChunkLoad, sys, CharacterUpdater, Server, StateExt,
|
||||
};
|
||||
use common::{
|
||||
character::CharacterId,
|
||||
@ -131,7 +131,9 @@ pub fn handle_create_npc(server: &mut Server, pos: Pos, mut npc: NpcBuilder) ->
|
||||
};
|
||||
|
||||
let entity = if let Some(rtsim_entity) = npc.rtsim_entity {
|
||||
entity.with(rtsim_entity).with(RepositionOnChunkLoad)
|
||||
entity.with(rtsim_entity).with(RepositionOnChunkLoad {
|
||||
needs_ground: false,
|
||||
})
|
||||
} else {
|
||||
entity
|
||||
};
|
||||
|
@ -1,6 +1,6 @@
|
||||
use hashbrown::HashSet;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use specs::{Component, NullStorage};
|
||||
use specs::{Component, VecStorage};
|
||||
use vek::*;
|
||||
|
||||
// Distance from fuzzy_chunk before snapping to current chunk
|
||||
@ -20,8 +20,10 @@ impl Component for RegionSubscription {
|
||||
}
|
||||
|
||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||
pub struct RepositionOnChunkLoad;
|
||||
pub struct RepositionOnChunkLoad {
|
||||
pub needs_ground: bool,
|
||||
}
|
||||
|
||||
impl Component for RepositionOnChunkLoad {
|
||||
type Storage = NullStorage<Self>;
|
||||
type Storage = VecStorage<Self>;
|
||||
}
|
||||
|
@ -659,7 +659,9 @@ impl StateExt for State {
|
||||
);
|
||||
|
||||
if let Some(waypoint) = waypoint {
|
||||
self.write_component_ignore_entity_dead(entity, RepositionOnChunkLoad);
|
||||
self.write_component_ignore_entity_dead(entity, RepositionOnChunkLoad {
|
||||
needs_ground: true,
|
||||
});
|
||||
self.write_component_ignore_entity_dead(entity, waypoint);
|
||||
self.write_component_ignore_entity_dead(entity, comp::Pos(waypoint.get_pos()));
|
||||
self.write_component_ignore_entity_dead(entity, comp::Vel(Vec3::zero()));
|
||||
|
@ -66,7 +66,7 @@ impl<'a> System<'a> for Sys {
|
||||
// TODO: Create a teleportation event to handle this instead of
|
||||
// processing the entity position move here
|
||||
pet_pos.0 = terrain
|
||||
.find_space(owner_pos.0.map(|e| e.floor() as i32))
|
||||
.find_ground(owner_pos.0.map(|e| e.floor() as i32))
|
||||
.map(|e| e as f32);
|
||||
}
|
||||
}
|
||||
|
@ -228,11 +228,11 @@ impl<'a> System<'a> for Sys {
|
||||
|
||||
// TODO: Consider putting this in another system since this forces us to take
|
||||
// positions by write rather than read access.
|
||||
let repositioned = (&entities, &mut positions, (&mut force_update).maybe(), reposition_on_load.mask())
|
||||
let repositioned = (&entities, &mut positions, (&mut force_update).maybe(), &mut reposition_on_load)
|
||||
// TODO: Consider using par_bridge() because Rayon has very poor work splitting for
|
||||
// sparse joins.
|
||||
.par_join()
|
||||
.filter_map(|(entity, pos, force_update, _)| {
|
||||
.filter_map(|(entity, pos, force_update, reposition)| {
|
||||
// NOTE: We use regular as casts rather than as_ because we want to saturate on
|
||||
// overflow.
|
||||
let entity_pos = pos.0.map(|x| x as i32);
|
||||
@ -240,10 +240,11 @@ impl<'a> System<'a> for Sys {
|
||||
// from having just logged in), reposition them.
|
||||
let chunk_pos = TerrainGrid::chunk_key(entity_pos);
|
||||
let chunk = terrain.get_key(chunk_pos)?;
|
||||
let new_pos = terrain
|
||||
.try_find_space(entity_pos)
|
||||
.map(|x| x.as_::<f32>())
|
||||
.unwrap_or_else(|| chunk.find_accessible_pos(entity_pos.xy(), false));
|
||||
let new_pos = if reposition.needs_ground {
|
||||
terrain.try_find_ground(entity_pos)
|
||||
} else {
|
||||
terrain.try_find_space(entity_pos)
|
||||
}.map(|x| x.as_::<f32>()).unwrap_or_else(|| chunk.find_accessible_pos(entity_pos.xy(), false));
|
||||
pos.0 = new_pos;
|
||||
force_update.map(|force_update| force_update.update());
|
||||
Some((entity, new_pos))
|
||||
|
Loading…
Reference in New Issue
Block a user