Store build areas outside of CanBuild component

This commit is contained in:
Louis Pearson 2021-03-23 17:59:18 -06:00
parent 120a0cd9a7
commit 77d48657c6
4 changed files with 68 additions and 14 deletions

View File

@ -2,11 +2,12 @@ use serde::{Deserialize, Serialize};
use specs::{Component, DerefFlaggedStorage};
use specs_idvs::IdvStorage;
use vek::geom::Aabb;
use crate::store::Id;
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
pub struct CanBuild {
pub building_is_on: bool,
pub build_area: Aabb<i32>,
pub build_areas: Vec<Id<Aabb<i32>>>,
}
impl Component for CanBuild {
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;

View File

@ -14,6 +14,7 @@ use common::{
time::DayPeriod,
trade::Trades,
vol::{ReadVol, WriteVol},
store::Store,
};
use common_base::span;
use common_ecs::{run_now, PhysicsMetrics, SysMetrics};
@ -39,6 +40,19 @@ const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
/// avoid such a situation.
const MAX_DELTA_TIME: f32 = 1.0;
#[derive(Default)]
pub struct BuildAreas {
pub areas: Store<geom::Aabb<i32>>,
}
impl BuildAreas {
pub fn new() -> Self {
Self {
areas: Store::default()
}
}
}
#[derive(Default)]
pub struct BlockChange {
blocks: HashMap<Vec3<i32>, Block>,
@ -204,6 +218,7 @@ impl State {
ecs.insert(PlayerEntity(None));
ecs.insert(TerrainGrid::new().unwrap());
ecs.insert(BlockChange::default());
ecs.insert(BuildAreas::new());
ecs.insert(TerrainChanges::default());
ecs.insert(EventBus::<LocalEvent>::default());
ecs.insert(game_mode);

View File

@ -30,9 +30,10 @@ use common_net::{
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
sync::WorldSyncExt,
};
use common_sys::state::BuildAreas;
use rand::Rng;
use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
use std::{convert::TryFrom, time::Duration};
use std::{convert::TryFrom, ops::DerefMut, time::Duration};
use vek::*;
use world::util::Sampler;
@ -1148,23 +1149,48 @@ fn handle_permit_build(
.get(target_player)
.is_some()
{
ecs.write_storage::<comp::CanBuild>().remove(target_player);
// ecs.write_storage::<comp::CanBuild>().remove(target_player);
// server.notify_client(
// client,
// ServerGeneral::server_msg(
// ChatType::CommandInfo,
// format!("Removed {}'s permission to build", target_alias),
// ),
// );
let bb_id = ecs
.write_resource::<BuildAreas>()
.deref_mut()
.areas
.insert(Aabb {
min: Vec3::new(xlo, ylo, zlo),
max: Vec3::new(xhi, yhi, zhi),
});
if let Some(mut comp_can_build) =
ecs.write_storage::<comp::CanBuild>().get_mut(target_player)
{
comp_can_build.build_areas.push(bb_id);
}
server.notify_client(
client,
ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("Removed {}'s permission to build", target_alias),
format!("Gave {} permission to build", target_alias),
),
);
} else {
let bb_id = ecs
.write_resource::<BuildAreas>()
.deref_mut()
.areas
.insert(Aabb {
min: Vec3::new(xlo, ylo, zlo),
max: Vec3::new(xhi, yhi, zhi),
});
let _ =
ecs.write_storage::<comp::CanBuild>()
.insert(target_player, comp::CanBuild {
building_is_on: false,
build_area: Aabb {
min: Vec3::new(xlo, ylo, zlo),
max: Vec3::new(xhi, yhi, zhi),
},
build_areas: vec![bb_id],
});
server.notify_client(
client,

View File

@ -7,7 +7,7 @@ use common::{
};
use common_ecs::{Job, Origin, Phase, System};
use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral};
use common_sys::state::BlockChange;
use common_sys::state::{BlockChange, BuildAreas};
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage};
use tracing::{debug, trace};
@ -29,6 +29,7 @@ impl Sys {
orientations: &mut WriteStorage<'_, Ori>,
controllers: &mut WriteStorage<'_, Controller>,
settings: &Read<'_, Settings>,
build_areas: &Read<'_, BuildAreas>,
msg: ClientGeneral,
) -> Result<(), crate::error::Error> {
let presence = match maybe_presence {
@ -103,17 +104,25 @@ impl Sys {
},
ClientGeneral::BreakBlock(pos) => {
if let Some(comp_can_build) = can_build.get(entity) {
if comp_can_build.building_is_on && comp_can_build.build_area.contains_point(pos) {
if let Ok(block) = terrain.get(pos) {
block_changes.set(pos, block.into_vacant());
if comp_can_build.building_is_on {
for area in comp_can_build.build_areas.iter() {
if build_areas.areas.get(*area).contains_point(pos) {
if let Ok(block) = terrain.get(pos) {
block_changes.set(pos, block.into_vacant());
}
}
}
}
}
},
ClientGeneral::PlaceBlock(pos, block) => {
if let Some(comp_can_build) = can_build.get(entity) {
if comp_can_build.building_is_on && comp_can_build.build_area.contains_point(pos) {
block_changes.try_set(pos, block);
if comp_can_build.building_is_on {
for area in comp_can_build.build_areas.iter() {
if build_areas.areas.get(*area).contains_point(pos) {
block_changes.try_set(pos, block);
}
}
}
}
},
@ -162,6 +171,7 @@ impl<'a> System<'a> for Sys {
WriteStorage<'a, Client>,
WriteStorage<'a, Controller>,
Read<'a, Settings>,
Read<'a, BuildAreas>,
);
const NAME: &'static str = "msg::in_game";
@ -186,6 +196,7 @@ impl<'a> System<'a> for Sys {
mut clients,
mut controllers,
settings,
build_areas,
): Self::SystemData,
) {
let mut server_emitter = server_event_bus.emitter();
@ -210,6 +221,7 @@ impl<'a> System<'a> for Sys {
&mut orientations,
&mut controllers,
&settings,
&build_areas,
msg,
)
});