Merge branch 'sam/permanent-spawn-safezone' into 'master'

Safezone is now permanently in existence at spawn.

See merge request veloren/veloren!2144
This commit is contained in:
Samuel Keiffer 2021-04-17 23:44:10 +00:00
commit 1892ec571d
7 changed files with 63 additions and 23 deletions

View File

@ -172,6 +172,10 @@ pub enum ServerEvent {
target: Uid, target: Uid,
max_range: Option<f32>, max_range: Option<f32>,
}, },
CreateSafezone {
range: Option<f32>,
pos: Pos,
},
} }
pub struct EventBus<E> { pub struct EventBus<E> {

View File

@ -1069,22 +1069,7 @@ fn handle_safezone(
) -> CmdResult<()> { ) -> CmdResult<()> {
let range = scan_fmt_some!(&args, &action.arg_fmt(), f32); let range = scan_fmt_some!(&args, &action.arg_fmt(), f32);
let pos = position(server, target, "target")?; let pos = position(server, target, "target")?;
server server.state.create_safezone(range, pos).build();
.state
.create_object(pos, comp::object::Body::BoltNature)
.with(comp::Mass(10_f32.powi(10)))
.with(comp::Auras::new(vec![Aura::new(
AuraKind::Buff {
kind: BuffKind::Invulnerability,
data: BuffData::new(1.0, Some(Duration::from_secs(1))),
category: BuffCategory::Natural,
source: BuffSource::World,
},
range.unwrap_or(100.0),
None,
AuraTarget::All,
)]))
.build();
server.notify_client( server.notify_client(
client, client,

View File

@ -19,7 +19,7 @@ use interaction::{
use inventory_manip::handle_inventory; use inventory_manip::handle_inventory;
use invite::{handle_invite, handle_invite_response}; use invite::{handle_invite, handle_invite_response};
use player::{handle_client_disconnect, handle_exit_ingame}; use player::{handle_client_disconnect, handle_exit_ingame};
use specs::{Entity as EcsEntity, WorldExt}; use specs::{Builder, Entity as EcsEntity, WorldExt};
use trade::{cancel_trade_for, handle_process_trade_action}; use trade::{cancel_trade_for, handle_process_trade_action};
mod entity_creation; mod entity_creation;
@ -212,6 +212,9 @@ impl Server {
target, target,
max_range, max_range,
} => handle_teleport_to(&self, entity, target, max_range), } => handle_teleport_to(&self, entity, target, max_range),
ServerEvent::CreateSafezone { range, pos } => {
self.state.create_safezone(range, pos).build();
},
} }
} }

View File

@ -114,7 +114,11 @@ use world::{
}; };
#[derive(Copy, Clone)] #[derive(Copy, Clone)]
struct SpawnPoint(Vec3<f32>); pub struct SpawnPoint(Vec3<f32>);
impl Default for SpawnPoint {
fn default() -> Self { Self(Vec3::new(0.0, 0.0, 256.0)) }
}
// Tick count used for throttling network updates // Tick count used for throttling network updates
// Note this doesn't account for dt (so update rate changes with tick rate) // Note this doesn't account for dt (so update rate changes with tick rate)
@ -299,7 +303,7 @@ impl Server {
}; };
#[cfg(feature = "worldgen")] #[cfg(feature = "worldgen")]
let spawn_point = { let spawn_point = SpawnPoint({
let index = index.as_index_ref(); let index = index.as_index_ref();
// NOTE: all of these `.map(|e| e as [type])` calls should compile into no-ops, // NOTE: all of these `.map(|e| e as [type])` calls should compile into no-ops,
// but are needed to be explicit about casting (and to make the compiler stop // but are needed to be explicit about casting (and to make the compiler stop
@ -327,12 +331,12 @@ impl Server {
}; };
world.find_lowest_accessible_pos(index, spawn_chunk) world.find_lowest_accessible_pos(index, spawn_chunk)
}; });
#[cfg(not(feature = "worldgen"))] #[cfg(not(feature = "worldgen"))]
let spawn_point = Vec3::new(0.0, 0.0, 256.0); let spawn_point = SpawnPoint::default();
// Set the spawn point we calculated above // Set the spawn point we calculated above
state.ecs_mut().insert(SpawnPoint(spawn_point)); state.ecs_mut().insert(spawn_point);
// Insert a default AABB for the world // Insert a default AABB for the world
// TODO: prevent this from being deleted // TODO: prevent this from being deleted

View File

@ -43,6 +43,7 @@ pub struct Settings {
pub max_player_group_size: u32, pub max_player_group_size: u32,
pub client_timeout: Duration, pub client_timeout: Duration,
pub spawn_town: Option<String>, pub spawn_town: Option<String>,
pub safe_spawn: bool,
} }
impl Default for Settings { impl Default for Settings {
@ -61,6 +62,7 @@ impl Default for Settings {
max_player_group_size: 6, max_player_group_size: 6,
client_timeout: Duration::from_secs(40), client_timeout: Duration::from_secs(40),
spawn_town: None, spawn_town: None,
safe_spawn: true,
} }
} }
} }

View File

@ -24,6 +24,7 @@ use specs::{
saveload::MarkerAllocator, Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder, saveload::MarkerAllocator, Builder, Entity as EcsEntity, EntityBuilder as EcsEntityBuilder,
Join, WorldExt, Join, WorldExt,
}; };
use std::time::Duration;
use tracing::warn; use tracing::warn;
use vek::*; use vek::*;
@ -72,6 +73,8 @@ pub trait StateExt {
pos: comp::Pos, pos: comp::Pos,
ori: comp::Ori, ori: comp::Ori,
) -> EcsEntityBuilder; ) -> EcsEntityBuilder;
/// Creates a safezone
fn create_safezone(&mut self, range: Option<f32>, pos: comp::Pos) -> EcsEntityBuilder;
// NOTE: currently only used for testing // NOTE: currently only used for testing
/// Queues chunk generation in the view distance of the persister, this /// Queues chunk generation in the view distance of the persister, this
/// entity must be built before those chunks are received (the builder /// entity must be built before those chunks are received (the builder
@ -318,6 +321,27 @@ impl StateExt for State {
}) })
} }
fn create_safezone(&mut self, range: Option<f32>, pos: comp::Pos) -> EcsEntityBuilder {
use comp::{
aura::{Aura, AuraKind, AuraTarget, Auras},
buff::{BuffCategory, BuffData, BuffKind, BuffSource},
};
self.ecs_mut()
.create_entity_synced()
.with(pos)
.with(Auras::new(vec![Aura::new(
AuraKind::Buff {
kind: BuffKind::Invulnerability,
data: BuffData::new(1.0, Some(Duration::from_secs(1))),
category: BuffCategory::Natural,
source: BuffSource::World,
},
range.unwrap_or(100.0),
None,
AuraTarget::All,
)]))
}
// NOTE: currently only used for testing // NOTE: currently only used for testing
/// Queues chunk generation in the view distance of the persister, this /// Queues chunk generation in the view distance of the persister, this
/// entity must be built before those chunks are received (the builder /// entity must be built before those chunks are received (the builder

View File

@ -1,5 +1,6 @@
use crate::{ use crate::{
chunk_generator::ChunkGenerator, client::Client, presence::Presence, rtsim::RtSim, Tick, chunk_generator::ChunkGenerator, client::Client, presence::Presence, rtsim::RtSim,
settings::Settings, SpawnPoint, Tick,
}; };
use common::{ use common::{
comp::{ comp::{
@ -33,6 +34,8 @@ impl<'a> System<'a> for Sys {
type SystemData = ( type SystemData = (
Read<'a, EventBus<ServerEvent>>, Read<'a, EventBus<ServerEvent>>,
Read<'a, Tick>, Read<'a, Tick>,
Read<'a, SpawnPoint>,
Read<'a, Settings>,
WriteExpect<'a, ChunkGenerator>, WriteExpect<'a, ChunkGenerator>,
WriteExpect<'a, TerrainGrid>, WriteExpect<'a, TerrainGrid>,
Write<'a, TerrainChanges>, Write<'a, TerrainChanges>,
@ -51,6 +54,8 @@ impl<'a> System<'a> for Sys {
( (
server_event_bus, server_event_bus,
tick, tick,
spawn_point,
server_settings,
mut chunk_generator, mut chunk_generator,
mut terrain, mut terrain,
mut terrain_changes, mut terrain_changes,
@ -218,6 +223,14 @@ impl<'a> System<'a> for Sys {
rtsim_entity: None, rtsim_entity: None,
}) })
} }
// Insert a safezone if chunk contains the spawn position
if server_settings.safe_spawn && is_spawn_chunk(key, *spawn_point, &terrain) {
server_emitter.emit(ServerEvent::CreateSafezone {
range: Some(100.0),
pos: Pos(spawn_point.0),
});
}
} }
// Remove chunks that are too far from players. // Remove chunks that are too far from players.
@ -271,3 +284,8 @@ pub fn chunk_in_vd(
adjusted_dist_sqr <= vd.pow(2) adjusted_dist_sqr <= vd.pow(2)
} }
fn is_spawn_chunk(chunk_pos: Vec2<i32>, spawn_pos: SpawnPoint, terrain: &TerrainGrid) -> bool {
let spawn_chunk_pos = terrain.pos_key(spawn_pos.0.map(|e| e as i32));
chunk_pos == spawn_chunk_pos
}