Updated changelog, fmt and clippy fixes

This commit is contained in:
Joshua Barretto 2020-12-13 17:40:15 +00:00
parent 9284aed8bd
commit 023888f560
28 changed files with 457 additions and 257 deletions

View File

@ -12,6 +12,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
- Added chat commands for inviting, kicking, leaving, and promoting in groups - Added chat commands for inviting, kicking, leaving, and promoting in groups
- Aura system - Aura system
- Campfire resting heal - Campfire resting heal
- Initial support for game plugins, both server-side and client-side
### Changed ### Changed

View File

@ -28,20 +28,20 @@ use common::{
outcome::Outcome, outcome::Outcome,
recipe::RecipeBook, recipe::RecipeBook,
span, span,
uid::{Uid, UidAllocator},
terrain::{block::Block, neighbors, BiomeKind, SitesKind, TerrainChunk, TerrainChunkSize}, terrain::{block::Block, neighbors, BiomeKind, SitesKind, TerrainChunk, TerrainChunkSize},
uid::{Uid, UidAllocator},
vol::RectVolSize, vol::RectVolSize,
}; };
use common_sys::state::State;
use common_net::{ use common_net::{
msg::{ msg::{
self, validate_chat_msg, world_msg::SiteInfo, ChatMsgValidationError, ClientGeneral, ClientMsg, self, validate_chat_msg, world_msg::SiteInfo, ChatMsgValidationError, ClientGeneral,
ClientRegister, ClientType, DisconnectReason, InviteAnswer, Notification, PingMsg, ClientMsg, ClientRegister, ClientType, DisconnectReason, InviteAnswer, Notification,
PlayerInfo, PlayerListUpdate, PresenceKind, RegisterError, ServerGeneral, ServerInfo, PingMsg, PlayerInfo, PlayerListUpdate, PresenceKind, RegisterError, ServerGeneral,
ServerInit, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG, ServerInfo, ServerInit, ServerRegisterAnswer, MAX_BYTES_CHAT_MSG,
}, },
sync::WorldSyncExt, sync::WorldSyncExt,
}; };
use common_sys::state::State;
use comp::BuffKind; use comp::BuffKind;
use futures_executor::block_on; use futures_executor::block_on;
use futures_timer::Delay; use futures_timer::Delay;

View File

@ -1,5 +1,5 @@
use common::comp;
use crate::sync; use crate::sync;
use common::comp;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::marker::PhantomData; use std::marker::PhantomData;
use sum_type::sum_type; use sum_type::sum_type;

View File

@ -1,15 +1,15 @@
use super::{ClientType, EcsCompPacket, PingMsg}; use super::{ClientType, EcsCompPacket, PingMsg};
use crate::sync;
use authc::AuthClientError;
use common::{ use common::{
character::{self, CharacterItem}, character::{self, CharacterItem},
comp, comp,
outcome::Outcome, outcome::Outcome,
recipe::RecipeBook, recipe::RecipeBook,
resources::TimeOfDay, resources::TimeOfDay,
uid::Uid,
terrain::{Block, TerrainChunk}, terrain::{Block, TerrainChunk},
uid::Uid,
}; };
use crate::sync;
use authc::AuthClientError;
use hashbrown::HashMap; use hashbrown::HashMap;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::time::Duration; use std::time::Duration;

View File

@ -5,10 +5,10 @@ mod sync_ext;
mod track; mod track;
// Reexports // Reexports
pub use common::uid::{Uid, UidAllocator};
pub use packet::{ pub use packet::{
handle_insert, handle_modify, handle_remove, CompPacket, CompSyncPackage, EntityPackage, handle_insert, handle_modify, handle_remove, CompPacket, CompSyncPackage, EntityPackage,
EntitySyncPackage, StatePackage, EntitySyncPackage, StatePackage,
}; };
pub use sync_ext::WorldSyncExt; pub use sync_ext::WorldSyncExt;
pub use track::UpdateTracker; pub use track::UpdateTracker;
pub use common::uid::{Uid, UidAllocator};

View File

@ -1,7 +1,7 @@
use uuid::Uuid;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use specs::{Component, FlaggedStorage, NullStorage}; use specs::{Component, FlaggedStorage, NullStorage};
use specs_idvs::IdvStorage; use specs_idvs::IdvStorage;
use uuid::Uuid;
const MAX_ALIAS_LEN: usize = 32; const MAX_ALIAS_LEN: usize = 32;

View File

@ -4,11 +4,7 @@ use comp::{
Ori, Pos, Ori, Pos,
}; };
use specs::Entity as EcsEntity; use specs::Entity as EcsEntity;
use std::{ use std::{collections::VecDeque, ops::DerefMut, sync::Mutex};
collections::VecDeque,
sync::Mutex,
ops::DerefMut,
};
use vek::*; use vek::*;
pub enum LocalEvent { pub enum LocalEvent {

View File

@ -48,12 +48,11 @@ pub mod store;
pub mod terrain; pub mod terrain;
pub mod time; pub mod time;
pub mod typed; pub mod typed;
pub mod util;
pub mod uid; pub mod uid;
pub mod util;
pub mod vol; pub mod vol;
pub mod volumes; pub mod volumes;
pub use combat::{Damage, DamageSource, GroupTarget, Knockback}; pub use combat::{Damage, DamageSource, GroupTarget, Knockback};
pub use explosion::{Explosion, RadiusEffect}; pub use explosion::{Explosion, RadiusEffect};
pub use loadout_builder::LoadoutBuilder; pub use loadout_builder::LoadoutBuilder;

View File

@ -15,11 +15,14 @@ pub struct DeltaTime(pub f32);
/// A resource that indicates what mode the local game is being played in. /// A resource that indicates what mode the local game is being played in.
#[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)] #[derive(Copy, Clone, Debug, Serialize, Deserialize, PartialEq, Eq)]
pub enum GameMode { pub enum GameMode {
/// The game is being played in server mode (i.e: the code is running server-side) /// The game is being played in server mode (i.e: the code is running
/// server-side)
Server, Server,
/// The game is being played in client mode (i.e: the code is running client-side) /// The game is being played in client mode (i.e: the code is running
/// client-side)
Client, Client,
/// The game is being played in singleplayer mode (i.e: both client and server at once) /// The game is being played in singleplayer mode (i.e: both client and
/// server at once)
// To be used later when we no longer start up an entirely new server for singleplayer // To be used later when we no longer start up an entirely new server for singleplayer
Singleplayer, Singleplayer,
} }

View File

@ -139,9 +139,7 @@ impl Body {
) )
} }
pub fn can_climb(&self) -> bool { pub fn can_climb(&self) -> bool { matches!(self, Body::Humanoid(_)) }
matches!(self, Body::Humanoid(_))
}
} }
/// Handles updating `Components` to move player based on state of `JoinData` /// Handles updating `Components` to move player based on state of `JoinData`

View File

@ -17,9 +17,9 @@ use common::{
path::{Chaser, TraversalConfig}, path::{Chaser, TraversalConfig},
resources::{DeltaTime, Time, TimeOfDay}, resources::{DeltaTime, Time, TimeOfDay},
span, span,
uid::{Uid, UidAllocator},
terrain::{Block, TerrainGrid}, terrain::{Block, TerrainGrid},
time::DayPeriod, time::DayPeriod,
uid::{Uid, UidAllocator},
util::Dir, util::Dir,
vol::ReadVol, vol::ReadVol,
}; };

View File

@ -8,8 +8,8 @@ use common::{
metrics::{PhysicsMetrics, SysMetrics}, metrics::{PhysicsMetrics, SysMetrics},
resources::DeltaTime, resources::DeltaTime,
span, span,
uid::Uid,
terrain::{Block, TerrainGrid}, terrain::{Block, TerrainGrid},
uid::Uid,
vol::ReadVol, vol::ReadVol,
}; };
use rayon::iter::ParallelIterator; use rayon::iter::ParallelIterator;

View File

@ -7,7 +7,7 @@ pub enum PluginError {
Toml(toml::de::Error), Toml(toml::de::Error),
NoConfig, NoConfig,
NoSuchModule, NoSuchModule,
PluginModuleError(PluginModuleError) PluginModuleError(PluginModuleError),
} }
#[derive(Debug)] #[derive(Debug)]
@ -18,4 +18,4 @@ pub enum PluginModuleError {
Instantiate(wasmer_runtime::error::Error), Instantiate(wasmer_runtime::error::Error),
RunFunction(RuntimeError), RunFunction(RuntimeError),
Encoding(Box<ErrorKind>), Encoding(Box<ErrorKind>),
} }

View File

@ -1,15 +1,22 @@
pub mod errors; pub mod errors;
pub mod module; pub mod module;
use common::assets::ASSETS_PATH; use common::assets::ASSETS_PATH;
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use std::{collections::{HashMap, HashSet}, fs, io::Read, path::{Path, PathBuf}}; use std::{
collections::{HashMap, HashSet},
fs,
io::Read,
path::{Path, PathBuf},
};
use tracing::{error, info}; use tracing::{error, info};
use plugin_api::Event; use plugin_api::Event;
use self::{ errors::PluginError, module::{PluginModule, PreparedEventQuery}}; use self::{
errors::PluginError,
module::{PluginModule, PreparedEventQuery},
};
use rayon::prelude::*; use rayon::prelude::*;
@ -58,7 +65,7 @@ impl Plugin {
.iter() .iter()
.map(|path| { .map(|path| {
let wasm_data = files.remove(path).ok_or(PluginError::NoSuchModule)?; let wasm_data = files.remove(path).ok_or(PluginError::NoSuchModule)?;
PluginModule::new(&wasm_data).map_err(|e| PluginError::PluginModuleError(e)) PluginModule::new(&wasm_data).map_err(PluginError::PluginModuleError)
}) })
.collect::<Result<_, _>>()?; .collect::<Result<_, _>>()?;
@ -69,10 +76,22 @@ impl Plugin {
}) })
} }
pub fn execute_prepared<T>(&self, event_name: &str, event: &PreparedEventQuery<T>) -> Result<Vec<T::Response>, PluginError> where T: Event { pub fn execute_prepared<T>(
self.modules.iter().flat_map(|module| { &self,
module.try_execute(event_name, event).map(|x| x.map_err(|e| PluginError::PluginModuleError(e))) event_name: &str,
}).collect::<Result<Vec<_>,_>>() event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, PluginError>
where
T: Event,
{
self.modules
.iter()
.flat_map(|module| {
module
.try_execute(event_name, event)
.map(|x| x.map_err(PluginError::PluginModuleError))
})
.collect::<Result<Vec<_>, _>>()
} }
} }
@ -89,13 +108,32 @@ impl PluginMgr {
Self::from_dir(assets_path) Self::from_dir(assets_path)
} }
pub fn execute_prepared<T>(&self, event_name: &str,event: &PreparedEventQuery<T>) -> Result<Vec<T::Response>, PluginError> where T: Event { pub fn execute_prepared<T>(
Ok(self.plugins.par_iter().map(|plugin| { &self,
plugin.execute_prepared(event_name, event) event_name: &str,
}).collect::<Result<Vec<_>,_>>()?.into_iter().flatten().collect()) event: &PreparedEventQuery<T>,
) -> Result<Vec<T::Response>, PluginError>
where
T: Event,
{
Ok(self
.plugins
.par_iter()
.map(|plugin| plugin.execute_prepared(event_name, event))
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten()
.collect())
} }
pub fn execute_event<T>(&self, event_name: &str,event: &T) -> Result<Vec<T::Response>, PluginError> where T: Event { pub fn execute_event<T>(
&self,
event_name: &str,
event: &T,
) -> Result<Vec<T::Response>, PluginError>
where
T: Event,
{
self.execute_prepared(event_name, &PreparedEventQuery::new(event)?) self.execute_prepared(event_name, &PreparedEventQuery::new(event)?)
} }

View File

@ -22,14 +22,14 @@ pub struct PluginModule {
} }
impl PluginModule { impl PluginModule {
// This function takes bytes from a WASM File and compile them // This function takes bytes from a WASM File and compile them
pub fn new(wasm_data: &Vec<u8>) -> Result<Self,PluginModuleError> { pub fn new(wasm_data: &[u8]) -> Result<Self, PluginModuleError> {
let module = compile(&wasm_data).map_err(|e| PluginModuleError::Compile(e))?; let module = compile(&wasm_data).map_err(PluginModuleError::Compile)?;
let instance = module let instance = module
.instantiate(&imports! {"env" => { .instantiate(&imports! {"env" => {
"raw_emit_actions" => func!(read_action), "raw_emit_actions" => func!(read_action),
}}).map_err(|e| PluginModuleError::Instantiate(e))?; }})
.map_err(PluginModuleError::Instantiate)?;
Ok(Self { Ok(Self {
events: instance.exports.into_iter().map(|(name, _)| name).collect(), events: instance.exports.into_iter().map(|(name, _)| name).collect(),
@ -37,12 +37,13 @@ impl PluginModule {
}) })
} }
// This function tries to execute an event for the current module. Will return None if the event doesn't exists // This function tries to execute an event for the current module. Will return
// None if the event doesn't exists
pub fn try_execute<T>( pub fn try_execute<T>(
&self, &self,
event_name: &str, event_name: &str,
request: &PreparedEventQuery<T>, request: &PreparedEventQuery<T>,
) -> Option<Result<T::Response,PluginModuleError>> ) -> Option<Result<T::Response, PluginModuleError>>
where where
T: Event, T: Event,
{ {
@ -51,21 +52,26 @@ impl PluginModule {
} }
let bytes = { let bytes = {
let instance = self.wasm_instance.lock().unwrap(); let instance = self.wasm_instance.lock().unwrap();
let func = match instance.exports.get(event_name).map_err(|e| PluginModuleError::FunctionGet(e)) { let func = match instance
.exports
.get(event_name)
.map_err(PluginModuleError::FunctionGet)
{
Ok(e) => e, Ok(e) => e,
Err(e) => return Some(Err(e)) Err(e) => return Some(Err(e)),
}; };
let mem = instance.context().memory(0); let mem = instance.context().memory(0);
match execute_raw(&mem, &func, &request.bytes).map_err(|e| PluginModuleError::RunFunction(e)) { match execute_raw(&mem, &func, &request.bytes).map_err(PluginModuleError::RunFunction) {
Ok(e) => e, Ok(e) => e,
Err(e) => return Some(Err(e)) Err(e) => return Some(Err(e)),
} }
}; };
Some(bincode::deserialize(&bytes).map_err(|e| PluginModuleError::Encoding(e))) Some(bincode::deserialize(&bytes).map_err(PluginModuleError::Encoding))
} }
} }
// This structure represent a Pre-encoded event object (Useful to avoid reencoding for each module in every plugin) // This structure represent a Pre-encoded event object (Useful to avoid
// reencoding for each module in every plugin)
pub struct PreparedEventQuery<T> { pub struct PreparedEventQuery<T> {
bytes: Vec<u8>, bytes: Vec<u8>,
_phantom: PhantomData<T>, _phantom: PhantomData<T>,
@ -79,7 +85,8 @@ impl<T: Event> PreparedEventQuery<T> {
T: Event, T: Event,
{ {
Ok(Self { Ok(Self {
bytes: bincode::serialize(&event).map_err(|e| PluginError::PluginModuleError(PluginModuleError::Encoding(e)))?, bytes: bincode::serialize(&event)
.map_err(|e| PluginError::PluginModuleError(PluginModuleError::Encoding(e)))?,
_phantom: PhantomData::default(), _phantom: PhantomData::default(),
}) })
} }
@ -87,7 +94,9 @@ impl<T: Event> PreparedEventQuery<T> {
const MEMORY_POS: usize = 100000; const MEMORY_POS: usize = 100000;
// This function is not public because this function should not be used without an interface to limit unsafe behaviours // This function is not public because this function should not be used without
// an interface to limit unsafe behaviours
#[allow(clippy::needless_range_loop)]
fn execute_raw( fn execute_raw(
memory: &Memory, memory: &Memory,
function: &Function, function: &Function,
@ -98,8 +107,7 @@ fn execute_raw(
for (cell, byte) in view[MEMORY_POS..len + MEMORY_POS].iter().zip(bytes.iter()) { for (cell, byte) in view[MEMORY_POS..len + MEMORY_POS].iter().zip(bytes.iter()) {
cell.set(*byte) cell.set(*byte)
} }
let start = function let start = function.call(MEMORY_POS as i32, len as u32)? as usize;
.call(MEMORY_POS as i32, len as u32)? as usize;
let view = memory.view::<u8>(); let view = memory.view::<u8>();
let mut new_len_bytes = [0u8; 4]; let mut new_len_bytes = [0u8; 4];
// TODO: It is probably better to dirrectly make the new_len_bytes // TODO: It is probably better to dirrectly make the new_len_bytes
@ -127,7 +135,7 @@ pub fn read_action(ctx: &mut Ctx, ptr: u32, len: u32) {
Err(e) => { Err(e) => {
tracing::error!(?e, "Can't decode action"); tracing::error!(?e, "Can't decode action");
return; return;
} },
}; };
for action in e { for action in e {
@ -135,16 +143,16 @@ pub fn read_action(ctx: &mut Ctx, ptr: u32, len: u32) {
Action::ServerClose => { Action::ServerClose => {
tracing::info!("Server closed by plugin"); tracing::info!("Server closed by plugin");
std::process::exit(-1); std::process::exit(-1);
} },
Action::Print(e) => { Action::Print(e) => {
tracing::info!("{}",e); tracing::info!("{}", e);
} },
Action::PlayerSendMessage(a, b) => { Action::PlayerSendMessage(a, b) => {
tracing::info!("SendMessage {} -> {}",a,b); tracing::info!("SendMessage {} -> {}", a, b);
} },
Action::KillEntity(e) => { Action::KillEntity(e) => {
tracing::info!("Kill Entity {}",e); tracing::info!("Kill Entity {}", e);
} },
} }
} }
} }

View File

@ -1,14 +1,15 @@
use crate::plugin::PluginMgr;
use common::{ use common::{
comp, comp,
event::{EventBus, LocalEvent, ServerEvent}, event::{EventBus, LocalEvent, ServerEvent},
metrics::{PhysicsMetrics, SysMetrics}, metrics::{PhysicsMetrics, SysMetrics},
region::RegionMap, region::RegionMap,
resources,
resources::{DeltaTime, Time, TimeOfDay}, resources::{DeltaTime, Time, TimeOfDay},
span, span,
terrain::{Block, TerrainChunk, TerrainGrid}, terrain::{Block, TerrainChunk, TerrainGrid},
time::DayPeriod, time::DayPeriod,
vol::{ReadVol, WriteVol}, vol::{ReadVol, WriteVol},
resources,
}; };
use common_net::sync::WorldSyncExt; use common_net::sync::WorldSyncExt;
use hashbrown::{HashMap, HashSet}; use hashbrown::{HashMap, HashSet};
@ -21,7 +22,6 @@ use specs::{
use std::{sync::Arc, time::Duration}; use std::{sync::Arc, time::Duration};
use tracing::info; use tracing::info;
use vek::*; use vek::*;
use crate::plugin::PluginMgr;
/// How much faster should an in-game day be compared to a real day? /// How much faster should an in-game day be compared to a real day?
// TODO: Don't hard-code this. // TODO: Don't hard-code this.
@ -90,6 +90,7 @@ pub struct State {
impl State { impl State {
/// Create a new `State` in client mode. /// Create a new `State` in client mode.
pub fn client() -> Self { Self::new(resources::GameMode::Client) } pub fn client() -> Self { Self::new(resources::GameMode::Client) }
/// Create a new `State` in server mode. /// Create a new `State` in server mode.
pub fn server() -> Self { Self::new(resources::GameMode::Server) } pub fn server() -> Self { Self::new(resources::GameMode::Server) }
@ -192,9 +193,9 @@ impl State {
// Load plugins from asset directory // Load plugins from asset directory
ecs.insert(match PluginMgr::from_assets() { ecs.insert(match PluginMgr::from_assets() {
Ok(plugin_mgr) => { Ok(plugin_mgr) => {
if let Err(e) = plugin_mgr.execute_event("on_load", &plugin_api::event::PluginLoadEvent { if let Err(e) = plugin_mgr
game_mode, .execute_event("on_load", &plugin_api::event::PluginLoadEvent { game_mode })
}) { {
tracing::error!(?e, "Failed to run plugin init"); tracing::error!(?e, "Failed to run plugin init");
info!("Error occurred when loading plugins. Running without plugins instead."); info!("Error occurred when loading plugins. Running without plugins instead.");
PluginMgr::default() PluginMgr::default()

View File

@ -1,15 +1,15 @@
use serde::{Serialize, de::DeserializeOwned, Deserialize};
use common::uid::Uid; use common::uid::Uid;
use serde::{de::DeserializeOwned, Deserialize, Serialize};
#[derive(Deserialize,Serialize,Debug)] #[derive(Deserialize, Serialize, Debug)]
pub enum Action { pub enum Action {
ServerClose, ServerClose,
Print(String), Print(String),
PlayerSendMessage(usize,String), PlayerSendMessage(usize, String),
KillEntity(usize) KillEntity(usize),
} }
pub trait Event: Serialize + DeserializeOwned + Send + Sync{ pub trait Event: Serialize + DeserializeOwned + Send + Sync {
type Response: Serialize + DeserializeOwned + Send + Sync; type Response: Serialize + DeserializeOwned + Send + Sync;
} }
@ -17,7 +17,7 @@ pub use common::resources::GameMode;
pub mod event { pub mod event {
use super::*; use super::*;
use serde::{Serialize,Deserialize}; use serde::{Deserialize, Serialize};
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct ChatCommandEvent { pub struct ChatCommandEvent {
@ -38,7 +38,7 @@ pub mod event {
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub struct PlayerJoinEvent { pub struct PlayerJoinEvent {
pub player_name: String, pub player_name: String,
pub player_id: usize pub player_id: usize,
} }
impl Event for PlayerJoinEvent { impl Event for PlayerJoinEvent {
@ -48,13 +48,11 @@ pub mod event {
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]
pub enum PlayerJoinResult { pub enum PlayerJoinResult {
CloseConnection, CloseConnection,
None None,
} }
impl Default for PlayerJoinResult { impl Default for PlayerJoinResult {
fn default() -> Self { fn default() -> Self { Self::None }
Self::None
}
} }
#[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)]

View File

@ -5,16 +5,13 @@ pub extern crate plugin_derive;
pub use plugin_api as api; pub use plugin_api as api;
pub use plugin_derive::*; pub use plugin_derive::*;
use serde::de::DeserializeOwned; use serde::{de::DeserializeOwned, Serialize};
use serde::Serialize;
extern "C" { extern "C" {
fn raw_emit_actions(ptr: *const u8, len: usize); fn raw_emit_actions(ptr: *const u8, len: usize);
} }
pub fn emit_action(action: api::Action) { pub fn emit_action(action: api::Action) { emit_actions(vec![action]) }
emit_actions(vec![action])
}
pub fn emit_actions(actions: Vec<api::Action>) { pub fn emit_actions(actions: Vec<api::Action>) {
let ret = bincode::serialize(&actions).unwrap(); let ret = bincode::serialize(&actions).unwrap();
@ -23,11 +20,12 @@ pub fn emit_actions(actions: Vec<api::Action>) {
} }
} }
pub fn read_input<T>(ptr: i32, len: u32) -> Result<T, &'static str> where T: DeserializeOwned{ pub fn read_input<T>(ptr: i32, len: u32) -> Result<T, &'static str>
let slice = unsafe { where
::std::slice::from_raw_parts(ptr as _, len as _) T: DeserializeOwned,
}; {
bincode::deserialize(slice).map_err(|_|"Failed to deserialize function input") let slice = unsafe { ::std::slice::from_raw_parts(ptr as _, len as _) };
bincode::deserialize(slice).map_err(|_| "Failed to deserialize function input")
} }
pub fn write_output(value: impl Serialize) -> i32 { pub fn write_output(value: impl Serialize) -> i32 {

View File

@ -19,8 +19,8 @@ use common::{
event::{EventBus, ServerEvent}, event::{EventBus, ServerEvent},
npc::{self, get_npc_name}, npc::{self, get_npc_name},
resources::TimeOfDay, resources::TimeOfDay,
uid::Uid,
terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize}, terrain::{Block, BlockKind, SpriteKind, TerrainChunkSize},
uid::Uid,
util::Dir, util::Dir,
vol::RectVolSize, vol::RectVolSize,
Damage, DamageSource, Explosion, LoadoutBuilder, RadiusEffect, Damage, DamageSource, Explosion, LoadoutBuilder, RadiusEffect,
@ -48,10 +48,10 @@ impl ChatCommandExt for ChatCommand {
if self.needs_admin() && !server.entity_is_admin(entity) { if self.needs_admin() && !server.entity_is_admin(entity) {
server.notify_client( server.notify_client(
entity, entity,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"You don't have permission to use '/{}'.", ChatType::CommandError,
self.keyword() format!("You don't have permission to use '/{}'.", self.keyword()),
)), ),
); );
return; return;
} else { } else {
@ -150,10 +150,13 @@ fn handle_give_item(
if inv.push(item).is_some() { if inv.push(item).is_some() {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Player inventory full. Gave 0 of {} items.", ChatType::CommandError,
give_amount format!(
)), "Player inventory full. Gave 0 of {} items.",
give_amount
),
),
); );
} }
}); });
@ -169,10 +172,13 @@ fn handle_give_item(
if inv.push(item.duplicate()).is_some() { if inv.push(item.duplicate()).is_some() {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Player inventory full. Gave {} of {} items.", ChatType::CommandError,
i, give_amount format!(
)), "Player inventory full. Gave {} of {} items.",
i, give_amount
),
),
); );
break; break;
} }
@ -191,7 +197,10 @@ fn handle_give_item(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Invalid item: {}", item_name)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Invalid item: {}", item_name),
),
); );
} }
} else { } else {
@ -218,13 +227,19 @@ fn handle_make_block(
), ),
None => server.notify_client( None => server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, String::from("You have no position.")), ServerGeneral::server_msg(
ChatType::CommandError,
String::from("You have no position."),
),
), ),
} }
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Invalid block kind: {}", block_name)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Invalid block kind: {}", block_name),
),
); );
} }
} else { } else {
@ -257,13 +272,19 @@ fn handle_make_sprite(
}, },
None => server.notify_client( None => server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, String::from("You have no position.")), ServerGeneral::server_msg(
ChatType::CommandError,
String::from("You have no position."),
),
), ),
} }
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Invalid sprite kind: {}", sprite_name)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Invalid sprite kind: {}", sprite_name),
),
); );
} }
} else { } else {
@ -283,7 +304,10 @@ fn handle_motd(
) { ) {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, (*server.editable_settings().server_description).clone()), ServerGeneral::server_msg(
ChatType::CommandError,
(*server.editable_settings().server_description).clone(),
),
); );
} }
@ -303,7 +327,10 @@ fn handle_set_motd(
.edit(data_dir.as_ref(), |d| **d = msg.clone()); .edit(data_dir.as_ref(), |d| **d = msg.clone());
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Server description set to \"{}\"", msg)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Server description set to \"{}\"", msg),
),
); );
}, },
Err(_) => { Err(_) => {
@ -313,7 +340,10 @@ fn handle_set_motd(
.edit(data_dir.as_ref(), |d| d.clear()); .edit(data_dir.as_ref(), |d| d.clear());
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Removed server description".to_string()), ServerGeneral::server_msg(
ChatType::CommandError,
"Removed server description".to_string(),
),
); );
}, },
} }
@ -459,7 +489,10 @@ fn handle_time(
None => { None => {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("'{}' is not a valid time.", n)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("'{}' is not a valid time.", n),
),
); );
return; return;
}, },
@ -518,7 +551,10 @@ fn handle_time(
Some(time) => format!("It is {}", time.format("%H:%M").to_string()), Some(time) => format!("It is {}", time.format("%H:%M").to_string()),
None => String::from("Unknown Time"), None => String::from("Unknown Time"),
}; };
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, msg)); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, msg),
);
return; return;
}, },
}; };
@ -530,10 +566,10 @@ fn handle_time(
{ {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!( ServerGeneral::server_msg(
"Time changed to: {}", ChatType::CommandInfo,
new_time.format("%H:%M").to_string(), format!("Time changed to: {}", new_time.format("%H:%M").to_string(),),
)), ),
); );
} }
} }
@ -585,7 +621,10 @@ fn handle_alias(
if let Ok(alias) = scan_fmt!(&args, &action.arg_fmt(), String) { if let Ok(alias) = scan_fmt!(&args, &action.arg_fmt(), String) {
if !comp::Player::alias_is_valid(&alias) { if !comp::Player::alias_is_valid(&alias) {
// Prevent silly aliases // Prevent silly aliases
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandError, "Invalid alias.")); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandError, "Invalid alias."),
);
return; return;
} }
let old_alias_optional = server let old_alias_optional = server
@ -610,9 +649,10 @@ fn handle_alias(
// Announce alias change if target has a Body. // Announce alias change if target has a Body.
if ecs.read_storage::<comp::Body>().get(target).is_some() { if ecs.read_storage::<comp::Body>().get(target).is_some() {
server.state.notify_players( server.state.notify_players(ServerGeneral::server_msg(
ServerGeneral::server_msg(ChatType::CommandInfo, format!("{} is now known as {}.", old_alias, player.alias)), ChatType::CommandInfo,
); format!("{} is now known as {}.", old_alias, player.alias),
));
} }
} }
} else { } else {
@ -657,7 +697,10 @@ fn handle_tp(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Unable to teleport to player!"), ServerGeneral::server_msg(
ChatType::CommandError,
"Unable to teleport to player!",
),
); );
} }
} else { } else {
@ -792,13 +835,19 @@ fn handle_spawn(
if let Some(uid) = server.state.ecs().uid_from_entity(new_entity) { if let Some(uid) = server.state.ecs().uid_from_entity(new_entity) {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("Spawned entity with ID: {}", uid)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("Spawned entity with ID: {}", uid),
),
); );
} }
} }
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("Spawned {} entities", amount)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("Spawned {} entities", amount),
),
); );
}, },
None => server.notify_client( None => server.notify_client(
@ -920,18 +969,21 @@ fn handle_players(
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, entity_tuples.join().fold( ServerGeneral::server_msg(
format!("{} online players:", entity_tuples.join().count()), ChatType::CommandInfo,
|s, (_, player, stat)| { entity_tuples.join().fold(
format!( format!("{} online players:", entity_tuples.join().count()),
"{}\n[{}]{} Lvl {}", |s, (_, player, stat)| {
s, format!(
player.alias, "{}\n[{}]{} Lvl {}",
stat.name, s,
stat.level.level() player.alias,
) stat.name,
}, stat.level.level()
)), )
},
),
),
); );
} }
@ -978,7 +1030,10 @@ fn handle_help(
action: &ChatCommand, action: &ChatCommand,
) { ) {
if let Some(cmd) = scan_fmt_some!(&args, &action.arg_fmt(), ChatCommand) { if let Some(cmd) = scan_fmt_some!(&args, &action.arg_fmt(), ChatCommand) {
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, cmd.help_string())); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, cmd.help_string()),
);
} else { } else {
let mut message = String::new(); let mut message = String::new();
for cmd in CHAT_COMMANDS.iter() { for cmd in CHAT_COMMANDS.iter() {
@ -991,7 +1046,10 @@ fn handle_help(
for (k, v) in CHAT_SHORTCUTS.iter() { for (k, v) in CHAT_SHORTCUTS.iter() {
message += &format!(" /{} => /{}", k, v.keyword()); message += &format!(" /{} => /{}", k, v.keyword());
} }
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, message)); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, message),
);
} }
} }
@ -1025,7 +1083,10 @@ fn handle_kill_npcs(
} else { } else {
"No NPCs on server.".to_string() "No NPCs on server.".to_string()
}; };
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, text)); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, text),
);
} }
#[allow(clippy::float_cmp)] // TODO: Pending review in #587 #[allow(clippy::float_cmp)] // TODO: Pending review in #587
@ -1079,10 +1140,10 @@ fn handle_object(
.build(); .build();
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!( ServerGeneral::server_msg(
"Spawned: {}", ChatType::CommandInfo,
obj_str_res.unwrap_or("<Unknown object>") format!("Spawned: {}", obj_str_res.unwrap_or("<Unknown object>")),
)), ),
); );
} else { } else {
return server.notify_client( return server.notify_client(
@ -1116,7 +1177,10 @@ fn handle_light(
if r < 0.0 || g < 0.0 || b < 0.0 { if r < 0.0 || g < 0.0 || b < 0.0 {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "cr, cg and cb values mustn't be negative."), ServerGeneral::server_msg(
ChatType::CommandError,
"cr, cg and cb values mustn't be negative.",
),
); );
return; return;
} }
@ -1155,7 +1219,10 @@ fn handle_light(
} else { } else {
builder.build(); builder.build();
} }
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, "Spawned object.")); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, "Spawned object."),
);
} else { } else {
server.notify_client( server.notify_client(
client, client,
@ -1189,12 +1256,18 @@ fn handle_lantern(
.into(); .into();
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, "You adjusted flame strength and color."), ServerGeneral::server_msg(
ChatType::CommandInfo,
"You adjusted flame strength and color.",
),
); );
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, "You adjusted flame strength."), ServerGeneral::server_msg(
ChatType::CommandInfo,
"You adjusted flame strength.",
),
); );
} }
} else { } else {
@ -1223,13 +1296,19 @@ fn handle_explosion(
if power > 512.0 { if power > 512.0 {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Explosion power mustn't be more than 512."), ServerGeneral::server_msg(
ChatType::CommandError,
"Explosion power mustn't be more than 512.",
),
); );
return; return;
} else if power <= 0.0 { } else if power <= 0.0 {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Explosion power must be more than 0."), ServerGeneral::server_msg(
ChatType::CommandError,
"Explosion power must be more than 0.",
),
); );
return; return;
} }
@ -1281,7 +1360,10 @@ fn handle_waypoint(
.ecs() .ecs()
.write_storage::<comp::Waypoint>() .write_storage::<comp::Waypoint>()
.insert(target, comp::Waypoint::temp_new(pos.0, *time)); .insert(target, comp::Waypoint::temp_new(pos.0, *time));
server.notify_client(client, ServerGeneral::server_msg(ChatType::CommandInfo, "Waypoint saved!")); server.notify_client(
client,
ServerGeneral::server_msg(ChatType::CommandInfo, "Waypoint saved!"),
);
server.notify_client( server.notify_client(
client, client,
ServerGeneral::Notification(Notification::WaypointSaved), ServerGeneral::Notification(Notification::WaypointSaved),
@ -1332,7 +1414,10 @@ fn handle_adminify(
None => { None => {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player '{}' not found!", alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player '{}' not found!", alias),
),
); );
}, },
} }
@ -1394,7 +1479,10 @@ fn handle_tell(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player '{}' not found!", alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player '{}' not found!", alias),
),
); );
} }
} else { } else {
@ -1432,7 +1520,10 @@ fn handle_faction(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Please join a faction with /join_faction"), ServerGeneral::server_msg(
ChatType::CommandError,
"Please join a faction with /join_faction",
),
); );
} }
} }
@ -1497,12 +1588,18 @@ fn handle_group_invite(
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("Invited {} to the group.", target_alias)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("Invited {} to the group.", target_alias),
),
); );
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player with alias {} not found", target_alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player with alias {} not found", target_alias),
),
) )
} }
} else { } else {
@ -1539,7 +1636,10 @@ fn handle_group_kick(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player with alias {} not found", target_alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player with alias {} not found", target_alias),
),
) )
} }
} else { } else {
@ -1593,7 +1693,10 @@ fn handle_group_promote(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player with alias {} not found", target_alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player with alias {} not found", target_alias),
),
) )
} }
} else { } else {
@ -1760,7 +1863,10 @@ fn handle_debug_column(
) { ) {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Unsupported without worldgen enabled"), ServerGeneral::server_msg(
ChatType::CommandError,
"Unsupported without worldgen enabled",
),
); );
} }
@ -1782,7 +1888,10 @@ fn handle_debug_column(
Some(pos) => wpos = pos.0.xy().map(|x| x as i32), Some(pos) => wpos = pos.0.xy().map(|x| x as i32),
None => server.notify_client( None => server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, String::from("You have no position.")), ServerGeneral::server_msg(
ChatType::CommandError,
String::from("You have no position."),
),
), ),
} }
} }
@ -1858,7 +1967,10 @@ fn find_target(
.find(|(_, player)| player.alias == alias) .find(|(_, player)| player.alias == alias)
.map(|(entity, _)| entity) .map(|(entity, _)| entity)
.ok_or_else(|| { .ok_or_else(|| {
ServerGeneral::server_msg(ChatType::CommandError, format!("Player '{}' not found!", alias)) ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player '{}' not found!", alias),
)
}) })
} else { } else {
Ok(fallback) Ok(fallback)
@ -1885,7 +1997,10 @@ fn handle_give_exp(
if let Some(stats) = ecs.write_storage::<comp::Stats>().get_mut(player) { if let Some(stats) = ecs.write_storage::<comp::Stats>().get_mut(player) {
stats.exp.change_by(exp); stats.exp.change_by(exp);
} else { } else {
error_msg = Some(ServerGeneral::server_msg(ChatType::CommandError, "Player has no stats!")); error_msg = Some(ServerGeneral::server_msg(
ChatType::CommandError,
"Player has no stats!",
));
} }
}, },
Err(e) => { Err(e) => {
@ -1936,7 +2051,10 @@ fn handle_set_level(
stats.level.set_level(lvl); stats.level.set_level(lvl);
body_type = Some(stats.body_type); body_type = Some(stats.body_type);
} else { } else {
error_msg = Some(ServerGeneral::server_msg(ChatType::CommandError, "Player has no stats!")); error_msg = Some(ServerGeneral::server_msg(
ChatType::CommandError,
"Player has no stats!",
));
body_type = None; body_type = None;
} }
@ -1986,7 +2104,10 @@ fn handle_debug(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, "Debug items not found? Something is very broken."), ServerGeneral::server_msg(
ChatType::CommandError,
"Debug items not found? Something is very broken.",
),
); );
} }
} }
@ -2070,7 +2191,10 @@ fn handle_sudo(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Unknown command: /{}", cmd)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Unknown command: /{}", cmd),
),
); );
} }
} else { } else {
@ -2090,11 +2214,14 @@ fn handle_version(
) { ) {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!( ServerGeneral::server_msg(
"Server is running {}[{}]", ChatType::CommandInfo,
common::util::GIT_HASH.to_string(), format!(
common::util::GIT_DATE.to_string(), "Server is running {}[{}]",
)), common::util::GIT_HASH.to_string(),
common::util::GIT_DATE.to_string(),
),
),
); );
} }
@ -2115,10 +2242,10 @@ fn handle_whitelist(
.map_err(|_| { .map_err(|_| {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Unable to determine UUID for username \"{}\"", ChatType::CommandError,
&username format!("Unable to determine UUID for username \"{}\"", &username),
)), ),
) )
}) })
.ok() .ok()
@ -2132,7 +2259,10 @@ fn handle_whitelist(
.edit(server.data_dir().as_ref(), |w| w.insert(uuid)); .edit(server.data_dir().as_ref(), |w| w.insert(uuid));
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("\"{}\" added to whitelist", username)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("\"{}\" added to whitelist", username),
),
); );
} }
} else if whitelist_action.eq_ignore_ascii_case("remove") { } else if whitelist_action.eq_ignore_ascii_case("remove") {
@ -2143,7 +2273,10 @@ fn handle_whitelist(
.edit(server.data_dir().as_ref(), |w| w.remove(&uuid)); .edit(server.data_dir().as_ref(), |w| w.remove(&uuid));
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("\"{}\" removed from whitelist", username)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("\"{}\" removed from whitelist", username),
),
); );
} }
} else { } else {
@ -2193,15 +2326,21 @@ fn handle_kick(
kick_player(server, target_player, &reason); kick_player(server, target_player, &reason);
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!( ServerGeneral::server_msg(
"Kicked {} from the server with reason: {}", ChatType::CommandInfo,
target_alias, reason format!(
)), "Kicked {} from the server with reason: {}",
target_alias, reason
),
),
); );
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("Player with alias {} not found", target_alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("Player with alias {} not found", target_alias),
),
) )
} }
} else { } else {
@ -2233,7 +2372,10 @@ fn handle_ban(
if server.editable_settings().banlist.contains_key(&uuid) { if server.editable_settings().banlist.contains_key(&uuid) {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!("{} is already on the banlist", target_alias)), ServerGeneral::server_msg(
ChatType::CommandError,
format!("{} is already on the banlist", target_alias),
),
) )
} else { } else {
server server
@ -2247,10 +2389,13 @@ fn handle_ban(
}); });
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!( ServerGeneral::server_msg(
"Added {} to the banlist with reason: {}", ChatType::CommandInfo,
target_alias, reason format!(
)), "Added {} to the banlist with reason: {}",
target_alias, reason
),
),
); );
// If the player is online kick them // If the player is online kick them
@ -2266,10 +2411,10 @@ fn handle_ban(
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Unable to determine UUID for username \"{}\"", ChatType::CommandError,
target_alias format!("Unable to determine UUID for username \"{}\"", target_alias),
)), ),
) )
} }
} else { } else {
@ -2303,15 +2448,18 @@ fn handle_unban(
}); });
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandInfo, format!("{} was successfully unbanned", username)), ServerGeneral::server_msg(
ChatType::CommandInfo,
format!("{} was successfully unbanned", username),
),
); );
} else { } else {
server.notify_client( server.notify_client(
client, client,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Unable to determine UUID for username \"{}\"", ChatType::CommandError,
username format!("Unable to determine UUID for username \"{}\"", username),
)), ),
) )
} }
} else { } else {

View File

@ -16,8 +16,8 @@ use common::{
lottery::Lottery, lottery::Lottery,
outcome::Outcome, outcome::Outcome,
rtsim::RtSimEntity, rtsim::RtSimEntity,
uid::{Uid, UidAllocator},
terrain::{Block, TerrainGrid}, terrain::{Block, TerrainGrid},
uid::{Uid, UidAllocator},
vol::ReadVol, vol::ReadVol,
Damage, DamageSource, Explosion, GroupTarget, RadiusEffect, Damage, DamageSource, Explosion, GroupTarget, RadiusEffect,
}; };
@ -227,8 +227,10 @@ pub fn handle_destroy(server: &mut Server, entity: EcsEntity, cause: HealthSourc
| HealthSource::Heal { by: _ } | HealthSource::Heal { by: _ }
| HealthSource::Unknown => KillSource::Other, | HealthSource::Unknown => KillSource::Other,
}; };
state state.notify_players(ServerGeneral::server_msg(
.notify_players(ServerGeneral::server_msg(comp::ChatType::Kill(kill_source, *uid), "".to_string())); comp::ChatType::Kill(kill_source, *uid),
"".to_string(),
));
} }
} }

View File

@ -98,8 +98,8 @@ pub fn handle_group(server: &mut Server, entity: specs::Entity, manip: GroupMani
if let Some(client) = clients.get(entity) { if let Some(client) = clients.get(entity) {
client.send_fallible(ServerGeneral::server_msg( client.send_fallible(ServerGeneral::server_msg(
ChatType::Meta, ChatType::Meta,
"Invite failed, pending invites plus current group size have reached \ "Invite failed, pending invites plus current group size have reached the \
the group size limit" group size limit"
.to_owned(), .to_owned(),
)); ));
} }

View File

@ -55,18 +55,17 @@ use common::{
recipe::default_recipe_book, recipe::default_recipe_book,
resources::TimeOfDay, resources::TimeOfDay,
rtsim::RtSimEntity, rtsim::RtSimEntity,
uid::Uid,
terrain::TerrainChunkSize, terrain::TerrainChunkSize,
uid::Uid,
vol::{ReadVol, RectVolSize}, vol::{ReadVol, RectVolSize},
}; };
use common_net::{ use common_net::{
msg::{
ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg,
},
sync::WorldSyncExt, sync::WorldSyncExt,
msg::{ClientType, DisconnectReason, ServerGeneral, ServerInfo, ServerInit, ServerMsg, WorldMapMsg},
};
use common_sys::{
state::State,
plugin::PluginMgr,
}; };
use common_sys::{plugin::PluginMgr, state::State};
use futures_executor::block_on; use futures_executor::block_on;
use metrics::{PhysicsMetrics, ServerMetrics, StateTickMetrics, TickMetrics}; use metrics::{PhysicsMetrics, ServerMetrics, StateTickMetrics, TickMetrics};
use network::{Network, Pid, ProtocolAddr}; use network::{Network, Pid, ProtocolAddr};
@ -1013,60 +1012,77 @@ impl Server {
command.execute(self, entity, args); command.execute(self, entity, args);
} else { } else {
let plugin_manager = self.state.ecs().read_resource::<PluginMgr>(); let plugin_manager = self.state.ecs().read_resource::<PluginMgr>();
let rs = plugin_manager.execute_event(&format!("on_command_{}",&kwd), &plugin_api::event::ChatCommandEvent { let rs = plugin_manager.execute_event(
command: kwd.clone(), &format!("on_command_{}", &kwd),
command_args: args.split(" ").map(|x| x.to_owned()).collect(), &plugin_api::event::ChatCommandEvent {
player: plugin_api::event::Player { command: kwd.clone(),
id: (*(self.state.ecs().read_storage::<Uid>().get(entity).expect("Can't get player UUID [This should never appen]"))).into() command_args: args.split(' ').map(|x| x.to_owned()).collect(),
player: plugin_api::event::Player {
id: *(self
.state
.ecs()
.read_storage::<Uid>()
.get(entity)
.expect("Can't get player UUID [This should never appen]")),
},
}, },
}); );
match rs { match rs {
Ok(e) => { Ok(e) => {
if e.is_empty() { if e.is_empty() {
self.notify_client( self.notify_client(
entity, entity,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Unknown command '/{}'.\nType '/help' for available commands", ChatType::CommandError,
kwd format!(
)) "Unknown command '/{}'.\nType '/help' for available commands",
kwd
),
),
); );
} else { } else {
e.into_iter().for_each(|e| { e.into_iter().for_each(|e| match e {
match e { Ok(e) => {
Ok(e) => { if !e.is_empty() {
if !e.is_empty() {
self.notify_client(
entity,
ServerGeneral::server_msg(ChatType::CommandInfo, e.join("\n")),
);
}
},
Err(e) => {
self.notify_client( self.notify_client(
entity, entity,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Error occurred while executing command '/{}'.\n{}", ChatType::CommandInfo,
kwd, e.join("\n"),
e ),
)),
); );
} }
} },
Err(e) => {
self.notify_client(
entity,
ServerGeneral::server_msg(
ChatType::CommandError,
format!(
"Error occurred while executing command '/{}'.\n{}",
kwd, e
),
),
);
},
}); });
} }
}, },
Err(e) => { Err(e) => {
error!(?e, "Can't execute command {} {}",kwd,args); error!(?e, "Can't execute command {} {}", kwd, args);
self.notify_client( self.notify_client(
entity, entity,
ServerGeneral::server_msg(ChatType::CommandError, format!( ServerGeneral::server_msg(
"Internal error while executing '/{}'.\nContact the server administrator", ChatType::CommandError,
kwd format!(
)) "Internal error while executing '/{}'.\nContact the server \
administrator",
kwd
),
),
); );
} },
} }
} }
} }

View File

@ -13,8 +13,8 @@ use common::{
region::{Event as RegionEvent, RegionMap}, region::{Event as RegionEvent, RegionMap},
resources::TimeOfDay, resources::TimeOfDay,
span, span,
uid::Uid,
terrain::TerrainChunkSize, terrain::TerrainChunkSize,
uid::Uid,
vol::RectVolSize, vol::RectVolSize,
}; };
use common_net::{msg::ServerGeneral, sync::CompSyncPackage}; use common_net::{msg::ServerGeneral, sync::CompSyncPackage};

View File

@ -7,7 +7,9 @@ use common::{
span, span,
uid::Uid, uid::Uid,
}; };
use common_net::msg::{validate_chat_msg, ChatMsgValidationError, ClientGeneral, MAX_BYTES_CHAT_MSG}; use common_net::msg::{
validate_chat_msg, ChatMsgValidationError, ClientGeneral, MAX_BYTES_CHAT_MSG,
};
use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write}; use specs::{Entities, Join, Read, ReadExpect, ReadStorage, System, Write};
use std::sync::atomic::Ordering; use std::sync::atomic::Ordering;
use tracing::{debug, error, warn}; use tracing::{debug, error, warn};

View File

@ -10,8 +10,8 @@ use common::{
comp::{Ori, Pos, Vel}, comp::{Ori, Pos, Vel},
region::{region_in_vd, regions_in_vd, Event as RegionEvent, RegionMap}, region::{region_in_vd, regions_in_vd, Event as RegionEvent, RegionMap},
span, span,
uid::Uid,
terrain::TerrainChunkSize, terrain::TerrainChunkSize,
uid::Uid,
vol::RectVolSize, vol::RectVolSize,
}; };
use common_net::msg::ServerGeneral; use common_net::msg::ServerGeneral;

View File

@ -328,9 +328,7 @@ impl<'a> Widget for Group<'a> {
let healths = client_state.ecs().read_storage::<common::comp::Health>(); let healths = client_state.ecs().read_storage::<common::comp::Health>();
let energy = client_state.ecs().read_storage::<common::comp::Energy>(); let energy = client_state.ecs().read_storage::<common::comp::Energy>();
let buffs = client_state.ecs().read_storage::<common::comp::Buffs>(); let buffs = client_state.ecs().read_storage::<common::comp::Buffs>();
let uid_allocator = client_state let uid_allocator = client_state.ecs().read_resource::<UidAllocator>();
.ecs()
.read_resource::<UidAllocator>();
// Keep track of the total number of widget ids we are using for buffs // Keep track of the total number of widget ids we are using for buffs
let mut total_buff_count = 0; let mut total_buff_count = 0;

View File

@ -5,11 +5,7 @@ use super::{
}; };
use crate::ui::{fonts::Fonts, img_ids}; use crate::ui::{fonts::Fonts, img_ids};
use client::{self, Client}; use client::{self, Client};
use common::{ use common::{comp, terrain::TerrainChunkSize, vol::RectVolSize};
comp,
terrain::TerrainChunkSize,
vol::RectVolSize,
};
use common_net::msg::world_msg::SiteKind; use common_net::msg::world_msg::SiteKind;
use conrod_core::{ use conrod_core::{
color, position, color, position,

View File

@ -62,12 +62,12 @@ use common::{
BuffKind, BuffKind,
}, },
span, span,
uid::Uid,
terrain::TerrainChunk, terrain::TerrainChunk,
uid::Uid,
util::srgba_to_linear, util::srgba_to_linear,
vol::RectRasterableVol, vol::RectRasterableVol,
}; };
use common_net::msg::{PresenceKind, Notification}; use common_net::msg::{Notification, PresenceKind};
use conrod_core::{ use conrod_core::{
text::cursor::Index, text::cursor::Index,
widget::{self, Button, Image, Text}, widget::{self, Button, Image, Text},
@ -2439,9 +2439,7 @@ impl Hud {
pub fn new_message(&mut self, msg: comp::ChatMsg) { self.new_messages.push_back(msg); } pub fn new_message(&mut self, msg: comp::ChatMsg) { self.new_messages.push_back(msg); }
pub fn new_notification(&mut self, msg: Notification) { pub fn new_notification(&mut self, msg: Notification) { self.new_notifications.push_back(msg); }
self.new_notifications.push_back(msg);
}
pub fn scale_change(&mut self, scale_change: ScaleChange) -> ScaleMode { pub fn scale_change(&mut self, scale_change: ScaleChange) -> ScaleMode {
let scale_mode = match scale_change { let scale_mode = match scale_change {