diff --git a/client/src/lib.rs b/client/src/lib.rs index a4985eebd5..be6f82bd67 100644 --- a/client/src/lib.rs +++ b/client/src/lib.rs @@ -401,8 +401,12 @@ impl Client { } => { if let Some(entity) = self.state.ecs().entity_from_uid(entity) { self.state.write_component(entity, pos); - self.state.write_component(entity, vel); - self.state.write_component(entity, ori); + if let Some(v) = vel { + self.state.write_component(entity, v); + }; + if let Some(o) = ori { + self.state.write_component(entity, o); + }; if let Some(a_s) = action_state { self.state.write_component(entity, a_s); } diff --git a/common/src/comp/visual.rs b/common/src/comp/visual.rs index df0102b46d..29e759ae95 100644 --- a/common/src/comp/visual.rs +++ b/common/src/comp/visual.rs @@ -3,6 +3,7 @@ use vek::*; #[derive(Copy, Clone, Debug, PartialEq, Serialize, Deserialize)] pub struct LightEmitter { + pub offset: Vec3, pub col: Rgb, pub strength: f32, } @@ -10,8 +11,9 @@ pub struct LightEmitter { impl Default for LightEmitter { fn default() -> Self { Self { + offset: Vec3::zero(), col: Rgb::one(), - strength: 250.0, + strength: 1.0, } } } diff --git a/common/src/msg/server.rs b/common/src/msg/server.rs index 636a33326a..499df4f4e3 100644 --- a/common/src/msg/server.rs +++ b/common/src/msg/server.rs @@ -38,8 +38,8 @@ pub enum ServerMsg { EntityPhysics { entity: u64, pos: comp::Pos, - vel: comp::Vel, - ori: comp::Ori, + vel: Option, + ori: Option, action_state: Option, }, TerrainChunkUpdate { diff --git a/server/src/cmd.rs b/server/src/cmd.rs index 843c3e2710..b78319e8b1 100644 --- a/server/src/cmd.rs +++ b/server/src/cmd.rs @@ -138,6 +138,18 @@ lazy_static! { "/object [Name]: Spawn an object", handle_object, ), + ChatCommand::new( + "light", + "{} {} {} {} {} {} {}", + "/light > < > <>>: Spawn entity with light", + handle_light, + ), + ChatCommand::new( + "lantern", + "{} ", + "/lantern : adds/remove light near player", + handle_lantern, + ), ]; } @@ -514,6 +526,81 @@ fn handle_object(server: &mut Server, entity: EcsEntity, args: String, _action: } } +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!(&args, action.arg_fmt, f32, f32, f32, f32, f32, f32, f32); + + let mut light_emitter = comp::LightEmitter::default(); + + if let (Some(r), Some(g), Some(b)) = (opt_r, opt_g, opt_b) { + 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 + }; + let pos = server + .state + .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::Chat(format!("Spawned object."))); + } else { + server + .clients + .notify(entity, ServerMsg::Chat(format!("You have no position!"))); + } +} +fn handle_lantern(server: &mut Server, entity: EcsEntity, _args: String, _action: &ChatCommand) { + if server + .state + .read_storage::() + .get(entity) + .is_some() + { + server + .state + .ecs() + .write_storage::() + .remove(entity); + server.clients.notify( + entity, + ServerMsg::Chat(String::from("You put out the lantern.")), + ); + } else { + let _ = server + .state + .ecs() + .write_storage::() + .insert( + entity, + comp::LightEmitter { + offset: Vec3::new(1.0, 0.2, 0.8), + col: Rgb::new(0.824, 0.365, 0.196), + strength: 1.5, + }, + ); + + server.clients.notify( + entity, + ServerMsg::Chat(String::from("You lighted your lantern.")), + ); + } +} fn handle_tell(server: &mut Server, entity: EcsEntity, args: String, action: &ChatCommand) { let opt_alias = scan_fmt!(&args, action.arg_fmt, String); match opt_alias { diff --git a/server/src/lib.rs b/server/src/lib.rs index e9e6bb5909..b73eea4284 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -172,7 +172,10 @@ impl Server { .with(comp::Vel(Vec3::zero())) .with(comp::Ori(Vec3::unit_y())) .with(comp::Body::Object(object)) - .with(comp::LightEmitter::default()) + .with(comp::LightEmitter { + offset: Vec3::unit_z(), + ..comp::LightEmitter::default() + }) .with(comp::ActionState::default()) .with(comp::ForceUpdate) } @@ -664,11 +667,11 @@ impl Server { state.write_component(entity, player); // Sync physics - for (&uid, &pos, &vel, &ori, action_state) in ( + for (&uid, &pos, vel, ori, action_state) in ( &state.ecs().read_storage::(), &state.ecs().read_storage::(), - &state.ecs().read_storage::(), - &state.ecs().read_storage::(), + state.ecs().read_storage::().maybe(), + state.ecs().read_storage::().maybe(), state.ecs().read_storage::().maybe(), ) .join() @@ -676,8 +679,8 @@ impl Server { client.notify(ServerMsg::EntityPhysics { entity: uid.into(), pos, - vel, - ori, + vel: vel.copied(), + ori: ori.copied(), action_state: action_state.copied(), }); } @@ -762,12 +765,12 @@ impl Server { } // Sync physics - for (entity, &uid, &pos, &vel, &ori, action_state, force_update) in ( + for (entity, &uid, &pos, vel, ori, action_state, force_update) in ( &self.state.ecs().entities(), &self.state.ecs().read_storage::(), &self.state.ecs().read_storage::(), - &self.state.ecs().read_storage::(), - &self.state.ecs().read_storage::(), + self.state.ecs().read_storage::().maybe(), + self.state.ecs().read_storage::().maybe(), self.state.ecs().read_storage::().maybe(), self.state.ecs().read_storage::().maybe(), ) @@ -776,8 +779,8 @@ impl Server { let msg = ServerMsg::EntityPhysics { entity: uid.into(), pos, - vel, - ori, + vel: vel.copied(), + ori: ori.copied(), action_state: action_state.copied(), }; diff --git a/voxygen/shaders/include/light.glsl b/voxygen/shaders/include/light.glsl index 43380077fe..6c4ab48b03 100644 --- a/voxygen/shaders/include/light.glsl +++ b/voxygen/shaders/include/light.glsl @@ -26,6 +26,7 @@ vec3 light_at(vec3 wpos, vec3 wnorm) { light += strength * lights[i].light_col.rgb + * lights[i].light_col.a * clamp(dot(normalize(light_pos - wpos), wnorm), LIGHT_AMBIENCE, 1.0); } return light; diff --git a/voxygen/src/scene/mod.rs b/voxygen/src/scene/mod.rs index 6de2e780a6..fd5cffde92 100644 --- a/voxygen/src/scene/mod.rs +++ b/voxygen/src/scene/mod.rs @@ -144,20 +144,28 @@ impl Scene { // Update light constants let mut lights = ( &client.state().ecs().read_storage::(), + client.state().ecs().read_storage::().maybe(), &client.state().ecs().read_storage::(), ) .join() - .filter(|(pos, _)| { + .filter(|(pos, _, _)| { (pos.0.distance_squared(player_pos) as f32) < self.loaded_distance.powf(2.0) + LIGHT_DIST_RADIUS }) - .map(|(pos, light_emitter)| { + .map(|(pos, ori, light_emitter)| { + let rot = { + if let Some(o) = ori { + Mat3::rotation_z(-o.0.x.atan2(o.0.y)) + } else { + Mat3::identity() + } + }; Light::new( - pos.0 + Vec3::unit_z(), + pos.0 + (rot * light_emitter.offset), light_emitter.col, light_emitter.strength, ) - }) // TODO: Don't add 1 to z! + }) .collect::>(); lights.sort_by_key(|light| { Vec3::from(Vec4::from(light.pos)).distance_squared(player_pos) as i32