Add Debug impls for a few plugin things

This commit is contained in:
Imbris 2021-01-23 13:44:46 -05:00
parent 457026a48e
commit b5ca279634
3 changed files with 180 additions and 127 deletions

View File

@ -24,18 +24,13 @@ use rayon::prelude::*;
pub enum PluginEnvironement {
LOCAL,
DISTANT,
BOTH
BOTH,
}
impl PluginEnvironement {
pub fn is_local(&self) -> bool { matches!(self, Self::LOCAL | Self::BOTH) }
pub fn is_local(&self) -> bool {
matches!(self, Self::LOCAL | Self::BOTH)
}
pub fn is_distant(&self) -> bool {
matches!(self, Self::DISTANT | Self::BOTH)
}
pub fn is_distant(&self) -> bool { matches!(self, Self::DISTANT | Self::BOTH) }
}
#[derive(Clone, Debug, Serialize, Deserialize)]
@ -62,6 +57,28 @@ pub enum PluginFile {
modules: Vec<PluginModule>,
files: HashMap<PathBuf, Vec<u8>>,
bytes: Vec<Vec<u8>>,
},
}
impl std::fmt::Debug for PluginFile {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
match self {
Self::ForDistant { data, bytes } => fmt
.debug_struct("ForDistant")
.field("data", data)
.field("num modules", &bytes.len())
.finish(),
Self::ForLocal { data, modules, .. } => fmt
.debug_struct("ForLocals")
.field("data", data)
.field("modules", modules)
.finish(),
Self::Both { data, modules, .. } => fmt
.debug_struct("Both")
.field("data", data)
.field("modules", modules)
.finish(),
}
}
}
@ -91,22 +108,26 @@ impl PluginFile {
)
.map_err(PluginError::Toml)?;
Ok(match (data.target.is_local(),data.target.is_distant()) {
(true,e) => {
Ok(match (data.target.is_local(), data.target.is_distant()) {
(true, e) => {
let mut bytes = Vec::new();
let modules = data
.modules
.iter()
.map(|path| {
let wasm_data = files.remove(path).ok_or(PluginError::NoSuchModule)?;
let tmp = PluginModule::new(data.name.to_owned(), &wasm_data).map_err(|e| {
PluginError::PluginModuleError(data.name.to_owned(), "<init>".to_owned(), e)
});
bytes.push(wasm_data);
tmp
})
.collect::<Result<_, _>>()?;
.modules
.iter()
.map(|path| {
let wasm_data = files.remove(path).ok_or(PluginError::NoSuchModule)?;
let tmp =
PluginModule::new(data.name.to_owned(), &wasm_data).map_err(|e| {
PluginError::PluginModuleError(
data.name.to_owned(),
"<init>".to_owned(),
e,
)
});
bytes.push(wasm_data);
tmp
})
.collect::<Result<_, _>>()?;
if e {
Self::Both {
data,
@ -122,30 +143,25 @@ impl PluginFile {
}
}
},
(false,_) => {
(false, _) => {
let bytes = data
.modules
.iter()
.map(|path| {
files.remove(path).ok_or(PluginError::NoSuchModule)
})
.collect::<Result<_, _>>()?;
Self::ForDistant {
data,
bytes,
}
}
.modules
.iter()
.map(|path| files.remove(path).ok_or(PluginError::NoSuchModule))
.collect::<Result<_, _>>()?;
Self::ForDistant { data, bytes }
},
})
}
pub fn get_data(&self) -> &PluginData {
// Wait for let-or syntax to be stable
match self {
Self::ForLocal {data,..} | Self::Both {data,..} | Self::ForDistant {data,..} => data
Self::ForLocal { data, .. }
| Self::Both { data, .. }
| Self::ForDistant { data, .. } => data,
}
}
}
impl PluginExecutable for PluginFile {
@ -157,35 +173,33 @@ impl PluginExecutable for PluginFile {
where
T: Event,
{
if let Self::ForLocal {modules,data,..} | Self::Both {modules,data,..} = self {
if let Self::ForLocal { modules, data, .. } | Self::Both { modules, data, .. } = self {
modules
.iter()
.flat_map(|module| {
module.try_execute(event_name, event).map(|x| {
x.map_err(|e| {
PluginError::PluginModuleError(
data.name.to_owned(),
event_name.to_owned(),
e,
)
.iter()
.flat_map(|module| {
module.try_execute(event_name, event).map(|x| {
x.map_err(|e| {
PluginError::PluginModuleError(
data.name.to_owned(),
event_name.to_owned(),
e,
)
})
})
})
})
.collect::<Result<Vec<_>, _>>()
.collect::<Result<Vec<_>, _>>()
} else {
Ok(Vec::new())
}
}
fn get_name(&self) -> &str {
&self.get_data().name
}
fn get_name(&self) -> &str { &self.get_data().name }
}
#[derive(Clone, Default)]
#[derive(Clone, Default, Debug)]
pub struct PluginMgr {
plugins: Vec<PluginFile>,
plugins_from_server: Vec<BinaryPlugin>
plugins_from_server: Vec<BinaryPlugin>,
}
impl PluginMgr {
@ -194,44 +208,70 @@ impl PluginMgr {
let mut assets_path = (&*ASSETS_PATH).clone();
assets_path.push("plugins");
info!("Searching {:?} for plugins...", assets_path);
Self::from_dir(assets_path)
let this = Self::from_dir(assets_path);
if this.is_ok() {
dbg!(&this.as_ref().unwrap().plugins);
}
this
}
pub fn load_server_plugins(&mut self, plugins: &Vec<(String,Vec<Vec<u8>>)>) {
let prepared = PreparedEventQuery::new(&plugin_api::event::PluginLoadEvent { game_mode: plugin_api::GameMode::Client }).unwrap();
self.plugins_from_server.extend(plugins.iter().flat_map(|(name,bytes)| {
info!("Loading {} with {} module(s) from server",name,bytes.len());
match BinaryPlugin::from_bytes(name.clone(), bytes) {
Ok(e) => {
if let Err(e) = e.modules.iter().flat_map(|x| {
x.try_execute("on_load", &prepared)
}).collect::<Result<Vec<_>, _>>() {
error!("Error while executing `on_load` on network retreived plugin: `{}` \n{:?}",name,e);
}
Some(e)
},
Err(e) => {
tracing::error!("Error while loading distant plugin! Contact the server administrator!\n{:?}",e);
pub fn load_server_plugins(&mut self, plugins: &Vec<(String, Vec<Vec<u8>>)>) {
let prepared = PreparedEventQuery::new(&plugin_api::event::PluginLoadEvent {
game_mode: plugin_api::GameMode::Client,
})
.unwrap();
self.plugins_from_server
.extend(plugins.iter().flat_map(|(name, bytes)| {
info!(
"Loading {} with {} module(s) from server",
name,
bytes.len()
);
match BinaryPlugin::from_bytes(name.clone(), bytes) {
Ok(e) => {
if let Err(e) = e
.modules
.iter()
.flat_map(|x| x.try_execute("on_load", &prepared))
.collect::<Result<Vec<_>, _>>()
{
error!(
"Error while executing `on_load` on network retreived plugin: \
`{}` \n{:?}",
name, e
);
}
Some(e)
},
Err(e) => {
tracing::error!(
"Error while loading distant plugin! Contact the server \
administrator!\n{:?}",
e
);
None
},
}
}));
println!("Plugins from server: {}", self.plugins_from_server.len());
dbg!(&self.plugins_from_server);
}
pub fn clear_server_plugins(&mut self) { self.plugins_from_server.clear(); }
pub fn get_module_bytes(&self) -> Vec<(String, Vec<Vec<u8>>)> {
self.plugins
.iter()
.flat_map(|x| {
if let PluginFile::ForDistant { data, bytes, .. }
| PluginFile::Both { data, bytes, .. } = x
{
Some((data.name.clone(), bytes.clone()))
} else {
None
}
}
}));
println!("Plugins from server: {}",self.plugins_from_server.len());
}
pub fn clear_server_plugins(&mut self) {
self.plugins_from_server.clear();
}
pub fn get_module_bytes(&self) -> Vec<(String,Vec<Vec<u8>>)> {
self.plugins.iter().flat_map(|x| {
if let PluginFile::ForDistant {data, bytes, ..} |
PluginFile::Both {data, bytes, ..} = x {
Some((data.name.clone(), bytes.clone()))
} else {
None
}
}).collect()
})
.collect()
}
pub fn execute_prepared<T>(
@ -242,7 +282,7 @@ impl PluginMgr {
where
T: Event,
{
println!("{}",event_name);
println!("{}", event_name);
let mut o = self
.plugins
.par_iter()
@ -251,17 +291,18 @@ impl PluginMgr {
.into_iter()
.flatten()
.collect::<Vec<_>>();
println!("Event exe 2 {}",self.plugins_from_server.len());
o.extend(self
.plugins_from_server
.par_iter()
.map(|plugin| {
println!("Event exe 3");
plugin.execute_prepared(event_name, event)
})
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten());
println!("Event exe 2 {}", self.plugins_from_server.len());
o.extend(
self.plugins_from_server
.par_iter()
.map(|plugin| {
println!("Event exe 3");
plugin.execute_prepared(event_name, event)
})
.collect::<Result<Vec<_>, _>>()?
.into_iter()
.flatten(),
);
Ok(o)
}
@ -273,7 +314,6 @@ impl PluginMgr {
where
T: Event,
{
println!("Event exe 1");
self.execute_prepared(event_name, &PreparedEventQuery::new(event)?)
}
@ -306,46 +346,51 @@ impl PluginMgr {
for plugin in &plugins {
match plugin {
PluginFile::Both { data, modules, .. } | PluginFile::ForLocal { data, modules, .. } => {
PluginFile::Both { data, modules, .. }
| PluginFile::ForLocal { data, modules, .. } => {
info!(
"Loaded plugin '{}' with {} module(s)",
data.name,
modules.len()
);
}
},
PluginFile::ForDistant { data, bytes } => {
info!(
"Loaded plugin '{}' with {} module(s)",
data.name,
bytes.len()
);
}
},
}
}
Ok(Self { plugins, plugins_from_server: Vec::new() })
Ok(Self {
plugins,
plugins_from_server: Vec::new(),
})
}
}
#[derive(Clone)]
#[derive(Clone, Debug)]
pub struct BinaryPlugin {
modules: Vec<PluginModule>,
name: String,
}
impl BinaryPlugin {
pub fn from_bytes(name: String, bytes: &Vec<Vec<u8>>) -> Result<Self, PluginError> {
Ok(
Self {
modules: bytes.iter().enumerate().map(|(i,module)| {
PluginModule::new(format!("{}-module({})",name,i), module).map_err(|e| {
Ok(Self {
modules: bytes
.iter()
.enumerate()
.map(|(i, module)| {
PluginModule::new(format!("{}-module({})", name, i), module).map_err(|e| {
PluginError::PluginModuleError(name.clone(), "<init>".to_owned(), e)
})
}).collect::<Result<Vec<_>,_>>()?,
name
}
)
})
.collect::<Result<Vec<_>, _>>()?,
name,
})
}
}
@ -362,7 +407,7 @@ impl PluginExecutable for BinaryPlugin {
self.modules
.iter()
.flat_map(|module| {
println!("1: {}",event_name);
println!("1: {}", event_name);
module.try_execute(event_name, event).map(|x| {
x.map_err(|e| {
PluginError::PluginModuleError(
@ -376,13 +421,10 @@ impl PluginExecutable for BinaryPlugin {
.collect::<Result<Vec<_>, _>>()
}
fn get_name(&self) -> &str {
&self.name
}
fn get_name(&self) -> &str { &self.name }
}
pub trait PluginExecutable {
fn execute_prepared<T>(
&self,
event_name: &str,

View File

@ -22,6 +22,15 @@ pub struct PluginModule {
name: String,
}
impl std::fmt::Debug for PluginModule {
fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result {
fmt.debug_struct("PluginModule")
.field("events", &self.events)
.field("name", &self.name)
.finish()
}
}
impl PluginModule {
// This function takes bytes from a WASM File and compile them
pub fn new(name: String, wasm_data: &[u8]) -> Result<Self, PluginModuleError> {

View File

@ -256,10 +256,10 @@ impl Server {
let map = WorldMapMsg {
dimensions_lg: Vec2::zero(),
max_height: 1.0,
rgba: vec![0],
rgba: common::grid::Grid::new(Vec2::new(1, 1), 1),
horizons: [(vec![0], vec![0]), (vec![0], vec![0])],
sea_level: 0.0,
alt: vec![30],
alt: common::grid::Grid::new(Vec2::new(1, 1), 1),
sites: Vec::new(),
};
@ -941,10 +941,12 @@ impl Server {
world_map: self.map.clone(),
recipe_book: default_recipe_book().cloned(),
#[cfg(feature = "plugins")]
plugins: Some(self
.state
.ecs()
.read_resource::<PluginMgr>().get_module_bytes()),
plugins: Some(
self.state
.ecs()
.read_resource::<PluginMgr>()
.get_module_bytes(),
),
#[cfg(not(feature = "plugins"))]
plugins: None,
ability_map: (&*self