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 std::{fmt::Display, rc::Rc};
|
||||||
|
|
||||||
use data::math_def::Vector3;
|
use data::math_def::{Coordinate, Vector3};
|
||||||
use proto::{ProtEntityType, SceneEntityInfo};
|
use proto::{MotionState, ProtEntityType, Retcode, SceneEntityInfo};
|
||||||
|
|
||||||
use crate::player::Player;
|
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 {
|
pub trait Entity {
|
||||||
fn get_entity_type(&self) -> ProtEntityType;
|
fn get_entity_type(&self) -> ProtEntityType;
|
||||||
fn get_group_id(&self) -> u32;
|
fn get_group_id(&self) -> u32;
|
||||||
|
@ -14,6 +26,10 @@ pub trait Entity {
|
||||||
fn rotation(&self) -> &Vector3;
|
fn rotation(&self) -> &Vector3;
|
||||||
fn set_position(&mut self, pos: Vector3);
|
fn set_position(&mut self, pos: Vector3);
|
||||||
fn set_rotation(&mut self, rot: 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 get_owner_player(&self) -> Option<Rc<Player>>;
|
||||||
|
|
||||||
fn is_on_scene(&self) -> bool {
|
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) {}
|
fn to_client(&self, _scene_entity_info: &mut SceneEntityInfo) {}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
mod entity;
|
mod entity;
|
||||||
|
|
||||||
pub use entity::Entity;
|
pub use entity::{Entity, MotionContext};
|
||||||
pub mod entity_mgr;
|
pub mod entity_mgr;
|
||||||
pub mod entity_utils;
|
pub mod entity_utils;
|
||||||
mod vision_context;
|
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 avatar_handler;
|
||||||
|
pub mod fight_handler;
|
||||||
pub mod login_handler;
|
pub mod login_handler;
|
||||||
pub mod player_handler;
|
pub mod player_handler;
|
||||||
pub mod player_misc_handler;
|
pub mod player_misc_handler;
|
||||||
|
@ -44,10 +45,12 @@ game_packet_handlers! {
|
||||||
PlayerMiscHandler::PingReq;
|
PlayerMiscHandler::PingReq;
|
||||||
PlayerHandler::SetPlayerBornDataReq;
|
PlayerHandler::SetPlayerBornDataReq;
|
||||||
PlayerHandler::PlayerLogoutReq;
|
PlayerHandler::PlayerLogoutReq;
|
||||||
|
PlayerHandler::UnionCmdNotify;
|
||||||
SceneHandler::EnterSceneReadyReq;
|
SceneHandler::EnterSceneReadyReq;
|
||||||
SceneHandler::SceneInitFinishReq;
|
SceneHandler::SceneInitFinishReq;
|
||||||
SceneHandler::EnterSceneDoneReq;
|
SceneHandler::EnterSceneDoneReq;
|
||||||
SceneHandler::PostEnterSceneReq;
|
SceneHandler::PostEnterSceneReq;
|
||||||
AvatarHandler::SetUpAvatarTeamReq;
|
AvatarHandler::SetUpAvatarTeamReq;
|
||||||
AvatarHandler::ChangeAvatarReq;
|
AvatarHandler::ChangeAvatarReq;
|
||||||
|
FightHandler::CombatInvocationsNotify;
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
use std::{error::Error, rc::Rc};
|
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 proto::{PlayerLogoutReason, ServerDisconnectClientNotify, SetPlayerBornDataRsp};
|
||||||
|
|
||||||
use crate::player::Player;
|
use crate::player::Player;
|
||||||
|
@ -38,3 +38,36 @@ pub fn on_player_logout_req(player: &Rc<Player>, packet: Packet) -> Result<(), B
|
||||||
|
|
||||||
Ok(())
|
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 common::net::tools::Packet;
|
||||||
|
use data::math_def::Vector3;
|
||||||
use proto::{
|
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;
|
use super::get_proto;
|
||||||
|
|
||||||
|
@ -68,3 +75,51 @@ pub fn on_post_enter_scene_req(player: &Rc<Player>, packet: Packet) -> Result<()
|
||||||
|
|
||||||
Ok(())
|
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},
|
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::{
|
use proto::{
|
||||||
avatar_bin::{self, Detail},
|
avatar_bin::{self, Detail},
|
||||||
AbilitySyncStateInfo, AnimatorParameterValueInfoPair, AvatarBin, AvatarExcelInfo, Cjnoehnhdgl,
|
AbilitySyncStateInfo, AnimatorParameterValueInfoPair, AvatarBin, AvatarExcelInfo, Cjnoehnhdgl,
|
||||||
|
@ -14,7 +18,7 @@ use proto::{
|
||||||
use crate::{
|
use crate::{
|
||||||
ability::AbilityComp,
|
ability::AbilityComp,
|
||||||
creature::{property::PropValueMap, Creature, FightPropComp, LifeState},
|
creature::{property::PropValueMap, Creature, FightPropComp, LifeState},
|
||||||
entity::Entity,
|
entity::{Entity, MotionContext},
|
||||||
item::EquipComp,
|
item::EquipComp,
|
||||||
player::{item::Item, Player},
|
player::{item::Item, Player},
|
||||||
skill::SkillComp,
|
skill::SkillComp,
|
||||||
|
@ -243,6 +247,7 @@ pub struct BaseAvatar {
|
||||||
pub rot: Vector3,
|
pub rot: Vector3,
|
||||||
pub last_valid_pos: Vector3,
|
pub last_valid_pos: Vector3,
|
||||||
pub last_valid_rot: Vector3,
|
pub last_valid_rot: Vector3,
|
||||||
|
pub coordinate: Coordinate,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl BaseAvatar {
|
impl BaseAvatar {
|
||||||
|
@ -426,6 +431,26 @@ impl Entity for Avatar {
|
||||||
self.base_avatar_mut().rot = rot;
|
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) {
|
fn to_client(&self, scene_entity_info: &mut SceneEntityInfo) {
|
||||||
scene_entity_info.entity_id = self.entity_id();
|
scene_entity_info.entity_id = self.entity_id();
|
||||||
scene_entity_info.entity_type = self.get_entity_type().into();
|
scene_entity_info.entity_type = self.get_entity_type().into();
|
||||||
|
|
|
@ -23,8 +23,8 @@ use proto::{
|
||||||
EnterSceneDoneReq, EnterSceneDoneRsp, EnterScenePeerNotify, EnterSceneReadyReq, EnterType,
|
EnterSceneDoneReq, EnterSceneDoneRsp, EnterScenePeerNotify, EnterSceneReadyReq, EnterType,
|
||||||
MpLevelEntityInfo, PacketHead, PingReq, PingRsp, PlayerData, PlayerDataBin, PlayerDataNotify,
|
MpLevelEntityInfo, PacketHead, PingReq, PingRsp, PlayerData, PlayerDataBin, PlayerDataNotify,
|
||||||
PlayerEnterSceneInfoNotify, PlayerEnterSceneNotify, PlayerLoginRsp, PostEnterSceneReq,
|
PlayerEnterSceneInfoNotify, PlayerEnterSceneNotify, PlayerLoginRsp, PostEnterSceneReq,
|
||||||
PostEnterSceneRsp, ResVersionConfig, Retcode, SavePlayerDataReq, SceneInitFinishReq,
|
PostEnterSceneRsp, Retcode, SavePlayerDataReq, SceneInitFinishReq, SetPlayerBornDataReq,
|
||||||
SetPlayerBornDataReq, TeamEnterSceneInfo, VisionType, YSMessage,
|
TeamEnterSceneInfo, VisionType, YSMessage,
|
||||||
};
|
};
|
||||||
use rand::RngCore;
|
use rand::RngCore;
|
||||||
|
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::{cell::RefCell, collections::BTreeMap, rc::Rc};
|
||||||
|
|
||||||
use crate::entity::Entity;
|
use crate::entity::Entity;
|
||||||
|
|
||||||
use super::region::Region;
|
use super::{region::Region, visitor::Visitor};
|
||||||
|
|
||||||
#[derive(Default)]
|
#[derive(Default)]
|
||||||
pub struct Grid {
|
pub struct Grid {
|
||||||
|
@ -30,6 +30,12 @@ impl Grid {
|
||||||
self.region_vec.push(region);
|
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>>> {
|
pub fn get_all_entity(&self) -> Vec<Rc<RefCell<dyn Entity>>> {
|
||||||
self.entity_map.values().map(|a| a.clone()).collect()
|
self.entity_map.values().map(|a| a.clone()).collect()
|
||||||
}
|
}
|
||||||
|
|
|
@ -5,7 +5,7 @@ use proto::ProtEntityType;
|
||||||
|
|
||||||
use crate::entity::Entity;
|
use crate::entity::Entity;
|
||||||
|
|
||||||
use super::{grid::Grid, region::Region, VisionLevelType};
|
use super::{grid::Grid, region::Region, visitor::Visitor, VisionLevelType};
|
||||||
|
|
||||||
#[allow(unused)]
|
#[allow(unused)]
|
||||||
pub struct GridMgr {
|
pub struct GridMgr {
|
||||||
|
@ -21,6 +21,10 @@ impl GridMgr {
|
||||||
self.grid_map.entry((x, y)).or_insert_with(Grid::default)
|
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(
|
pub fn place_entity(
|
||||||
&mut self,
|
&mut self,
|
||||||
entity: Rc<RefCell<dyn Entity>>,
|
entity: Rc<RefCell<dyn Entity>>,
|
||||||
|
@ -47,6 +51,115 @@ impl GridMgr {
|
||||||
grid.del_entity(entity);
|
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)]
|
#[allow(dead_code)]
|
||||||
pub fn place_region(&mut self, region: Region, coordinate: Coordinate) -> Result<(), ()> {
|
pub fn place_region(&mut self, region: Region, coordinate: Coordinate) -> Result<(), ()> {
|
||||||
let grid = self.get_grid(coordinate.x, coordinate.y);
|
let grid = self.get_grid(coordinate.x, coordinate.y);
|
||||||
|
|
|
@ -10,6 +10,7 @@ mod scene;
|
||||||
pub mod scene_mgr;
|
pub mod scene_mgr;
|
||||||
mod scene_sight_comp;
|
mod scene_sight_comp;
|
||||||
mod scene_team;
|
mod scene_team;
|
||||||
|
mod visitor;
|
||||||
|
|
||||||
pub use mp_level_entity::MPLevelEntity;
|
pub use mp_level_entity::MPLevelEntity;
|
||||||
pub use player_scene_comp::{EnterSceneState, PlayerSceneComp};
|
pub use player_scene_comp::{EnterSceneState, PlayerSceneComp};
|
||||||
|
|
|
@ -268,6 +268,59 @@ impl Scene {
|
||||||
.insert(uid, player_location);
|
.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) {
|
fn notify_scene_and_host_data(&self, uid: u32) {
|
||||||
let Some(player) = self.base().find_player(uid) else {
|
let Some(player) = self.base().find_player(uid) else {
|
||||||
tracing::warn!("find_player failed, uid:{uid}");
|
tracing::warn!("find_player failed, uid:{uid}");
|
||||||
|
|
|
@ -1,12 +1,15 @@
|
||||||
use std::{cell::RefCell, collections::HashMap, rc::Rc};
|
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 num_enum::FromPrimitive;
|
||||||
use proto::Retcode;
|
use proto::{ProtEntityType, Retcode};
|
||||||
|
|
||||||
use crate::entity::Entity;
|
use crate::entity::Entity;
|
||||||
|
|
||||||
use super::grid_mgr::GridMgr;
|
use super::{
|
||||||
|
grid_mgr::GridMgr,
|
||||||
|
visitor::{Visitor, VisitorType},
|
||||||
|
};
|
||||||
|
|
||||||
#[derive(Debug, Default, Clone, Copy, FromPrimitive)]
|
#[derive(Debug, Default, Clone, Copy, FromPrimitive)]
|
||||||
#[repr(u32)]
|
#[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 {
|
pub fn pos_to_coordinate(&self, range_type: VisionLevelType, pos: &Vector2) -> Coordinate {
|
||||||
match self {
|
match self {
|
||||||
Self::Grid(grid_comp) => grid_comp.pos_to_coordinate(range_type, pos),
|
Self::Grid(grid_comp) => grid_comp.pos_to_coordinate(range_type, pos),
|
||||||
|
@ -177,6 +194,66 @@ impl SceneGridComp {
|
||||||
grid_mgr.remove_entity(entity, coordinate);
|
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 {
|
pub fn pos_to_coordinate(&self, range_type: VisionLevelType, pos: &Vector2) -> Coordinate {
|
||||||
let grid_width = Self::get_grid_width(range_type);
|
let grid_width = Self::get_grid_width(range_type);
|
||||||
Coordinate {
|
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 {
|
pub fn to_bin(&self) -> VectorBin {
|
||||||
VectorBin {
|
VectorBin {
|
||||||
x: self.x,
|
x: self.x,
|
||||||
|
|
File diff suppressed because it is too large
Load diff
Loading…
Reference in a new issue