From 98c06922600f70a76103385e7a432ab64292e13b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Piotr=20Korg=C3=B3l?= Date: Fri, 9 Aug 2019 16:22:59 +0200 Subject: [PATCH] Add AdminPerms component, make some commands require it --- common/src/comp/admin.rs | 7 + common/src/comp/mod.rs | 2 + common/src/state.rs | 1 + server/src/cmd.rs | 754 +++++++++++++++++++++------------------ 4 files changed, 408 insertions(+), 356 deletions(-) create mode 100644 common/src/comp/admin.rs diff --git a/common/src/comp/admin.rs b/common/src/comp/admin.rs new file mode 100644 index 0000000000..fd4c30c5fb --- /dev/null +++ b/common/src/comp/admin.rs @@ -0,0 +1,7 @@ +use specs::{Component, VecStorage}; + +pub struct AdminPerms; + +impl Component for AdminPerms { + type Storage = VecStorage; +} diff --git a/common/src/comp/mod.rs b/common/src/comp/mod.rs index bee5458a2c..7fd9c132fc 100644 --- a/common/src/comp/mod.rs +++ b/common/src/comp/mod.rs @@ -10,6 +10,7 @@ mod phys; mod player; mod stats; mod visual; +mod admin; // Reexports pub use action_state::ActionState; @@ -26,3 +27,4 @@ pub use phys::{ForceUpdate, Ori, Pos, Scale, Vel}; pub use player::Player; pub use stats::{Dying, Exp, HealthSource, Level, Stats}; pub use visual::LightEmitter; +pub use admin::AdminPerms; diff --git a/common/src/state.rs b/common/src/state.rs index 7c38442b2f..d6b4dbdace 100644 --- a/common/src/state.rs +++ b/common/src/state.rs @@ -145,6 +145,7 @@ impl State { ecs.register::(); ecs.register::(); ecs.register::(); + ecs.register::(); // Controller effects ecs.register::(); ecs.register::(); diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 9078851e6e..7d4d51e07d 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -161,44 +161,65 @@ lazy_static! { ]; } +fn is_admin(server: &mut Server, entity: EcsEntity) -> bool { + if server + .state + .read_storage::() + .get(entity) + .is_some() + { + true + } else { + server.clients.notify( + entity, + ServerMsg::private(String::from("You have no permissions to do that")), + ); + false + } +} + fn handle_jump(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { - match server.state.read_component_cloned::(entity) { - Some(current_pos) => { - server - .state - .write_component(entity, comp::Pos(current_pos.0 + Vec3::new(x, y, z))); - server.state.write_component(entity, comp::ForceUpdate); + if is_admin(server, entity) { + if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { + match server.state.read_component_cloned::(entity) { + Some(current_pos) => { + server + .state + .write_component(entity, comp::Pos(current_pos.0 + Vec3::new(x, y, z))); + server.state.write_component(entity, comp::ForceUpdate); + } + None => server.clients.notify( + entity, + ServerMsg::private(String::from("You have no position!")), + ), } - None => server.clients.notify( - entity, - ServerMsg::private(String::from("You have no position!")), - ), } } } fn handle_goto(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { - if server - .state - .read_component_cloned::(entity) - .is_some() - { - server + if is_admin(server, entity) { + if let Ok((x, y, z)) = scan_fmt!(&args, action.arg_fmt, f32, f32, f32) { + if server .state - .write_component(entity, comp::Pos(Vec3::new(x, y, z))); - server.state.write_component(entity, comp::ForceUpdate); + .read_component_cloned::(entity) + .is_some() + { + server + .state + .write_component(entity, comp::Pos(Vec3::new(x, y, z))); + server.state.write_component(entity, comp::ForceUpdate); + } else { + server.clients.notify( + entity, + ServerMsg::private(String::from("You don't have a position!")), + ); + } } else { - server.clients.notify( - entity, - ServerMsg::private(String::from("You don't have a position!")), - ); + server + .clients + .notify(entity, ServerMsg::private(String::from(action.help_string))); } - } else { - server - .clients - .notify(entity, ServerMsg::private(String::from(action.help_string))); } } @@ -212,74 +233,78 @@ fn handle_kill(server: &mut Server, entity: EcsEntity, _args: String, _action: & } fn handle_time(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - let time = scan_fmt_some!(&args, action.arg_fmt, String); - let new_time = match time.as_ref().map(|s| s.as_str()) { - Some("night") => NaiveTime::from_hms(0, 0, 0), - Some("dawn") => NaiveTime::from_hms(5, 0, 0), - Some("day") => NaiveTime::from_hms(12, 0, 0), - Some("dusk") => NaiveTime::from_hms(17, 0, 0), - Some(n) => match n.parse() { - Ok(n) => n, - Err(_) => match NaiveTime::parse_from_str(n, "%H:%M") { - Ok(time) => time, - Err(_) => { - server.clients.notify( - entity, - ServerMsg::private(format!("'{}' is not a valid time.", n)), - ); - return; - } + if is_admin(server, entity) { + let time = scan_fmt_some!(&args, action.arg_fmt, String); + let new_time = match time.as_ref().map(|s| s.as_str()) { + Some("night") => NaiveTime::from_hms(0, 0, 0), + Some("dawn") => NaiveTime::from_hms(5, 0, 0), + Some("day") => NaiveTime::from_hms(12, 0, 0), + Some("dusk") => NaiveTime::from_hms(17, 0, 0), + Some(n) => match n.parse() { + Ok(n) => n, + Err(_) => match NaiveTime::parse_from_str(n, "%H:%M") { + Ok(time) => time, + Err(_) => { + server.clients.notify( + entity, + ServerMsg::private(format!("'{}' is not a valid time.", n)), + ); + return; + } + }, }, - }, - None => { - let time_in_seconds = server.state.ecs_mut().read_resource::().0; + None => { + let time_in_seconds = server.state.ecs_mut().read_resource::().0; - let current_time = NaiveTime::from_num_seconds_from_midnight_opt( - // Wraps around back to 0s if it exceeds 24 hours (24 hours = 86400s) - (time_in_seconds as u64 % 86400) as u32, - 0, - ); - let msg = match current_time { - Some(time) => format!("Current time is: {}", time.format("%H:%M").to_string()), - None => String::from("Unknown Time"), - }; - server.clients.notify(entity, ServerMsg::private(msg)); - return; - } - }; + let current_time = NaiveTime::from_num_seconds_from_midnight_opt( + // Wraps around back to 0s if it exceeds 24 hours (24 hours = 86400s) + (time_in_seconds as u64 % 86400) as u32, + 0, + ); + let msg = match current_time { + Some(time) => format!("Current time is: {}", time.format("%H:%M").to_string()), + None => String::from("Unknown Time"), + }; + server.clients.notify(entity, ServerMsg::private(msg)); + return; + } + }; - server.state.ecs_mut().write_resource::().0 = - new_time.num_seconds_from_midnight() as f64; + server.state.ecs_mut().write_resource::().0 = + new_time.num_seconds_from_midnight() as f64; - server.clients.notify( - entity, - ServerMsg::private(format!( - "Time changed to: {}", - new_time.format("%H:%M").to_string() - )), - ); + server.clients.notify( + entity, + ServerMsg::private(format!( + "Time changed to: {}", + new_time.format("%H:%M").to_string() + )), + ); + } } fn handle_health(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - if let Ok(hp) = scan_fmt!(&args, action.arg_fmt, u32) { - if let Some(stats) = server - .state - .ecs_mut() - .write_storage::() - .get_mut(entity) - { - stats.health.set_to(hp, comp::HealthSource::Command); + if is_admin(server, entity) { + if let Ok(hp) = scan_fmt!(&args, action.arg_fmt, u32) { + if let Some(stats) = server + .state + .ecs_mut() + .write_storage::() + .get_mut(entity) + { + stats.health.set_to(hp, comp::HealthSource::Command); + } else { + server.clients.notify( + entity, + ServerMsg::private(String::from("You have no health.")), + ); + } } else { server.clients.notify( entity, - ServerMsg::private(String::from("You have no position.")), + ServerMsg::private(String::from("You must specify health amount!")), ); } - } else { - server.clients.notify( - entity, - ServerMsg::private(String::from("You must specify health amount!")), - ); } } @@ -299,89 +324,98 @@ fn handle_alias(server: &mut Server, entity: EcsEntity, args: String, action: &C } fn handle_tp(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { - let ecs = server.state.ecs(); - let opt_player = (&ecs.entities(), &ecs.read_storage::()) - .join() - .find(|(_, player)| player.alias == alias) - .map(|(entity, _)| entity); - match server.state.read_component_cloned::(entity) { - Some(_pos) => match opt_player { - Some(player) => match server.state.read_component_cloned::(player) { - Some(pos) => { - server.state.write_component(entity, pos); - server.state.write_component(entity, comp::ForceUpdate); + if is_admin(server, entity) { + if let Ok(alias) = scan_fmt!(&args, action.arg_fmt, String) { + let ecs = server.state.ecs(); + let opt_player = (&ecs.entities(), &ecs.read_storage::()) + .join() + .find(|(_, player)| player.alias == alias) + .map(|(entity, _)| entity); + match server.state.read_component_cloned::(entity) { + Some(_pos) => match opt_player { + Some(player) => match server.state.read_component_cloned::(player) { + Some(pos) => { + server.state.write_component(entity, pos); + server.state.write_component(entity, comp::ForceUpdate); + } + None => server.clients.notify( + entity, + ServerMsg::private(format!( + "Unable to teleport to player '{}'!", + alias + )), + ), + }, + None => { + server.clients.notify( + entity, + ServerMsg::private(format!("Player '{}' not found!", alias)), + ); + server + .clients + .notify(entity, ServerMsg::private(String::from(action.help_string))); } - None => server.clients.notify( - entity, - ServerMsg::private(format!("Unable to teleport to player '{}'!", alias)), - ), }, None => { - server.clients.notify( - entity, - ServerMsg::private(format!("Player '{}' not found!", alias)), - ); server .clients - .notify(entity, ServerMsg::private(String::from(action.help_string))); + .notify(entity, ServerMsg::private(format!("You have no position!"))); } - }, - None => { - server - .clients - .notify(entity, ServerMsg::private(format!("You have no position!"))); } + } else { + server + .clients + .notify(entity, ServerMsg::private(String::from(action.help_string))); } - } else { - server - .clients - .notify(entity, ServerMsg::private(String::from(action.help_string))); } } fn handle_spawn(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - match scan_fmt_some!(&args, action.arg_fmt, String, NpcKind, String) { - (Some(opt_align), Some(id), opt_amount) => { - if let Some(agent) = alignment_to_agent(&opt_align, entity) { - let amount = opt_amount - .and_then(|a| a.parse().ok()) - .filter(|x| *x > 0) - .unwrap_or(1) - .min(10); + if is_admin(server, entity) { + match scan_fmt_some!(&args, action.arg_fmt, String, NpcKind, String) { + (Some(opt_align), Some(id), opt_amount) => { + if let Some(agent) = alignment_to_agent(&opt_align, entity) { + let amount = opt_amount + .and_then(|a| a.parse().ok()) + .filter(|x| *x > 0) + .unwrap_or(1) + .min(10); - match server.state.read_component_cloned::(entity) { - Some(pos) => { - for _ in 0..amount { - let vel = Vec3::new( - rand::thread_rng().gen_range(-2.0, 3.0), - rand::thread_rng().gen_range(-2.0, 3.0), - 10.0, + match server.state.read_component_cloned::(entity) { + Some(pos) => { + for _ in 0..amount { + let vel = Vec3::new( + rand::thread_rng().gen_range(-2.0, 3.0), + rand::thread_rng().gen_range(-2.0, 3.0), + 10.0, + ); + + let body = kind_to_body(id); + server + .create_npc(pos, get_npc_name(id), body) + .with(comp::Vel(vel)) + .with(agent) + .build(); + } + server.clients.notify( + entity, + ServerMsg::private( + format!("Spawned {} entities", amount).to_owned(), + ), ); - - let body = kind_to_body(id); - server - .create_npc(pos, get_npc_name(id), body) - .with(comp::Vel(vel)) - .with(agent) - .build(); } - server.clients.notify( + None => server.clients.notify( entity, - ServerMsg::private(format!("Spawned {} entities", amount).to_owned()), - ); + ServerMsg::private("You have no position!".to_owned()), + ), } - None => server.clients.notify( - entity, - ServerMsg::private("You have no position!".to_owned()), - ), } } - } - _ => { - server - .clients - .notify(entity, ServerMsg::private(String::from(action.help_string))); + _ => { + server + .clients + .notify(entity, ServerMsg::private(String::from(action.help_string))); + } } } } @@ -411,31 +445,33 @@ fn handle_players(server: &mut Server, entity: EcsEntity, _args: String, _action } fn handle_build(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { - if server - .state - .read_storage::() - .get(entity) - .is_some() - { - server + if is_admin(server, entity) { + if server .state - .ecs() - .write_storage::() - .remove(entity); - server.clients.notify( - entity, - ServerMsg::private(String::from("Toggled off build mode!")), - ); - } else { - let _ = server - .state - .ecs() - .write_storage::() - .insert(entity, comp::CanBuild); - server.clients.notify( - entity, - ServerMsg::private(String::from("Toggled on build mode!")), - ); + .read_storage::() + .get(entity) + .is_some() + { + server + .state + .ecs() + .write_storage::() + .remove(entity); + server.clients.notify( + entity, + ServerMsg::private(String::from("Toggled off build mode!")), + ); + } else { + let _ = server + .state + .ecs() + .write_storage::() + .insert(entity, comp::CanBuild); + server.clients.notify( + entity, + ServerMsg::private(String::from("Toggled on build mode!")), + ); + } } } @@ -468,219 +504,225 @@ fn kind_to_body(kind: NpcKind) -> comp::Body { } fn handle_killnpcs(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { - let ecs = server.state.ecs(); - let mut stats = ecs.write_storage::(); - let players = ecs.read_storage::(); - let mut count = 0; - for (stats, ()) in (&mut stats, !&players).join() { - count += 1; - stats.health.set_to(0, comp::HealthSource::Command); + if is_admin(server, entity) { + let ecs = server.state.ecs(); + let mut stats = ecs.write_storage::(); + let players = ecs.read_storage::(); + let mut count = 0; + for (stats, ()) in (&mut stats, !&players).join() { + count += 1; + stats.health.set_to(0, comp::HealthSource::Command); + } + let text = if count > 0 { + format!("Destroyed {} NPCs.", count) + } else { + "No NPCs on server.".to_string() + }; + server.clients.notify(entity, ServerMsg::private(text)); } - let text = if count > 0 { - format!("Destroyed {} NPCs.", count) - } else { - "No NPCs on server.".to_string() - }; - server.clients.notify(entity, ServerMsg::private(text)); } fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: &ChatCommand) { - let obj_type = scan_fmt!(&args, _action.arg_fmt, String); + if is_admin(server, entity) { + let obj_type = scan_fmt!(&args, _action.arg_fmt, String); - let pos = server - .state - .ecs() - .read_storage::() - .get(entity) - .copied(); - let ori = server - .state - .ecs() - .read_storage::() - .get(entity) - .copied(); - /*let builder = server - .create_object(pos, ori, obj_type) - .with(ori);*/ - if let (Some(pos), Some(ori)) = (pos, ori) { - let obj_type = match obj_type.as_ref().map(String::as_str) { - Ok("scarecrow") => comp::object::Body::Scarecrow, - Ok("cauldron") => comp::object::Body::Cauldron, - Ok("chest_vines") => comp::object::Body::ChestVines, - Ok("chest") => comp::object::Body::Chest, - Ok("chest_dark") => comp::object::Body::ChestDark, - Ok("chest_demon") => comp::object::Body::ChestDemon, - Ok("chest_gold") => comp::object::Body::ChestGold, - Ok("chest_light") => comp::object::Body::ChestLight, - Ok("chest_open") => comp::object::Body::ChestOpen, - Ok("chest_skull") => comp::object::Body::ChestSkull, - Ok("pumpkin") => comp::object::Body::Pumpkin, - Ok("pumpkin_2") => comp::object::Body::Pumpkin2, - Ok("pumpkin_3") => comp::object::Body::Pumpkin3, - Ok("pumpkin_4") => comp::object::Body::Pumpkin4, - Ok("pumpkin_5") => comp::object::Body::Pumpkin5, - Ok("campfire") => comp::object::Body::Campfire, - Ok("lantern_ground") => comp::object::Body::LanternGround, - Ok("lantern_ground_open") => comp::object::Body::LanternGroundOpen, - Ok("lantern_2") => comp::object::Body::LanternStanding2, - Ok("lantern") => comp::object::Body::LanternStanding, - Ok("potion_blue") => comp::object::Body::PotionBlue, - Ok("potion_green") => comp::object::Body::PotionGreen, - Ok("potion_red") => comp::object::Body::PotionRed, - Ok("crate") => comp::object::Body::Crate, - Ok("tent") => comp::object::Body::Tent, - Ok("bomb") => comp::object::Body::Bomb, - Ok("window_spooky") => comp::object::Body::WindowSpooky, - Ok("door_spooky") => comp::object::Body::DoorSpooky, - Ok("carpet") => comp::object::Body::Carpet, - Ok("table_human") => comp::object::Body::Table, - Ok("table_human_2") => comp::object::Body::Table2, - Ok("table_human_3") => comp::object::Body::Table3, - Ok("drawer") => comp::object::Body::Drawer, - Ok("bed_human_blue") => comp::object::Body::BedBlue, - Ok("anvil") => comp::object::Body::Anvil, - Ok("gravestone") => comp::object::Body::Gravestone, - Ok("gravestone_2") => comp::object::Body::Gravestone2, - Ok("chair") => comp::object::Body::Chair, - Ok("chair_2") => comp::object::Body::Chair2, - Ok("chair_3") => comp::object::Body::Chair3, - Ok("bench_human") => comp::object::Body::Bench, - Ok("bedroll") => comp::object::Body::Bedroll, - Ok("carpet_human_round") => comp::object::Body::CarpetHumanRound, - Ok("carpet_human_square") => comp::object::Body::CarpetHumanSquare, - Ok("carpet_human_square_2") => comp::object::Body::CarpetHumanSquare2, - Ok("carpet_human_squircle") => comp::object::Body::CarpetHumanSquircle, - _ => { - return server.clients.notify( - entity, - ServerMsg::private(String::from("Object not found!")), - ); - } - }; - server - .create_object(pos, obj_type) - .with(comp::Ori( - // converts player orientation into a 90° rotation for the object by using the axis with the highest value - ori.0 - .map(|e| { - if e.abs() == ori.0.map(|e| e.abs()).reduce_partial_max() { - e - } else { - 0.0 - } - }) - .normalized(), - )) - .build(); - server - .clients - .notify(entity, ServerMsg::private(format!("Spawned object."))); - } else { - server - .clients - .notify(entity, ServerMsg::private(format!("You have no position!"))); + let pos = server + .state + .ecs() + .read_storage::() + .get(entity) + .copied(); + let ori = server + .state + .ecs() + .read_storage::() + .get(entity) + .copied(); + /*let builder = server + .create_object(pos, ori, obj_type) + .with(ori);*/ + if let (Some(pos), Some(ori)) = (pos, ori) { + let obj_type = match obj_type.as_ref().map(String::as_str) { + Ok("scarecrow") => comp::object::Body::Scarecrow, + Ok("cauldron") => comp::object::Body::Cauldron, + Ok("chest_vines") => comp::object::Body::ChestVines, + Ok("chest") => comp::object::Body::Chest, + Ok("chest_dark") => comp::object::Body::ChestDark, + Ok("chest_demon") => comp::object::Body::ChestDemon, + Ok("chest_gold") => comp::object::Body::ChestGold, + Ok("chest_light") => comp::object::Body::ChestLight, + Ok("chest_open") => comp::object::Body::ChestOpen, + Ok("chest_skull") => comp::object::Body::ChestSkull, + Ok("pumpkin") => comp::object::Body::Pumpkin, + Ok("pumpkin_2") => comp::object::Body::Pumpkin2, + Ok("pumpkin_3") => comp::object::Body::Pumpkin3, + Ok("pumpkin_4") => comp::object::Body::Pumpkin4, + Ok("pumpkin_5") => comp::object::Body::Pumpkin5, + Ok("campfire") => comp::object::Body::Campfire, + Ok("lantern_ground") => comp::object::Body::LanternGround, + Ok("lantern_ground_open") => comp::object::Body::LanternGroundOpen, + Ok("lantern_2") => comp::object::Body::LanternStanding2, + Ok("lantern") => comp::object::Body::LanternStanding, + Ok("potion_blue") => comp::object::Body::PotionBlue, + Ok("potion_green") => comp::object::Body::PotionGreen, + Ok("potion_red") => comp::object::Body::PotionRed, + Ok("crate") => comp::object::Body::Crate, + Ok("tent") => comp::object::Body::Tent, + Ok("bomb") => comp::object::Body::Bomb, + Ok("window_spooky") => comp::object::Body::WindowSpooky, + Ok("door_spooky") => comp::object::Body::DoorSpooky, + Ok("carpet") => comp::object::Body::Carpet, + Ok("table_human") => comp::object::Body::Table, + Ok("table_human_2") => comp::object::Body::Table2, + Ok("table_human_3") => comp::object::Body::Table3, + Ok("drawer") => comp::object::Body::Drawer, + Ok("bed_human_blue") => comp::object::Body::BedBlue, + Ok("anvil") => comp::object::Body::Anvil, + Ok("gravestone") => comp::object::Body::Gravestone, + Ok("gravestone_2") => comp::object::Body::Gravestone2, + Ok("chair") => comp::object::Body::Chair, + Ok("chair_2") => comp::object::Body::Chair2, + Ok("chair_3") => comp::object::Body::Chair3, + Ok("bench_human") => comp::object::Body::Bench, + Ok("bedroll") => comp::object::Body::Bedroll, + Ok("carpet_human_round") => comp::object::Body::CarpetHumanRound, + Ok("carpet_human_square") => comp::object::Body::CarpetHumanSquare, + Ok("carpet_human_square_2") => comp::object::Body::CarpetHumanSquare2, + Ok("carpet_human_squircle") => comp::object::Body::CarpetHumanSquircle, + _ => { + return server.clients.notify( + entity, + ServerMsg::private(String::from("Object not found!")), + ); + } + }; + server + .create_object(pos, obj_type) + .with(comp::Ori( + // converts player orientation into a 90° rotation for the object by using the axis with the highest value + ori.0 + .map(|e| { + if e.abs() == ori.0.map(|e| e.abs()).reduce_partial_max() { + e + } else { + 0.0 + } + }) + .normalized(), + )) + .build(); + server + .clients + .notify(entity, ServerMsg::private(format!("Spawned object."))); + } else { + server + .clients + .notify(entity, ServerMsg::private(format!("You have no position!"))); + } } } fn handle_light(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - let (opt_r, opt_g, opt_b, opt_x, opt_y, opt_z, opt_s) = - scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32); + if is_admin(server, entity) { + let (opt_r, opt_g, opt_b, opt_x, opt_y, opt_z, opt_s) = + scan_fmt_some!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32); - let mut light_emitter = comp::LightEmitter::default(); + let mut light_emitter = comp::LightEmitter::default(); - if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) { - let r = r.max(0.0).min(1.0); - let g = g.max(0.0).min(1.0); - let b = b.max(0.0).min(1.0); - light_emitter.col = Rgb::new(r, g, b) - }; - if let (Some(x), Some(y), Some(z)) = (opt_x, opt_y, opt_z) { - light_emitter.offset = Vec3::new(x, y, z) - }; - if let Some(s) = opt_s { - light_emitter.strength = s.max(0.0) - }; - let pos = server - .state - .ecs() - .read_storage::() - .get(entity) - .copied(); - if let Some(pos) = pos { - server + if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) { + let r = r.max(0.0).min(1.0); + let g = g.max(0.0).min(1.0); + let b = b.max(0.0).min(1.0); + light_emitter.col = Rgb::new(r, g, b) + }; + if let (Some(x), Some(y), Some(z)) = (opt_x, opt_y, opt_z) { + light_emitter.offset = Vec3::new(x, y, z) + }; + if let Some(s) = opt_s { + light_emitter.strength = s.max(0.0) + }; + let pos = server .state - .ecs_mut() - .create_entity_synced() - .with(pos) - .with(comp::ForceUpdate) - .with(light_emitter) - .build(); - server - .clients - .notify(entity, ServerMsg::private(format!("Spawned object."))); - } else { - server - .clients - .notify(entity, ServerMsg::private(format!("You have no position!"))); + .ecs() + .read_storage::() + .get(entity) + .copied(); + if let Some(pos) = pos { + server + .state + .ecs_mut() + .create_entity_synced() + .with(pos) + .with(comp::ForceUpdate) + .with(light_emitter) + .build(); + server + .clients + .notify(entity, ServerMsg::private(format!("Spawned object."))); + } else { + server + .clients + .notify(entity, ServerMsg::private(format!("You have no position!"))); + } } } fn handle_lantern(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { - let opt_s = scan_fmt_some!(&args, action.arg_fmt, f32); + let opt_s = scan_fmt_some!(&args, action.arg_fmt, f32); - if server - .state - .read_storage::() - .get(entity) - .is_some() - { - if let Some(s) = opt_s { - if let Some(light) = server - .state - .ecs() - .write_storage::() - .get_mut(entity) - { - light.strength = s.max(0.1).min(20.0); + if server + .state + .read_storage::() + .get(entity) + .is_some() + { + if let Some(s) = opt_s { + if let Some(light) = server + .state + .ecs() + .write_storage::() + .get_mut(entity) + { + light.strength = s.max(0.1).min(20.0); + server.clients.notify( + entity, + ServerMsg::private(String::from("You played with flame strength.")), + ); + } + } else { + server + .state + .ecs() + .write_storage::() + .remove(entity); server.clients.notify( entity, - ServerMsg::private(String::from("You played with flame strength.")), + ServerMsg::private(String::from("You put out the lantern.")), ); } } else { - server + let _ = server .state .ecs() .write_storage::() - .remove(entity); + .insert( + entity, + comp::LightEmitter { + offset: Vec3::new(0.5, 0.2, 0.8), + col: Rgb::new(1.0, 0.75, 0.3), + strength: if let Some(s) = opt_s { + s.max(0.0).min(20.0) + } else { + 6.0 + }, + }, + ); + server.clients.notify( entity, - ServerMsg::private(String::from("You put out the lantern.")), + ServerMsg::private(String::from("You lighted your lantern.")), ); } - } else { - let _ = server - .state - .ecs() - .write_storage::() - .insert( - entity, - comp::LightEmitter { - offset: Vec3::new(0.5, 0.2, 0.8), - col: Rgb::new(1.0, 0.75, 0.3), - strength: if let Some(s) = opt_s { - s.max(0.0).min(20.0) - } else { - 6.0 - }, - }, - ); - - server.clients.notify( - entity, - ServerMsg::private(String::from("You lighted your lantern.")), - ); - } } fn handle_explosion(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) {