From 0c9a94202799ccbbecb7a93bbca367be0ae13165 Mon Sep 17 00:00:00 2001 From: Maxicarlos08 Date: Thu, 3 Aug 2023 20:36:19 +0200 Subject: [PATCH] refactor teleporter system and include nearby pets --- assets/voxygen/shaders/particle-vert.glsl | 5 +- common/src/comp/body/object.rs | 2 +- common/src/event.rs | 2 +- common/systems/src/controller.rs | 7 +- server/src/events/entity_manipulation.rs | 9 +- server/src/sys/teleporter.rs | 115 +++++++++++----------- voxygen/src/session/mod.rs | 5 +- 7 files changed, 68 insertions(+), 77 deletions(-) diff --git a/assets/voxygen/shaders/particle-vert.glsl b/assets/voxygen/shaders/particle-vert.glsl index 3fab3114a0..af733b1492 100644 --- a/assets/voxygen/shaders/particle-vert.glsl +++ b/assets/voxygen/shaders/particle-vert.glsl @@ -693,7 +693,6 @@ void main() { spin_in_axis(vec3(rand6, rand7, rand8), rand9 * 3 + lifetime * 5) ); break; -<<<<<<< HEAD case INK: f_reflect = 0.0; // Magic water doesn't reflect light, it emits it float black_color = 0.3 + 0.2 * rand3 + 0.3 * max(floor(rand4 + 0.3), 0.0); @@ -703,7 +702,8 @@ void main() { vec3(ink_size), vec4(0.5 * black_color, 0.75 * black_color, black_color, 1), spin_in_axis(vec3(rand6, rand7, rand8), percent() * 10 + 3 * rand9) -======= + ); + break; case UPWARD_PORTAL_FIZZ: f_reflect = 0.0; attr = Attr( @@ -711,7 +711,6 @@ void main() { vec3(max(1.0, 0.05 * length(start_pos + inst_dir * percent()))), vec4(vec3(1.23, 1.41, 1.44), 1.0),// * (1.0 - length(inst_dir) * 0.1), identity()//spin_in_axis(perp_axis, asin(inst_dir.z / length(inst_dir)) + PI / 2.0) ->>>>>>> 70e6945e87 (portal particles) ); break; default: diff --git a/common/src/comp/body/object.rs b/common/src/comp/body/object.rs index 8119470f95..313e617f07 100644 --- a/common/src/comp/body/object.rs +++ b/common/src/comp/body/object.rs @@ -331,7 +331,7 @@ impl Body { Body::LightningBolt => "lightning_bolt", Body::SpearIcicle => "spear_icicle", Body::Portal => "portal", - Self::PortalActive => "portal_active", + Body::PortalActive => "portal_active", } } diff --git a/common/src/event.rs b/common/src/event.rs index 0090f7d9a8..0c673de324 100644 --- a/common/src/event.rs +++ b/common/src/event.rs @@ -339,7 +339,7 @@ pub enum ServerEvent { StartTeleporting { entity: EcsEntity, portal: EcsEntity, - } + }, } pub struct EventBus { diff --git a/common/systems/src/controller.rs b/common/systems/src/controller.rs index 7d713ca4cc..4ad8a18177 100644 --- a/common/systems/src/controller.rs +++ b/common/systems/src/controller.rs @@ -140,12 +140,9 @@ impl<'a> System<'a> for Sys { }, ControlEvent::ActivatePortal(portal_uid) => { if let Some(portal) = read_data.id_maps.uid_entity(portal_uid) { - server_emitter.emit(ServerEvent::StartTeleporting { - entity, - portal, - }); + server_emitter.emit(ServerEvent::StartTeleporting { entity, portal }); } - } + }, } } } diff --git a/server/src/events/entity_manipulation.rs b/server/src/events/entity_manipulation.rs index 3d6672135e..2a9c0f3f9a 100644 --- a/server/src/events/entity_manipulation.rs +++ b/server/src/events/entity_manipulation.rs @@ -1693,10 +1693,9 @@ pub fn handle_start_teleporting(server: &mut Server, entity: EcsEntity, portal: ) }) { - let _ = teleportings - .insert(entity, comp::Teleporting { - portal, - end_time: Time(end_time), - }); + let _ = teleportings.insert(entity, comp::Teleporting { + portal, + end_time: Time(end_time), + }); } } diff --git a/server/src/sys/teleporter.rs b/server/src/sys/teleporter.rs index 5cbab22e24..d099968ed5 100644 --- a/server/src/sys/teleporter.rs +++ b/server/src/sys/teleporter.rs @@ -1,15 +1,17 @@ use common::{ - comp::{object, Agent, Body, CharacterState, Pos, Teleporter, Teleporting}, + comp::{object, Agent, Alignment, Body, CharacterState, Pos, Teleporter, Teleporting}, event::{EventBus, ServerEvent}, resources::Time, + uid::Uid, CachedSpatialGrid, }; use common_ecs::{Origin, Phase, System}; -use specs::{Entities, Entity, Join, Read, ReadStorage, WriteStorage}; +use specs::{Entities, Join, Read, ReadStorage, WriteStorage}; use vek::Vec3; pub const TELEPORT_RADIUS: f32 = 3.; const MAX_AGGRO_DIST: f32 = 200.; // If an entity further than this is aggroed at a player, the portal will still work +const PET_TELEPORT_RADIUS: f32 = 20.; #[derive(Default)] pub struct Sys; @@ -22,7 +24,9 @@ impl<'a> System<'a> for Sys { type SystemData = ( Entities<'a>, ReadStorage<'a, Pos>, + ReadStorage<'a, Uid>, ReadStorage<'a, Teleporter>, + ReadStorage<'a, Alignment>, ReadStorage<'a, Agent>, WriteStorage<'a, Teleporting>, ReadStorage<'a, Body>, @@ -41,7 +45,9 @@ impl<'a> System<'a> for Sys { ( entities, positions, + uids, teleporters, + alignments, agent, mut teleporting, bodies, @@ -64,44 +70,20 @@ impl<'a> System<'a> for Sys { }) }; - let mut teleporting_updates = Vec::new(); + let mut cancel_teleporting = Vec::new(); - for (portal_entity, teleporter_pos, body, teleporter) in + for (portal_entity, teleporter_pos, body, _) in (&entities, &positions, &bodies, &teleporters).join() { - let nearby_entities = spatial_grid + let is_active = spatial_grid .0 - .in_circle_aabr(teleporter_pos.0.xy(), TELEPORT_RADIUS); - - let mut is_active = false; - - for (entity, pos, character_state, teleporting) in - nearby_entities.filter_map(|entity| { - ( - &entities, - &positions, - &character_states, - teleporting.maybe(), - ) + .in_circle_aabr(teleporter_pos.0.xy(), TELEPORT_RADIUS) + .any(|entity| { + (&positions, &teleporting) .join() .get(entity, &entities) - .filter(|(_, pos, _, _)| in_portal_range(pos.0, teleporter_pos.0)) - }) - { - if !matches!( - character_state, - CharacterState::Idle(_) | CharacterState::Wielding(_) - ) || (teleporter.requires_no_aggro && check_aggro(entity, pos.0)) - { - if teleporting.is_some() { - teleporting_updates.push((entity, None)); - }; - - continue; - } - - is_active |= teleporting.is_some(); - } + .map_or(false, |(pos, _)| in_portal_range(pos.0, teleporter_pos.0)) + }); if (*body == Body::Object(object::Body::PortalActive)) != is_active { event_bus.emit_now(ServerEvent::ChangeBody { @@ -115,41 +97,58 @@ impl<'a> System<'a> for Sys { } } - update_teleporting(&mut teleporting_updates, &mut teleporting); - - for (entity, position, teleporting) in (&entities, &positions, &teleporting).join() { - let mut remove = || teleporting_updates.push((entity, None)); + for (entity, uid, position, teleporting, character_state) in ( + &entities, + &uids, + &positions, + &teleporting, + &character_states, + ) + .join() + { let portal_pos = positions.get(teleporting.portal); let Some(teleporter) = teleporters.get(teleporting.portal) else { - remove(); + cancel_teleporting.push(entity); continue }; if portal_pos.map_or(true, |portal_pos| { !in_portal_range(position.0, portal_pos.0) - }) { - remove(); + }) || (teleporter.requires_no_aggro && check_aggro(entity, position.0)) + || !matches!( + character_state, + CharacterState::Idle(_) | CharacterState::Wielding(_) + ) + { + cancel_teleporting.push(entity); } else if teleporting.end_time.0 <= time.0 { - remove(); - event_bus.emit_now(ServerEvent::TeleportToPosition { - entity, - position: teleporter.target, - }); + // Send teleport events for all nearby pets and the owner + let nearby = spatial_grid + .0 + .in_circle_aabr(position.0.xy(), PET_TELEPORT_RADIUS) + .filter_map(|entity| { + (&entities, &positions, &alignments) + .join() + .get(entity, &entities) + }) + .filter_map(|(entity, entity_position, alignment)| { + (matches!(alignment, Alignment::Owned(entity_uid) if entity_uid == uid) + && entity_position.0.distance_squared(position.0) + <= PET_TELEPORT_RADIUS.powi(2)) + .then_some(entity) + }); + + for entity in nearby { + cancel_teleporting.push(entity); + event_bus.emit_now(ServerEvent::TeleportToPosition { + entity, + position: teleporter.target, + }); + } } } - update_teleporting(&mut teleporting_updates, &mut teleporting); - } -} - -fn update_teleporting( - updates: &mut Vec<(Entity, Option)>, - teleporting: &mut WriteStorage<'_, Teleporting>, -) { - for (entity, update) in updates.drain(..) { - if let Some(add) = update { - let _ = teleporting.insert(entity, add); - } else { + for entity in cancel_teleporting { let _ = teleporting.remove(entity); } } diff --git a/voxygen/src/session/mod.rs b/voxygen/src/session/mod.rs index bff2648e58..990ad2a2b1 100644 --- a/voxygen/src/session/mod.rs +++ b/voxygen/src/session/mod.rs @@ -1029,10 +1029,7 @@ impl PlayState for SessionState { Interactable::Entity(entity) => { let body = client .state() - .ecs() - .read_storage::() - .get(*entity) - .map(ToOwned::to_owned); + .read_component_cloned::(*entity); if client .state()