mirror of
https://github.com/RustySamovar/RustySamovar.git
synced 2024-11-24 11:23:33 +00:00
One step close to DB
This commit is contained in:
parent
4d32da1e2e
commit
2f0741868e
@ -23,8 +23,8 @@ serde_json = "1.0"
|
|||||||
pretty_env_logger = "0.4"
|
pretty_env_logger = "0.4"
|
||||||
num-traits = "0.2"
|
num-traits = "0.2"
|
||||||
num-derive = "0.3"
|
num-derive = "0.3"
|
||||||
|
|
||||||
pretty-hex = "0.2"
|
pretty-hex = "0.2"
|
||||||
|
sea-orm = { version = "0.3", features = [ "sqlx-all", "runtime-async-std-native-tls" ] }
|
||||||
|
|
||||||
[target.'cfg(windows)'.dependencies]
|
[target.'cfg(windows)'.dependencies]
|
||||||
openssl = { version = "0.10", features = ["vendored"] }
|
openssl = { version = "0.10", features = ["vendored"] }
|
||||||
|
@ -86,6 +86,10 @@ pub fn packet_processor(args: TokenStream, input: TokenStream) -> TokenStream {
|
|||||||
return self.packet_callbacks.keys().cloned().collect();
|
return self.packet_callbacks.keys().cloned().collect();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn is_supported(&self, packet_id: &proto::PacketId) -> bool {
|
||||||
|
return self.packet_callbacks.contains_key(&packet_id);
|
||||||
|
}
|
||||||
|
|
||||||
fn process(&mut self, user_id: u32, packet_id: proto::PacketId, metadata: Vec<u8>, data: Vec<u8>) {
|
fn process(&mut self, user_id: u32, packet_id: proto::PacketId, metadata: Vec<u8>, data: Vec<u8>) {
|
||||||
let callback = self.packet_callbacks.get(&packet_id);
|
let callback = self.packet_callbacks.get(&packet_id);
|
||||||
let metadata = proto::PacketHead::decode(&mut std::io::Cursor::new(metadata)).unwrap();
|
let metadata = proto::PacketHead::decode(&mut std::io::Cursor::new(metadata)).unwrap();
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
pub trait PacketProcessor {
|
pub trait PacketProcessor {
|
||||||
fn register(&mut self);
|
fn register(&mut self);
|
||||||
fn supported(&self) -> Vec<proto::PacketId>;
|
fn supported(&self) -> Vec<proto::PacketId>;
|
||||||
|
fn is_supported(&self, packet_id: &proto::PacketId) -> bool;
|
||||||
fn process(&mut self, user_id: u32, packet_id: proto::PacketId, metadata: Vec<u8>, data: Vec<u8>);
|
fn process(&mut self, user_id: u32, packet_id: proto::PacketId, metadata: Vec<u8>, data: Vec<u8>);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -30,3 +31,23 @@ macro_rules! register_callback {
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! build_and_send {
|
||||||
|
($self:ident, $user_id: ident, $metadata:ident, $id:ident { $($i:ident : $e:expr,)* }) => {{
|
||||||
|
$self.packets_to_send_tx.send(
|
||||||
|
IpcMessage::new_from_proto(
|
||||||
|
$user_id,
|
||||||
|
proto::PacketId::$id,
|
||||||
|
$metadata,
|
||||||
|
&proto::$id { $($i: $e,)* ..proto::$id::default() }
|
||||||
|
)
|
||||||
|
).unwrap();
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! build {
|
||||||
|
($id:ident { $($i:ident : $e:expr,)* }) => {{
|
||||||
|
proto::$id { $($i: $e,)* ..proto::$id::default() }
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
28
src/dbmanager/avatar_info.rs
Normal file
28
src/dbmanager/avatar_info.rs
Normal file
@ -0,0 +1,28 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "avatar_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub character_id: u32,
|
||||||
|
pub avatar_type: u8,
|
||||||
|
pub guid: u64,
|
||||||
|
pub born_time: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
26
src/dbmanager/avatar_team_info.rs
Normal file
26
src/dbmanager/avatar_team_info.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "avatar_team_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub team_id: u8,
|
||||||
|
pub guid: u64,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
336
src/dbmanager/database_manager.rs
Normal file
336
src/dbmanager/database_manager.rs
Normal file
@ -0,0 +1,336 @@
|
|||||||
|
// Database Manager
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use sea_orm::{entity::*, error::*, query::*, DbConn, FromQueryResult, Database};
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
pub use super::player_info::Model as PlayerInfo;
|
||||||
|
use super::player_info::Entity as PlayerInfoEntity;
|
||||||
|
|
||||||
|
pub use super::avatar_info::Model as AvatarInfo;
|
||||||
|
use super::avatar_info::Entity as AvatarInfoEntity;
|
||||||
|
|
||||||
|
pub use super::scene_info::Model as SceneInfo;
|
||||||
|
use super::scene_info::Entity as SceneInfoEntity;
|
||||||
|
|
||||||
|
pub use super::team_info::Model as TeamInfo;
|
||||||
|
use super::team_info::Entity as TeamInfoEntity;
|
||||||
|
|
||||||
|
pub use super::avatar_team_info::Model as AvatarTeamInfo;
|
||||||
|
use super::avatar_team_info::Entity as AvatarTeamInfoEntity;
|
||||||
|
|
||||||
|
pub use super::team_selection_info::Model as TeamSelectionInfo;
|
||||||
|
use super::team_selection_info::Entity as TeamSelectionInfoEntity;
|
||||||
|
|
||||||
|
macro_rules! collection {
|
||||||
|
// map-like
|
||||||
|
($($k:expr => $v:expr),* $(,)?) => {{
|
||||||
|
use std::iter::{Iterator, IntoIterator};
|
||||||
|
Iterator::collect(IntoIterator::into_iter([$(($k, $v),)*]))
|
||||||
|
}};
|
||||||
|
// set-like
|
||||||
|
($($v:expr),* $(,)?) => {{
|
||||||
|
use std::iter::{Iterator, IntoIterator};
|
||||||
|
Iterator::collect(IntoIterator::into_iter([$($v,)*]))
|
||||||
|
}};
|
||||||
|
}
|
||||||
|
|
||||||
|
trait Block {
|
||||||
|
fn wait(self) -> <Self as futures::Future>::Output
|
||||||
|
where Self: Sized, Self: futures::Future
|
||||||
|
{
|
||||||
|
futures::executor::block_on(self)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<F,T> Block for F
|
||||||
|
where F: futures::Future<Output = T>
|
||||||
|
{}
|
||||||
|
|
||||||
|
pub struct DatabaseManager {
|
||||||
|
db: DbConn,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl DatabaseManager {
|
||||||
|
pub fn new(conn_string: &str) -> Self {
|
||||||
|
return DatabaseManager {
|
||||||
|
db: Database::connect(conn_string).wait().unwrap(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn _get_player_info(&self, uid: u32) -> Option<PlayerInfo> {
|
||||||
|
match PlayerInfoEntity::find_by_id(uid).one(&self.db).wait() {
|
||||||
|
Err(_) => { println!("DB ERROR!"); None },
|
||||||
|
Ok(p_info) => p_info,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_info(&self, uid: u32) -> Option<PlayerInfo> {
|
||||||
|
Some(PlayerInfo {
|
||||||
|
uid: uid,
|
||||||
|
nick_name: "Fapper".into(),
|
||||||
|
level: 56,
|
||||||
|
signature: "Hello world!".into(),
|
||||||
|
birthday: 0,
|
||||||
|
world_level: 8,
|
||||||
|
namecard_id: 210051,
|
||||||
|
finish_achievement_num: 42,
|
||||||
|
tower_floor_index: 1,
|
||||||
|
tower_level_index: 1,
|
||||||
|
avatar_id: 10000007,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_props(&self, uid: u32) -> Option<HashMap<u32, i64>> {
|
||||||
|
Some(collection! {
|
||||||
|
proto::PropType::PropIsSpringAutoUse as u32 => 1,
|
||||||
|
proto::PropType::PropIsFlyable as u32 => 1,
|
||||||
|
proto::PropType::PropIsTransferable as u32 => 1,
|
||||||
|
proto::PropType::PropPlayerLevel as u32 => 56,
|
||||||
|
proto::PropType::PropPlayerExp as u32 => 1337,
|
||||||
|
proto::PropType::PropPlayerHcoin as u32 => 9001,
|
||||||
|
proto::PropType::PropPlayerScoin as u32 => 9002,
|
||||||
|
proto::PropType::PropPlayerWorldLevel as u32 => 8,
|
||||||
|
proto::PropType::PropPlayerResin as u32 => 159,
|
||||||
|
proto::PropType::PropPlayerMcoin as u32 => 9003,
|
||||||
|
proto::PropType::PropMaxStamina as u32 => 120,
|
||||||
|
proto::PropType::PropCurPersistStamina as u32 => 120,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_avatar_props(&self, guid: u64) -> Option<HashMap<u32, i64>> {
|
||||||
|
let map = collection! {
|
||||||
|
proto::PropType::PropExp as u32 => 0,
|
||||||
|
proto::PropType::PropLevel as u32 => 80,
|
||||||
|
proto::PropType::PropBreakLevel as u32 => 5,
|
||||||
|
proto::PropType::PropSatiationVal as u32 => 0,
|
||||||
|
proto::PropType::PropSatiationPenaltyTime as u32 => 0,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_avatar_equip(&self, guid: u64) -> Option<Vec<u64>> {
|
||||||
|
let equip = vec![Self::SPOOFED_WEAPON_GUID];
|
||||||
|
|
||||||
|
return Some(equip);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_skill_levels(&self, guid: u64) -> Option<HashMap<u32,u32>> {
|
||||||
|
let map = collection! {
|
||||||
|
10068 => 3,
|
||||||
|
100553 => 3,
|
||||||
|
10067 => 3,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_avatar_fight_props(&self, guid: u64) -> Option<HashMap<u32, f32>> {
|
||||||
|
let map = collection! {
|
||||||
|
proto::FightPropType::FightPropBaseHp as u32 => 9000.0,
|
||||||
|
proto::FightPropType::FightPropHp as u32 => 3000.0,
|
||||||
|
proto::FightPropType::FightPropHpPercent as u32 => 0.0746000,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropBaseAttack as u32 => 600.0,
|
||||||
|
proto::FightPropType::FightPropAttack as u32 => 50.0,
|
||||||
|
proto::FightPropType::FightPropAttackPercent as u32 => 0.40,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropBaseDefense as u32 => 600.0,
|
||||||
|
proto::FightPropType::FightPropDefense as u32 => 40.0,
|
||||||
|
proto::FightPropType::FightPropDefensePercent as u32 => 0.04,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropCritical as u32 => 0.99,
|
||||||
|
proto::FightPropType::FightPropAntiCritical as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropCriticalHurt as u32 => 0.99,
|
||||||
|
proto::FightPropType::FightPropChargeEfficiency as u32 => 1.337,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropHealAdd as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropHealedAdd as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropElementMastery as u32 => 42.0,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropPhysicalSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropPhysicalAddHurt as u32 => 0.271828,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropFireAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropElecAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropWaterAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropGrassAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropWindAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropRockAddHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropIceAddHurt as u32 => 0.00000,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropFireSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropElecSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropWaterSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropGrassSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropWindSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropRockSubHurt as u32 => 0.00000,
|
||||||
|
proto::FightPropType::FightPropIceSubHurt as u32 => 0.00000,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropMaxWindEnergy as u32 => 60.0000,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropCurWindEnergy as u32 => 60.0000,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropCurHp as u32 => 10000.0,
|
||||||
|
|
||||||
|
proto::FightPropType::FightPropMaxHp as u32 => 12000.0,
|
||||||
|
proto::FightPropType::FightPropCurAttack as u32 => 900.0,
|
||||||
|
proto::FightPropType::FightPropCurDefense as u32 => 700.0,
|
||||||
|
proto::FightPropType::FightPropCurSpeed as u32 => 10.00000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(map);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_open_state(&self, uid: u32) -> Option<HashMap<u32, u32>> {
|
||||||
|
Some(collection! {
|
||||||
|
proto::OpenStateType::OpenStatePaimon as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStatePlayerLvupGuide as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateGacha as u32 => 1,
|
||||||
|
proto::OpenStateType::OpenStateGuideGacha as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateGuideTeam as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateGuideBag as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateLimitRegionFreshmeat as u32 => 1,
|
||||||
|
proto::OpenStateType::OpenStateLimitRegionGlobal as u32 => 1,
|
||||||
|
proto::OpenStateType::OpenStateMultiplayer as u32 => 0,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateAvatarFashion as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateGuideAppearance as u32 => 1,
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateShopTypeMall as u32 => 1, // 900
|
||||||
|
proto::OpenStateType::OpenStateShopTypeRecommanded as u32 => 1, // 901
|
||||||
|
proto::OpenStateType::OpenStateShopTypeGenesiscrystal as u32 => 1, // 902
|
||||||
|
proto::OpenStateType::OpenStateShopTypeGiftpackage as u32 => 1, // 903
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenAdventureManual as u32 => 1, // 1100
|
||||||
|
proto::OpenStateType::OpenAdventureManualMonster as u32 => 1, // 1103
|
||||||
|
proto::OpenStateType::OpenAdventureManualBossDungeon as u32 => 1, // 1104
|
||||||
|
|
||||||
|
proto::OpenStateType::OpenStateMengdeInfusedcrystal as u32 => 1,
|
||||||
|
proto::OpenStateType::OpenStateLiyueInfusedcrystal as u32 => 1,
|
||||||
|
proto::OpenStateType::OpenStateInazumaMainquestFinished as u32 => 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_inventory(&self, uid: u32) -> Option<Vec<proto::Item>> {
|
||||||
|
let mut weapon = proto::Weapon::default();
|
||||||
|
weapon.level = 70;
|
||||||
|
weapon.promote_level = 4;
|
||||||
|
weapon.affix_map = collection!{111406 => 0};
|
||||||
|
|
||||||
|
let mut equip = proto::Equip::default();
|
||||||
|
equip.is_locked = true;
|
||||||
|
equip.detail = Some(proto::equip::Detail::Weapon(weapon));
|
||||||
|
|
||||||
|
let mut item = proto::Item::default();
|
||||||
|
item.item_id = 11406;
|
||||||
|
item.guid = Self::SPOOFED_WEAPON_GUID;
|
||||||
|
item.detail = Some(proto::item::Detail::Equip(equip));
|
||||||
|
|
||||||
|
return Some(vec![item]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_avatars(&self, uid: u32) -> Option<Vec<AvatarInfo>> {
|
||||||
|
let ai = AvatarInfo {
|
||||||
|
uid: uid,
|
||||||
|
character_id: 7,
|
||||||
|
avatar_type: 1,
|
||||||
|
guid: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
born_time: 1633790000,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(vec![ai]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_scene_info(&self, uid: u32) -> Option<SceneInfo> {
|
||||||
|
let si = SceneInfo {
|
||||||
|
uid: uid,
|
||||||
|
scene_id: Self::SPOOFED_SCENE_ID,
|
||||||
|
scene_token: Self::SPOOFED_SCENE_TOKEN,
|
||||||
|
pos_x: -3400.0,
|
||||||
|
pos_y: 233.0,
|
||||||
|
pos_z: 3427.6,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(si);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_teams(&self, uid: u32) -> Option<Vec<TeamInfo>> {
|
||||||
|
let t1 = TeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
id: 1,
|
||||||
|
name: "Team 1".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let t2 = TeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
id: 2,
|
||||||
|
name: "Team 2".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let t3 = TeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
id: 3,
|
||||||
|
name: "Team 3".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
let t4 = TeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
id: 4,
|
||||||
|
name: "Team 4".to_string(),
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(vec![t1, t2, t3, t4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_teams_avatars(&self, uid: u32) -> Option<Vec<AvatarTeamInfo>> {
|
||||||
|
let a1 = AvatarTeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
team_id: 1,
|
||||||
|
guid: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
let a2 = AvatarTeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
team_id: 2,
|
||||||
|
guid: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
let a3 = AvatarTeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
team_id: 3,
|
||||||
|
guid: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
let a4 = AvatarTeamInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
team_id: 4,
|
||||||
|
guid: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(vec![a1, a2, a3, a4]);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_player_team_selection(&self, uid: u32) -> Option<TeamSelectionInfo> {
|
||||||
|
let tsi = TeamSelectionInfo {
|
||||||
|
uid: uid.clone(),
|
||||||
|
avatar: Self::SPOOFED_AVATAR_GUID,
|
||||||
|
team: 1,
|
||||||
|
};
|
||||||
|
|
||||||
|
return Some(tsi);
|
||||||
|
}
|
||||||
|
|
||||||
|
const BASE_GUID: u64 = 0x2400000000000000;
|
||||||
|
const SPOOFED_AVATAR_GUID: u64 = Self::BASE_GUID + 1;
|
||||||
|
const SPOOFED_WEAPON_GUID: u64 = Self::BASE_GUID + 2;
|
||||||
|
const SPOOFED_SCENE_ID: u32 = 3;
|
||||||
|
const SPOOFED_SCENE_TOKEN: u32 = 0x1234;
|
||||||
|
}
|
10
src/dbmanager/mod.rs
Normal file
10
src/dbmanager/mod.rs
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
pub mod database_manager;
|
||||||
|
|
||||||
|
pub use self::database_manager::DatabaseManager;
|
||||||
|
|
||||||
|
mod player_info;
|
||||||
|
mod avatar_info;
|
||||||
|
mod scene_info;
|
||||||
|
mod avatar_team_info;
|
||||||
|
mod team_info;
|
||||||
|
mod team_selection_info;
|
34
src/dbmanager/player_info.rs
Normal file
34
src/dbmanager/player_info.rs
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "player_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub nick_name: String,
|
||||||
|
pub level: u8,
|
||||||
|
pub signature: String,
|
||||||
|
pub birthday: u32,
|
||||||
|
pub world_level: u8,
|
||||||
|
pub namecard_id: u32,
|
||||||
|
pub finish_achievement_num: u32,
|
||||||
|
pub tower_floor_index: u8,
|
||||||
|
pub tower_level_index: u8,
|
||||||
|
pub avatar_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
29
src/dbmanager/scene_info.rs
Normal file
29
src/dbmanager/scene_info.rs
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "scene_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub scene_id: u32,
|
||||||
|
pub scene_token: u32,
|
||||||
|
pub pos_x: f32,
|
||||||
|
pub pos_y: f32,
|
||||||
|
pub pos_z: f32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
26
src/dbmanager/team_info.rs
Normal file
26
src/dbmanager/team_info.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "team_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub id: u8,
|
||||||
|
pub name: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
26
src/dbmanager/team_selection_info.rs
Normal file
26
src/dbmanager/team_selection_info.rs
Normal file
@ -0,0 +1,26 @@
|
|||||||
|
// Database Manager
|
||||||
|
|
||||||
|
use sea_orm::entity::prelude::*;
|
||||||
|
|
||||||
|
#[derive(Clone, Debug, PartialEq, DeriveEntityModel)]
|
||||||
|
#[sea_orm(table_name = "team_selection_info")]
|
||||||
|
pub struct Model {
|
||||||
|
#[sea_orm(primary_key)]
|
||||||
|
pub uid: u32,
|
||||||
|
pub avatar: u64,
|
||||||
|
pub team: u8,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Copy, Clone, Debug, EnumIter)]
|
||||||
|
pub enum Relation {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl RelationTrait for Relation {
|
||||||
|
fn def(&self) -> RelationDef {
|
||||||
|
match self {
|
||||||
|
_ => panic!("Unknown relation type!"),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl ActiveModelBehavior for ActiveModel {}
|
24
src/jsonmanager/avatar_skill_depot.rs
Normal file
24
src/jsonmanager/avatar_skill_depot.rs
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
use serde::{Serialize, Deserialize};
|
||||||
|
|
||||||
|
#[serde(rename_all="PascalCase")]
|
||||||
|
#[derive(Serialize,Deserialize, Clone)]
|
||||||
|
pub struct ProudSkillOpenConfig {
|
||||||
|
pub proud_skill_group_id: Option<u32>,
|
||||||
|
pub need_avatar_promote_level: Option<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[serde(rename_all="PascalCase")]
|
||||||
|
#[derive(Serialize, Deserialize, Clone)]
|
||||||
|
pub struct AvatarSkillDepot {
|
||||||
|
pub id: u32,
|
||||||
|
pub energy_skill: Option<u32>,
|
||||||
|
pub skills: Vec<u32>,
|
||||||
|
pub sub_skills: Vec<u32>,
|
||||||
|
pub extra_abilities: Vec<String>,
|
||||||
|
pub talents: Vec<u32>,
|
||||||
|
pub talent_star_name: String,
|
||||||
|
pub inherent_proud_skill_opens: Vec<ProudSkillOpenConfig>,
|
||||||
|
pub skill_depot_ability_group: String,
|
||||||
|
pub leader_talent: Option<u32>,
|
||||||
|
pub attack_mode_skill: Option<u32>,
|
||||||
|
}
|
49
src/jsonmanager/json_manager.rs
Normal file
49
src/jsonmanager/json_manager.rs
Normal file
@ -0,0 +1,49 @@
|
|||||||
|
use std::fs::read_to_string; // use instead of std::fs::File
|
||||||
|
use std::path::Path;
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use serde::Deserialize;
|
||||||
|
use serde::de::DeserializeOwned;
|
||||||
|
|
||||||
|
use super::avatar_skill_depot::AvatarSkillDepot;
|
||||||
|
|
||||||
|
struct JsonReader {
|
||||||
|
base_path: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub struct JsonManager {
|
||||||
|
reader: JsonReader,
|
||||||
|
pub avatar_skill_depot: HashMap<u32,AvatarSkillDepot>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonManager {
|
||||||
|
pub fn new(directory: &str) -> JsonManager {
|
||||||
|
let reader = JsonReader::new(directory);
|
||||||
|
|
||||||
|
let asd: Vec<AvatarSkillDepot> = reader.read_json_list("AvatarSkillDepot");
|
||||||
|
|
||||||
|
return JsonManager {
|
||||||
|
reader: reader,
|
||||||
|
avatar_skill_depot: asd.into_iter().map(|a| (a.id, a)).collect(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl JsonReader {
|
||||||
|
pub fn new(directory: &str) -> JsonReader {
|
||||||
|
return JsonReader {
|
||||||
|
base_path: directory.to_owned(),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
fn read_json_list<T>(&self, name: &str) -> Vec<T>
|
||||||
|
where T: DeserializeOwned
|
||||||
|
{
|
||||||
|
let path = format!("{}/{}ExcelConfigData.json", self.base_path, name);
|
||||||
|
|
||||||
|
let json_file_path = Path::new(&path);
|
||||||
|
let json_file_str = read_to_string(json_file_path).unwrap_or_else(|_| panic!("File {} not found", path));
|
||||||
|
let data: Vec<T> = serde_json::from_str(&json_file_str).expect("Error while reading json");
|
||||||
|
return data;
|
||||||
|
}
|
||||||
|
}
|
5
src/jsonmanager/mod.rs
Normal file
5
src/jsonmanager/mod.rs
Normal file
@ -0,0 +1,5 @@
|
|||||||
|
mod json_manager;
|
||||||
|
|
||||||
|
pub use self::json_manager::JsonManager;
|
||||||
|
|
||||||
|
mod avatar_skill_depot;
|
@ -7,9 +7,13 @@ use std::thread;
|
|||||||
|
|
||||||
mod server;
|
mod server;
|
||||||
mod utils;
|
mod utils;
|
||||||
|
mod dbmanager;
|
||||||
|
mod jsonmanager;
|
||||||
|
|
||||||
use server::NetworkServer;
|
use server::NetworkServer;
|
||||||
use server::DispatchServer;
|
use server::DispatchServer;
|
||||||
|
use dbmanager::DatabaseManager;
|
||||||
|
use jsonmanager::JsonManager;
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
pretty_env_logger::init();
|
pretty_env_logger::init();
|
||||||
|
@ -7,6 +7,8 @@ use std::io::Write;
|
|||||||
use std::time::SystemTime;
|
use std::time::SystemTime;
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
use crate::utils::TimeManager;
|
||||||
|
|
||||||
extern crate kcp;
|
extern crate kcp;
|
||||||
extern crate mhycrypt;
|
extern crate mhycrypt;
|
||||||
|
|
||||||
@ -106,7 +108,7 @@ impl ClientConnection {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn elapsed_time_millis(&self) -> u32 {
|
fn elapsed_time_millis(&self) -> u32 {
|
||||||
return SystemTime::now().duration_since(self.established_time).unwrap().as_millis().try_into().unwrap();
|
return TimeManager::duration_since(self.established_time).try_into().unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn send_udp_packet(&mut self, data: &[u8]) {
|
pub fn send_udp_packet(&mut self, data: &[u8]) {
|
||||||
|
@ -7,18 +7,29 @@ use crate::server::GameWorld;
|
|||||||
use packet_processor::PacketProcessor;
|
use packet_processor::PacketProcessor;
|
||||||
use crate::server::IpcMessage;
|
use crate::server::IpcMessage;
|
||||||
|
|
||||||
|
use crate::DatabaseManager;
|
||||||
|
use crate::JsonManager;
|
||||||
|
use crate::server::LoginManager;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
pub struct GameServer {
|
pub struct GameServer {
|
||||||
packets_to_process_rx: mpsc::Receiver<IpcMessage>,
|
packets_to_process_rx: mpsc::Receiver<IpcMessage>,
|
||||||
packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
||||||
worlds: HashMap<u32, GameWorld>,
|
worlds: HashMap<u32, GameWorld>,
|
||||||
|
login_manager: LoginManager,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl GameServer {
|
impl GameServer {
|
||||||
pub fn new(packets_to_process_rx: mpsc::Receiver<IpcMessage>, packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameServer {
|
pub fn new(packets_to_process_rx: mpsc::Receiver<IpcMessage>, packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameServer {
|
||||||
|
let db = DatabaseManager::new("sqlite://./database.db3");
|
||||||
|
let jm = JsonManager::new("./json");
|
||||||
|
let lm = LoginManager::new(Arc::new(db), Arc::new(jm), packets_to_send_tx.clone());
|
||||||
|
|
||||||
let gs = GameServer {
|
let gs = GameServer {
|
||||||
packets_to_process_rx: packets_to_process_rx,
|
packets_to_process_rx: packets_to_process_rx,
|
||||||
packets_to_send_tx: packets_to_send_tx,
|
packets_to_send_tx: packets_to_send_tx,
|
||||||
worlds: HashMap::new(),
|
worlds: HashMap::new(),
|
||||||
|
login_manager: lm,
|
||||||
};
|
};
|
||||||
|
|
||||||
return gs;
|
return gs;
|
||||||
@ -34,17 +45,21 @@ impl GameServer {
|
|||||||
|
|
||||||
loop {
|
loop {
|
||||||
let IpcMessage(user_id, packet_id, metadata, data) = self.packets_to_process_rx.recv().unwrap();
|
let IpcMessage(user_id, packet_id, metadata, data) = self.packets_to_process_rx.recv().unwrap();
|
||||||
|
|
||||||
// TODO: each user_id will have a distinct world!
|
|
||||||
let world = match self.worlds.entry(user_id) {
|
|
||||||
Occupied(world) => world.into_mut(),
|
|
||||||
Vacant(entry) => {
|
|
||||||
let mut world = GameWorld::new(self.packets_to_send_tx.clone());
|
|
||||||
entry.insert(world)
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
world.process(user_id, packet_id, metadata, data);
|
if (self.login_manager.is_supported(&packet_id)) {
|
||||||
|
self.login_manager.process(user_id, packet_id, metadata, data);
|
||||||
|
} else {
|
||||||
|
// TODO: each user_id will have a distinct world!
|
||||||
|
let world = match self.worlds.entry(user_id) {
|
||||||
|
Occupied(world) => world.into_mut(),
|
||||||
|
Vacant(entry) => {
|
||||||
|
let mut world = GameWorld::new(self.packets_to_send_tx.clone());
|
||||||
|
entry.insert(world)
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
world.process(user_id, packet_id, metadata, data);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -24,28 +24,8 @@ macro_rules! collection {
|
|||||||
}};
|
}};
|
||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! build_and_send {
|
|
||||||
($id:ident, $self:ident, $user_id: ident, $metadata:ident, { $($i:ident : $e:expr,)* }) => {{
|
|
||||||
$self.packets_to_send_tx.send(
|
|
||||||
IpcMessage::new_from_proto(
|
|
||||||
$user_id,
|
|
||||||
proto::PacketId::$id,
|
|
||||||
$metadata,
|
|
||||||
&proto::$id { $($i: $e,)* ..proto::$id::default() }
|
|
||||||
)
|
|
||||||
).unwrap();
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
macro_rules! build {
|
|
||||||
($id:ident, { $($i:ident : $e:expr,)* }) => {{
|
|
||||||
proto::$id { $($i: $e,)* ..proto::$id::default() }
|
|
||||||
}};
|
|
||||||
}
|
|
||||||
|
|
||||||
#[packet_processor(
|
#[packet_processor(
|
||||||
PingReq,
|
PingReq,
|
||||||
PlayerLoginReq,
|
|
||||||
GetPlayerSocialDetailReq,
|
GetPlayerSocialDetailReq,
|
||||||
EnterSceneReadyReq,
|
EnterSceneReadyReq,
|
||||||
SceneInitFinishReq,
|
SceneInitFinishReq,
|
||||||
@ -63,7 +43,7 @@ impl GameWorld {
|
|||||||
const SPOOFED_AVATAR_GUID: u64 = GameWorld::BASE_GUID + 1;
|
const SPOOFED_AVATAR_GUID: u64 = GameWorld::BASE_GUID + 1;
|
||||||
const SPOOFED_WEAPON_EID: u32 = 0x6000000 + 146;
|
const SPOOFED_WEAPON_EID: u32 = 0x6000000 + 146;
|
||||||
const SPOOFED_WEAPON_GUID: u64 = GameWorld::BASE_GUID + 2;
|
const SPOOFED_WEAPON_GUID: u64 = GameWorld::BASE_GUID + 2;
|
||||||
const SPOOFED_SCENE_TOKEN: u32 = 1234;
|
const SPOOFED_SCENE_TOKEN: u32 = 0x1234;
|
||||||
const SPOOFED_SCENE_ID: u32 = 3;
|
const SPOOFED_SCENE_ID: u32 = 3;
|
||||||
|
|
||||||
pub fn new(packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameWorld {
|
pub fn new(packets_to_send_tx: mpsc::Sender<IpcMessage>) -> GameWorld {
|
||||||
@ -81,82 +61,31 @@ impl GameWorld {
|
|||||||
rsp.client_time = req.client_time;
|
rsp.client_time = req.client_time;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_player_login(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::PlayerLoginReq, rsp: &mut proto::PlayerLoginRsp) {
|
|
||||||
build_and_send! ( PlayerDataNotify, self, user_id, metadata,
|
|
||||||
{ nick_name: "Fapper".into(), server_time: self.timestamp(), prop_map: self.spoof_player_props(), }
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send! ( OpenStateUpdateNotify, self, user_id, metadata,
|
|
||||||
{ open_state_map: self.spoof_world_props(), }
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send! (StoreWeightLimitNotify, self, user_id, metadata,
|
|
||||||
{
|
|
||||||
store_type: proto::StoreType::StorePack as i32,
|
|
||||||
weight_limit: 30000,
|
|
||||||
material_count_limit: 2000,
|
|
||||||
weapon_count_limit: 2000,
|
|
||||||
reliquary_count_limit: 1000,
|
|
||||||
furniture_count_limit: 2000,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send! (PlayerStoreNotify, self, user_id, metadata,
|
|
||||||
{store_type: proto::StoreType::StorePack as i32, weight_limit: 30000, item_list: self.spoof_inventory(),}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send! (AvatarDataNotify, self, user_id, metadata,
|
|
||||||
{
|
|
||||||
avatar_list: vec![self.spoof_default_avatar2()],
|
|
||||||
avatar_team_map: self.spoof_team_map(),
|
|
||||||
cur_avatar_team_id: 2,
|
|
||||||
choose_avatar_guid: GameWorld::SPOOFED_AVATAR_GUID,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send! (PlayerEnterSceneNotify, self, user_id, metadata,
|
|
||||||
{
|
|
||||||
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
|
||||||
r#type: proto::EnterType::EnterSelf as i32,
|
|
||||||
scene_begin_time: self.timestamp(),
|
|
||||||
pos: Some(proto::Vector {x: -3400.0, y: 203.0, z: -3427.60}),
|
|
||||||
target_uid: user_id,
|
|
||||||
world_level: 8,
|
|
||||||
enter_scene_token: GameWorld::SPOOFED_SCENE_TOKEN,
|
|
||||||
//enter_reason: 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn process_get_player_social_detail(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::GetPlayerSocialDetailReq, rsp: &mut proto::GetPlayerSocialDetailRsp) {
|
fn process_get_player_social_detail(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::GetPlayerSocialDetailReq, rsp: &mut proto::GetPlayerSocialDetailRsp) {
|
||||||
let avatar_info = build!(SocialShowAvatarInfo,
|
let avatar_info = build!(SocialShowAvatarInfo {
|
||||||
{
|
avatar_id: 10000007,
|
||||||
avatar_id: 10000007,
|
level: 80,
|
||||||
level: 80,
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let details = build!(SocialDetail,
|
let details = build!(SocialDetail {
|
||||||
{
|
uid: user_id,
|
||||||
uid: user_id,
|
nickname: "Fukker".to_string(),
|
||||||
nickname: "Fukker".to_string(),
|
level: 56,
|
||||||
level: 56,
|
avatar_id: 10000007,
|
||||||
avatar_id: 10000007,
|
signature: "Fuck you".to_string(),
|
||||||
signature: "Fuck you".to_string(),
|
birthday: Some(proto::Birthday {month: 2, day: 11}),
|
||||||
birthday: Some(proto::Birthday {month: 2, day: 11}),
|
world_level: 8,
|
||||||
world_level: 8,
|
online_state: proto::FriendOnlineState::FriendOnline as i32,
|
||||||
online_state: proto::FriendOnlineState::FriendOnline as i32,
|
is_friend: true,
|
||||||
is_friend: true,
|
is_mp_mode_available: true,
|
||||||
is_mp_mode_available: true,
|
name_card_id: 210051,
|
||||||
name_card_id: 210051,
|
finish_achievement_num: 42,
|
||||||
finish_achievement_num: 42,
|
tower_floor_index: 1,
|
||||||
tower_floor_index: 1,
|
tower_level_index: 1,
|
||||||
tower_level_index: 1,
|
show_avatar_info_list: vec![avatar_info], // TODO
|
||||||
show_avatar_info_list: vec![avatar_info], // TODO
|
show_name_card_id_list: vec![210051],
|
||||||
show_name_card_id_list: vec![210051],
|
// Field 25!
|
||||||
// Field 25!
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
rsp.detail_data = Some(details);
|
rsp.detail_data = Some(details);
|
||||||
}
|
}
|
||||||
@ -164,107 +93,91 @@ impl GameWorld {
|
|||||||
fn process_enter_scene_ready(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::EnterSceneReadyReq, rsp: &mut proto::EnterSceneReadyRsp) {
|
fn process_enter_scene_ready(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::EnterSceneReadyReq, rsp: &mut proto::EnterSceneReadyRsp) {
|
||||||
rsp.enter_scene_token = req.enter_scene_token;
|
rsp.enter_scene_token = req.enter_scene_token;
|
||||||
|
|
||||||
build_and_send!(EnterScenePeerNotify, self, user_id, metadata,
|
build_and_send!(self, user_id, metadata, EnterScenePeerNotify {
|
||||||
{
|
dest_scene_id: GameWorld::SPOOFED_SCENE_ID,
|
||||||
dest_scene_id: GameWorld::SPOOFED_SCENE_ID,
|
peer_id: 1,
|
||||||
peer_id: 1,
|
host_peer_id: 1,
|
||||||
host_peer_id: 1,
|
enter_scene_token: GameWorld::SPOOFED_SCENE_TOKEN,
|
||||||
enter_scene_token: GameWorld::SPOOFED_SCENE_TOKEN,
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn process_scene_init_finish(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::SceneInitFinishReq, rsp: &mut proto::SceneInitFinishRsp) {
|
fn process_scene_init_finish(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::SceneInitFinishReq, rsp: &mut proto::SceneInitFinishRsp) {
|
||||||
rsp.enter_scene_token = GameWorld::SPOOFED_SCENE_TOKEN;
|
rsp.enter_scene_token = GameWorld::SPOOFED_SCENE_TOKEN;
|
||||||
|
|
||||||
build_and_send!(WorldDataNotify, self, user_id, metadata,
|
build_and_send!(self, user_id, metadata, WorldDataNotify {
|
||||||
{ world_prop_map: self.remap(&collection!{1 => 8, 2 => 0}), }
|
world_prop_map: self.remap(&collection!{1 => 8, 2 => 0}),
|
||||||
);
|
});
|
||||||
|
|
||||||
let online_player_info = build!(OnlinePlayerInfo,
|
let online_player_info = build!(OnlinePlayerInfo {
|
||||||
{
|
uid: user_id,
|
||||||
uid: user_id,
|
nickname: "Fukker".to_string(),
|
||||||
nickname: "Fukker".to_string(),
|
player_level: 56,
|
||||||
player_level: 56,
|
avatar_id: 10000007,
|
||||||
avatar_id: 10000007,
|
mp_setting_type: proto::MpSettingType::MpSettingEnterAfterApply as i32,
|
||||||
mp_setting_type: proto::MpSettingType::MpSettingEnterAfterApply as i32,
|
cur_player_num_in_world: 1,
|
||||||
cur_player_num_in_world: 1,
|
world_level: 8,
|
||||||
world_level: 8,
|
name_card_id: 210051,
|
||||||
name_card_id: 210051,
|
signature: "Fuck you!".to_string(),
|
||||||
signature: "Fuck you!".to_string(),
|
// TODO: Field 12!
|
||||||
// TODO: Field 12!
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send!(WorldPlayerInfoNotify, self, user_id, metadata,
|
build_and_send!(self, user_id, metadata, WorldPlayerInfoNotify {
|
||||||
{
|
player_info_list: vec![online_player_info.clone()],
|
||||||
player_info_list: vec![online_player_info.clone()],
|
player_uid_list: vec![user_id],
|
||||||
player_uid_list: vec![user_id],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let scene_player_info_e = build!(ScenePlayerInfo,
|
let scene_player_info_e = build!(ScenePlayerInfo {
|
||||||
{
|
uid: user_id,
|
||||||
uid: user_id,
|
peer_id: 1,
|
||||||
peer_id: 1,
|
name: "Fukker".to_string(),
|
||||||
name: "Fukker".to_string(),
|
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
||||||
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
online_player_info: Some(online_player_info),
|
||||||
online_player_info: Some(online_player_info),
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send!(ScenePlayerInfoNotify, self, user_id, metadata,
|
build_and_send!(self, user_id, metadata, ScenePlayerInfoNotify {
|
||||||
{
|
player_info_list: vec![scene_player_info_e],
|
||||||
player_info_list: vec![scene_player_info_e],
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let avatar_enter_info = build!(AvatarEnterSceneInfo,
|
let avatar_enter_info = build!(AvatarEnterSceneInfo {
|
||||||
{
|
avatar_guid: GameWorld::SPOOFED_AVATAR_GUID,
|
||||||
avatar_guid: GameWorld::SPOOFED_AVATAR_GUID,
|
avatar_entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
||||||
avatar_entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
weapon_guid: GameWorld::SPOOFED_WEAPON_GUID,
|
||||||
weapon_guid: GameWorld::SPOOFED_WEAPON_GUID,
|
weapon_entity_id: GameWorld::SPOOFED_WEAPON_EID,
|
||||||
weapon_entity_id: GameWorld::SPOOFED_WEAPON_EID,
|
});
|
||||||
}
|
let mp_level_info = build!(MpLevelEntityInfo {
|
||||||
);
|
entity_id: 0xb000000 + 146,
|
||||||
let mp_level_info = build!(MpLevelEntityInfo,
|
authority_peer_id: 1,
|
||||||
{
|
});
|
||||||
entity_id: 0xb000000 + 146,
|
let team_enter_info = build!(TeamEnterSceneInfo { team_entity_id: 0x9000000 + 1, });
|
||||||
authority_peer_id: 1,
|
|
||||||
}
|
|
||||||
);
|
|
||||||
let team_enter_info = build!(TeamEnterSceneInfo, { team_entity_id: 0x9000000 + 1, });
|
|
||||||
|
|
||||||
build_and_send!(PlayerEnterSceneInfoNotify, self, user_id, metadata,
|
build_and_send!(self, user_id, metadata, PlayerEnterSceneInfoNotify {
|
||||||
{
|
enter_scene_token: GameWorld::SPOOFED_SCENE_TOKEN,
|
||||||
enter_scene_token: GameWorld::SPOOFED_SCENE_TOKEN,
|
avatar_enter_info: vec![avatar_enter_info],
|
||||||
avatar_enter_info: vec![avatar_enter_info],
|
cur_avatar_entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
||||||
cur_avatar_entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
mp_level_entity_info: Some(mp_level_info),
|
||||||
mp_level_entity_info: Some(mp_level_info),
|
team_enter_info: Some(team_enter_info),
|
||||||
team_enter_info: Some(team_enter_info),
|
});
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
build_and_send!(PlayerGameTimeNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, PlayerGameTimeNotify {
|
||||||
game_time: 5*60*60,
|
game_time: 5*60*60,
|
||||||
uid: user_id,
|
uid: user_id,
|
||||||
});
|
});
|
||||||
|
|
||||||
build_and_send!(SceneTimeNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, SceneTimeNotify {
|
||||||
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
||||||
scene_time: 9000,
|
scene_time: 9000,
|
||||||
});
|
});
|
||||||
|
|
||||||
build_and_send!(SceneDataNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, SceneDataNotify {
|
||||||
level_config_name_list: vec!["Level_BigWorld".to_string()],
|
level_config_name_list: vec!["Level_BigWorld".to_string()],
|
||||||
});
|
});
|
||||||
|
|
||||||
build_and_send!(HostPlayerNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, HostPlayerNotify {
|
||||||
host_uid: user_id,
|
host_uid: user_id,
|
||||||
host_peer_id: 1,
|
host_peer_id: 1,
|
||||||
});
|
});
|
||||||
|
|
||||||
let scene_team_avatar = build!(SceneTeamAvatar, {
|
let scene_team_avatar = build!(SceneTeamAvatar {
|
||||||
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
scene_id: GameWorld::SPOOFED_SCENE_ID,
|
||||||
player_uid: user_id,
|
player_uid: user_id,
|
||||||
avatar_guid: GameWorld::SPOOFED_AVATAR_GUID,
|
avatar_guid: GameWorld::SPOOFED_AVATAR_GUID,
|
||||||
@ -275,7 +188,7 @@ impl GameWorld {
|
|||||||
scene_entity_info: Some(self.spoof_scene_default_avatar(user_id)),
|
scene_entity_info: Some(self.spoof_scene_default_avatar(user_id)),
|
||||||
ability_control_block: Some(self.spoof_default_abilities()),
|
ability_control_block: Some(self.spoof_default_abilities()),
|
||||||
});
|
});
|
||||||
build_and_send!(SceneTeamUpdateNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, SceneTeamUpdateNotify {
|
||||||
scene_team_avatar_list: vec![scene_team_avatar],
|
scene_team_avatar_list: vec![scene_team_avatar],
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@ -283,7 +196,7 @@ impl GameWorld {
|
|||||||
fn process_enter_scene_done(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::EnterSceneDoneReq, rsp: &mut proto::EnterSceneDoneRsp) {
|
fn process_enter_scene_done(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::EnterSceneDoneReq, rsp: &mut proto::EnterSceneDoneRsp) {
|
||||||
rsp.enter_scene_token = req.enter_scene_token;
|
rsp.enter_scene_token = req.enter_scene_token;
|
||||||
|
|
||||||
build_and_send!(SceneEntityAppearNotify, self, user_id, metadata, {
|
build_and_send!(self, user_id, metadata, SceneEntityAppearNotify {
|
||||||
entity_list: vec![self.spoof_scene_default_avatar(user_id)],
|
entity_list: vec![self.spoof_scene_default_avatar(user_id)],
|
||||||
appear_type: proto::VisionType::VisionBorn as i32,
|
appear_type: proto::VisionType::VisionBorn as i32,
|
||||||
});
|
});
|
||||||
@ -299,13 +212,13 @@ impl GameWorld {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn spoof_scene_default_avatar(&self, user_id: u32) -> proto::SceneEntityInfo {
|
fn spoof_scene_default_avatar(&self, user_id: u32) -> proto::SceneEntityInfo {
|
||||||
let motion_info = build!(MotionInfo, {
|
let motion_info = build!(MotionInfo {
|
||||||
pos: Some(proto::Vector {x: -3400.0, y: 203.0, z: -3427.0}),
|
pos: Some(proto::Vector {x: -3400.0, y: 233.0, z: -3427.0}),
|
||||||
rot: Some(proto::Vector::default()),
|
rot: Some(proto::Vector::default()),
|
||||||
speed: Some(proto::Vector::default()),
|
speed: Some(proto::Vector::default()),
|
||||||
});
|
});
|
||||||
|
|
||||||
let weapon = build!(SceneWeaponInfo, {
|
let weapon = build!(SceneWeaponInfo {
|
||||||
entity_id: GameWorld::SPOOFED_WEAPON_EID,
|
entity_id: GameWorld::SPOOFED_WEAPON_EID,
|
||||||
gadget_id: 50011406, // TODO!
|
gadget_id: 50011406, // TODO!
|
||||||
item_id: 11406,
|
item_id: 11406,
|
||||||
@ -315,7 +228,7 @@ impl GameWorld {
|
|||||||
affix_map: collection! { 111406 => 0 },
|
affix_map: collection! { 111406 => 0 },
|
||||||
});
|
});
|
||||||
|
|
||||||
let scene_avatar_info = build!(SceneAvatarInfo, {
|
let scene_avatar_info = build!(SceneAvatarInfo {
|
||||||
uid: user_id,
|
uid: user_id,
|
||||||
avatar_id: 10000007,
|
avatar_id: 10000007,
|
||||||
guid: GameWorld::SPOOFED_AVATAR_GUID,
|
guid: GameWorld::SPOOFED_AVATAR_GUID,
|
||||||
@ -330,13 +243,13 @@ impl GameWorld {
|
|||||||
weapon: Some(weapon),
|
weapon: Some(weapon),
|
||||||
});
|
});
|
||||||
|
|
||||||
let scene_ai_info = build!(SceneEntityAiInfo, {
|
let scene_ai_info = build!(SceneEntityAiInfo {
|
||||||
is_ai_open: true,
|
is_ai_open: true,
|
||||||
born_pos: Some(proto::Vector::default()),
|
born_pos: Some(proto::Vector::default()),
|
||||||
});
|
});
|
||||||
let authority_info = build!(EntityAuthorityInfo, { ai_info: Some(scene_ai_info), });
|
let authority_info = build!(EntityAuthorityInfo { ai_info: Some(scene_ai_info), });
|
||||||
|
|
||||||
let scene_entity_info = build!(SceneEntityInfo, {
|
let scene_entity_info = build!(SceneEntityInfo {
|
||||||
entity_type: proto::ProtEntityType::ProtEntityAvatar as i32,
|
entity_type: proto::ProtEntityType::ProtEntityAvatar as i32,
|
||||||
entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
entity_id: GameWorld::SPOOFED_AVATAR_EID,
|
||||||
life_state: 1,
|
life_state: 1,
|
||||||
@ -350,99 +263,6 @@ impl GameWorld {
|
|||||||
return scene_entity_info;
|
return scene_entity_info;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spoof_default_avatar2(&self) -> proto::AvatarInfo {
|
|
||||||
let mut avatar_info = build!(AvatarInfo, {
|
|
||||||
avatar_id: 10000007,
|
|
||||||
avatar_type: 1,
|
|
||||||
guid: GameWorld::SPOOFED_AVATAR_GUID,
|
|
||||||
skill_depot_id: 704,
|
|
||||||
born_time: 1633790000,
|
|
||||||
talent_id_list: vec![71, 72, 73, 74, 75, 76],
|
|
||||||
prop_map: self.spoof_avatar_props(),
|
|
||||||
fight_prop_map: self.spoof_avatar_fight_props(),
|
|
||||||
fetter_info: Some(self.spoof_fetter_info()),
|
|
||||||
equip_guid_list: vec![GameWorld::SPOOFED_WEAPON_GUID],
|
|
||||||
inherent_proud_skill_list: vec![72101, 72201],
|
|
||||||
skill_level_map: collection!{100553 => 3, 10067 => 3, 10068 => 3},
|
|
||||||
proud_skill_extra_level_map: collection!{739 => 3, 732 => 3},
|
|
||||||
});
|
|
||||||
|
|
||||||
return avatar_info;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spoof_team_map(&self) -> HashMap<u32, proto::AvatarTeam> {
|
|
||||||
let at = build!(AvatarTeam, {
|
|
||||||
team_name: "Fuck yea".to_string(),
|
|
||||||
avatar_guid_list: vec![GameWorld::SPOOFED_AVATAR_GUID],
|
|
||||||
});
|
|
||||||
|
|
||||||
return collection! {
|
|
||||||
1 => at.clone(),
|
|
||||||
2 => at.clone(),
|
|
||||||
3 => at.clone(),
|
|
||||||
4 => at.clone(),
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spoof_player_props(&self) -> HashMap<u32, proto::PropValue> {
|
|
||||||
// TODO: fill!
|
|
||||||
let map = collection! {
|
|
||||||
proto::PropType::PropIsSpringAutoUse as u32 => 1,
|
|
||||||
proto::PropType::PropIsFlyable as u32 => 1,
|
|
||||||
proto::PropType::PropIsTransferable as u32 => 1,
|
|
||||||
proto::PropType::PropPlayerLevel as u32 => 56,
|
|
||||||
proto::PropType::PropPlayerExp as u32 => 1337,
|
|
||||||
proto::PropType::PropPlayerHcoin as u32 => 9001,
|
|
||||||
proto::PropType::PropPlayerScoin as u32 => 9002,
|
|
||||||
proto::PropType::PropPlayerWorldLevel as u32 => 8,
|
|
||||||
proto::PropType::PropPlayerResin as u32 => 159,
|
|
||||||
proto::PropType::PropPlayerMcoin as u32 => 9003,
|
|
||||||
proto::PropType::PropMaxStamina as u32 => 120,
|
|
||||||
proto::PropType::PropCurPersistStamina as u32 => 120,
|
|
||||||
};
|
|
||||||
|
|
||||||
return self.remap(&map);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spoof_world_props(&self) -> HashMap<u32, u32> {
|
|
||||||
// TODO: fill!
|
|
||||||
let map = collection! {
|
|
||||||
proto::OpenStateType::OpenStatePaimon as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStatePlayerLvupGuide as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateGacha as u32 => 1,
|
|
||||||
proto::OpenStateType::OpenStateGuideGacha as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateGuideTeam as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateGuideBag as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateLimitRegionFreshmeat as u32 => 1,
|
|
||||||
proto::OpenStateType::OpenStateLimitRegionGlobal as u32 => 1,
|
|
||||||
proto::OpenStateType::OpenStateMultiplayer as u32 => 0,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateAvatarFashion as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateGuideAppearance as u32 => 1,
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateShopTypeMall as u32 => 1, // 900
|
|
||||||
proto::OpenStateType::OpenStateShopTypeRecommanded as u32 => 1, // 901
|
|
||||||
proto::OpenStateType::OpenStateShopTypeGenesiscrystal as u32 => 1, // 902
|
|
||||||
proto::OpenStateType::OpenStateShopTypeGiftpackage as u32 => 1, // 903
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenAdventureManual as u32 => 1, // 1100
|
|
||||||
proto::OpenStateType::OpenAdventureManualMonster as u32 => 1, // 1103
|
|
||||||
proto::OpenStateType::OpenAdventureManualBossDungeon as u32 => 1, // 1104
|
|
||||||
|
|
||||||
proto::OpenStateType::OpenStateMengdeInfusedcrystal as u32 => 1,
|
|
||||||
proto::OpenStateType::OpenStateLiyueInfusedcrystal as u32 => 1,
|
|
||||||
proto::OpenStateType::OpenStateInazumaMainquestFinished as u32 => 1,
|
|
||||||
};
|
|
||||||
|
|
||||||
return map;
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spoof_avatar_props_raw(&self) -> HashMap<u32,i64> {
|
fn spoof_avatar_props_raw(&self) -> HashMap<u32,i64> {
|
||||||
// TODO: fill!
|
// TODO: fill!
|
||||||
let map = collection! {
|
let map = collection! {
|
||||||
@ -456,13 +276,6 @@ impl GameWorld {
|
|||||||
return map;
|
return map;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spoof_avatar_props(&self) -> HashMap<u32, proto::PropValue> {
|
|
||||||
// TODO: fill!
|
|
||||||
let map = self.spoof_avatar_props_raw();
|
|
||||||
|
|
||||||
return self.remap(&map);
|
|
||||||
}
|
|
||||||
|
|
||||||
fn spoof_avatar_fight_props(&self) -> HashMap<u32,f32> {
|
fn spoof_avatar_fight_props(&self) -> HashMap<u32,f32> {
|
||||||
// TODO: fill!
|
// TODO: fill!
|
||||||
let map = collection! {
|
let map = collection! {
|
||||||
@ -612,24 +425,6 @@ impl GameWorld {
|
|||||||
return afi;
|
return afi;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn spoof_inventory(&self) -> Vec<proto::Item> {
|
|
||||||
let mut weapon = proto::Weapon::default();
|
|
||||||
weapon.level = 70;
|
|
||||||
weapon.promote_level = 4;
|
|
||||||
weapon.affix_map = collection!{111406 => 0};
|
|
||||||
|
|
||||||
let mut equip = proto::Equip::default();
|
|
||||||
equip.is_locked = true;
|
|
||||||
equip.detail = Some(proto::equip::Detail::Weapon(weapon));
|
|
||||||
|
|
||||||
let mut item = proto::Item::default();
|
|
||||||
item.item_id = 11406;
|
|
||||||
item.guid = GameWorld::SPOOFED_WEAPON_GUID;
|
|
||||||
item.detail = Some(proto::item::Detail::Equip(equip));
|
|
||||||
|
|
||||||
return vec![item];
|
|
||||||
}
|
|
||||||
|
|
||||||
fn remap(&self, map: &HashMap<u32, i64>) -> HashMap<u32, proto::PropValue> {
|
fn remap(&self, map: &HashMap<u32, i64>) -> HashMap<u32, proto::PropValue> {
|
||||||
let mut hashmap = HashMap::<u32, proto::PropValue>::new();
|
let mut hashmap = HashMap::<u32, proto::PropValue>::new();
|
||||||
|
|
||||||
@ -673,8 +468,4 @@ impl GameWorld {
|
|||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
fn timestamp(&self) -> u64 {
|
|
||||||
return SystemTime::now().duration_since(SystemTime::UNIX_EPOCH).unwrap().as_millis() as u64;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
231
src/server/login_manager.rs
Normal file
231
src/server/login_manager.rs
Normal file
@ -0,0 +1,231 @@
|
|||||||
|
use std::sync::{mpsc, Arc};
|
||||||
|
use std::collections::HashMap;
|
||||||
|
|
||||||
|
use prost::Message;
|
||||||
|
|
||||||
|
use crate::server::IpcMessage;
|
||||||
|
|
||||||
|
use packet_processor_macro::*;
|
||||||
|
#[macro_use]
|
||||||
|
use packet_processor::*;
|
||||||
|
|
||||||
|
use crate::DatabaseManager;
|
||||||
|
use crate::JsonManager;
|
||||||
|
|
||||||
|
use crate::utils::IdManager;
|
||||||
|
use crate::utils::TimeManager;
|
||||||
|
|
||||||
|
use crate::dbmanager::database_manager::AvatarInfo as DbAvatarInfo;
|
||||||
|
|
||||||
|
#[packet_processor(PlayerLoginReq)]
|
||||||
|
pub struct LoginManager {
|
||||||
|
packets_to_send_tx: mpsc::Sender<IpcMessage>,
|
||||||
|
db: Arc<DatabaseManager>,
|
||||||
|
jm: Arc<JsonManager>,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl LoginManager {
|
||||||
|
pub fn new(db: Arc<DatabaseManager>, jm: Arc<JsonManager>, packets_to_send_tx: mpsc::Sender<IpcMessage>) -> LoginManager {
|
||||||
|
let mut lm = LoginManager {
|
||||||
|
packet_callbacks: HashMap::new(),
|
||||||
|
packets_to_send_tx: packets_to_send_tx,
|
||||||
|
db: db.clone(),
|
||||||
|
jm: jm.clone(),
|
||||||
|
};
|
||||||
|
|
||||||
|
lm.register();
|
||||||
|
|
||||||
|
return lm;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn process_player_login(&self, user_id: u32, metadata: &proto::PacketHead, req: &proto::PlayerLoginReq, rsp: &mut proto::PlayerLoginRsp) {
|
||||||
|
let user = match self.db.get_player_info(user_id) {
|
||||||
|
Some(user) => user,
|
||||||
|
None => panic!("User {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let player_props = match self.db.get_player_props(user_id) {
|
||||||
|
Some(props) => Self::remap(&props),
|
||||||
|
None => panic!("Props for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let open_state = match self.db.get_open_state(user_id) {
|
||||||
|
Some(state) => state,
|
||||||
|
None => panic!("Open state for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let inventory = match self.db.get_inventory(user_id) {
|
||||||
|
Some(inventory) => inventory,
|
||||||
|
None => panic!("Inventory for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let avatar_list = match self.db.get_avatars(user_id) {
|
||||||
|
Some(avatars) => avatars
|
||||||
|
.into_iter()
|
||||||
|
.map(|a| self.build_avatar_info(&a))
|
||||||
|
.collect(),
|
||||||
|
None => panic!("Avatars for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let team_map = self.retrieve_team_info(user_id);
|
||||||
|
|
||||||
|
let (current_avatar, current_team) = match self.db.get_player_team_selection(user_id) {
|
||||||
|
Some(team_selection) => (team_selection.avatar, team_selection.team),
|
||||||
|
None => panic!("Team selection info for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let scene_info = match self.db.get_player_scene_info(user_id) {
|
||||||
|
Some(scene_info) => scene_info,
|
||||||
|
None => panic!("Scene info for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
build_and_send! ( self, user_id, metadata, PlayerDataNotify {
|
||||||
|
nick_name: user.nick_name, server_time: TimeManager::timestamp(), prop_map: player_props,
|
||||||
|
});
|
||||||
|
|
||||||
|
build_and_send! ( self, user_id, metadata, OpenStateUpdateNotify {
|
||||||
|
open_state_map: open_state,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: hardcoded limits!
|
||||||
|
build_and_send! (self, user_id, metadata, StoreWeightLimitNotify {
|
||||||
|
store_type: proto::StoreType::StorePack as i32,
|
||||||
|
weight_limit: 30000,
|
||||||
|
material_count_limit: 2000,
|
||||||
|
weapon_count_limit: 2000,
|
||||||
|
reliquary_count_limit: 1000,
|
||||||
|
furniture_count_limit: 2000,
|
||||||
|
});
|
||||||
|
|
||||||
|
// TODO: hardcoded limit!
|
||||||
|
build_and_send! (self, user_id, metadata, PlayerStoreNotify {
|
||||||
|
store_type: proto::StoreType::StorePack as i32, weight_limit: 30000, item_list: inventory,
|
||||||
|
});
|
||||||
|
|
||||||
|
build_and_send! (self, user_id, metadata, AvatarDataNotify {
|
||||||
|
avatar_list: avatar_list,
|
||||||
|
avatar_team_map: team_map,
|
||||||
|
cur_avatar_team_id: current_team.into(),
|
||||||
|
choose_avatar_guid: current_avatar,
|
||||||
|
});
|
||||||
|
|
||||||
|
build_and_send! (self, user_id, metadata, PlayerEnterSceneNotify {
|
||||||
|
scene_id: scene_info.scene_id,
|
||||||
|
r#type: proto::EnterType::EnterSelf as i32,
|
||||||
|
scene_begin_time: TimeManager::timestamp(),
|
||||||
|
pos: Some(proto::Vector {x: scene_info.pos_x, y: scene_info.pos_y, z: scene_info.pos_z}),
|
||||||
|
target_uid: user_id,
|
||||||
|
world_level: user.world_level as u32,
|
||||||
|
enter_scene_token: scene_info.scene_token,
|
||||||
|
//enter_reason: 1,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
fn retrieve_team_info(&self, user_id: u32) -> HashMap<u32, proto::AvatarTeam> {
|
||||||
|
let player_teams = match self.db.get_player_teams(user_id) {
|
||||||
|
Some(teams) => teams,
|
||||||
|
None => panic!("Teams for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let player_teams_avatars = match self.db.get_player_teams_avatars(user_id) {
|
||||||
|
Some(team_avatars) => team_avatars,
|
||||||
|
None => panic!("Team avatars for user {} not found!", user_id),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut team_map = HashMap::<u32, proto::AvatarTeam>::new();
|
||||||
|
|
||||||
|
for team in player_teams {
|
||||||
|
let at = build! ( AvatarTeam {
|
||||||
|
team_name: team.name.clone(),
|
||||||
|
avatar_guid_list: player_teams_avatars.clone().into_iter().filter(|a| a.team_id == team.id).map(|a| a.guid).collect(),
|
||||||
|
});
|
||||||
|
|
||||||
|
team_map.insert(team.id.into(), at);
|
||||||
|
};
|
||||||
|
|
||||||
|
return team_map;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn build_avatar_info(&self, a: &DbAvatarInfo) -> proto::AvatarInfo {
|
||||||
|
let di = IdManager::get_depot_id_by_char_id(a.character_id);
|
||||||
|
|
||||||
|
let asd = &self.jm.avatar_skill_depot[&di];
|
||||||
|
|
||||||
|
let asl = self.db.get_skill_levels(a.guid).unwrap_or_else(|| panic!("No skill levels for avatar {}!", a.guid));
|
||||||
|
|
||||||
|
let mut slm = HashMap::new();
|
||||||
|
|
||||||
|
match asd.energy_skill {
|
||||||
|
Some(es) => {
|
||||||
|
if (asl.contains_key(&es)) {
|
||||||
|
slm.insert(es, asl[&es]);
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
for s in &asd.skills {
|
||||||
|
if (*s != 0) {
|
||||||
|
if (asl.contains_key(s)) {
|
||||||
|
slm.insert(*s, asl[s]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let ap = self.db.get_avatar_props(a.guid).unwrap_or_else(|| panic!("Props not found for avatar {}!", a.guid));
|
||||||
|
let afp = self.db.get_avatar_fight_props(a.guid).unwrap_or_else(|| panic!("Fight props not found for avatar {}!", a.guid));
|
||||||
|
|
||||||
|
let pli = proto::PropType::PropBreakLevel as u32;
|
||||||
|
|
||||||
|
let promote_level = if ap.contains_key(&pli) { ap[&pli] as u32 } else { 0 };
|
||||||
|
|
||||||
|
let ips = asd.inherent_proud_skill_opens
|
||||||
|
.clone()
|
||||||
|
.into_iter()
|
||||||
|
.filter(|s| s.proud_skill_group_id != None)
|
||||||
|
.filter(|s| s.need_avatar_promote_level == None || s.need_avatar_promote_level.unwrap() <= promote_level)
|
||||||
|
.map(|s| s.proud_skill_group_id.unwrap())
|
||||||
|
.map(|s| s * 100 + 1) // TODO: ugly hack! Fix it by reading ProudSkillExcelConfigData!
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
// TODO: properly fill!
|
||||||
|
let afi = build!(AvatarFetterInfo {
|
||||||
|
exp_level: 1,
|
||||||
|
// TODO: fill fetter list!
|
||||||
|
});
|
||||||
|
|
||||||
|
let egi = self.db.get_avatar_equip(a.guid).unwrap_or_else(|| panic!("Equip not found for avatar {}!", a.guid));
|
||||||
|
|
||||||
|
// TODO: ugly ugly hack!
|
||||||
|
let mut fuck = HashMap::new();
|
||||||
|
fuck.insert(732, 3);
|
||||||
|
fuck.insert(739, 3);
|
||||||
|
|
||||||
|
let ai = build!(AvatarInfo {
|
||||||
|
avatar_id: IdManager::get_avatar_id_by_char_id(a.character_id),
|
||||||
|
avatar_type: a.avatar_type.into(),
|
||||||
|
guid: a.guid,
|
||||||
|
born_time: a.born_time,
|
||||||
|
skill_depot_id: asd.id,
|
||||||
|
talent_id_list: asd.talents.clone(),
|
||||||
|
prop_map: Self::remap(&ap),
|
||||||
|
fight_prop_map: afp,
|
||||||
|
fetter_info: Some(afi),
|
||||||
|
equip_guid_list: egi,
|
||||||
|
inherent_proud_skill_list: ips, //vec![72101, 72201],
|
||||||
|
skill_level_map: slm,
|
||||||
|
proud_skill_extra_level_map: fuck, //collection!{739 => 3, 732 => 3},
|
||||||
|
});
|
||||||
|
return ai;
|
||||||
|
}
|
||||||
|
|
||||||
|
fn remap(map: &HashMap<u32, i64>) -> HashMap<u32, proto::PropValue> {
|
||||||
|
let mut hashmap = HashMap::<u32, proto::PropValue>::new();
|
||||||
|
|
||||||
|
for (key, value) in map {
|
||||||
|
hashmap.insert(*key, build!(PropValue { r#type: *key, val: *value, value: Some(proto::prop_value::Value::Ival(*value)), }));
|
||||||
|
}
|
||||||
|
|
||||||
|
return hashmap;
|
||||||
|
}
|
||||||
|
}
|
@ -2,6 +2,7 @@ mod network_server;
|
|||||||
mod game_server;
|
mod game_server;
|
||||||
mod game_world;
|
mod game_world;
|
||||||
mod auth_manager;
|
mod auth_manager;
|
||||||
|
mod login_manager;
|
||||||
mod client_connection;
|
mod client_connection;
|
||||||
mod ipc_message;
|
mod ipc_message;
|
||||||
mod dispatch_server;
|
mod dispatch_server;
|
||||||
@ -10,6 +11,7 @@ pub use self::network_server::NetworkServer;
|
|||||||
pub use self::game_server::GameServer;
|
pub use self::game_server::GameServer;
|
||||||
pub use self::game_world::GameWorld;
|
pub use self::game_world::GameWorld;
|
||||||
pub use self::auth_manager::AuthManager;
|
pub use self::auth_manager::AuthManager;
|
||||||
|
pub use self::login_manager::LoginManager;
|
||||||
pub use self::client_connection::ClientConnection;
|
pub use self::client_connection::ClientConnection;
|
||||||
pub use self::ipc_message::IpcMessage;
|
pub use self::ipc_message::IpcMessage;
|
||||||
pub use self::dispatch_server::DispatchServer;
|
pub use self::dispatch_server::DispatchServer;
|
||||||
|
35
src/utils/id_manager.rs
Normal file
35
src/utils/id_manager.rs
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
pub struct IdManager {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl IdManager {
|
||||||
|
const AVATAR_ID_OFFSET: u32 = 10_000_000;
|
||||||
|
|
||||||
|
const DEPOT_ID_MULT: u32 = 100;
|
||||||
|
const DEPOT_ID_OFFSET: u32 = 1;
|
||||||
|
|
||||||
|
const PROUD_SKILL_MULT: u32 = 100;
|
||||||
|
const PROUD_SKILL_OFFSET: u32 = 1;
|
||||||
|
|
||||||
|
pub fn get_avatar_id_by_char_id(character_id: u32) -> u32 {
|
||||||
|
if (character_id > 100) {
|
||||||
|
panic!("Invalid character ID: {}", character_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
return character_id + Self::AVATAR_ID_OFFSET;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn get_depot_id_by_char_id(character_id: u32) -> u32 {
|
||||||
|
if (character_id > 100) {
|
||||||
|
panic!("Invalid character ID: {}", character_id);
|
||||||
|
}
|
||||||
|
|
||||||
|
let mut offset = Self::DEPOT_ID_OFFSET;
|
||||||
|
|
||||||
|
println!("HACK: main hero is fixed to Wind!");
|
||||||
|
if (character_id == 5 || character_id == 7) {
|
||||||
|
offset = 4;
|
||||||
|
}
|
||||||
|
|
||||||
|
return character_id * Self::DEPOT_ID_MULT + offset;
|
||||||
|
}
|
||||||
|
}
|
@ -1,5 +1,9 @@
|
|||||||
mod handshake_packet;
|
mod handshake_packet;
|
||||||
mod data_packet;
|
mod data_packet;
|
||||||
|
mod id_manager;
|
||||||
|
mod time_manager;
|
||||||
|
|
||||||
pub use self::handshake_packet::HandshakePacket;
|
pub use self::handshake_packet::HandshakePacket;
|
||||||
pub use self::data_packet::DataPacket;
|
pub use self::data_packet::DataPacket;
|
||||||
|
pub use self::id_manager::IdManager;
|
||||||
|
pub use self::time_manager::TimeManager;
|
||||||
|
15
src/utils/time_manager.rs
Normal file
15
src/utils/time_manager.rs
Normal file
@ -0,0 +1,15 @@
|
|||||||
|
use std::time::SystemTime;
|
||||||
|
use std::convert::TryInto;
|
||||||
|
|
||||||
|
pub struct TimeManager {
|
||||||
|
}
|
||||||
|
|
||||||
|
impl TimeManager {
|
||||||
|
pub fn duration_since(time_point: SystemTime) -> u64 {
|
||||||
|
SystemTime::now().duration_since(time_point).unwrap().as_millis().try_into().unwrap()
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn timestamp() -> u64 {
|
||||||
|
return Self::duration_since(SystemTime::UNIX_EPOCH);
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user