mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'knarkzel/fix-npc-spawn' into 'master'
Fix bug that caused campfires and other stuff to duplicate See merge request veloren/veloren!1543
This commit is contained in:
commit
da9b23d4f6
@ -81,6 +81,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||
- Adjusted some keybindings
|
||||
- Consumables can now trigger multiple effects and buffs
|
||||
- Overhauled overworld spawns depending on chunk attributes
|
||||
- Fixed a bug which caused campfires and other stuff to duplicate
|
||||
|
||||
### Removed
|
||||
|
||||
|
13
common/src/comp/home_chunk.rs
Normal file
13
common/src/comp/home_chunk.rs
Normal file
@ -0,0 +1,13 @@
|
||||
use specs::Component;
|
||||
use specs_idvs::IdvStorage;
|
||||
use vek::Vec2;
|
||||
|
||||
/// This component exists in order to fix a bug that caused entitites
|
||||
/// such as campfires to duplicate because the chunk was double-loaded.
|
||||
/// See https://gitlab.com/veloren/veloren/-/merge_requests/1543
|
||||
#[derive(Copy, Clone, Default, Debug, PartialEq)]
|
||||
pub struct HomeChunk(pub Vec2<i32>);
|
||||
|
||||
impl Component for HomeChunk {
|
||||
type Storage = IdvStorage<Self>;
|
||||
}
|
@ -10,6 +10,7 @@ mod controller;
|
||||
mod energy;
|
||||
pub mod group;
|
||||
mod health;
|
||||
pub mod home_chunk;
|
||||
mod inputs;
|
||||
mod inventory;
|
||||
mod last;
|
||||
@ -47,6 +48,7 @@ pub use controller::{
|
||||
pub use energy::{Energy, EnergyChange, EnergySource};
|
||||
pub use group::Group;
|
||||
pub use health::{Health, HealthChange, HealthSource};
|
||||
pub use home_chunk::HomeChunk;
|
||||
pub use inputs::CanBuild;
|
||||
pub use inventory::{
|
||||
item,
|
||||
|
@ -104,6 +104,7 @@ pub enum ServerEvent {
|
||||
agent: Option<comp::Agent>,
|
||||
alignment: comp::Alignment,
|
||||
scale: comp::Scale,
|
||||
home_chunk: Option<comp::HomeChunk>,
|
||||
drop_item: Option<Item>,
|
||||
},
|
||||
CreateWaypoint(Vec3<f32>),
|
||||
|
@ -2,7 +2,7 @@ use crate::{sys, Server, StateExt};
|
||||
use common::{
|
||||
character::CharacterId,
|
||||
comp::{
|
||||
self, beam, shockwave, Agent, Alignment, Body, Gravity, Health, Item, ItemDrop,
|
||||
self, beam, shockwave, Agent, Alignment, Body, Gravity, Health, HomeChunk, Item, ItemDrop,
|
||||
LightEmitter, Loadout, Ori, Pos, Projectile, Scale, Stats, Vel, WaypointArea,
|
||||
},
|
||||
outcome::Outcome,
|
||||
@ -49,6 +49,7 @@ pub fn handle_create_npc(
|
||||
alignment: Alignment,
|
||||
scale: Scale,
|
||||
drop_item: Option<Item>,
|
||||
home_chunk: Option<HomeChunk>,
|
||||
) {
|
||||
let group = match alignment {
|
||||
Alignment::Wild => None,
|
||||
@ -83,6 +84,12 @@ pub fn handle_create_npc(
|
||||
entity
|
||||
};
|
||||
|
||||
let entity = if let Some(home_chunk) = home_chunk {
|
||||
entity.with(home_chunk)
|
||||
} else {
|
||||
entity
|
||||
};
|
||||
|
||||
entity.build();
|
||||
}
|
||||
|
||||
|
@ -115,9 +115,11 @@ impl Server {
|
||||
agent,
|
||||
alignment,
|
||||
scale,
|
||||
home_chunk,
|
||||
drop_item,
|
||||
} => handle_create_npc(
|
||||
self, pos, stats, health, loadout, body, agent, alignment, scale, drop_item,
|
||||
home_chunk,
|
||||
),
|
||||
ServerEvent::CreateWaypoint(pos) => handle_create_waypoint(self, pos),
|
||||
ServerEvent::ClientDisconnect(entity) => {
|
||||
|
@ -54,7 +54,6 @@ use common::{
|
||||
},
|
||||
outcome::Outcome,
|
||||
recipe::default_recipe_book,
|
||||
spiral::Spiral2d,
|
||||
state::{State, TimeOfDay},
|
||||
sync::WorldSyncExt,
|
||||
terrain::TerrainChunkSize,
|
||||
@ -197,6 +196,7 @@ impl Server {
|
||||
state.ecs_mut().register::<RegionSubscription>();
|
||||
state.ecs_mut().register::<Client>();
|
||||
state.ecs_mut().register::<Presence>();
|
||||
state.ecs_mut().register::<comp::HomeChunk>();
|
||||
|
||||
//Alias validator
|
||||
let banned_words_paths = &settings.banned_words_files;
|
||||
@ -524,19 +524,17 @@ impl Server {
|
||||
&self.state.ecs().entities(),
|
||||
&self.state.ecs().read_storage::<comp::Pos>(),
|
||||
!&self.state.ecs().read_storage::<comp::Player>(),
|
||||
&self.state.ecs().read_storage::<comp::HomeChunk>(),
|
||||
)
|
||||
.join()
|
||||
.filter(|(_, pos, _)| {
|
||||
.filter(|(_, pos, _, home_chunk)| {
|
||||
let chunk_key = terrain.pos_key(pos.0.map(|e| e.floor() as i32));
|
||||
// Check not only this chunk, but also all neighbours to avoid immediate
|
||||
// despawning if the entity walks outside of a valid chunk
|
||||
// briefly. If the entity isn't even near a loaded chunk then we get
|
||||
// rid of it.
|
||||
Spiral2d::new()
|
||||
.take(9)
|
||||
.all(|offs| terrain.get_key(chunk_key + offs).is_none())
|
||||
// Check if both this chunk and the NPCs `home_chunk` is unloaded. If so,
|
||||
// we delete them. We check for `home_chunk` in order to avoid duplicating
|
||||
// the entity under some circumstances.
|
||||
terrain.get_key(chunk_key).is_none() && terrain.get_key(home_chunk.0).is_none()
|
||||
})
|
||||
.map(|(entity, _, _)| entity)
|
||||
.map(|(entity, _, _, _)| entity)
|
||||
.collect::<Vec<_>>()
|
||||
};
|
||||
|
||||
|
@ -187,6 +187,7 @@ impl<'a> System<'a> for Sys {
|
||||
body,
|
||||
alignment,
|
||||
scale: comp::Scale(scale),
|
||||
home_chunk: Some(comp::HomeChunk(key)),
|
||||
drop_item: entity.loot_drop,
|
||||
})
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user