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);
|
let old_pos = pos.0.map(|e| e.floor() as i32);
|
||||||
pos.0 = safe_pos
|
pos.0 = safe_pos
|
||||||
.map(|p| p.0.map(|e| e.floor()))
|
.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);
|
+ Vec3::new(0.5, 0.5, 0.0);
|
||||||
if let Some(force_update) = force_update.get_mut(rider) {
|
if let Some(force_update) = force_update.get_mut(rider) {
|
||||||
force_update.update();
|
force_update.update();
|
||||||
|
@ -222,11 +222,13 @@ impl TerrainChunkMeta {
|
|||||||
pub type TerrainChunk = chonk::Chonk<Block, TerrainChunkSize, TerrainChunkMeta>;
|
pub type TerrainChunk = chonk::Chonk<Block, TerrainChunkSize, TerrainChunkMeta>;
|
||||||
pub type TerrainGrid = VolGrid2d<TerrainChunk>;
|
pub type TerrainGrid = VolGrid2d<TerrainChunk>;
|
||||||
|
|
||||||
|
const TERRAIN_GRID_SEARCH_DIST: i32 = 63;
|
||||||
|
|
||||||
impl TerrainGrid {
|
impl TerrainGrid {
|
||||||
/// Find a location suitable for spawning an entity near the given
|
/// Find a location suitable for spawning an entity near the given
|
||||||
/// position (but in the same chunk).
|
/// position (but in the same chunk).
|
||||||
pub fn find_space(&self, pos: Vec3<i32>) -> Vec3<i32> {
|
pub fn find_ground(&self, pos: Vec3<i32>) -> Vec3<i32> {
|
||||||
self.try_find_space(pos).unwrap_or(pos)
|
self.try_find_ground(pos).unwrap_or(pos)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn is_space(&self, pos: Vec3<i32>) -> bool {
|
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>> {
|
pub fn try_find_space(&self, pos: Vec3<i32>) -> Option<Vec3<i32>> {
|
||||||
const SEARCH_DIST: i32 = 63;
|
(0..TERRAIN_GRID_SEARCH_DIST * 2 + 1)
|
||||||
(0..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(|i| if i % 2 == 0 { i } else { -i } / 2)
|
||||||
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
.map(|z_diff| pos + Vec3::unit_z() * z_diff)
|
||||||
.find(|pos| {
|
.find(|pos| {
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use crate::{
|
use crate::{
|
||||||
client::Client, events::player::handle_exit_ingame, persistence::PersistedComponents, sys,
|
client::Client, events::player::handle_exit_ingame, persistence::PersistedComponents,
|
||||||
CharacterUpdater, Server, StateExt, presence::RepositionOnChunkLoad,
|
presence::RepositionOnChunkLoad, sys, CharacterUpdater, Server, StateExt,
|
||||||
};
|
};
|
||||||
use common::{
|
use common::{
|
||||||
character::CharacterId,
|
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 {
|
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 {
|
} else {
|
||||||
entity
|
entity
|
||||||
};
|
};
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
use hashbrown::HashSet;
|
use hashbrown::HashSet;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, NullStorage};
|
use specs::{Component, VecStorage};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
|
|
||||||
// Distance from fuzzy_chunk before snapping to current chunk
|
// Distance from fuzzy_chunk before snapping to current chunk
|
||||||
@ -20,8 +20,10 @@ impl Component for RegionSubscription {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
#[derive(Copy, Clone, Debug, Default, Serialize, Deserialize)]
|
||||||
pub struct RepositionOnChunkLoad;
|
pub struct RepositionOnChunkLoad {
|
||||||
|
pub needs_ground: bool,
|
||||||
|
}
|
||||||
|
|
||||||
impl Component for RepositionOnChunkLoad {
|
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 {
|
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, waypoint);
|
||||||
self.write_component_ignore_entity_dead(entity, comp::Pos(waypoint.get_pos()));
|
self.write_component_ignore_entity_dead(entity, comp::Pos(waypoint.get_pos()));
|
||||||
self.write_component_ignore_entity_dead(entity, comp::Vel(Vec3::zero()));
|
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
|
// TODO: Create a teleportation event to handle this instead of
|
||||||
// processing the entity position move here
|
// processing the entity position move here
|
||||||
pet_pos.0 = terrain
|
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);
|
.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
|
// TODO: Consider putting this in another system since this forces us to take
|
||||||
// positions by write rather than read access.
|
// 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
|
// TODO: Consider using par_bridge() because Rayon has very poor work splitting for
|
||||||
// sparse joins.
|
// sparse joins.
|
||||||
.par_join()
|
.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
|
// NOTE: We use regular as casts rather than as_ because we want to saturate on
|
||||||
// overflow.
|
// overflow.
|
||||||
let entity_pos = pos.0.map(|x| x as i32);
|
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.
|
// from having just logged in), reposition them.
|
||||||
let chunk_pos = TerrainGrid::chunk_key(entity_pos);
|
let chunk_pos = TerrainGrid::chunk_key(entity_pos);
|
||||||
let chunk = terrain.get_key(chunk_pos)?;
|
let chunk = terrain.get_key(chunk_pos)?;
|
||||||
let new_pos = terrain
|
let new_pos = if reposition.needs_ground {
|
||||||
.try_find_space(entity_pos)
|
terrain.try_find_ground(entity_pos)
|
||||||
.map(|x| x.as_::<f32>())
|
} else {
|
||||||
.unwrap_or_else(|| chunk.find_accessible_pos(entity_pos.xy(), false));
|
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;
|
pos.0 = new_pos;
|
||||||
force_update.map(|force_update| force_update.update());
|
force_update.map(|force_update| force_update.update());
|
||||||
Some((entity, new_pos))
|
Some((entity, new_pos))
|
||||||
|
Loading…
Reference in New Issue
Block a user