mirror of
https://gitlab.com/veloren/veloren.git
synced 2024-08-30 18:12:32 +00:00
Merge branch 'zesterer/release-map' into 'master'
Added location system, switched to release map See merge request veloren/veloren!3213
This commit is contained in:
commit
d463b67ef4
BIN
assets/world/map/veloren_0_9_0_0.bin
(Stored with Git LFS)
BIN
assets/world/map/veloren_0_9_0_0.bin
(Stored with Git LFS)
Binary file not shown.
@ -108,6 +108,9 @@ pub enum ChatCommand {
|
||||
Wiring,
|
||||
World,
|
||||
MakeVolume,
|
||||
Location,
|
||||
CreateLocation,
|
||||
DeleteLocation,
|
||||
}
|
||||
|
||||
#[derive(Debug, PartialEq, Serialize, Deserialize, Clone)]
|
||||
@ -320,7 +323,7 @@ impl ChatCommand {
|
||||
),
|
||||
ChatCommand::Ban => cmd(
|
||||
vec![
|
||||
Any("username", Required),
|
||||
PlayerName(Required),
|
||||
Boolean("overwrite", "true".to_string(), Optional),
|
||||
Any("ban duration", Optional),
|
||||
Message(Optional),
|
||||
@ -458,7 +461,7 @@ impl ChatCommand {
|
||||
Some(Admin),
|
||||
),
|
||||
ChatCommand::Kick => cmd(
|
||||
vec![Any("username", Required), Message(Optional)],
|
||||
vec![PlayerName(Required), Message(Optional)],
|
||||
"Kick a player with a given username",
|
||||
Some(Moderator),
|
||||
),
|
||||
@ -559,7 +562,7 @@ impl ChatCommand {
|
||||
),
|
||||
ChatCommand::ServerPhysics => cmd(
|
||||
vec![
|
||||
Any("username", Required),
|
||||
PlayerName(Required),
|
||||
Boolean("enabled", "true".to_string(), Optional),
|
||||
],
|
||||
"Set/unset server-authoritative physics for an account",
|
||||
@ -621,7 +624,7 @@ impl ChatCommand {
|
||||
Some(Moderator),
|
||||
),
|
||||
ChatCommand::Unban => cmd(
|
||||
vec![Any("username", Required)],
|
||||
vec![PlayerName(Required)],
|
||||
"Remove the ban for the given username",
|
||||
Some(Moderator),
|
||||
),
|
||||
@ -633,7 +636,7 @@ impl ChatCommand {
|
||||
),
|
||||
ChatCommand::Wiring => cmd(vec![], "Create wiring element", Some(Admin)),
|
||||
ChatCommand::Whitelist => cmd(
|
||||
vec![Any("add/remove", Required), Any("username", Required)],
|
||||
vec![Any("add/remove", Required), PlayerName(Required)],
|
||||
"Adds/removes username to whitelist",
|
||||
Some(Moderator),
|
||||
),
|
||||
@ -643,6 +646,19 @@ impl ChatCommand {
|
||||
None,
|
||||
),
|
||||
ChatCommand::MakeVolume => cmd(vec![], "Create a volume (experimental)", Some(Admin)),
|
||||
ChatCommand::Location => {
|
||||
cmd(vec![Any("name", Required)], "Teleport to a location", None)
|
||||
},
|
||||
ChatCommand::CreateLocation => cmd(
|
||||
vec![Any("name", Required)],
|
||||
"Create a location at the current position",
|
||||
Some(Moderator),
|
||||
),
|
||||
ChatCommand::DeleteLocation => cmd(
|
||||
vec![Any("name", Required)],
|
||||
"Delete a location",
|
||||
Some(Moderator),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
@ -715,6 +731,9 @@ impl ChatCommand {
|
||||
ChatCommand::Whitelist => "whitelist",
|
||||
ChatCommand::World => "world",
|
||||
ChatCommand::MakeVolume => "make_volume",
|
||||
ChatCommand::Location => "location",
|
||||
ChatCommand::CreateLocation => "create_location",
|
||||
ChatCommand::DeleteLocation => "delete_location",
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -4,6 +4,7 @@
|
||||
|
||||
use crate::{
|
||||
client::Client,
|
||||
location::Locations,
|
||||
login_provider::LoginProvider,
|
||||
settings::{
|
||||
Ban, BanAction, BanInfo, EditableSetting, SettingError, WhitelistInfo, WhitelistRecord,
|
||||
@ -182,6 +183,9 @@ fn do_command(
|
||||
ChatCommand::Whitelist => handle_whitelist,
|
||||
ChatCommand::World => handle_world,
|
||||
ChatCommand::MakeVolume => handle_make_volume,
|
||||
ChatCommand::Location => handle_location,
|
||||
ChatCommand::CreateLocation => handle_create_location,
|
||||
ChatCommand::DeleteLocation => handle_delete_location,
|
||||
};
|
||||
|
||||
handler(server, client, target, args, cmd)
|
||||
@ -3516,3 +3520,101 @@ fn set_skills(skill_set: &mut comp::SkillSet, preset: &str) -> CmdResult<()> {
|
||||
Err("Such preset doesn't exist".to_owned())
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_location(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: Vec<String>,
|
||||
_action: &ChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
if let Some(name) = parse_args!(args, String) {
|
||||
let loc = server.state.ecs().read_resource::<Locations>().get(&name);
|
||||
match loc {
|
||||
Ok(loc) => position_mut(server, target, "target", |target_pos| {
|
||||
target_pos.0 = loc;
|
||||
}),
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
} else {
|
||||
let locations = server.state.ecs().read_resource::<Locations>();
|
||||
let mut locations = locations.iter().map(|s| s.as_str()).collect::<Vec<_>>();
|
||||
locations.sort_unstable();
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerGeneral::server_msg(
|
||||
ChatType::CommandInfo,
|
||||
if locations.is_empty() {
|
||||
"No locations currently exist".to_owned()
|
||||
} else {
|
||||
format!("Available locations:\n{}", locations.join(", "))
|
||||
},
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_create_location(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
target: EcsEntity,
|
||||
args: Vec<String>,
|
||||
action: &ChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
if let Some(name) = parse_args!(args, String) {
|
||||
let target_pos = position(server, target, "target")?;
|
||||
|
||||
let res = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.write_resource::<Locations>()
|
||||
.insert(name.clone(), target_pos.0);
|
||||
match res {
|
||||
Ok(()) => {
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerGeneral::server_msg(
|
||||
ChatType::CommandInfo,
|
||||
format!("Created location '{}'", name),
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
} else {
|
||||
Err(action.help_string())
|
||||
}
|
||||
}
|
||||
|
||||
fn handle_delete_location(
|
||||
server: &mut Server,
|
||||
client: EcsEntity,
|
||||
_target: EcsEntity,
|
||||
args: Vec<String>,
|
||||
action: &ChatCommand,
|
||||
) -> CmdResult<()> {
|
||||
if let Some(name) = parse_args!(args, String) {
|
||||
let res = server
|
||||
.state
|
||||
.ecs_mut()
|
||||
.write_resource::<Locations>()
|
||||
.remove(&name);
|
||||
match res {
|
||||
Ok(()) => {
|
||||
server.notify_client(
|
||||
client,
|
||||
ServerGeneral::server_msg(
|
||||
ChatType::CommandInfo,
|
||||
format!("Deleted location '{}'", name),
|
||||
),
|
||||
);
|
||||
Ok(())
|
||||
},
|
||||
Err(e) => Err(e.to_string()),
|
||||
}
|
||||
} else {
|
||||
Err(action.help_string())
|
||||
}
|
||||
}
|
||||
|
@ -23,6 +23,7 @@ mod data_dir;
|
||||
pub mod error;
|
||||
pub mod events;
|
||||
pub mod input;
|
||||
pub mod location;
|
||||
pub mod login_provider;
|
||||
pub mod metrics;
|
||||
pub mod persistence;
|
||||
@ -55,6 +56,7 @@ use crate::{
|
||||
cmd::ChatCommandExt,
|
||||
connection_handler::ConnectionHandler,
|
||||
data_dir::DataDir,
|
||||
location::Locations,
|
||||
login_provider::LoginProvider,
|
||||
persistence::PersistedComponents,
|
||||
presence::{Presence, RegionSubscription, RepositionOnChunkLoad},
|
||||
@ -243,6 +245,7 @@ impl Server {
|
||||
});
|
||||
state.ecs_mut().insert(EventBus::<ServerEvent>::default());
|
||||
state.ecs_mut().insert(Vec::<ChunkRequest>::new());
|
||||
state.ecs_mut().insert(Locations::default());
|
||||
state.ecs_mut().insert(LoginProvider::new(
|
||||
settings.auth_server_address.clone(),
|
||||
Arc::clone(&runtime),
|
||||
|
65
server/src/location.rs
Normal file
65
server/src/location.rs
Normal file
@ -0,0 +1,65 @@
|
||||
use hashbrown::HashMap;
|
||||
use std::fmt;
|
||||
use vek::*;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum LocationError<'a> {
|
||||
InvalidName(String),
|
||||
DuplicateName(String),
|
||||
DoesNotExist(&'a str),
|
||||
}
|
||||
|
||||
impl<'a> fmt::Display for LocationError<'a> {
|
||||
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
|
||||
match self {
|
||||
Self::InvalidName(name) => write!(
|
||||
f,
|
||||
"Location name '{}' is invalid. Names may only contain lowercase ASCII and \
|
||||
underscores",
|
||||
name
|
||||
),
|
||||
Self::DuplicateName(name) => write!(
|
||||
f,
|
||||
"Location '{}' already exists, consider deleting it first",
|
||||
name
|
||||
),
|
||||
Self::DoesNotExist(name) => write!(f, "Location '{}' does not exist", name),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Locations are moderator-defined positions that can be teleported between by
|
||||
/// players. They currently do not persist between server sessions.
|
||||
#[derive(Default)]
|
||||
pub struct Locations {
|
||||
locations: HashMap<String, Vec3<f32>>,
|
||||
}
|
||||
|
||||
impl Locations {
|
||||
pub fn insert(&mut self, name: String, pos: Vec3<f32>) -> Result<(), LocationError<'static>> {
|
||||
if name.chars().all(|c| c.is_ascii_lowercase() || c == '_') {
|
||||
self.locations
|
||||
.try_insert(name, pos)
|
||||
.map(|_| ())
|
||||
.map_err(|o| LocationError::DuplicateName(o.entry.key().clone()))
|
||||
} else {
|
||||
Err(LocationError::InvalidName(name))
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get<'a>(&self, name: &'a str) -> Result<Vec3<f32>, LocationError<'a>> {
|
||||
self.locations
|
||||
.get(name)
|
||||
.copied()
|
||||
.ok_or(LocationError::DoesNotExist(name))
|
||||
}
|
||||
|
||||
pub fn iter(&self) -> impl Iterator<Item = &String> { self.locations.keys() }
|
||||
|
||||
pub fn remove<'a>(&mut self, name: &'a str) -> Result<(), LocationError<'a>> {
|
||||
self.locations
|
||||
.remove(name)
|
||||
.map(|_| ())
|
||||
.ok_or(LocationError::DoesNotExist(name))
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user