Implement movement handling and last player position saving
This commit is contained in:
parent
d1de5685ae
commit
574aaa5469
16 changed files with 979 additions and 389 deletions
|
@ -1,10 +1,22 @@
|
|||
use std::{fmt::Display, rc::Rc};
|
||||
|
||||
use data::math_def::Vector3;
|
||||
use proto::{ProtEntityType, SceneEntityInfo};
|
||||
use data::math_def::{Coordinate, Vector3};
|
||||
use proto::{MotionState, ProtEntityType, Retcode, SceneEntityInfo};
|
||||
|
||||
use crate::player::Player;
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub struct MotionContext {
|
||||
pub scene_time_ms: u64,
|
||||
pub reliable_seq: u32,
|
||||
pub is_reliable: bool,
|
||||
pub exclude_uid: u32,
|
||||
pub is_notify: bool,
|
||||
pub interval_velocity: u32,
|
||||
pub sync_uid_vec: Vec<u32>,
|
||||
pub is_do_move: bool,
|
||||
}
|
||||
|
||||
pub trait Entity {
|
||||
fn get_entity_type(&self) -> ProtEntityType;
|
||||
fn get_group_id(&self) -> u32;
|
||||
|
@ -14,6 +26,10 @@ pub trait Entity {
|
|||
fn rotation(&self) -> &Vector3;
|
||||
fn set_position(&mut self, pos: Vector3);
|
||||
fn set_rotation(&mut self, rot: Vector3);
|
||||
fn set_coordinate(&mut self, _coordinate: Coordinate) {}
|
||||
fn get_coordinate(&self) -> Coordinate {
|
||||
Coordinate::default()
|
||||
}
|
||||
fn get_owner_player(&self) -> Option<Rc<Player>>;
|
||||
|
||||
fn is_on_scene(&self) -> bool {
|
||||
|
@ -43,6 +59,37 @@ pub trait Entity {
|
|||
}
|
||||
}
|
||||
|
||||
fn set_motion_info(
|
||||
&mut self,
|
||||
motion_info: &proto::MotionInfo,
|
||||
motion_context: &MotionContext,
|
||||
) -> Result<(), Retcode> {
|
||||
self.set_motion_info_base(motion_info, motion_context)
|
||||
}
|
||||
|
||||
fn set_motion_info_base(
|
||||
&mut self,
|
||||
motion_info: &proto::MotionInfo,
|
||||
_motion_context: &MotionContext,
|
||||
) -> Result<(), Retcode> {
|
||||
match motion_info.state() {
|
||||
MotionState::MotionNone => (),
|
||||
_ => {
|
||||
let _speed = motion_info.speed.clone().unwrap_or_default();
|
||||
let rot = motion_info.rot.as_ref().unwrap();
|
||||
let pos = motion_info.pos.as_ref().unwrap();
|
||||
|
||||
self.set_rotation(Vector3::from_client(rot));
|
||||
self.set_position(Vector3::from_client(pos));
|
||||
// TODO: Entity::checkMoveSpeed
|
||||
}
|
||||
}
|
||||
|
||||
// TODO: broadcast
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_client(&self, _scene_entity_info: &mut SceneEntityInfo) {}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
mod entity;
|
||||
|
||||
pub use entity::Entity;
|
||||
pub use entity::{Entity, MotionContext};
|
||||
pub mod entity_mgr;
|
||||
pub mod entity_utils;
|
||||
mod vision_context;
|
||||
|
|
61
gameserver/src/handler/fight_handler.rs
Normal file
61
gameserver/src/handler/fight_handler.rs
Normal file
|
@ -0,0 +1,61 @@
|
|||
use std::{error::Error, rc::Rc};
|
||||
|
||||
use common::net::tools::Packet;
|
||||
use prost::Message;
|
||||
use proto::{CombatTypeArgument, EntityMoveInfo};
|
||||
|
||||
use crate::player::Player;
|
||||
|
||||
use super::{get_proto, scene_handler};
|
||||
|
||||
pub fn on_combat_invocations_notify(
|
||||
player: &Rc<Player>,
|
||||
packet: Packet,
|
||||
) -> Result<(), Box<dyn Error>> {
|
||||
let notify = get_proto!(packet, CombatInvocationsNotify);
|
||||
|
||||
for entry in notify.invoke_list {
|
||||
match entry.argument_type() {
|
||||
CombatTypeArgument::EntityMove => {
|
||||
let Ok(entity_move_info) = EntityMoveInfo::decode(&*entry.combat_data) else {
|
||||
tracing::warn!("combat invoke type: proto::EntityMoveInfo fail to parse, len:{}, base64:{}, player:{}", entry.combat_data.len(), rbase64::encode(&*entry.combat_data), player.uid);
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let (cur_scene, cur_avatar) = {
|
||||
(
|
||||
player
|
||||
.player_scene_comp
|
||||
.borrow()
|
||||
.get_cur_scene()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
player
|
||||
.player_avatar_comp
|
||||
.borrow()
|
||||
.get_cur_avatar()
|
||||
.unwrap()
|
||||
.clone(),
|
||||
)
|
||||
};
|
||||
|
||||
let mut sync_uid_vec = Vec::new();
|
||||
if let Err(ret) = scene_handler::process_entity_move_info(
|
||||
cur_scene,
|
||||
player,
|
||||
cur_avatar,
|
||||
&entity_move_info,
|
||||
&mut sync_uid_vec,
|
||||
) {
|
||||
tracing::warn!("process_entity_move_info fails, ret:{ret:?}");
|
||||
}
|
||||
}
|
||||
unhandled => tracing::warn!(
|
||||
"wrong combat type, player:{}, type:{unhandled:?}",
|
||||
player.uid,
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
|
@ -1,4 +1,5 @@
|
|||
pub mod avatar_handler;
|
||||
pub mod fight_handler;
|
||||
pub mod login_handler;
|
||||
pub mod player_handler;
|
||||
pub mod player_misc_handler;
|
||||
|
@ -44,10 +45,12 @@ game_packet_handlers! {
|
|||
PlayerMiscHandler::PingReq;
|
||||
PlayerHandler::SetPlayerBornDataReq;
|
||||
PlayerHandler::PlayerLogoutReq;
|
||||
PlayerHandler::UnionCmdNotify;
|
||||
SceneHandler::EnterSceneReadyReq;
|
||||
SceneHandler::SceneInitFinishReq;
|
||||
SceneHandler::EnterSceneDoneReq;
|
||||
SceneHandler::PostEnterSceneReq;
|
||||
AvatarHandler::SetUpAvatarTeamReq;
|
||||
AvatarHandler::ChangeAvatarReq;
|
||||
FightHandler::CombatInvocationsNotify;
|
||||
}
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
use std::{error::Error, rc::Rc};
|
||||
|
||||
use common::net::tools::Packet;
|
||||
use common::{net::tools::Packet, tools::time_utils};
|
||||
use proto::{PlayerLogoutReason, ServerDisconnectClientNotify, SetPlayerBornDataRsp};
|
||||
|
||||
use crate::player::Player;
|
||||
|
@ -38,3 +38,36 @@ pub fn on_player_logout_req(player: &Rc<Player>, packet: Packet) -> Result<(), B
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn on_union_cmd_notify(player: &Rc<Player>, packet: Packet) -> Result<(), Box<dyn Error>> {
|
||||
// TODO: PlayerHandler::checkUnionFrequent
|
||||
|
||||
let notify = get_proto!(packet, UnionCmdNotify);
|
||||
for cmd in notify.cmd_list {
|
||||
let last_time = time_utils::get_now_ms();
|
||||
|
||||
let err = super::process_packet(
|
||||
player,
|
||||
Packet {
|
||||
cmd_id: cmd.message_id as u16,
|
||||
recv_vec: cmd.body,
|
||||
head: proto::PacketHead::default(),
|
||||
},
|
||||
)
|
||||
.err();
|
||||
|
||||
let time = time_utils::get_now_ms();
|
||||
tracing::info!(
|
||||
"|UnionSubCmd|{}|{}|{}|",
|
||||
player.uid,
|
||||
cmd.message_id,
|
||||
time - last_time
|
||||
);
|
||||
|
||||
if let Some(err) = err {
|
||||
tracing::warn!("UnionSubCmd process failed: {err:?}");
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -1,11 +1,18 @@
|
|||
use std::{error::Error, rc::Rc};
|
||||
use std::{cell::RefCell, error::Error, rc::Rc};
|
||||
|
||||
use common::net::tools::Packet;
|
||||
use data::math_def::Vector3;
|
||||
use proto::{
|
||||
EnterSceneDoneRsp, EnterSceneReadyRsp, PostEnterSceneRsp, Retcode, SceneInitFinishRsp,
|
||||
EnterSceneDoneRsp, EnterSceneReadyRsp, EntityMoveInfo, PostEnterSceneRsp, Retcode,
|
||||
SceneInitFinishRsp,
|
||||
};
|
||||
|
||||
use crate::player::Player;
|
||||
use crate::{
|
||||
creature::{Creature, LifeState},
|
||||
entity::{Entity, MotionContext},
|
||||
player::{avatar::Avatar, Player},
|
||||
scene::Scene,
|
||||
};
|
||||
|
||||
use super::get_proto;
|
||||
|
||||
|
@ -68,3 +75,51 @@ pub fn on_post_enter_scene_req(player: &Rc<Player>, packet: Packet) -> Result<()
|
|||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn process_entity_move_info(
|
||||
scene: Rc<RefCell<Scene>>,
|
||||
player: &Rc<Player>,
|
||||
cur_avatar: Rc<RefCell<Avatar>>,
|
||||
move_info: &EntityMoveInfo,
|
||||
_sync_uid_vec: &mut Vec<u32>,
|
||||
) -> Result<(), Retcode> {
|
||||
if move_info.entity_id == cur_avatar.borrow().entity_id() {
|
||||
if cur_avatar.borrow().get_life_state() != LifeState::LifeAlive {
|
||||
tracing::info!(
|
||||
"avatar is not alive:{}",
|
||||
cur_avatar.borrow() as std::cell::Ref<dyn Entity>
|
||||
);
|
||||
return Err(Retcode::RetFail);
|
||||
}
|
||||
} else {
|
||||
return Err(Retcode::RetFail); // TODO: non cur avatar also has some handling
|
||||
}
|
||||
|
||||
let motion_info = move_info.motion_info.as_ref().unwrap();
|
||||
let (Some(pos), Some(rot)) = (motion_info.pos.as_ref(), motion_info.rot.as_ref()) else {
|
||||
return Ok(());
|
||||
};
|
||||
|
||||
let context = MotionContext {
|
||||
scene_time_ms: move_info.scene_time as u64,
|
||||
reliable_seq: move_info.reliable_seq,
|
||||
is_reliable: move_info.is_reliable,
|
||||
exclude_uid: player.uid,
|
||||
is_notify: false,
|
||||
is_do_move: true,
|
||||
interval_velocity: 0,
|
||||
sync_uid_vec: Vec::new(),
|
||||
};
|
||||
|
||||
scene.borrow_mut().entity_move_to(
|
||||
cur_avatar.clone() as Rc<RefCell<dyn Entity>>,
|
||||
Vector3::from_client(pos),
|
||||
Vector3::from_client(rot),
|
||||
);
|
||||
|
||||
let _ = cur_avatar
|
||||
.borrow_mut()
|
||||
.set_motion_info(motion_info, &context);
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
|
|
@ -3,7 +3,11 @@ use std::{
|
|||
rc::{Rc, Weak},
|
||||
};
|
||||
|
||||
use data::{math_def::Vector3, prop_type::PROP_LEVEL, ElementType, FightPropType};
|
||||
use data::{
|
||||
math_def::{Coordinate, Vector3},
|
||||
prop_type::PROP_LEVEL,
|
||||
ElementType, FightPropType,
|
||||
};
|
||||
use proto::{
|
||||
avatar_bin::{self, Detail},
|
||||
AbilitySyncStateInfo, AnimatorParameterValueInfoPair, AvatarBin, AvatarExcelInfo, Cjnoehnhdgl,
|
||||
|
@ -14,7 +18,7 @@ use proto::{
|
|||
use crate::{
|
||||
ability::AbilityComp,
|
||||
creature::{property::PropValueMap, Creature, FightPropComp, LifeState},
|
||||
entity::Entity,
|
||||
entity::{Entity, MotionContext},
|
||||
item::EquipComp,
|
||||
player::{item::Item, Player},
|
||||
skill::SkillComp,
|
||||
|
@ -243,6 +247,7 @@ pub struct BaseAvatar {
|
|||
pub rot: Vector3,
|
||||
pub last_valid_pos: Vector3,
|
||||
pub last_valid_rot: Vector3,
|
||||
pub coordinate: Coordinate,
|
||||
}
|
||||
|
||||
impl BaseAvatar {
|
||||
|
@ -426,6 +431,26 @@ impl Entity for Avatar {
|
|||
self.base_avatar_mut().rot = rot;
|
||||
}
|
||||
|
||||
fn set_coordinate(&mut self, coordinate: Coordinate) {
|
||||
self.base_avatar_mut().coordinate = coordinate;
|
||||
}
|
||||
|
||||
fn get_coordinate(&self) -> Coordinate {
|
||||
self.base_avatar().coordinate.clone()
|
||||
}
|
||||
|
||||
fn set_motion_info(
|
||||
&mut self,
|
||||
motion_info: &proto::MotionInfo,
|
||||
motion_context: &MotionContext,
|
||||
) -> Result<(), proto::Retcode> {
|
||||
self.set_motion_info_base(motion_info, motion_context)?;
|
||||
self.set_last_valid_position(Vector3::from_client(motion_info.pos.as_ref().unwrap()));
|
||||
self.set_last_valid_rotation(Vector3::from_client(motion_info.rot.as_ref().unwrap()));
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn to_client(&self, scene_entity_info: &mut SceneEntityInfo) {
|
||||
scene_entity_info.entity_id = self.entity_id();
|
||||
scene_entity_info.entity_type = self.get_entity_type().into();
|
||||
|
|
|
@ -23,8 +23,8 @@ use proto::{
|
|||
EnterSceneDoneReq, EnterSceneDoneRsp, EnterScenePeerNotify, EnterSceneReadyReq, EnterType,
|
||||
MpLevelEntityInfo, PacketHead, PingReq, PingRsp, PlayerData, PlayerDataBin, PlayerDataNotify,
|
||||
PlayerEnterSceneInfoNotify, PlayerEnterSceneNotify, PlayerLoginRsp, PostEnterSceneReq,
|
||||
PostEnterSceneRsp, ResVersionConfig, Retcode, SavePlayerDataReq, SceneInitFinishReq,
|
||||
SetPlayerBornDataReq, TeamEnterSceneInfo, VisionType, YSMessage,
|
||||
PostEnterSceneRsp, Retcode, SavePlayerDataReq, SceneInitFinishReq, SetPlayerBornDataReq,
|
||||
TeamEnterSceneInfo, VisionType, YSMessage,
|
||||
};
|
||||
use rand::RngCore;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::BTreeMap, rc::Rc};
|
|||
|
||||
use crate::entity::Entity;
|
||||
|
||||
use super::region::Region;
|
||||
use super::{region::Region, visitor::Visitor};
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct Grid {
|
||||
|
@ -30,6 +30,12 @@ impl Grid {
|
|||
self.region_vec.push(region);
|
||||
}
|
||||
|
||||
pub fn accept(&self, visitor: &mut Visitor) {
|
||||
self.entity_map
|
||||
.values()
|
||||
.for_each(|e| visitor.visit_entity(&e));
|
||||
}
|
||||
|
||||
pub fn get_all_entity(&self) -> Vec<Rc<RefCell<dyn Entity>>> {
|
||||
self.entity_map.values().map(|a| a.clone()).collect()
|
||||
}
|
||||
|
|
|
@ -5,7 +5,7 @@ use proto::ProtEntityType;
|
|||
|
||||
use crate::entity::Entity;
|
||||
|
||||
use super::{grid::Grid, region::Region, VisionLevelType};
|
||||
use super::{grid::Grid, region::Region, visitor::Visitor, VisionLevelType};
|
||||
|
||||
#[allow(unused)]
|
||||
pub struct GridMgr {
|
||||
|
@ -21,6 +21,10 @@ impl GridMgr {
|
|||
self.grid_map.entry((x, y)).or_insert_with(Grid::default)
|
||||
}
|
||||
|
||||
pub fn find_grid(&self, x: i32, y: i32) -> Option<&Grid> {
|
||||
self.grid_map.get(&(x, y))
|
||||
}
|
||||
|
||||
pub fn place_entity(
|
||||
&mut self,
|
||||
entity: Rc<RefCell<dyn Entity>>,
|
||||
|
@ -47,6 +51,115 @@ impl GridMgr {
|
|||
grid.del_entity(entity);
|
||||
}
|
||||
|
||||
pub fn entity_move_to(&mut self, entity: &Rc<RefCell<dyn Entity>>, coordinate: &Coordinate) {
|
||||
let prev_coordinate = entity.borrow().get_coordinate();
|
||||
if *coordinate == prev_coordinate {
|
||||
return;
|
||||
}
|
||||
|
||||
let prev_grid = self.get_grid(prev_coordinate.x, prev_coordinate.y);
|
||||
prev_grid.del_entity(entity);
|
||||
|
||||
let grid = self.get_grid(coordinate.x, coordinate.y);
|
||||
grid.add_entity(entity.clone());
|
||||
|
||||
entity.borrow_mut().set_coordinate(coordinate.clone());
|
||||
}
|
||||
|
||||
pub fn visit_diff_grids(
|
||||
&self,
|
||||
center1: &Coordinate,
|
||||
center2: &Coordinate,
|
||||
t1: &mut Visitor,
|
||||
t2: &mut Visitor,
|
||||
) {
|
||||
let sight_radius = self.sight_radius as i32;
|
||||
|
||||
let left_x1 = center1.x - sight_radius;
|
||||
let right_x1 = center1.x + sight_radius;
|
||||
let low_y1 = center1.y - sight_radius;
|
||||
let up_y1 = center1.y + sight_radius;
|
||||
|
||||
let left_x2 = center2.x - sight_radius;
|
||||
let right_x2 = center2.x + sight_radius;
|
||||
let low_y2 = center2.y - sight_radius;
|
||||
let up_y2 = center2.y + sight_radius;
|
||||
|
||||
if right_x1 >= left_x2 && right_x2 >= left_x1 && up_y1 >= low_y2 && up_y2 >= low_y1 {
|
||||
let mut low_y = low_y1;
|
||||
let mut up_y = up_y1;
|
||||
|
||||
if center1.y >= center2.y {
|
||||
if center1.y > center2.y {
|
||||
for j in up_y1..up_y2 {
|
||||
for i in left_x1..=right_x1 {
|
||||
self.visit_grid(i, j, t1);
|
||||
}
|
||||
}
|
||||
for j in low_y2..low_y1 {
|
||||
for i in left_x2..=right_x2 {
|
||||
self.visit_grid(i, j, t2);
|
||||
}
|
||||
}
|
||||
|
||||
low_y = low_y1;
|
||||
up_y = up_y2;
|
||||
}
|
||||
} else {
|
||||
for j in low_y1..low_y2 {
|
||||
for i in left_x1..=right_x1 {
|
||||
self.visit_grid(i, j, t1);
|
||||
}
|
||||
}
|
||||
for j in up_y2..up_y1 {
|
||||
for i in left_x2..=right_x2 {
|
||||
self.visit_grid(i, j, t2);
|
||||
}
|
||||
}
|
||||
|
||||
low_y = low_y2;
|
||||
up_y = up_y1;
|
||||
}
|
||||
|
||||
for j in low_y..=up_y {
|
||||
if center1.x >= center2.x {
|
||||
if center1.x > center2.x {
|
||||
for i in left_x2..left_x1 {
|
||||
self.visit_grid(i, j, t2);
|
||||
}
|
||||
for i in right_x1..right_x2 {
|
||||
self.visit_grid(i, j, t1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in left_x1..left_x2 {
|
||||
self.visit_grid(i, j, t1);
|
||||
}
|
||||
for i in right_x2..right_x1 {
|
||||
self.visit_grid(i, j, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
for i in left_x1..=right_x1 {
|
||||
for j in low_y1..=up_y1 {
|
||||
self.visit_grid(i, j, t1);
|
||||
}
|
||||
}
|
||||
for i in left_x2..=right_x2 {
|
||||
for j in low_y2..=up_y2 {
|
||||
self.visit_grid(i, j, t2);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_grid(&self, x: i32, y: i32, visitor: &mut Visitor) {
|
||||
if let Some(grid) = self.find_grid(x, y) {
|
||||
grid.accept(visitor);
|
||||
}
|
||||
}
|
||||
|
||||
#[allow(dead_code)]
|
||||
pub fn place_region(&mut self, region: Region, coordinate: Coordinate) -> Result<(), ()> {
|
||||
let grid = self.get_grid(coordinate.x, coordinate.y);
|
||||
|
|
|
@ -10,6 +10,7 @@ mod scene;
|
|||
pub mod scene_mgr;
|
||||
mod scene_sight_comp;
|
||||
mod scene_team;
|
||||
mod visitor;
|
||||
|
||||
pub use mp_level_entity::MPLevelEntity;
|
||||
pub use player_scene_comp::{EnterSceneState, PlayerSceneComp};
|
||||
|
|
|
@ -268,6 +268,59 @@ impl Scene {
|
|||
.insert(uid, player_location);
|
||||
}
|
||||
|
||||
pub fn entity_move_to(&mut self, entity: Rc<RefCell<dyn Entity>>, pos: Vector3, rot: Vector3) {
|
||||
if !entity.borrow().is_on_scene() {
|
||||
tracing::info!("entity is not on scene {}", entity.borrow());
|
||||
return;
|
||||
}
|
||||
|
||||
let sight_comp = self.base_mut().sight_comp.as_mut().unwrap();
|
||||
|
||||
let mut meet_entity_vec = Vec::new();
|
||||
let mut miss_entity_vec = Vec::new();
|
||||
|
||||
sight_comp.entity_move_to(
|
||||
entity.clone(),
|
||||
pos.clone(),
|
||||
&mut miss_entity_vec,
|
||||
&mut meet_entity_vec,
|
||||
);
|
||||
|
||||
if let Some(player) = entity.borrow().get_owner_player() {
|
||||
player.send_proto(SceneEntityDisappearNotify {
|
||||
param: 0,
|
||||
disappear_type: VisionType::VisionMiss.into(),
|
||||
entity_list: miss_entity_vec
|
||||
.into_iter()
|
||||
.map(|e| e.borrow().entity_id())
|
||||
.collect(),
|
||||
});
|
||||
|
||||
player.send_proto(SceneEntityAppearNotify {
|
||||
param: 0,
|
||||
appear_type: VisionType::VisionMeet.into(),
|
||||
entity_list: meet_entity_vec
|
||||
.into_iter()
|
||||
.map(|e| {
|
||||
let mut appear_entity_info = SceneEntityInfo::default();
|
||||
e.borrow().to_client(&mut appear_entity_info);
|
||||
appear_entity_info
|
||||
})
|
||||
.collect(),
|
||||
});
|
||||
|
||||
if player.uid == self.base().owner_uid() {
|
||||
let base_mut = self.base_mut();
|
||||
let owner_location = &mut base_mut.owner_player_location;
|
||||
|
||||
owner_location.cur_pos = pos.clone();
|
||||
owner_location.cur_rot = rot.clone();
|
||||
owner_location.last_valid_pos = pos.clone();
|
||||
owner_location.last_valid_rot = rot.clone();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
fn notify_scene_and_host_data(&self, uid: u32) {
|
||||
let Some(player) = self.base().find_player(uid) else {
|
||||
tracing::warn!("find_player failed, uid:{uid}");
|
||||
|
|
|
@ -1,12 +1,15 @@
|
|||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
||||
|
||||
use data::math_def::{Coordinate, Vector2};
|
||||
use data::math_def::{Coordinate, Vector2, Vector3};
|
||||
use num_enum::FromPrimitive;
|
||||
use proto::Retcode;
|
||||
use proto::{ProtEntityType, Retcode};
|
||||
|
||||
use crate::entity::Entity;
|
||||
|
||||
use super::grid_mgr::GridMgr;
|
||||
use super::{
|
||||
grid_mgr::GridMgr,
|
||||
visitor::{Visitor, VisitorType},
|
||||
};
|
||||
|
||||
#[derive(Debug, Default, Clone, Copy, FromPrimitive)]
|
||||
#[repr(u32)]
|
||||
|
@ -52,6 +55,20 @@ impl SceneSightComp {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn entity_move_to(
|
||||
&mut self,
|
||||
entity: Rc<RefCell<dyn Entity>>,
|
||||
dest_pos: Vector3,
|
||||
miss_entity_vec: &mut Vec<Rc<RefCell<dyn Entity>>>,
|
||||
meet_entity_vec: &mut Vec<Rc<RefCell<dyn Entity>>>,
|
||||
) {
|
||||
match self {
|
||||
Self::Grid(grid_comp) => {
|
||||
grid_comp.entity_move_to(entity, dest_pos, miss_entity_vec, meet_entity_vec)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos_to_coordinate(&self, range_type: VisionLevelType, pos: &Vector2) -> Coordinate {
|
||||
match self {
|
||||
Self::Grid(grid_comp) => grid_comp.pos_to_coordinate(range_type, pos),
|
||||
|
@ -177,6 +194,66 @@ impl SceneGridComp {
|
|||
grid_mgr.remove_entity(entity, coordinate);
|
||||
}
|
||||
|
||||
pub fn entity_move_to(
|
||||
&mut self,
|
||||
entity: Rc<RefCell<dyn Entity>>,
|
||||
dest_pos: Vector3,
|
||||
miss_entity_vec: &mut Vec<Rc<RefCell<dyn Entity>>>,
|
||||
meet_entity_vec: &mut Vec<Rc<RefCell<dyn Entity>>>,
|
||||
) {
|
||||
let range_type = self.get_vision_level_type(&entity);
|
||||
let pos = Vector2 {
|
||||
x: dest_pos.x,
|
||||
y: dest_pos.z,
|
||||
};
|
||||
let coordinate = self.pos_to_coordinate(range_type, &pos);
|
||||
|
||||
let grid_mgr = &mut self.grid_mgr_arr[range_type as usize];
|
||||
grid_mgr.entity_move_to(&entity, &coordinate);
|
||||
|
||||
let mut miss_visitor = Visitor::new(VisitorType::Entity, entity.clone());
|
||||
let mut meet_visitor = Visitor::new(VisitorType::Entity, entity.clone());
|
||||
|
||||
if entity.borrow().get_entity_type() == ProtEntityType::ProtEntityAvatar {
|
||||
let prev_pos = entity.borrow().position().clone();
|
||||
|
||||
self.visit_diff_grids(&prev_pos, &dest_pos, &mut miss_visitor, &mut meet_visitor);
|
||||
}
|
||||
|
||||
miss_entity_vec.extend(miss_visitor.get_entity_vec().iter().cloned());
|
||||
meet_entity_vec.extend(meet_visitor.get_entity_vec().iter().cloned());
|
||||
}
|
||||
|
||||
pub fn visit_diff_grids(
|
||||
&self,
|
||||
from_pos: &Vector3,
|
||||
to_pos: &Vector3,
|
||||
miss_visitor: &mut Visitor,
|
||||
meet_visitor: &mut Visitor,
|
||||
) {
|
||||
for (i, grid_mgr) in self.grid_mgr_arr.iter().enumerate() {
|
||||
let c1 = self.pos_to_coordinate(
|
||||
VisionLevelType::from_primitive(i as u32),
|
||||
&Vector2 {
|
||||
x: from_pos.x,
|
||||
y: from_pos.z,
|
||||
},
|
||||
);
|
||||
|
||||
let c2 = self.pos_to_coordinate(
|
||||
VisionLevelType::from_primitive(i as u32),
|
||||
&Vector2 {
|
||||
x: to_pos.x,
|
||||
y: to_pos.z,
|
||||
},
|
||||
);
|
||||
|
||||
if c1 != c2 {
|
||||
grid_mgr.visit_diff_grids(&c1, &c2, miss_visitor, meet_visitor);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub fn pos_to_coordinate(&self, range_type: VisionLevelType, pos: &Vector2) -> Coordinate {
|
||||
let grid_width = Self::get_grid_width(range_type);
|
||||
Coordinate {
|
||||
|
|
62
gameserver/src/scene/visitor.rs
Normal file
62
gameserver/src/scene/visitor.rs
Normal file
|
@ -0,0 +1,62 @@
|
|||
use std::{cell::RefCell, rc::Rc};
|
||||
|
||||
use proto::ProtEntityType;
|
||||
|
||||
use crate::entity::Entity;
|
||||
|
||||
pub struct Visitor {
|
||||
visitor_type: VisitorType,
|
||||
visitor_entity: Rc<RefCell<dyn Entity>>,
|
||||
entity_vec: Vec<Rc<RefCell<dyn Entity>>>,
|
||||
}
|
||||
|
||||
pub enum VisitorType {
|
||||
Entity,
|
||||
// Gather,
|
||||
// Authority,
|
||||
}
|
||||
|
||||
impl Visitor {
|
||||
pub fn new(visitor_type: VisitorType, entity: Rc<RefCell<dyn Entity>>) -> Self {
|
||||
Self {
|
||||
visitor_type,
|
||||
visitor_entity: entity,
|
||||
entity_vec: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn visit_entity(&mut self, entity: &Rc<RefCell<dyn Entity>>) {
|
||||
if self.can_add_entity(entity) {
|
||||
self.entity_vec.push(entity.clone());
|
||||
}
|
||||
}
|
||||
|
||||
pub fn get_entity_vec(&self) -> &Vec<Rc<RefCell<dyn Entity>>> {
|
||||
&self.entity_vec
|
||||
}
|
||||
|
||||
fn can_add_entity(&self, entity: &Rc<RefCell<dyn Entity>>) -> bool {
|
||||
match self.visitor_type {
|
||||
VisitorType::Entity => {
|
||||
let visitor_entity_type = self.visitor_entity.borrow().get_entity_type();
|
||||
let entity_type = entity.borrow().get_entity_type();
|
||||
|
||||
if entity_type == ProtEntityType::ProtEntityEyePoint {
|
||||
if visitor_entity_type != ProtEntityType::ProtEntityAvatar
|
||||
&& visitor_entity_type != ProtEntityType::ProtEntityEyePoint
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if entity_type > ProtEntityType::ProtEntityEyePoint
|
||||
|| entity_type == ProtEntityType::ProtEntityWeather
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
entity.borrow().entity_id() != self.visitor_entity.borrow().entity_id()
|
||||
}
|
||||
}
|
|
@ -34,6 +34,14 @@ impl Vector3 {
|
|||
}
|
||||
}
|
||||
|
||||
pub fn from_client(client: &Vector) -> Self {
|
||||
Self {
|
||||
x: client.x,
|
||||
y: client.y,
|
||||
z: client.z,
|
||||
}
|
||||
}
|
||||
|
||||
pub fn to_bin(&self) -> VectorBin {
|
||||
VectorBin {
|
||||
x: self.x,
|
||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue