mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'desttinghim/build-areas' into 'master'
Build Areas See merge request veloren/veloren!1978
This commit is contained in:
commit
973a2af753
@ -14,9 +14,12 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
- You can now jump out of rolls for a slight jump boost
|
- You can now jump out of rolls for a slight jump boost
|
||||||
- Dungeons now have multiple kinds of stairs.
|
- Dungeons now have multiple kinds of stairs.
|
||||||
- Trades now display item prices in tooltips.
|
- Trades now display item prices in tooltips.
|
||||||
|
- Admin designated build areas
|
||||||
|
|
||||||
### Changed
|
### Changed
|
||||||
|
|
||||||
|
- Permission to build is no longer tied to being an admin
|
||||||
|
|
||||||
### Removed
|
### Removed
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
@ -40,6 +40,9 @@ pub enum ChatCommand {
|
|||||||
Alias,
|
Alias,
|
||||||
Ban,
|
Ban,
|
||||||
Build,
|
Build,
|
||||||
|
BuildAreaAdd,
|
||||||
|
BuildAreaList,
|
||||||
|
BuildAreaRemove,
|
||||||
Campfire,
|
Campfire,
|
||||||
Debug,
|
Debug,
|
||||||
DebugColumn,
|
DebugColumn,
|
||||||
@ -68,9 +71,12 @@ pub enum ChatCommand {
|
|||||||
MakeSprite,
|
MakeSprite,
|
||||||
Motd,
|
Motd,
|
||||||
Object,
|
Object,
|
||||||
|
PermitBuild,
|
||||||
Players,
|
Players,
|
||||||
Region,
|
Region,
|
||||||
RemoveLights,
|
RemoveLights,
|
||||||
|
RevokeBuild,
|
||||||
|
RevokeBuildAll,
|
||||||
Safezone,
|
Safezone,
|
||||||
Say,
|
Say,
|
||||||
SetMotd,
|
SetMotd,
|
||||||
@ -94,6 +100,9 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
|||||||
ChatCommand::Alias,
|
ChatCommand::Alias,
|
||||||
ChatCommand::Ban,
|
ChatCommand::Ban,
|
||||||
ChatCommand::Build,
|
ChatCommand::Build,
|
||||||
|
ChatCommand::BuildAreaAdd,
|
||||||
|
ChatCommand::BuildAreaList,
|
||||||
|
ChatCommand::BuildAreaRemove,
|
||||||
ChatCommand::Campfire,
|
ChatCommand::Campfire,
|
||||||
ChatCommand::Debug,
|
ChatCommand::Debug,
|
||||||
ChatCommand::DebugColumn,
|
ChatCommand::DebugColumn,
|
||||||
@ -122,9 +131,12 @@ pub static CHAT_COMMANDS: &[ChatCommand] = &[
|
|||||||
ChatCommand::MakeSprite,
|
ChatCommand::MakeSprite,
|
||||||
ChatCommand::Motd,
|
ChatCommand::Motd,
|
||||||
ChatCommand::Object,
|
ChatCommand::Object,
|
||||||
|
ChatCommand::PermitBuild,
|
||||||
ChatCommand::Players,
|
ChatCommand::Players,
|
||||||
ChatCommand::Region,
|
ChatCommand::Region,
|
||||||
ChatCommand::RemoveLights,
|
ChatCommand::RemoveLights,
|
||||||
|
ChatCommand::RevokeBuild,
|
||||||
|
ChatCommand::RevokeBuildAll,
|
||||||
ChatCommand::Safezone,
|
ChatCommand::Safezone,
|
||||||
ChatCommand::Say,
|
ChatCommand::Say,
|
||||||
ChatCommand::SetMotd,
|
ChatCommand::SetMotd,
|
||||||
@ -235,7 +247,26 @@ impl ChatCommand {
|
|||||||
"Ban a player with a given username",
|
"Ban a player with a given username",
|
||||||
Admin,
|
Admin,
|
||||||
),
|
),
|
||||||
ChatCommand::Build => cmd(vec![], "Toggles build mode on and off", Admin),
|
ChatCommand::Build => cmd(vec![], "Toggles build mode on and off", NoAdmin),
|
||||||
|
ChatCommand::BuildAreaAdd => cmd(
|
||||||
|
vec![
|
||||||
|
Any("name", Required),
|
||||||
|
Integer("xlo", 0, Required),
|
||||||
|
Integer("xhi", 10, Required),
|
||||||
|
Integer("ylo", 0, Required),
|
||||||
|
Integer("yhi", 10, Required),
|
||||||
|
Integer("zlo", 0, Required),
|
||||||
|
Integer("zhi", 10, Required),
|
||||||
|
],
|
||||||
|
"Adds a new build area",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
|
ChatCommand::BuildAreaList => cmd(vec![], "List all build areas", Admin),
|
||||||
|
ChatCommand::BuildAreaRemove => cmd(
|
||||||
|
vec![Any("name", Required)],
|
||||||
|
"Removes specified build area",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
ChatCommand::Campfire => cmd(vec![], "Spawns a campfire", Admin),
|
ChatCommand::Campfire => cmd(vec![], "Spawns a campfire", Admin),
|
||||||
ChatCommand::Debug => cmd(vec![], "Place all debug items into your pack.", Admin),
|
ChatCommand::Debug => cmd(vec![], "Place all debug items into your pack.", Admin),
|
||||||
ChatCommand::DebugColumn => cmd(
|
ChatCommand::DebugColumn => cmd(
|
||||||
@ -368,12 +399,27 @@ impl ChatCommand {
|
|||||||
"Spawn an object",
|
"Spawn an object",
|
||||||
Admin,
|
Admin,
|
||||||
),
|
),
|
||||||
|
ChatCommand::PermitBuild => cmd(
|
||||||
|
vec![Any("area_name", Required)],
|
||||||
|
"Grants player a bounded box they can build in",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
ChatCommand::Players => cmd(vec![], "Lists players currently online", NoAdmin),
|
ChatCommand::Players => cmd(vec![], "Lists players currently online", NoAdmin),
|
||||||
ChatCommand::RemoveLights => cmd(
|
ChatCommand::RemoveLights => cmd(
|
||||||
vec![Float("radius", 20.0, Optional)],
|
vec![Float("radius", 20.0, Optional)],
|
||||||
"Removes all lights spawned by players",
|
"Removes all lights spawned by players",
|
||||||
Admin,
|
Admin,
|
||||||
),
|
),
|
||||||
|
ChatCommand::RevokeBuild => cmd(
|
||||||
|
vec![Any("area_name", Required)],
|
||||||
|
"Revokes build area permission for player",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
|
ChatCommand::RevokeBuildAll => cmd(
|
||||||
|
vec![],
|
||||||
|
"Revokes all build area permissions for player",
|
||||||
|
Admin,
|
||||||
|
),
|
||||||
ChatCommand::Region => cmd(
|
ChatCommand::Region => cmd(
|
||||||
vec![Message(Optional)],
|
vec![Message(Optional)],
|
||||||
"Send messages to everyone in your region of the world",
|
"Send messages to everyone in your region of the world",
|
||||||
@ -460,6 +506,9 @@ impl ChatCommand {
|
|||||||
ChatCommand::Alias => "alias",
|
ChatCommand::Alias => "alias",
|
||||||
ChatCommand::Ban => "ban",
|
ChatCommand::Ban => "ban",
|
||||||
ChatCommand::Build => "build",
|
ChatCommand::Build => "build",
|
||||||
|
ChatCommand::BuildAreaAdd => "build_area_add",
|
||||||
|
ChatCommand::BuildAreaList => "build_area_list",
|
||||||
|
ChatCommand::BuildAreaRemove => "build_area_remove",
|
||||||
ChatCommand::Campfire => "campfire",
|
ChatCommand::Campfire => "campfire",
|
||||||
ChatCommand::Debug => "debug",
|
ChatCommand::Debug => "debug",
|
||||||
ChatCommand::DebugColumn => "debug_column",
|
ChatCommand::DebugColumn => "debug_column",
|
||||||
@ -488,9 +537,12 @@ impl ChatCommand {
|
|||||||
ChatCommand::MakeSprite => "make_sprite",
|
ChatCommand::MakeSprite => "make_sprite",
|
||||||
ChatCommand::Motd => "motd",
|
ChatCommand::Motd => "motd",
|
||||||
ChatCommand::Object => "object",
|
ChatCommand::Object => "object",
|
||||||
|
ChatCommand::PermitBuild => "permit_build",
|
||||||
ChatCommand::Players => "players",
|
ChatCommand::Players => "players",
|
||||||
ChatCommand::Region => "region",
|
ChatCommand::Region => "region",
|
||||||
ChatCommand::RemoveLights => "remove_lights",
|
ChatCommand::RemoveLights => "remove_lights",
|
||||||
|
ChatCommand::RevokeBuild => "revoke_build",
|
||||||
|
ChatCommand::RevokeBuildAll => "revoke_build_all",
|
||||||
ChatCommand::Safezone => "safezone",
|
ChatCommand::Safezone => "safezone",
|
||||||
ChatCommand::Say => "say",
|
ChatCommand::Say => "say",
|
||||||
ChatCommand::SetMotd => "set_motd",
|
ChatCommand::SetMotd => "set_motd",
|
||||||
|
@ -1,8 +1,15 @@
|
|||||||
|
use crate::depot::Id;
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
use specs::{Component, DerefFlaggedStorage, NullStorage};
|
use specs::{Component, DerefFlaggedStorage};
|
||||||
|
use specs_idvs::IdvStorage;
|
||||||
|
use std::collections::HashSet;
|
||||||
|
use vek::geom::Aabb;
|
||||||
|
|
||||||
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
#[derive(Clone, Debug, Default, PartialEq, Serialize, Deserialize)]
|
||||||
pub struct CanBuild;
|
pub struct CanBuild {
|
||||||
impl Component for CanBuild {
|
pub enabled: bool,
|
||||||
type Storage = DerefFlaggedStorage<Self, NullStorage<Self>>;
|
pub build_areas: HashSet<Id<Aabb<i32>>>,
|
||||||
|
}
|
||||||
|
impl Component for CanBuild {
|
||||||
|
type Storage = DerefFlaggedStorage<Self, IdvStorage<Self>>;
|
||||||
}
|
}
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
use std::{
|
use std::{
|
||||||
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
|
cmp::{Eq, Ord, Ordering, PartialEq, PartialOrd},
|
||||||
fmt, hash,
|
fmt, hash,
|
||||||
@ -6,6 +7,7 @@ use std::{
|
|||||||
};
|
};
|
||||||
|
|
||||||
/// Type safe index into Depot
|
/// Type safe index into Depot
|
||||||
|
#[derive(Deserialize, Serialize)]
|
||||||
pub struct Id<T> {
|
pub struct Id<T> {
|
||||||
idx: u32,
|
idx: u32,
|
||||||
gen: u32,
|
gen: u32,
|
||||||
|
@ -6,6 +6,7 @@ use crate::plugin::PluginMgr;
|
|||||||
use common::uid::UidAllocator;
|
use common::uid::UidAllocator;
|
||||||
use common::{
|
use common::{
|
||||||
comp,
|
comp,
|
||||||
|
depot::{Depot, Id},
|
||||||
event::{EventBus, LocalEvent, ServerEvent},
|
event::{EventBus, LocalEvent, ServerEvent},
|
||||||
region::RegionMap,
|
region::RegionMap,
|
||||||
resources::{DeltaTime, GameMode, PlayerEntity, Time, TimeOfDay},
|
resources::{DeltaTime, GameMode, PlayerEntity, Time, TimeOfDay},
|
||||||
@ -39,6 +40,21 @@ const DAY_CYCLE_FACTOR: f64 = 24.0 * 2.0;
|
|||||||
/// avoid such a situation.
|
/// avoid such a situation.
|
||||||
const MAX_DELTA_TIME: f32 = 1.0;
|
const MAX_DELTA_TIME: f32 = 1.0;
|
||||||
|
|
||||||
|
#[derive(Default)]
|
||||||
|
pub struct BuildAreas {
|
||||||
|
pub areas: Depot<geom::Aabb<i32>>,
|
||||||
|
pub area_names: HashMap<String, Id<Aabb<i32>>>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl BuildAreas {
|
||||||
|
pub fn new() -> Self {
|
||||||
|
Self {
|
||||||
|
areas: Depot::default(),
|
||||||
|
area_names: HashMap::new(),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct BlockChange {
|
pub struct BlockChange {
|
||||||
blocks: HashMap<Vec3<i32>, Block>,
|
blocks: HashMap<Vec3<i32>, Block>,
|
||||||
@ -204,6 +220,7 @@ impl State {
|
|||||||
ecs.insert(PlayerEntity(None));
|
ecs.insert(PlayerEntity(None));
|
||||||
ecs.insert(TerrainGrid::new().unwrap());
|
ecs.insert(TerrainGrid::new().unwrap());
|
||||||
ecs.insert(BlockChange::default());
|
ecs.insert(BlockChange::default());
|
||||||
|
ecs.insert(BuildAreas::new());
|
||||||
ecs.insert(TerrainChanges::default());
|
ecs.insert(TerrainChanges::default());
|
||||||
ecs.insert(EventBus::<LocalEvent>::default());
|
ecs.insert(EventBus::<LocalEvent>::default());
|
||||||
ecs.insert(game_mode);
|
ecs.insert(game_mode);
|
||||||
|
@ -30,9 +30,15 @@ use common_net::{
|
|||||||
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
msg::{DisconnectReason, Notification, PlayerListUpdate, ServerGeneral},
|
||||||
sync::WorldSyncExt,
|
sync::WorldSyncExt,
|
||||||
};
|
};
|
||||||
|
use common_sys::state::BuildAreas;
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
|
use specs::{Builder, Entity as EcsEntity, Join, WorldExt};
|
||||||
use std::{convert::TryFrom, time::Duration};
|
use std::{
|
||||||
|
collections::HashSet,
|
||||||
|
convert::TryFrom,
|
||||||
|
ops::{Deref, DerefMut},
|
||||||
|
time::Duration,
|
||||||
|
};
|
||||||
use vek::*;
|
use vek::*;
|
||||||
use world::util::Sampler;
|
use world::util::Sampler;
|
||||||
|
|
||||||
@ -81,6 +87,9 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
|||||||
ChatCommand::Alias => handle_alias,
|
ChatCommand::Alias => handle_alias,
|
||||||
ChatCommand::Ban => handle_ban,
|
ChatCommand::Ban => handle_ban,
|
||||||
ChatCommand::Build => handle_build,
|
ChatCommand::Build => handle_build,
|
||||||
|
ChatCommand::BuildAreaAdd => handle_build_area_add,
|
||||||
|
ChatCommand::BuildAreaList => handle_build_area_list,
|
||||||
|
ChatCommand::BuildAreaRemove => handle_build_area_remove,
|
||||||
ChatCommand::Campfire => handle_spawn_campfire,
|
ChatCommand::Campfire => handle_spawn_campfire,
|
||||||
ChatCommand::Debug => handle_debug,
|
ChatCommand::Debug => handle_debug,
|
||||||
ChatCommand::DebugColumn => handle_debug_column,
|
ChatCommand::DebugColumn => handle_debug_column,
|
||||||
@ -109,9 +118,12 @@ fn get_handler(cmd: &ChatCommand) -> CommandHandler {
|
|||||||
ChatCommand::MakeSprite => handle_make_sprite,
|
ChatCommand::MakeSprite => handle_make_sprite,
|
||||||
ChatCommand::Motd => handle_motd,
|
ChatCommand::Motd => handle_motd,
|
||||||
ChatCommand::Object => handle_object,
|
ChatCommand::Object => handle_object,
|
||||||
|
ChatCommand::PermitBuild => handle_permit_build,
|
||||||
ChatCommand::Players => handle_players,
|
ChatCommand::Players => handle_players,
|
||||||
ChatCommand::Region => handle_region,
|
ChatCommand::Region => handle_region,
|
||||||
ChatCommand::RemoveLights => handle_remove_lights,
|
ChatCommand::RemoveLights => handle_remove_lights,
|
||||||
|
ChatCommand::RevokeBuild => handle_revoke_build,
|
||||||
|
ChatCommand::RevokeBuildAll => handle_revoke_build_all,
|
||||||
ChatCommand::Safezone => handle_safezone,
|
ChatCommand::Safezone => handle_safezone,
|
||||||
ChatCommand::Say => handle_say,
|
ChatCommand::Say => handle_say,
|
||||||
ChatCommand::SetMotd => handle_set_motd,
|
ChatCommand::SetMotd => handle_set_motd,
|
||||||
@ -1116,6 +1128,105 @@ fn handle_safezone(
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn handle_permit_build(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
target: EcsEntity,
|
||||||
|
args: String,
|
||||||
|
action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
if let Some(area_name) = scan_fmt_some!(&args, &action.arg_fmt(), String) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
if server
|
||||||
|
.state
|
||||||
|
.read_storage::<comp::CanBuild>()
|
||||||
|
.get(target)
|
||||||
|
.is_none()
|
||||||
|
{
|
||||||
|
let _ = ecs
|
||||||
|
.write_storage::<comp::CanBuild>()
|
||||||
|
.insert(target, comp::CanBuild {
|
||||||
|
enabled: false,
|
||||||
|
build_areas: HashSet::new(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if let Some(bb_id) = ecs
|
||||||
|
.read_resource::<BuildAreas>()
|
||||||
|
.deref()
|
||||||
|
.area_names
|
||||||
|
.get(&area_name)
|
||||||
|
{
|
||||||
|
if let Some(mut comp_can_build) = ecs.write_storage::<comp::CanBuild>().get_mut(target)
|
||||||
|
{
|
||||||
|
comp_can_build.build_areas.insert(*bb_id);
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
format!("Permission to build in {} granted", area_name),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandError, action.help_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_revoke_build(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
target: EcsEntity,
|
||||||
|
args: String,
|
||||||
|
action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
if let Some(area_name) = scan_fmt_some!(&args, &action.arg_fmt(), String) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
if let Some(bb_id) = ecs
|
||||||
|
.read_resource::<BuildAreas>()
|
||||||
|
.deref()
|
||||||
|
.area_names
|
||||||
|
.get(&area_name)
|
||||||
|
{
|
||||||
|
if let Some(mut comp_can_build) = ecs.write_storage::<comp::CanBuild>().get_mut(target)
|
||||||
|
{
|
||||||
|
comp_can_build.build_areas.retain(|&x| x != *bb_id);
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
format!("Permission to build in {} revoked", area_name),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandError, action.help_string()),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_revoke_build_all(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
target: EcsEntity,
|
||||||
|
_args: String,
|
||||||
|
_action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
|
||||||
|
ecs.write_storage::<comp::CanBuild>().remove(target);
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandInfo, "All build permissions revoked"),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
fn handle_players(
|
fn handle_players(
|
||||||
server: &mut Server,
|
server: &mut Server,
|
||||||
client: EcsEntity,
|
client: EcsEntity,
|
||||||
@ -1150,30 +1261,152 @@ fn handle_build(
|
|||||||
_args: String,
|
_args: String,
|
||||||
_action: &ChatCommand,
|
_action: &ChatCommand,
|
||||||
) {
|
) {
|
||||||
if server
|
if let Some(mut can_build) = server
|
||||||
.state
|
.state
|
||||||
.read_storage::<comp::CanBuild>()
|
.ecs()
|
||||||
.get(target)
|
.write_storage::<comp::CanBuild>()
|
||||||
.is_some()
|
.get_mut(target)
|
||||||
{
|
{
|
||||||
server
|
if can_build.enabled {
|
||||||
.state
|
can_build.enabled = false;
|
||||||
.ecs()
|
server.notify_client(
|
||||||
.write_storage::<comp::CanBuild>()
|
client,
|
||||||
.remove(target);
|
ServerGeneral::server_msg(ChatType::CommandInfo, "Toggled off build mode!"),
|
||||||
server.notify_client(
|
);
|
||||||
client,
|
} else {
|
||||||
ServerGeneral::server_msg(ChatType::CommandInfo, "Toggled off build mode!"),
|
can_build.enabled = true;
|
||||||
);
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(ChatType::CommandInfo, "Toggled on build mode!"),
|
||||||
|
);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
let _ = server
|
|
||||||
.state
|
|
||||||
.ecs()
|
|
||||||
.write_storage::<comp::CanBuild>()
|
|
||||||
.insert(target, comp::CanBuild);
|
|
||||||
server.notify_client(
|
server.notify_client(
|
||||||
client,
|
client,
|
||||||
ServerGeneral::server_msg(ChatType::CommandInfo, "Toggled on build mode!"),
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
"You do not have permission to build.",
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_build_area_add(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
_target: EcsEntity,
|
||||||
|
args: String,
|
||||||
|
action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
if let (Some(area_name), Some(xlo), Some(xhi), Some(ylo), Some(yhi), Some(zlo), Some(zhi)) = scan_fmt_some!(
|
||||||
|
&args,
|
||||||
|
&action.arg_fmt(),
|
||||||
|
String,
|
||||||
|
i32,
|
||||||
|
i32,
|
||||||
|
i32,
|
||||||
|
i32,
|
||||||
|
i32,
|
||||||
|
i32
|
||||||
|
) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
if ecs
|
||||||
|
.read_resource::<BuildAreas>()
|
||||||
|
.deref()
|
||||||
|
.area_names
|
||||||
|
.contains_key(&area_name)
|
||||||
|
{
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandError,
|
||||||
|
format!("Build zone {} already exists!", area_name),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
let bb_id = ecs.write_resource::<BuildAreas>().deref_mut().areas.insert(
|
||||||
|
Aabb {
|
||||||
|
min: Vec3::new(xlo, ylo, zlo),
|
||||||
|
max: Vec3::new(xhi, yhi, zhi),
|
||||||
|
}
|
||||||
|
.made_valid(),
|
||||||
|
);
|
||||||
|
ecs.write_resource::<BuildAreas>()
|
||||||
|
.deref_mut()
|
||||||
|
.area_names
|
||||||
|
.insert(area_name.clone(), bb_id);
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
format!("Created build zone {}", area_name),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_build_area_list(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
_target: EcsEntity,
|
||||||
|
_args: String,
|
||||||
|
_action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
let build_areas = ecs.read_resource::<BuildAreas>();
|
||||||
|
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
build_areas.area_names.iter().fold(
|
||||||
|
"Build Areas:".to_string(),
|
||||||
|
|acc, (area_name, bb_id)| {
|
||||||
|
if let Some(aabb) = build_areas.areas.get(*bb_id) {
|
||||||
|
format!("{}\n{}: {} to {}", acc, area_name, aabb.min, aabb.max)
|
||||||
|
} else {
|
||||||
|
acc
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
fn handle_build_area_remove(
|
||||||
|
server: &mut Server,
|
||||||
|
client: EcsEntity,
|
||||||
|
_target: EcsEntity,
|
||||||
|
args: String,
|
||||||
|
action: &ChatCommand,
|
||||||
|
) {
|
||||||
|
if let Some(area_name) = scan_fmt_some!(&args, &action.arg_fmt(), String) {
|
||||||
|
let ecs = server.state.ecs();
|
||||||
|
let mut build_areas = ecs.write_resource::<BuildAreas>();
|
||||||
|
|
||||||
|
let bb_id = match build_areas.area_names.get(&area_name) {
|
||||||
|
Some(x) => *x,
|
||||||
|
None => {
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandError,
|
||||||
|
format!("No such build area '{}'", area_name),
|
||||||
|
),
|
||||||
|
);
|
||||||
|
return;
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
let _ = build_areas.area_names.remove(&area_name);
|
||||||
|
let _ = build_areas.areas.remove(bb_id);
|
||||||
|
server.notify_client(
|
||||||
|
client,
|
||||||
|
ServerGeneral::server_msg(
|
||||||
|
ChatType::CommandInfo,
|
||||||
|
format!("Removed build zone {}", area_name),
|
||||||
|
),
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -7,7 +7,7 @@ use common::{
|
|||||||
};
|
};
|
||||||
use common_ecs::{Job, Origin, Phase, System};
|
use common_ecs::{Job, Origin, Phase, System};
|
||||||
use common_net::msg::{ClientGeneral, PresenceKind, ServerGeneral};
|
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 specs::{Entities, Join, Read, ReadExpect, ReadStorage, Write, WriteStorage};
|
||||||
use tracing::{debug, trace};
|
use tracing::{debug, trace};
|
||||||
|
|
||||||
@ -29,6 +29,7 @@ impl Sys {
|
|||||||
orientations: &mut WriteStorage<'_, Ori>,
|
orientations: &mut WriteStorage<'_, Ori>,
|
||||||
controllers: &mut WriteStorage<'_, Controller>,
|
controllers: &mut WriteStorage<'_, Controller>,
|
||||||
settings: &Read<'_, Settings>,
|
settings: &Read<'_, Settings>,
|
||||||
|
build_areas: &Read<'_, BuildAreas>,
|
||||||
msg: ClientGeneral,
|
msg: ClientGeneral,
|
||||||
) -> Result<(), crate::error::Error> {
|
) -> Result<(), crate::error::Error> {
|
||||||
let presence = match maybe_presence {
|
let presence = match maybe_presence {
|
||||||
@ -102,13 +103,39 @@ impl Sys {
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::BreakBlock(pos) => {
|
ClientGeneral::BreakBlock(pos) => {
|
||||||
if let Some(block) = can_build.get(entity).and_then(|_| terrain.get(pos).ok()) {
|
if let Some(comp_can_build) = can_build.get(entity) {
|
||||||
block_changes.set(pos, block.into_vacant());
|
if comp_can_build.enabled {
|
||||||
|
for area in comp_can_build.build_areas.iter() {
|
||||||
|
if let Some(block) = build_areas
|
||||||
|
.areas
|
||||||
|
.get(*area)
|
||||||
|
// TODO: Make this an exclusive check on the upper bound of the AABB
|
||||||
|
// Vek defaults to inclusive which is not optimal
|
||||||
|
.filter(|aabb| aabb.contains_point(pos))
|
||||||
|
.and_then(|_| terrain.get(pos).ok())
|
||||||
|
{
|
||||||
|
block_changes.set(pos, block.into_vacant());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::PlaceBlock(pos, block) => {
|
ClientGeneral::PlaceBlock(pos, block) => {
|
||||||
if can_build.get(entity).is_some() {
|
if let Some(comp_can_build) = can_build.get(entity) {
|
||||||
block_changes.try_set(pos, block);
|
if comp_can_build.enabled {
|
||||||
|
for area in comp_can_build.build_areas.iter() {
|
||||||
|
if build_areas
|
||||||
|
.areas
|
||||||
|
.get(*area)
|
||||||
|
// TODO: Make this an exclusive check on the upper bound of the AABB
|
||||||
|
// Vek defaults to inclusive which is not optimal
|
||||||
|
.filter(|aabb| aabb.contains_point(pos))
|
||||||
|
.is_some()
|
||||||
|
{
|
||||||
|
block_changes.try_set(pos, block);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
ClientGeneral::UnlockSkill(skill) => {
|
ClientGeneral::UnlockSkill(skill) => {
|
||||||
@ -156,6 +183,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
WriteStorage<'a, Client>,
|
WriteStorage<'a, Client>,
|
||||||
WriteStorage<'a, Controller>,
|
WriteStorage<'a, Controller>,
|
||||||
Read<'a, Settings>,
|
Read<'a, Settings>,
|
||||||
|
Read<'a, BuildAreas>,
|
||||||
);
|
);
|
||||||
|
|
||||||
const NAME: &'static str = "msg::in_game";
|
const NAME: &'static str = "msg::in_game";
|
||||||
@ -180,6 +208,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
mut clients,
|
mut clients,
|
||||||
mut controllers,
|
mut controllers,
|
||||||
settings,
|
settings,
|
||||||
|
build_areas,
|
||||||
): Self::SystemData,
|
): Self::SystemData,
|
||||||
) {
|
) {
|
||||||
let mut server_emitter = server_event_bus.emitter();
|
let mut server_emitter = server_event_bus.emitter();
|
||||||
@ -204,6 +233,7 @@ impl<'a> System<'a> for Sys {
|
|||||||
&mut orientations,
|
&mut orientations,
|
||||||
&mut controllers,
|
&mut controllers,
|
||||||
&settings,
|
&settings,
|
||||||
|
&build_areas,
|
||||||
msg,
|
msg,
|
||||||
)
|
)
|
||||||
});
|
});
|
||||||
|
@ -317,7 +317,7 @@ impl PlayState for SessionState {
|
|||||||
.state()
|
.state()
|
||||||
.read_storage::<comp::CanBuild>()
|
.read_storage::<comp::CanBuild>()
|
||||||
.get(player_entity)
|
.get(player_entity)
|
||||||
.is_some();
|
.map_or_else(|| false, |cb| cb.enabled);
|
||||||
|
|
||||||
let is_mining = self
|
let is_mining = self
|
||||||
.client
|
.client
|
||||||
|
Loading…
Reference in New Issue
Block a user