feat!: Refactor, Update to version 2.5.x, Add Battle Scepter
This commit is contained in:
+3
-1
@@ -1,5 +1,5 @@
|
|||||||
[workspace]
|
[workspace]
|
||||||
members = [ "gameserver", "proto", "sdkserver"]
|
members = ["gameserver", "proto", "sdkserver"]
|
||||||
resolver = "2"
|
resolver = "2"
|
||||||
|
|
||||||
[workspace.package]
|
[workspace.package]
|
||||||
@@ -54,6 +54,8 @@ tracing-subscriber = { version = "0.3.18", features = [
|
|||||||
tracing-bunyan-formatter = "0.3.9"
|
tracing-bunyan-formatter = "0.3.9"
|
||||||
|
|
||||||
proto = { path = "proto/" }
|
proto = { path = "proto/" }
|
||||||
|
proto-derive = { path = "proto/proto-derive" }
|
||||||
|
|
||||||
|
|
||||||
[profile.release]
|
[profile.release]
|
||||||
strip = true # Automatically strip symbols from the binary.
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
|||||||
+7580
-509
File diff suppressed because it is too large
Load Diff
@@ -28,5 +28,6 @@ tracing-bunyan-formatter.workspace = true
|
|||||||
|
|
||||||
prost.workspace = true
|
prost.workspace = true
|
||||||
proto.workspace = true
|
proto.workspace = true
|
||||||
|
proto-derive.workspace = true
|
||||||
|
|
||||||
rand.workspace = true
|
rand.workspace = true
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ use anyhow::Result;
|
|||||||
|
|
||||||
mod logging;
|
mod logging;
|
||||||
mod net;
|
mod net;
|
||||||
|
mod tools;
|
||||||
mod util;
|
mod util;
|
||||||
|
|
||||||
use logging::init_tracing;
|
use logging::init_tracing;
|
||||||
|
|||||||
@@ -1,45 +1,29 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
|
||||||
use crate::{net::PlayerSession, util};
|
use crate::{net::PlayerSession, util};
|
||||||
|
|
||||||
pub async fn on_player_get_token_cs_req(
|
pub async fn on_player_get_token_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_body: &PlayerGetTokenCsReq,
|
_body: &PlayerGetTokenCsReq,
|
||||||
) -> Result<()> {
|
res: &mut PlayerGetTokenScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.msg = String::from("OK");
|
||||||
CMD_PLAYER_GET_TOKEN_SC_RSP,
|
res.uid = 25;
|
||||||
PlayerGetTokenScRsp {
|
|
||||||
retcode: 0,
|
|
||||||
msg: String::from("OK"),
|
|
||||||
uid: 25,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_player_login_cs_req(
|
pub async fn on_player_login_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &PlayerLoginCsReq,
|
body: &PlayerLoginCsReq,
|
||||||
) -> Result<()> {
|
res: &mut PlayerLoginScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.login_random = body.login_random;
|
||||||
CMD_PLAYER_LOGIN_SC_RSP,
|
res.server_timestamp_ms = util::cur_timestamp_ms();
|
||||||
PlayerLoginScRsp {
|
res.stamina = 240;
|
||||||
login_random: body.login_random,
|
res.basic_info = Some(PlayerBasicInfo {
|
||||||
server_timestamp_ms: util::cur_timestamp_ms(),
|
nickname: String::from("RobinSR"),
|
||||||
stamina: 240,
|
level: 70,
|
||||||
basic_info: Some(PlayerBasicInfo {
|
world_level: 6,
|
||||||
nickname: String::from("RobinSR"),
|
stamina: 240,
|
||||||
level: 70,
|
..Default::default()
|
||||||
world_level: 6,
|
});
|
||||||
stamina: 240,
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,55 +2,48 @@ use crate::net::tools::FreesrData;
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
static UNLOCKED_AVATARS: [u32; 56] = [
|
static UNLOCKED_AVATARS: [u32; 57] = [
|
||||||
8001, 1001, 1002, 1003, 1004, 1005, 1006, 1008, 1009, 1013, 1101, 1102, 1103, 1104, 1105, 1106,
|
8001, 1001, 1002, 1003, 1004, 1005, 1006, 1008, 1009, 1013, 1101, 1102, 1103, 1104, 1105, 1106,
|
||||||
1107, 1108, 1109, 1110, 1111, 1112, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210,
|
1107, 1108, 1109, 1110, 1111, 1112, 1201, 1202, 1203, 1204, 1205, 1206, 1207, 1208, 1209, 1210,
|
||||||
1211, 1212, 1213, 1214, 1215, 1217, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1312,
|
1211, 1212, 1213, 1214, 1215, 1217, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1312,
|
||||||
1315, 1310, 1314, 1218, 1221, 1220, 1222, 1223,
|
1315, 1310, 1314, 1218, 1221, 1220, 1222, 1223, 1317,
|
||||||
];
|
];
|
||||||
|
|
||||||
pub async fn on_get_avatar_data_cs_req(
|
pub async fn on_get_avatar_data_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &GetAvatarDataCsReq,
|
body: &GetAvatarDataCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetAvatarDataScRsp,
|
||||||
|
) {
|
||||||
let json = FreesrData::load().await;
|
let json = FreesrData::load().await;
|
||||||
session
|
res.is_get_all = body.is_get_all;
|
||||||
.send(
|
res.avatar_list = UNLOCKED_AVATARS
|
||||||
CMD_GET_AVATAR_DATA_SC_RSP,
|
.iter()
|
||||||
GetAvatarDataScRsp {
|
.map(|id| {
|
||||||
retcode: 0,
|
json.avatars
|
||||||
is_get_all: body.is_get_all,
|
.get(id)
|
||||||
avatar_list: UNLOCKED_AVATARS
|
.map(|v| {
|
||||||
.iter()
|
v.to_avatar_proto(
|
||||||
.map(|id| {
|
json.lightcones.iter().find(|v| v.equip_avatar == *id),
|
||||||
json.avatars
|
json.relics
|
||||||
.get(id)
|
.iter()
|
||||||
.map(|v| {
|
.filter(|v| v.equip_avatar == *id)
|
||||||
v.to_avatar_proto(
|
.collect(),
|
||||||
json.lightcones.iter().find(|v| v.equip_avatar == *id),
|
)
|
||||||
json.relics
|
})
|
||||||
.iter()
|
.unwrap_or(Avatar {
|
||||||
.filter(|v| v.equip_avatar == *id)
|
base_avatar_id: *id,
|
||||||
.collect(),
|
level: 80,
|
||||||
)
|
promotion: 6,
|
||||||
})
|
rank: 6,
|
||||||
.unwrap_or(Avatar {
|
skilltree_list: (1..=4)
|
||||||
base_avatar_id: *id,
|
.map(|m| AvatarSkillTree {
|
||||||
level: 80,
|
point_id: (*id) * 1000 + m,
|
||||||
promotion: 6,
|
level: 1,
|
||||||
rank: 6,
|
})
|
||||||
skilltree_list: (1..=4)
|
.collect(),
|
||||||
.map(|m| AvatarSkillTree {
|
first_met_timestamp: 1712924677,
|
||||||
point_id: (*id) * 1000 + m,
|
..Default::default()
|
||||||
level: 1,
|
})
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect();
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,70 +1,53 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use rand::Rng;
|
use rand::Rng;
|
||||||
|
use rogue_magic_battle_unit_info::Item;
|
||||||
|
|
||||||
use crate::net::tools::{self, BattleType, Monster};
|
use crate::net::tools::{self, BattleType, Monster};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn on_start_cocoon_stage_cs_req(
|
pub async fn on_start_cocoon_stage_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &StartCocoonStageCsReq,
|
body: &StartCocoonStageCsReq,
|
||||||
) -> Result<()> {
|
res: &mut StartCocoonStageScRsp,
|
||||||
|
) {
|
||||||
let battle_info = create_battle_info().await;
|
let battle_info = create_battle_info().await;
|
||||||
|
|
||||||
let rsp = StartCocoonStageScRsp {
|
res.prop_entity_id = body.prop_entity_id;
|
||||||
retcode: 0,
|
res.cocoon_id = body.cocoon_id;
|
||||||
prop_entity_id: body.prop_entity_id,
|
res.wave = body.wave;
|
||||||
cocoon_id: body.cocoon_id,
|
res.battle_info = Some(battle_info);
|
||||||
wave: body.wave,
|
|
||||||
battle_info: Some(battle_info),
|
|
||||||
};
|
|
||||||
|
|
||||||
session.send(CMD_START_COCOON_STAGE_SC_RSP, rsp).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_pve_battle_result_cs_req(
|
pub async fn on_pve_battle_result_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &PveBattleResultCsReq,
|
body: &PveBattleResultCsReq,
|
||||||
) -> Result<()> {
|
res: &mut PveBattleResultScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.end_status = body.end_status;
|
||||||
CMD_PVE_BATTLE_RESULT_SC_RSP,
|
res.battle_id = body.battle_id;
|
||||||
PveBattleResultScRsp {
|
|
||||||
retcode: 0,
|
|
||||||
end_status: body.end_status,
|
|
||||||
battle_id: body.battle_id,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_scene_cast_skill_cs_req(
|
pub async fn on_scene_cast_skill_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
request: &SceneCastSkillCsReq,
|
request: &SceneCastSkillCsReq,
|
||||||
) -> Result<()> {
|
res: &mut SceneCastSkillScRsp,
|
||||||
|
) {
|
||||||
|
res.attacked_group_id = request.attacked_group_id;
|
||||||
|
|
||||||
let battle_info = create_battle_info().await;
|
let battle_info = create_battle_info().await;
|
||||||
|
|
||||||
let mut resp = SceneCastSkillScRsp {
|
|
||||||
attacked_group_id: request.attacked_group_id,
|
|
||||||
retcode: 0,
|
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
let targets = request
|
let targets = request
|
||||||
.assist_monster_entity_id_list
|
.hit_target_entity_id_list
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|id| **id > 30_000 || **id < 1_000)
|
.filter(|id| **id > 30_000 || **id < 1_000)
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
if targets.is_empty() {
|
if targets.is_empty() {
|
||||||
return session.send(CMD_SCENE_CAST_SKILL_SC_RSP, resp).await;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
resp.battle_info = Some(battle_info);
|
res.battle_info = Some(battle_info);
|
||||||
|
|
||||||
session.send(CMD_SCENE_CAST_SKILL_SC_RSP, resp).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn create_battle_info() -> SceneBattleInfo {
|
async fn create_battle_info() -> SceneBattleInfo {
|
||||||
@@ -237,11 +220,62 @@ async fn create_battle_info() -> SceneBattleInfo {
|
|||||||
max_sp: 10_000,
|
max_sp: 10_000,
|
||||||
}),
|
}),
|
||||||
}),
|
}),
|
||||||
|
skill_info: vec![],
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
// monsters
|
// monsters
|
||||||
battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters);
|
battle_info.monster_wave_list = Monster::to_scene_monster_waves(&player.battle_config.monsters);
|
||||||
|
|
||||||
|
if !player.battle_config.scepters.is_empty() {
|
||||||
|
battle_info.rogue_magic_battle_info = Some(RogueMagicBattleInfo {
|
||||||
|
player_detail_info: Some(RogueMagicBattleUnitInfo {
|
||||||
|
item: Some(Item::BattleRogueMagicData(BattleRogueMagicData {
|
||||||
|
round_cnt: Some(BattleRogueMagicRoundCount {
|
||||||
|
hhfjaibgama: 3,
|
||||||
|
mmkolnbikjh: 0,
|
||||||
|
}),
|
||||||
|
battle_scepter_list: player
|
||||||
|
.battle_config
|
||||||
|
.scepters
|
||||||
|
.iter()
|
||||||
|
.map(|scepter| {
|
||||||
|
let mut battle_scepter = BattleRogueMagicScepter {
|
||||||
|
level: scepter.level,
|
||||||
|
scepter_id: scepter.id,
|
||||||
|
magic_unit_list: Vec::new(),
|
||||||
|
slot_count_map: HashMap::from([(3, 0), (4, 0), (5, 0)]),
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut index = [0u32; 3];
|
||||||
|
|
||||||
|
for component in &scepter.components {
|
||||||
|
let (slot_type, locked) = match component.component_type {
|
||||||
|
tools::RogueMagicComponentType::Passive => (3u32, false),
|
||||||
|
tools::RogueMagicComponentType::Active => (4, true),
|
||||||
|
tools::RogueMagicComponentType::Attach => (5, false),
|
||||||
|
};
|
||||||
|
|
||||||
|
let slot_index = &mut index[slot_type as usize - 3];
|
||||||
|
battle_scepter.magic_unit_list.push(BattleRogueMagicUnit {
|
||||||
|
level: component.level,
|
||||||
|
unit_id: component.id,
|
||||||
|
slot_id: *slot_index,
|
||||||
|
locked,
|
||||||
|
counter_map: Default::default(),
|
||||||
|
});
|
||||||
|
*slot_index += 1;
|
||||||
|
*battle_scepter.slot_count_map.get_mut(&slot_type).unwrap() += 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
battle_scepter
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
})),
|
||||||
|
}),
|
||||||
|
scepter: Some(Igefngnckog { ojibobnaikh: 5 }),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
battle_info
|
battle_info
|
||||||
}
|
}
|
||||||
|
|||||||
+165
-212
@@ -8,118 +8,91 @@ use crate::{
|
|||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
|
const SERVER_UID: u32 = 727;
|
||||||
|
const SERVER_HEAD_ICON: u32 = 201008;
|
||||||
|
const SERVER_CHAT_BUBBLE_ID: u32 = 220005;
|
||||||
|
const SERVER_CHAT_HISTORY: [&str; 4] = [
|
||||||
|
"'sync'",
|
||||||
|
"'mc {mc_id}' mc_id can be set from 8001 to 8006",
|
||||||
|
"'march {march_id}' march_id can be set 1001 or 1224",
|
||||||
|
"available command:",
|
||||||
|
];
|
||||||
|
|
||||||
pub async fn on_get_friend_login_info_cs_req(
|
pub async fn on_get_friend_login_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetFriendLoginInfoCsReq,
|
_req: &GetFriendLoginInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetFriendLoginInfoScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.friend_uid_list = vec![SERVER_UID];
|
||||||
CMD_GET_FRIEND_LOGIN_INFO_SC_RSP,
|
|
||||||
GetFriendLoginInfoScRsp {
|
|
||||||
mnacbpjeche: vec![727],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_friend_list_info_cs_req(
|
pub async fn on_get_friend_list_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetFriendListInfoCsReq,
|
_req: &GetFriendListInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetFriendListInfoScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.friend_list = vec![FriendListInfo {
|
||||||
CMD_GET_FRIEND_LIST_INFO_SC_RSP,
|
friend_name: String::from("RobinSR"),
|
||||||
GetFriendListInfoScRsp {
|
simple_info: Some(SimpleInfo {
|
||||||
friend_list: vec![FriendListInfo {
|
uid: SERVER_UID,
|
||||||
friend_name: String::from("RobinSR"),
|
platform_type: PlatformType::Pc.into(),
|
||||||
simple_info: Some(SimpleInfo {
|
online_status: FriendOnlineStatus::Online.into(),
|
||||||
uid: 727,
|
head_icon: SERVER_HEAD_ICON,
|
||||||
platform_type: 3,
|
chat_bubble_id: SERVER_CHAT_BUBBLE_ID,
|
||||||
online_status: 1,
|
level: 70,
|
||||||
head_icon: 201008,
|
nickname: String::from("Server"),
|
||||||
chat_bubble_id: 220005,
|
signature: String::from("omg"),
|
||||||
level: 70,
|
..Default::default()
|
||||||
nickname: String::from("Server"),
|
}),
|
||||||
signature: String::from("omg"),
|
is_marked: true,
|
||||||
..Default::default()
|
sent_time: 0,
|
||||||
}),
|
..Default::default()
|
||||||
is_marked: true,
|
}];
|
||||||
sent_time: 0,
|
|
||||||
..Default::default()
|
|
||||||
}],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_private_chat_history_cs_req(
|
pub async fn on_get_private_chat_history_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
req: &GetPrivateChatHistoryCsReq,
|
req: &GetPrivateChatHistoryCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetPrivateChatHistoryScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
let cur_time = cur_timestamp_ms();
|
||||||
CMD_GET_PRIVATE_CHAT_HISTORY_SC_RSP,
|
res.chat_list = SERVER_CHAT_HISTORY
|
||||||
GetPrivateChatHistoryScRsp {
|
.iter()
|
||||||
chat_list: vec![
|
.map(|text| Chat {
|
||||||
Chat {
|
msg_type: MsgType::CustomText.into(),
|
||||||
msg_type: MsgType::CustomText.into(),
|
sent_time: cur_time,
|
||||||
sent_time: cur_timestamp_ms(),
|
text: String::from(*text),
|
||||||
text: "'sync'".to_string(),
|
sender_uid: SERVER_UID,
|
||||||
sender_uid: 727,
|
..Default::default()
|
||||||
..Default::default()
|
})
|
||||||
},
|
.collect();
|
||||||
Chat {
|
res.to_uid = req.to_uid;
|
||||||
msg_type: MsgType::CustomText.into(),
|
res.from_uid = SERVER_UID;
|
||||||
sent_time: cur_timestamp_ms(),
|
|
||||||
text: "'mc {mc_id}' mc_id can be set from 8001 to 8006".to_string(),
|
|
||||||
sender_uid: 727,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Chat {
|
|
||||||
msg_type: MsgType::CustomText.into(),
|
|
||||||
sent_time: cur_timestamp_ms(),
|
|
||||||
text: "'march {march_id}' march_id can be set 1001 or 1224".to_string(),
|
|
||||||
sender_uid: 727,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
Chat {
|
|
||||||
msg_type: MsgType::CustomText.into(),
|
|
||||||
sent_time: cur_timestamp_ms(),
|
|
||||||
text: "available command:".to_string(),
|
|
||||||
sender_uid: 727,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
sender_id: 0, // from
|
|
||||||
to_uid: req.to_uid, // to
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_send_msg_cs_req(session: &mut PlayerSession, body: &SendMsgCsReq) -> Result<()> {
|
pub async fn on_send_msg_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &SendMsgCsReq,
|
||||||
|
_res: &mut SendMsgScRsp,
|
||||||
|
) {
|
||||||
let mut json = FreesrData::load().await;
|
let mut json = FreesrData::load().await;
|
||||||
|
|
||||||
if let Some((cmd, args)) = parse_command(&body.text) {
|
if let Some((cmd, args)) = parse_command(&body.text) {
|
||||||
match cmd {
|
match cmd {
|
||||||
"sync" => {
|
"sync" => {
|
||||||
sync_player(session, json).await?;
|
sync_player(session, json).await;
|
||||||
session
|
session
|
||||||
.send(
|
.send(RevcMsgScNotify {
|
||||||
CMD_REVC_MSG_SC_NOTIFY,
|
msg_type: body.msg_type,
|
||||||
RevcMsgScNotify {
|
text: String::from("Inventory Synced"),
|
||||||
msg_type: body.msg_type,
|
emote: body.emote,
|
||||||
text: String::from("Inventory Synced"),
|
from_uid: SERVER_UID, // from
|
||||||
emote: body.emote,
|
to_uid: 25, // to
|
||||||
from_uid: 727, // from
|
chat_type: body.chat_type,
|
||||||
to_uid: 25, // to
|
..Default::default()
|
||||||
chat_type: body.chat_type,
|
})
|
||||||
},
|
.await
|
||||||
)
|
.unwrap();
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"mc" => {
|
"mc" => {
|
||||||
let mc = MultiPathAvatar::from(
|
let mc = MultiPathAvatar::from(
|
||||||
@@ -133,28 +106,25 @@ pub async fn on_send_msg_cs_req(session: &mut PlayerSession, body: &SendMsgCsReq
|
|||||||
json.save().await;
|
json.save().await;
|
||||||
|
|
||||||
session
|
session
|
||||||
.send(
|
.send(AvatarPathChangedNotify {
|
||||||
CMD_AVATAR_PATH_CHANGED_NOTIFY,
|
base_avatar_id: 8001,
|
||||||
AvatarPathChangedNotify {
|
cur_multi_path_avatar_type: mc as i32,
|
||||||
base_avatar_id: 8001,
|
})
|
||||||
cur_multi_path_avatar_type: mc as i32,
|
.await
|
||||||
},
|
.unwrap();
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
session
|
||||||
.send(
|
.send(RevcMsgScNotify {
|
||||||
CMD_REVC_MSG_SC_NOTIFY,
|
msg_type: body.msg_type,
|
||||||
RevcMsgScNotify {
|
text: format!("Success change mc to {:#?}", mc),
|
||||||
msg_type: body.msg_type,
|
emote: body.emote,
|
||||||
text: format!("Success change mc to {:#?}", mc),
|
from_uid: SERVER_UID, // from
|
||||||
emote: body.emote,
|
to_uid: 25, // to
|
||||||
from_uid: 727, // from
|
chat_type: body.chat_type,
|
||||||
to_uid: 25, // to
|
..Default::default()
|
||||||
chat_type: body.chat_type,
|
})
|
||||||
},
|
.await
|
||||||
)
|
.unwrap();
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
"march" => {
|
"march" => {
|
||||||
let march_type = MultiPathAvatar::from(
|
let march_type = MultiPathAvatar::from(
|
||||||
@@ -168,42 +138,29 @@ pub async fn on_send_msg_cs_req(session: &mut PlayerSession, body: &SendMsgCsReq
|
|||||||
json.save().await;
|
json.save().await;
|
||||||
|
|
||||||
session
|
session
|
||||||
.send(
|
.send(AvatarPathChangedNotify {
|
||||||
CMD_AVATAR_PATH_CHANGED_NOTIFY,
|
base_avatar_id: 1001,
|
||||||
AvatarPathChangedNotify {
|
cur_multi_path_avatar_type: march_type as i32,
|
||||||
base_avatar_id: 1001,
|
})
|
||||||
cur_multi_path_avatar_type: march_type as i32,
|
.await
|
||||||
},
|
.unwrap();
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
session
|
||||||
.send(
|
.send(RevcMsgScNotify {
|
||||||
CMD_REVC_MSG_SC_NOTIFY,
|
msg_type: body.msg_type,
|
||||||
RevcMsgScNotify {
|
text: format!("Success change march to {:#?}", march_type),
|
||||||
msg_type: body.msg_type,
|
emote: body.emote,
|
||||||
text: format!("Success change march to {:#?}", march_type),
|
from_uid: SERVER_UID, // from
|
||||||
emote: body.emote,
|
to_uid: 25, // to
|
||||||
from_uid: 727, // from
|
chat_type: body.chat_type,
|
||||||
to_uid: 25, // to
|
..Default::default()
|
||||||
chat_type: body.chat_type,
|
})
|
||||||
},
|
.await
|
||||||
)
|
.unwrap();
|
||||||
.await?;
|
|
||||||
}
|
}
|
||||||
_ => {}
|
_ => {}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_SEND_MSG_SC_RSP,
|
|
||||||
SendMsgScRsp {
|
|
||||||
retcode: 0,
|
|
||||||
end_time: 0,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn parse_command(command: &str) -> Option<(&str, Vec<&str>)> {
|
fn parse_command(command: &str) -> Option<(&str, Vec<&str>)> {
|
||||||
@@ -216,72 +173,68 @@ fn parse_command(command: &str) -> Option<(&str, Vec<&str>)> {
|
|||||||
Some((parts[0], parts[1..].to_vec()))
|
Some((parts[0], parts[1..].to_vec()))
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn sync_player(session: &mut PlayerSession, json: FreesrData) -> Result<()> {
|
async fn sync_player(session: &mut PlayerSession, json: FreesrData) {
|
||||||
|
// clear relics & lightcones
|
||||||
session
|
session
|
||||||
.send(
|
.send(PlayerSyncScNotify {
|
||||||
CMD_PLAYER_SYNC_SC_NOTIFY,
|
del_equipment_list: (2000..3500).collect(),
|
||||||
PlayerSyncScNotify {
|
del_relic_list: (1..2000).collect(),
|
||||||
del_equipment_list: (2000..3500).collect(),
|
..Default::default()
|
||||||
del_relic_list: (1..2000).collect(),
|
})
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_PLAYER_SYNC_SC_NOTIFY,
|
|
||||||
PlayerSyncScNotify {
|
|
||||||
avatar_sync: Some(AvatarSync {
|
|
||||||
avatar_list: json
|
|
||||||
.avatars
|
|
||||||
.values()
|
|
||||||
.map(|avatar| avatar.to_avatar_proto(Option::None, vec![]))
|
|
||||||
.collect::<Vec<_>>(),
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_PLAYER_SYNC_SC_NOTIFY,
|
|
||||||
PlayerSyncScNotify {
|
|
||||||
relic_list: json.relics.iter().map(|v| v.to_relic_proto()).collect(),
|
|
||||||
equipment_list: json
|
|
||||||
.lightcones
|
|
||||||
.iter()
|
|
||||||
.map(|v| v.to_equipment_proto())
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_PLAYER_SYNC_SC_NOTIFY,
|
|
||||||
PlayerSyncScNotify {
|
|
||||||
avatar_sync: Some(AvatarSync {
|
|
||||||
avatar_list: json
|
|
||||||
.avatars
|
|
||||||
.values()
|
|
||||||
.map(|avatar| {
|
|
||||||
avatar.to_avatar_proto(
|
|
||||||
json.lightcones
|
|
||||||
.iter()
|
|
||||||
.find(|v| v.equip_avatar == avatar.avatar_id),
|
|
||||||
json.relics
|
|
||||||
.iter()
|
|
||||||
.filter(|v| v.equip_avatar == avatar.avatar_id)
|
|
||||||
.collect(),
|
|
||||||
)
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
}),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Sync avatars
|
||||||
|
session
|
||||||
|
.send(PlayerSyncScNotify {
|
||||||
|
avatar_sync: Some(AvatarSync {
|
||||||
|
avatar_list: json
|
||||||
|
.avatars
|
||||||
|
.values()
|
||||||
|
.map(|avatar| avatar.to_avatar_proto(Option::None, vec![]))
|
||||||
|
.collect::<Vec<_>>(),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Sync new relics
|
||||||
|
session
|
||||||
|
.send(PlayerSyncScNotify {
|
||||||
|
relic_list: json.relics.iter().map(|v| v.to_relic_proto()).collect(),
|
||||||
|
equipment_list: json
|
||||||
|
.lightcones
|
||||||
|
.iter()
|
||||||
|
.map(|v| v.to_equipment_proto())
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
|
|
||||||
|
// Sync new lightcones
|
||||||
|
session
|
||||||
|
.send(PlayerSyncScNotify {
|
||||||
|
avatar_sync: Some(AvatarSync {
|
||||||
|
avatar_list: json
|
||||||
|
.avatars
|
||||||
|
.values()
|
||||||
|
.map(|avatar| {
|
||||||
|
avatar.to_avatar_proto(
|
||||||
|
json.lightcones
|
||||||
|
.iter()
|
||||||
|
.find(|v| v.equip_avatar == avatar.avatar_id),
|
||||||
|
json.relics
|
||||||
|
.iter()
|
||||||
|
.filter(|v| v.equip_avatar == avatar.avatar_id)
|
||||||
|
.collect(),
|
||||||
|
)
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.await
|
||||||
|
.unwrap()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,10 +1,11 @@
|
|||||||
pub use super::*;
|
pub use super::*;
|
||||||
|
|
||||||
pub async fn on_get_gacha_info_cs_req(
|
pub async fn on_get_gacha_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetGachaInfoCsReq,
|
_req: &GetGachaInfoCsReq,
|
||||||
) -> anyhow::Result<()> {
|
res: &mut GetGachaInfoScRsp,
|
||||||
let gacha = GachaInfo {
|
) {
|
||||||
|
res.gacha_info_list = vec![GachaInfo {
|
||||||
end_time: 1924992000,
|
end_time: 1924992000,
|
||||||
begin_time: 0,
|
begin_time: 0,
|
||||||
gacha_ceiling: Some(GachaCeiling::default()),
|
gacha_ceiling: Some(GachaCeiling::default()),
|
||||||
@@ -17,47 +18,31 @@ pub async fn on_get_gacha_info_cs_req(
|
|||||||
],
|
],
|
||||||
gacha_id: 1001,
|
gacha_id: 1001,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
}];
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_GET_GACHA_INFO_SC_RSP,
|
|
||||||
GetGachaInfoScRsp {
|
|
||||||
gacha_info_list: vec![gacha],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_do_gacha_cs_req(
|
pub async fn on_do_gacha_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
req: &DoGachaCsReq,
|
req: &DoGachaCsReq,
|
||||||
) -> anyhow::Result<()> {
|
res: &mut DoGachaScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.gacha_id = req.gacha_id;
|
||||||
CMD_DO_GACHA_SC_RSP,
|
res.gacha_num = req.gacha_num;
|
||||||
DoGachaScRsp {
|
res.gacha_item_list = (0..req.gacha_num)
|
||||||
gacha_id: req.gacha_id,
|
.map(|v| GachaItem {
|
||||||
gacha_num: req.gacha_num,
|
is_new: false,
|
||||||
gacha_item_list: (0..req.gacha_num)
|
gacha_item: Some(Item {
|
||||||
.map(|v| GachaItem {
|
item_id: if v % 2 == 0 { 1310 } else { 1314 },
|
||||||
is_new: false,
|
|
||||||
gacha_item: Some(Item {
|
|
||||||
item_id: if v % 2 == 0 { 1310 } else { 1314 },
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
token_item: Some(ItemList {
|
|
||||||
item_list: vec![Item {
|
|
||||||
item_id: 251,
|
|
||||||
num: 100,
|
|
||||||
..Default::default()
|
|
||||||
}],
|
|
||||||
}),
|
|
||||||
transfer_item_list: Some(ItemList { item_list: vec![] }),
|
|
||||||
})
|
|
||||||
.collect(),
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
},
|
}),
|
||||||
)
|
token_item: Some(ItemList {
|
||||||
.await
|
item_list: vec![Item {
|
||||||
}
|
item_id: 251,
|
||||||
|
num: 100,
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
}),
|
||||||
|
transfer_item_list: Some(ItemList { item_list: vec![] }),
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,96 +1,66 @@
|
|||||||
use anyhow::Result;
|
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
|
||||||
use crate::net::{tools::FreesrData, PlayerSession};
|
use crate::net::{tools::FreesrData, PlayerSession};
|
||||||
|
|
||||||
pub async fn on_get_bag_cs_req(session: &mut PlayerSession, _: &GetBagCsReq) -> Result<()> {
|
pub async fn on_get_bag_cs_req(
|
||||||
|
_session: &mut PlayerSession,
|
||||||
|
_req: &GetBagCsReq,
|
||||||
|
res: &mut GetBagScRsp,
|
||||||
|
) {
|
||||||
let player = FreesrData::load().await;
|
let player = FreesrData::load().await;
|
||||||
|
|
||||||
session
|
res.equipment_list = player
|
||||||
.send(
|
.lightcones
|
||||||
CMD_GET_BAG_SC_RSP,
|
.iter()
|
||||||
GetBagScRsp {
|
.map(|v| v.to_equipment_proto())
|
||||||
equipment_list: player
|
.collect();
|
||||||
.lightcones
|
res.relic_list = player.relics.iter().map(|v| v.to_relic_proto()).collect();
|
||||||
.iter()
|
res.material_list = vec![
|
||||||
.map(|v| v.to_equipment_proto())
|
Material {
|
||||||
.collect(),
|
tid: 101, // Normal Pass
|
||||||
relic_list: player.relics.iter().map(|v| v.to_relic_proto()).collect(),
|
num: 999999,
|
||||||
material_list: vec![
|
..Default::default()
|
||||||
Material {
|
},
|
||||||
tid: 101, // Normal Pass
|
Material {
|
||||||
num: 999999,
|
tid: 102, // Special Pass
|
||||||
..Default::default()
|
num: 999999,
|
||||||
},
|
..Default::default()
|
||||||
Material {
|
},
|
||||||
tid: 102, // Special Pass
|
];
|
||||||
num: 999999,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_archive_data_cs_req(
|
pub async fn on_get_archive_data_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetArchiveDataCsReq,
|
_: &GetArchiveDataCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetArchiveDataScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.archive_data = Some(ArchiveData::default());
|
||||||
CMD_GET_ARCHIVE_DATA_SC_RSP,
|
|
||||||
GetArchiveDataScRsp {
|
|
||||||
archive_data: Some(ArchiveData::default()),
|
|
||||||
retcode: 0,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_dress_relic_avatar_cs_req(
|
pub async fn on_dress_relic_avatar_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &DressRelicAvatarCsReq,
|
_req: &DressRelicAvatarCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut DressRelicAvatarScRsp,
|
||||||
// ?
|
) {
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_DRESS_RELIC_AVATAR_SC_RSP,
|
|
||||||
DressRelicAvatarScRsp::default(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_take_off_relic_cs_req(
|
pub async fn on_take_off_relic_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &TakeOffRelicCsReq,
|
_req: &TakeOffRelicCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut TakeOffRelicScRsp,
|
||||||
// ?
|
) {
|
||||||
session
|
|
||||||
.send(CMD_TAKE_OFF_RELIC_SC_RSP, TakeOffRelicScRsp::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_dress_avatar_cs_req(
|
pub async fn on_dress_avatar_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &DressAvatarCsReq,
|
_req: &DressAvatarCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut DressAvatarScRsp,
|
||||||
// ?
|
) {
|
||||||
session
|
|
||||||
.send(CMD_DRESS_AVATAR_SC_RSP, DressAvatarScRsp::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_take_off_equipment_cs_req(
|
pub async fn on_take_off_equipment_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &TakeOffEquipmentCsReq,
|
_req: &TakeOffEquipmentCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut TakeOffEquipmentScRsp,
|
||||||
// ?
|
) {
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_TAKE_OFF_EQUIPMENT_SC_RSP,
|
|
||||||
TakeOffEquipmentScRsp::default(),
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -6,34 +6,26 @@ use crate::net::tools::{self, AvatarJson, FreesrData};
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn on_get_all_lineup_data_cs_req(
|
pub async fn on_get_all_lineup_data_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_body: &GetAllLineupDataCsReq,
|
_body: &GetAllLineupDataCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetAllLineupDataScRsp,
|
||||||
|
) {
|
||||||
let player = tools::FreesrData::load().await;
|
let player = tools::FreesrData::load().await;
|
||||||
let lineup = LineupInfo {
|
res.lineup_list = vec![LineupInfo {
|
||||||
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
||||||
name: "Squad 1".to_string(),
|
name: "Squad 1".to_string(),
|
||||||
mp: 5,
|
mp: 5,
|
||||||
max_mp: 5,
|
max_mp: 5,
|
||||||
avatar_list: AvatarJson::to_lineup_avatars(&player),
|
avatar_list: AvatarJson::to_lineup_avatars(&player),
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
}];
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_GET_ALL_LINEUP_DATA_SC_RSP,
|
|
||||||
GetAllLineupDataScRsp {
|
|
||||||
lineup_list: vec![lineup],
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_cur_lineup_data_cs_req(
|
pub async fn on_get_cur_lineup_data_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_body: &GetCurLineupDataCsReq,
|
_body: &GetCurLineupDataCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetCurLineupDataScRsp,
|
||||||
|
) {
|
||||||
let player = tools::FreesrData::load().await;
|
let player = tools::FreesrData::load().await;
|
||||||
let lineup = LineupInfo {
|
let lineup = LineupInfo {
|
||||||
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
||||||
@@ -46,95 +38,63 @@ pub async fn on_get_cur_lineup_data_cs_req(
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
session
|
res.lineup = Some(lineup)
|
||||||
.send(
|
|
||||||
CMD_GET_CUR_LINEUP_DATA_SC_RSP,
|
|
||||||
GetCurLineupDataScRsp {
|
|
||||||
lineup: Some(lineup),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_join_lineup_cs_req(
|
pub async fn on_join_lineup_cs_req(
|
||||||
session: &mut PlayerSession,
|
session: &mut PlayerSession,
|
||||||
body: &JoinLineupCsReq,
|
body: &JoinLineupCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut JoinLineupScRsp,
|
||||||
// update lineups
|
) {
|
||||||
// TODO: FIX THESE SHIT
|
let mut player = tools::FreesrData::load().await;
|
||||||
{
|
let lineups = &mut player.lineups;
|
||||||
let mut player = tools::FreesrData::load().await;
|
lineups.insert(
|
||||||
let lineups = &mut player.lineups;
|
body.slot,
|
||||||
lineups.insert(
|
if body.base_avatar_id == 8001 {
|
||||||
body.slot,
|
player.main_character as u32
|
||||||
if body.base_avatar_id == 8001 {
|
} else if body.base_avatar_id == 1001 {
|
||||||
player.main_character as u32
|
player.march_type as u32
|
||||||
} else if body.base_avatar_id == 1001 {
|
} else {
|
||||||
player.march_type as u32
|
body.base_avatar_id
|
||||||
} else {
|
},
|
||||||
body.base_avatar_id
|
);
|
||||||
},
|
player.save_lineup().await;
|
||||||
);
|
refresh_lineup(session, &player).await;
|
||||||
player.save_lineup().await;
|
|
||||||
}
|
|
||||||
|
|
||||||
{
|
|
||||||
let player = tools::FreesrData::load().await;
|
|
||||||
|
|
||||||
refresh_lineup(session, &player).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
session
|
|
||||||
.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_replace_lineup_cs_req(
|
pub async fn on_replace_lineup_cs_req(
|
||||||
_session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
req: &ReplaceLineupCsReq,
|
req: &ReplaceLineupCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut ReplaceLineupScRsp,
|
||||||
{
|
) {
|
||||||
let mut player = tools::FreesrData::load().await;
|
let mut player = tools::FreesrData::load().await;
|
||||||
|
|
||||||
let lineups = &mut player.lineups;
|
let lineups = &mut player.lineups;
|
||||||
for (slot, avatar_id) in &mut *lineups {
|
for (slot, avatar_id) in &mut *lineups {
|
||||||
if let Some(lineup) = req.slots.get(*slot as usize) {
|
if let Some(lineup) = req.slots.get(*slot as usize) {
|
||||||
*avatar_id = if lineup.id == 8001 {
|
*avatar_id = if lineup.id == 8001 {
|
||||||
player.main_character as u32
|
player.main_character as u32
|
||||||
} else if lineup.id == 1001 {
|
} else if lineup.id == 1001 {
|
||||||
player.march_type as u32
|
player.march_type as u32
|
||||||
} else {
|
|
||||||
lineup.id
|
|
||||||
};
|
|
||||||
} else {
|
} else {
|
||||||
*avatar_id = 0;
|
lineup.id
|
||||||
}
|
};
|
||||||
|
} else {
|
||||||
|
*avatar_id = 0;
|
||||||
}
|
}
|
||||||
player.save_lineup().await;
|
|
||||||
}
|
}
|
||||||
|
player.save_lineup().await;
|
||||||
{
|
refresh_lineup(_session, &player).await;
|
||||||
let player = tools::FreesrData::load().await;
|
|
||||||
|
|
||||||
refresh_lineup(_session, &player).await?;
|
|
||||||
}
|
|
||||||
|
|
||||||
_session
|
|
||||||
.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_quit_lineup_cs_req(
|
pub async fn on_quit_lineup_cs_req(
|
||||||
_session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &QuitLineupCsReq,
|
_: &QuitLineupCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut QuitLineupScRsp,
|
||||||
_session
|
) {
|
||||||
.send(CMD_JOIN_LINEUP_SC_RSP, JoinLineupScRsp::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn refresh_lineup(sess: &mut PlayerSession, player: &FreesrData) -> Result<()> {
|
async fn refresh_lineup(session: &mut PlayerSession, player: &FreesrData) {
|
||||||
let lineup = LineupInfo {
|
let lineup = LineupInfo {
|
||||||
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
extra_lineup_type: ExtraLineupType::LineupNone.into(),
|
||||||
name: "Squad 1".to_string(),
|
name: "Squad 1".to_string(),
|
||||||
@@ -144,9 +104,8 @@ async fn refresh_lineup(sess: &mut PlayerSession, player: &FreesrData) -> Result
|
|||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
sess.send(
|
session
|
||||||
CMD_SCENE_GROUP_REFRESH_SC_NOTIFY,
|
.send(SceneGroupRefreshScNotify {
|
||||||
SceneGroupRefreshScNotify {
|
|
||||||
group_refresh_info: vec![SceneGroupRefreshInfo {
|
group_refresh_info: vec![SceneGroupRefreshInfo {
|
||||||
group_id: 0,
|
group_id: 0,
|
||||||
state: 0,
|
state: 0,
|
||||||
@@ -170,31 +129,23 @@ async fn refresh_lineup(sess: &mut PlayerSession, player: &FreesrData) -> Result
|
|||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
}],
|
}],
|
||||||
},
|
})
|
||||||
)
|
.await
|
||||||
.await?;
|
.unwrap();
|
||||||
|
|
||||||
sess.send(
|
session
|
||||||
CMD_SYNC_LINEUP_NOTIFY,
|
.send(SyncLineupNotify {
|
||||||
SyncLineupNotify {
|
|
||||||
lineup: Some(lineup),
|
lineup: Some(lineup),
|
||||||
reason_list: vec![],
|
reason_list: vec![],
|
||||||
},
|
})
|
||||||
)
|
.await
|
||||||
.await
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_change_lineup_leader_cs_req(
|
pub async fn on_change_lineup_leader_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &ChangeLineupLeaderCsReq,
|
body: &ChangeLineupLeaderCsReq,
|
||||||
) -> Result<()> {
|
res: &mut ChangeLineupLeaderScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.slot = body.slot;
|
||||||
CMD_CHANGE_LINEUP_LEADER_SC_RSP,
|
|
||||||
ChangeLineupLeaderScRsp {
|
|
||||||
slot: body.slot,
|
|
||||||
retcode: 0,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,37 +1,29 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
use anyhow::Result;
|
|
||||||
|
|
||||||
pub async fn on_get_mail_cs_req(session: &mut PlayerSession, _: &GetMailCsReq) -> Result<()> {
|
pub async fn on_get_mail_cs_req(
|
||||||
session
|
_session: &mut PlayerSession,
|
||||||
.send(
|
_req: &GetMailCsReq,
|
||||||
CMD_GET_MAIL_SC_RSP,
|
res: &mut GetMailScRsp,
|
||||||
GetMailScRsp {
|
) {
|
||||||
is_end: true,
|
res.is_end = true;
|
||||||
mail_list: vec![ClientMail {
|
res.mail_list = vec![ClientMail {
|
||||||
title: String::from("Welcome!"),
|
title: String::from("Welcome!"),
|
||||||
sender: String::from("Server"),
|
sender: String::from("Server"),
|
||||||
content: String::from("Welcome!"),
|
content: String::from("Welcome!"),
|
||||||
id: 1,
|
id: 1,
|
||||||
is_read: false,
|
is_read: false,
|
||||||
time: 1716041089,
|
time: 1716041089,
|
||||||
expire_time: 1718633089,
|
expire_time: 1718633089,
|
||||||
para_list: vec![],
|
para_list: vec![],
|
||||||
attachment: Some(ItemList {
|
attachment: Some(ItemList {
|
||||||
item_list: vec![Item {
|
item_list: vec![Item {
|
||||||
item_id: 1310,
|
item_id: 1310,
|
||||||
level: 80,
|
level: 80,
|
||||||
num: 1,
|
num: 1,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}],
|
}],
|
||||||
}),
|
}),
|
||||||
mail_type: MailType::Normal.into(),
|
mail_type: MailType::Normal.into(),
|
||||||
template_id: 0,
|
template_id: 0,
|
||||||
}],
|
}];
|
||||||
notice_mail_list: vec![],
|
}
|
||||||
start: 0,
|
|
||||||
retcode: 0,
|
|
||||||
total_num: 1,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -1,23 +1,18 @@
|
|||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn on_get_mission_status_cs_req(
|
pub async fn on_get_mission_status_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &GetMissionStatusCsReq,
|
body: &GetMissionStatusCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetMissionStatusScRsp,
|
||||||
let rsp = GetMissionStatusScRsp {
|
) {
|
||||||
retcode: 0,
|
res.finished_main_mission_id_list = body.main_mission_id_list.clone();
|
||||||
finished_main_mission_id_list: body.main_mission_id_list.clone(),
|
res.sub_mission_status_list = body
|
||||||
sub_mission_status_list: body
|
.sub_mission_id_list
|
||||||
.sub_mission_id_list
|
.iter()
|
||||||
.iter()
|
.map(|id| Mission {
|
||||||
.map(|id| Mission {
|
id: *id,
|
||||||
id: *id,
|
progress: 1,
|
||||||
progress: 1,
|
status: MissionStatus::MissionFinish.into(),
|
||||||
status: MissionStatus::MissionFinish.into(),
|
})
|
||||||
})
|
.collect();
|
||||||
.collect(),
|
}
|
||||||
..Default::default()
|
|
||||||
};
|
|
||||||
|
|
||||||
session.send(CMD_GET_MISSION_STATUS_SC_RSP, rsp).await
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ mod mail;
|
|||||||
mod mission;
|
mod mission;
|
||||||
mod player;
|
mod player;
|
||||||
mod scene;
|
mod scene;
|
||||||
mod tutorial;
|
|
||||||
|
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use paste::paste;
|
use paste::paste;
|
||||||
@@ -30,7 +29,6 @@ pub use mail::*;
|
|||||||
pub use mission::*;
|
pub use mission::*;
|
||||||
pub use player::*;
|
pub use player::*;
|
||||||
pub use scene::*;
|
pub use scene::*;
|
||||||
// pub use tutorial::*;
|
|
||||||
|
|
||||||
#[allow(unused_imports)]
|
#[allow(unused_imports)]
|
||||||
use proto::{
|
use proto::{
|
||||||
|
|||||||
@@ -1,157 +1,113 @@
|
|||||||
use std::collections::HashMap;
|
use std::collections::HashMap;
|
||||||
|
|
||||||
use crate::{net::tools::FreesrData, util};
|
use crate::{net::tools::FreesrData, util::cur_timestamp_ms};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
pub async fn on_get_basic_info_cs_req(
|
pub async fn on_get_basic_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_body: &GetBasicInfoCsReq,
|
_body: &GetBasicInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetBasicInfoScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.player_setting_info = Some(PlayerSettingInfo::default());
|
||||||
CMD_GET_BASIC_INFO_SC_RSP,
|
res.gender = Gender::Woman as u32;
|
||||||
GetBasicInfoScRsp {
|
res.is_gender_set = true;
|
||||||
retcode: 0,
|
|
||||||
player_setting_info: Some(PlayerSettingInfo::default()),
|
|
||||||
gender: Gender::Woman as u32,
|
|
||||||
is_gender_set: true,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_player_heart_beat_cs_req(
|
pub async fn on_player_heart_beat_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
body: &PlayerHeartBeatCsReq,
|
body: &PlayerHeartBeatCsReq,
|
||||||
) -> Result<()> {
|
res: &mut PlayerHeartBeatScRsp,
|
||||||
session
|
) {
|
||||||
.send(
|
res.client_time_ms = body.client_time_ms;
|
||||||
CMD_PLAYER_HEART_BEAT_SC_RSP,
|
res.server_time_ms = cur_timestamp_ms();
|
||||||
PlayerHeartBeatScRsp {
|
res.download_data = Some(ClientDownloadData {
|
||||||
retcode: 0,
|
version: 51,
|
||||||
client_time_ms: body.client_time_ms,
|
time: res.server_time_ms as i64,
|
||||||
server_time_ms: util::cur_timestamp_ms(),
|
data: rbase64::decode("bG9jYWwgZnVuY3Rpb24gYmV0YV90ZXh0KG9iaikKICAgIGxvY2FsIGdhbWVPYmplY3QgPSBDUy5Vbml0eUVuZ2luZS5HYW1lT2JqZWN0LkZpbmQoIlVJUm9vdC9BYm92ZURpYWxvZy9CZXRhSGludERpYWxvZyhDbG9uZSkiKQoKICAgIGlmIGdhbWVPYmplY3QgdGhlbgogICAgICAgIGxvY2FsIHRleHRDb21wb25lbnQgPSBnYW1lT2JqZWN0OkdldENvbXBvbmVudEluQ2hpbGRyZW4odHlwZW9mKENTLlJQRy5DbGllbnQuTG9jYWxpemVkVGV4dCkpCgogICAgICAgIGlmIHRleHRDb21wb25lbnQgdGhlbgogICAgICAgICAgICB0ZXh0Q29tcG9uZW50LnRleHQgPSAiUm9iaW5TUiBpcyBhIGZyZWUgYW5kIG9wZW4gc291cmNlIHNvZnR3YXJlLiBkaXNjb3JkLmdnL3JldmVyc2Vkcm9vbXMiCiAgICAgICAgZW5kCiAgICBlbHNlCiAgICBlbmQKZW5kCgpiZXRhX3RleHQoKQ==").unwrap()
|
||||||
download_data: Some(ClientDownloadData {
|
});
|
||||||
version: 51,
|
|
||||||
time: util::cur_timestamp_ms() as i64,
|
|
||||||
data: rbase64::decode("bG9jYWwgZnVuY3Rpb24gYmV0YV90ZXh0KG9iaikKICAgIGxvY2FsIGdhbWVPYmplY3QgPSBDUy5Vbml0eUVuZ2luZS5HYW1lT2JqZWN0LkZpbmQoIlVJUm9vdC9BYm92ZURpYWxvZy9CZXRhSGludERpYWxvZyhDbG9uZSkiKQoKICAgIGlmIGdhbWVPYmplY3QgdGhlbgogICAgICAgIGxvY2FsIHRleHRDb21wb25lbnQgPSBnYW1lT2JqZWN0OkdldENvbXBvbmVudEluQ2hpbGRyZW4odHlwZW9mKENTLlJQRy5DbGllbnQuTG9jYWxpemVkVGV4dCkpCgogICAgICAgIGlmIHRleHRDb21wb25lbnQgdGhlbgogICAgICAgICAgICB0ZXh0Q29tcG9uZW50LnRleHQgPSAiUm9iaW5TUiBpcyBhIGZyZWUgYW5kIG9wZW4gc291cmNlIHNvZnR3YXJlLiBkaXNjb3JkLmdnL3JldmVyc2Vkcm9vbXMiCiAgICAgICAgZW5kCiAgICBlbHNlCiAgICBlbmQKZW5kCgpiZXRhX3RleHQoKQ==").unwrap()
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub type PlayerLoginFinishCsReq = Dummy;
|
|
||||||
|
|
||||||
pub async fn on_player_login_finish_cs_req(
|
pub async fn on_player_login_finish_cs_req(
|
||||||
session: &mut PlayerSession,
|
session: &mut PlayerSession,
|
||||||
_: &PlayerLoginFinishCsReq,
|
_req: &PlayerLoginFinishCsReq,
|
||||||
|
_res: &mut PlayerLoginFinishScRsp,
|
||||||
) -> Result<()> {
|
) -> Result<()> {
|
||||||
session
|
session
|
||||||
.send(CMD_PLAYER_LOGIN_FINISH_SC_RSP, Dummy::default())
|
.send(ContentPackageSyncDataScNotify {
|
||||||
.await?;
|
data: Some(PackageData {
|
||||||
|
info_list: vec![
|
||||||
session
|
200001, 200002, 200003, 200004, 150017, 150015, 150021, 150018, 130011, 130012,
|
||||||
.send(
|
130013,
|
||||||
CMD_CONTENT_PACKAGE_SYNC_DATA_SC_NOTIFY,
|
]
|
||||||
ContentPackageSyncDataScNotify {
|
.iter()
|
||||||
data: Some(PackageData {
|
.map(|v| ContentInfo {
|
||||||
info_list: vec![
|
status: ContentPackageStatus::Finished.into(),
|
||||||
ContentInfo {
|
content_id: *v,
|
||||||
status: ContentPackageStatus::Finished.into(),
|
})
|
||||||
content_id: 200001,
|
.collect(),
|
||||||
},
|
..Default::default()
|
||||||
ContentInfo {
|
}),
|
||||||
status: ContentPackageStatus::Finished.into(),
|
})
|
||||||
content_id: 200002,
|
.await
|
||||||
},
|
|
||||||
ContentInfo {
|
|
||||||
status: ContentPackageStatus::Finished.into(),
|
|
||||||
content_id: 200003,
|
|
||||||
},
|
|
||||||
ContentInfo {
|
|
||||||
status: ContentPackageStatus::Finished.into(),
|
|
||||||
content_id: 150017,
|
|
||||||
},
|
|
||||||
ContentInfo {
|
|
||||||
status: ContentPackageStatus::Finished.into(),
|
|
||||||
content_id: 150015,
|
|
||||||
},
|
|
||||||
],
|
|
||||||
..Default::default()
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_multi_path_avatar_info_cs_req(
|
pub async fn on_get_multi_path_avatar_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetMultiPathAvatarInfoCsReq,
|
_req: &GetMultiPathAvatarInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetMultiPathAvatarInfoScRsp,
|
||||||
|
) {
|
||||||
let json = FreesrData::load().await;
|
let json = FreesrData::load().await;
|
||||||
|
|
||||||
session
|
res.current_multi_path_avatar_id = HashMap::from([
|
||||||
.send(
|
(8001, json.main_character.get_type().into()),
|
||||||
CMD_GET_MULTI_PATH_AVATAR_INFO_SC_RSP,
|
(1001, json.march_type.get_type().into()),
|
||||||
GetMultiPathAvatarInfoScRsp {
|
]);
|
||||||
retcode: 0,
|
|
||||||
multi_path_avatar_type_info_list: vec![
|
res.multi_path_avatar_type_info_list = vec![
|
||||||
MultiPathAvatarTypeInfo {
|
MultiPathAvatarTypeInfo {
|
||||||
avatar_id: json.main_character as i32,
|
avatar_id: json.main_character as i32,
|
||||||
rank: 6,
|
rank: 6,
|
||||||
equip_relic_list: json
|
equip_relic_list: json
|
||||||
.relics
|
.relics
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v| v.equip_avatar == json.main_character as u32)
|
.filter(|v| v.equip_avatar == json.main_character as u32)
|
||||||
.map(|v| v.to_equipment_relic_proto())
|
.map(|v| v.to_equipment_relic_proto())
|
||||||
.collect(),
|
.collect(),
|
||||||
skilltree_list: (1..=4)
|
skilltree_list: (1..=4)
|
||||||
.map(|v| AvatarSkillTree {
|
.map(|v| AvatarSkillTree {
|
||||||
level: 1,
|
level: 1,
|
||||||
point_id: (json.main_character as u32) * 1000 + v,
|
point_id: (json.main_character as u32) * 1000 + v,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
path_equipment_id: json
|
path_equipment_id: json
|
||||||
.lightcones
|
.lightcones
|
||||||
.iter()
|
.iter()
|
||||||
.find(|v| v.equip_avatar == json.main_character as u32)
|
.find(|v| v.equip_avatar == json.main_character as u32)
|
||||||
.map(|v| v.internal_uid)
|
.map(|v| v.internal_uid)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
},
|
},
|
||||||
MultiPathAvatarTypeInfo {
|
MultiPathAvatarTypeInfo {
|
||||||
avatar_id: json.march_type as i32,
|
avatar_id: json.march_type as i32,
|
||||||
rank: 6,
|
rank: 6,
|
||||||
equip_relic_list: json
|
equip_relic_list: json
|
||||||
.relics
|
.relics
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|v| v.equip_avatar == json.march_type as u32)
|
.filter(|v| v.equip_avatar == json.march_type as u32)
|
||||||
.map(|v| v.to_equipment_relic_proto())
|
.map(|v| v.to_equipment_relic_proto())
|
||||||
.collect(),
|
.collect(),
|
||||||
skilltree_list: (1..=4)
|
skilltree_list: (1..=4)
|
||||||
.map(|v| AvatarSkillTree {
|
.map(|v| AvatarSkillTree {
|
||||||
level: 1,
|
level: 1,
|
||||||
point_id: (json.march_type as u32) * 1000 + v,
|
point_id: (json.march_type as u32) * 1000 + v,
|
||||||
})
|
})
|
||||||
.collect(),
|
.collect(),
|
||||||
path_equipment_id: json
|
path_equipment_id: json
|
||||||
.lightcones
|
.lightcones
|
||||||
.iter()
|
.iter()
|
||||||
.find(|v| v.equip_avatar == json.march_type as u32)
|
.find(|v| v.equip_avatar == json.march_type as u32)
|
||||||
.map(|v| v.internal_uid)
|
.map(|v| v.internal_uid)
|
||||||
.unwrap_or_default(),
|
.unwrap_or_default(),
|
||||||
},
|
},
|
||||||
],
|
];
|
||||||
current_multi_path_avatar_id: HashMap::from([
|
|
||||||
(8001, json.main_character.get_type().into()),
|
|
||||||
(1001, json.march_type.get_type().into()),
|
|
||||||
]),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,95 +1,65 @@
|
|||||||
use lazy_static::lazy_static;
|
use lazy_static::lazy_static;
|
||||||
use prost::Message;
|
|
||||||
use scene_entity_info::Entity;
|
use scene_entity_info::Entity;
|
||||||
use tokio::sync::Mutex;
|
use tokio::sync::Mutex;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
net::{
|
net::tools::{AvatarJson, FreesrData, Position},
|
||||||
tools::{AvatarJson, FreesrData, Position},
|
tools::resources::GAME_RES,
|
||||||
tools_res::{PropState, GAME_RESOURCES},
|
|
||||||
},
|
|
||||||
util::{self},
|
util::{self},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::*;
|
use super::*;
|
||||||
|
|
||||||
#[derive(Message)]
|
|
||||||
pub struct Dummy {}
|
|
||||||
|
|
||||||
pub async fn on_get_cur_scene_info_cs_req(
|
pub async fn on_get_cur_scene_info_cs_req(
|
||||||
session: &mut PlayerSession,
|
session: &mut PlayerSession,
|
||||||
_body: &GetCurSceneInfoCsReq,
|
_body: &GetCurSceneInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetCurSceneInfoScRsp,
|
||||||
|
) {
|
||||||
let mut player = FreesrData::load().await;
|
let mut player = FreesrData::load().await;
|
||||||
let entry = player.scene.entry_id;
|
let entry = player.scene.entry_id;
|
||||||
|
|
||||||
let scene = load_scene(session, &mut player, entry, false, Option::<u32>::None).await;
|
let scene = load_scene(session, &mut player, entry, false, Option::<u32>::None).await;
|
||||||
|
|
||||||
let resp = GetCurSceneInfoScRsp {
|
res.scene = if let Ok(scene) = scene {
|
||||||
retcode: 0,
|
Some(scene)
|
||||||
scene: if let Ok(scene) = scene {
|
} else {
|
||||||
Some(scene)
|
Some(SceneInfo {
|
||||||
} else {
|
game_mode_type: 3,
|
||||||
Some(SceneInfo {
|
entry_id: player.scene.entry_id,
|
||||||
game_mode_type: 1,
|
plane_id: player.scene.plane_id,
|
||||||
entry_id: player.scene.entry_id,
|
floor_id: player.scene.floor_id,
|
||||||
plane_id: player.scene.plane_id,
|
..Default::default()
|
||||||
floor_id: player.scene.floor_id,
|
})
|
||||||
..Default::default()
|
|
||||||
})
|
|
||||||
},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
session.send(CMD_GET_CUR_SCENE_INFO_SC_RSP, resp).await?;
|
|
||||||
if !player.position.is_empty() {
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_SCENE_ENTITY_MOVE_SC_NOTIFY,
|
|
||||||
SceneEntityMoveScNotify {
|
|
||||||
entity_id: 0,
|
|
||||||
entry_id: player.scene.entry_id,
|
|
||||||
motion: Some(player.position.to_motion()),
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
};
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// enterscene
|
|
||||||
pub async fn on_enter_scene_cs_req(
|
pub async fn on_enter_scene_cs_req(
|
||||||
session: &mut PlayerSession,
|
session: &mut PlayerSession,
|
||||||
request: &EnterSceneCsReq,
|
req: &EnterSceneCsReq,
|
||||||
) -> Result<()> {
|
res: &mut EnterSceneScRsp,
|
||||||
|
) {
|
||||||
let mut player = FreesrData::load().await;
|
let mut player = FreesrData::load().await;
|
||||||
|
|
||||||
// send packet first
|
if load_scene(
|
||||||
session
|
|
||||||
.send(CMD_ENTER_SCENE_SC_RSP, Dummy::default())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
load_scene(
|
|
||||||
session,
|
session,
|
||||||
&mut player,
|
&mut player,
|
||||||
request.entry_id,
|
req.entry_id,
|
||||||
true,
|
true,
|
||||||
Some(request.teleport_id),
|
Some(req.teleport_id),
|
||||||
)
|
)
|
||||||
.await?;
|
.await
|
||||||
|
.is_err()
|
||||||
Ok(())
|
{
|
||||||
|
res.retcode = Nbbhhpnhond::RetSceneEntryIdNotMatch as u32;
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
// getscenemapinfocsreq
|
|
||||||
pub async fn on_get_scene_map_info_cs_req(
|
pub async fn on_get_scene_map_info_cs_req(
|
||||||
sesison: &mut PlayerSession,
|
_sesison: &mut PlayerSession,
|
||||||
request: &GetSceneMapInfoCsReq,
|
req: &GetSceneMapInfoCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetSceneMapInfoScRsp,
|
||||||
let mut map_infos = Vec::<MazeMapData>::new();
|
) {
|
||||||
|
for entry_id in &req.entry_id_list {
|
||||||
for entry_id in &request.entry_id_list {
|
|
||||||
let mut map_info = MazeMapData {
|
let mut map_info = MazeMapData {
|
||||||
retcode: 0,
|
retcode: 0,
|
||||||
unlocked_chest_list: vec![
|
unlocked_chest_list: vec![
|
||||||
@@ -114,51 +84,37 @@ pub async fn on_get_scene_map_info_cs_req(
|
|||||||
map_info.lighten_section_list.push(i)
|
map_info.lighten_section_list.push(i)
|
||||||
}
|
}
|
||||||
|
|
||||||
let group_config = GAME_RESOURCES.map_entrance.get(entry_id).and_then(|v| {
|
let group_config = GAME_RES
|
||||||
GAME_RESOURCES
|
.level_output_configs
|
||||||
.level_group
|
.get(&entry_id)
|
||||||
.get(&format!("P{}_F{}", v.plane_id, v.floor_id))
|
.and_then(|v| v.iter().next());
|
||||||
});
|
|
||||||
if let Some(level) = group_config {
|
|
||||||
// add teleports
|
|
||||||
for teleport in &level.teleports {
|
|
||||||
map_info.unlocked_teleport_list.push(*teleport.0)
|
|
||||||
}
|
|
||||||
|
|
||||||
for (group_id, group) in &level.group_items {
|
if let Some((_, group_config)) = group_config {
|
||||||
|
for (_, (group_id, group)) in group_config.scenes.iter().enumerate() {
|
||||||
map_info.maze_group_list.push(MazeGroup {
|
map_info.maze_group_list.push(MazeGroup {
|
||||||
group_id: *group_id,
|
group_id: *group_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
});
|
});
|
||||||
|
|
||||||
// prop
|
for (teleport, _) in &group.teleports {
|
||||||
|
map_info.unlocked_teleport_list.push(*teleport)
|
||||||
|
}
|
||||||
|
|
||||||
for prop in &group.props {
|
for prop in &group.props {
|
||||||
|
if prop.prop_state != 8 {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
map_info.maze_prop_list.push(MazeProp {
|
map_info.maze_prop_list.push(MazeProp {
|
||||||
group_id: prop.group_id,
|
group_id: prop.group_id,
|
||||||
state: if prop.prop_state_list.contains(&PropState::CheckPointEnable) {
|
state: prop.prop_state,
|
||||||
PropState::CheckPointEnable as u32
|
config_id: prop.inst_id,
|
||||||
} else {
|
|
||||||
prop.state.clone() as u32
|
|
||||||
},
|
|
||||||
config_id: prop.id,
|
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
map_infos.push(map_info)
|
res.map_list.push(map_info)
|
||||||
}
|
}
|
||||||
|
|
||||||
sesison
|
|
||||||
.send(
|
|
||||||
CMD_GET_SCENE_MAP_INFO_SC_RSP,
|
|
||||||
GetSceneMapInfoScRsp {
|
|
||||||
retcode: 0,
|
|
||||||
map_list: map_infos,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
lazy_static! {
|
lazy_static! {
|
||||||
@@ -166,24 +122,21 @@ lazy_static! {
|
|||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_scene_entity_move_cs_req(
|
pub async fn on_scene_entity_move_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
request: &SceneEntityMoveCsReq,
|
req: &SceneEntityMoveCsReq,
|
||||||
) -> Result<()> {
|
_res: &mut SceneEntityMoveScRsp,
|
||||||
|
) {
|
||||||
let mut player = FreesrData::load().await;
|
let mut player = FreesrData::load().await;
|
||||||
let mut timestamp = NEXT_SCENE_SAVE.lock().await;
|
let mut timestamp = NEXT_SCENE_SAVE.lock().await;
|
||||||
|
|
||||||
if util::cur_timestamp_ms() <= *timestamp {
|
if util::cur_timestamp_ms() <= *timestamp {
|
||||||
session
|
return;
|
||||||
.send(CMD_SCENE_ENTITY_MOVE_SC_RSP, Dummy::default())
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
return Ok(());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// save every 5 sec
|
// save every 5 sec
|
||||||
*timestamp = util::cur_timestamp_ms() + (5 * 1000);
|
*timestamp = util::cur_timestamp_ms() + (5 * 1000);
|
||||||
|
|
||||||
for entity in &request.entity_motion_list {
|
for entity in &req.entity_motion_list {
|
||||||
if entity.entity_id != 0 {
|
if entity.entity_id != 0 {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -201,99 +154,101 @@ pub async fn on_scene_entity_move_cs_req(
|
|||||||
}
|
}
|
||||||
|
|
||||||
player.save().await;
|
player.save().await;
|
||||||
session
|
|
||||||
.send(CMD_SCENE_ENTITY_MOVE_SC_RSP, Dummy::default())
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn on_get_entered_scene_cs_req(
|
pub async fn on_get_entered_scene_cs_req(
|
||||||
session: &mut PlayerSession,
|
_session: &mut PlayerSession,
|
||||||
_: &GetEnteredSceneCsReq,
|
_req: &GetEnteredSceneCsReq,
|
||||||
) -> Result<()> {
|
res: &mut GetEnteredSceneScRsp,
|
||||||
let scenes = GAME_RESOURCES
|
) {
|
||||||
.map_entrance
|
res.entered_scene_info = GAME_RES
|
||||||
|
.level_output_configs
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|(_, v)| {
|
.map(|(_, v)| {
|
||||||
!v.finish_main_mission_list.is_empty() || !v.finish_sub_mission_list.is_empty()
|
v.iter()
|
||||||
})
|
.filter(|(_, v)| v.is_entered_scene_info)
|
||||||
.map(|(_, v)| EnteredSceneInfo {
|
.map(|(k, _)| {
|
||||||
floor_id: v.floor_id,
|
let split: Vec<_> = k.split("_").collect();
|
||||||
plane_id: v.plane_id,
|
let plane_id = &split[0][1..];
|
||||||
|
let floor_id = &split[1][1..];
|
||||||
|
EnteredSceneInfo {
|
||||||
|
floor_id: floor_id.parse().unwrap(),
|
||||||
|
plane_id: plane_id.parse().unwrap(),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.collect::<Vec<_>>()
|
||||||
})
|
})
|
||||||
|
.flatten()
|
||||||
.collect::<Vec<_>>();
|
.collect::<Vec<_>>();
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_GET_ENTERED_SCENE_SC_RSP,
|
|
||||||
GetEnteredSceneScRsp {
|
|
||||||
entered_scene_info: scenes,
|
|
||||||
retcode: 0,
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn load_scene(
|
async fn load_scene(
|
||||||
session: &mut PlayerSession,
|
session: &mut PlayerSession,
|
||||||
json: &mut FreesrData,
|
json: &mut FreesrData,
|
||||||
entry_id: u32,
|
entry_id: u32,
|
||||||
_save: bool,
|
save_scene: bool,
|
||||||
teleport_id: Option<u32>,
|
teleport_id: Option<u32>,
|
||||||
) -> Result<SceneInfo> {
|
) -> Result<SceneInfo> {
|
||||||
let enterance = GAME_RESOURCES
|
let (name, scene) = GAME_RES
|
||||||
.map_entrance
|
.level_output_configs
|
||||||
.get(&entry_id)
|
.get(&entry_id)
|
||||||
.ok_or_else(|| anyhow::format_err!("Map Entrance Not Found"))?;
|
.map(|v| v.iter().next())
|
||||||
|
.flatten()
|
||||||
|
.ok_or_else(|| {
|
||||||
|
tracing::error!("Map Entrance Not Found {}", entry_id);
|
||||||
|
anyhow::format_err!("Map Entrance Not Found {}", entry_id)
|
||||||
|
})?;
|
||||||
|
|
||||||
let plane = GAME_RESOURCES
|
let split: Vec<_> = name.split("_").collect();
|
||||||
.maze_plane
|
let plane_id = *&split[0][1..].parse::<u32>()?;
|
||||||
.get(&enterance.plane_id)
|
let floor_id = *&split[1][1..].parse::<u32>()?;
|
||||||
.ok_or_else(|| anyhow::format_err!("Map Plane Not Found"))?;
|
|
||||||
|
|
||||||
let group_config = GAME_RESOURCES
|
let mut json_pos = json.position.clone();
|
||||||
.level_group
|
|
||||||
.get(&format!("P{}_F{}", enterance.plane_id, enterance.floor_id))
|
|
||||||
.ok_or_else(|| anyhow::format_err!("Group Config Not Found"))?;
|
|
||||||
|
|
||||||
let mut position = json.position.clone();
|
|
||||||
if let Some(teleport_id) = teleport_id {
|
if let Some(teleport_id) = teleport_id {
|
||||||
if let Some(teleport) = group_config.teleports.get(&teleport_id) {
|
if let Some(teleport) = scene
|
||||||
let anchor = group_config
|
.scenes
|
||||||
.group_items
|
.iter()
|
||||||
.get(&teleport.anchor_group_id.unwrap_or_default())
|
.find_map(|(_, v)| v.teleports.get(&teleport_id))
|
||||||
.and_then(|v| v.anchors.get(&teleport.anchor_id.unwrap_or_default()));
|
{
|
||||||
if let Some(anchor) = anchor {
|
json_pos.x = teleport.pos.x;
|
||||||
position.x = (anchor.pos_x * 1000f64) as i32;
|
json_pos.y = teleport.pos.y;
|
||||||
position.y = (anchor.pos_y * 1000f64) as i32;
|
json_pos.z = teleport.pos.z;
|
||||||
position.z = (anchor.pos_z * 1000f64) as i32;
|
json_pos.rot_y = teleport.rot.y;
|
||||||
position.rot_y = (anchor.rot_y * 1000f64) as i32;
|
} else {
|
||||||
|
if let Some((_, teleport)) = scene
|
||||||
|
.scenes
|
||||||
|
.iter()
|
||||||
|
.find_map(|v| v.1.teleports.iter().next())
|
||||||
|
{
|
||||||
|
json_pos.x = teleport.pos.x;
|
||||||
|
json_pos.y = teleport.pos.y;
|
||||||
|
json_pos.z = teleport.pos.z;
|
||||||
|
json_pos.rot_y = teleport.rot.y;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let mut scene_info = SceneInfo {
|
let mut scene_info = SceneInfo {
|
||||||
floor_id: enterance.floor_id,
|
floor_id,
|
||||||
plane_id: enterance.plane_id,
|
plane_id,
|
||||||
entry_id,
|
entry_id,
|
||||||
game_mode_type: plane.plane_type as u32,
|
game_mode_type: *(&scene.plane_type) as u32,
|
||||||
leader_entity_id: 1,
|
leader_entity_id: 1,
|
||||||
world_id: plane.world_id,
|
world_id: scene.world_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let lineup_info = AvatarJson::to_lineup_info(&json.lineups);
|
let lineup_info = AvatarJson::to_lineup_info(&json.lineups);
|
||||||
let player_pos = MotionInfo {
|
let player_pos = MotionInfo {
|
||||||
// rot
|
|
||||||
rot: Some(Vector {
|
rot: Some(Vector {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: position.rot_y,
|
y: json_pos.rot_y,
|
||||||
z: 0,
|
z: 0,
|
||||||
}),
|
}),
|
||||||
// pos
|
|
||||||
pos: Some(Vector {
|
pos: Some(Vector {
|
||||||
x: position.x,
|
x: json_pos.x,
|
||||||
y: position.y,
|
y: json_pos.y,
|
||||||
z: position.z,
|
z: json_pos.z,
|
||||||
}),
|
}),
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -302,37 +257,30 @@ async fn load_scene(
|
|||||||
let mut npc_entity_id = 20_000;
|
let mut npc_entity_id = 20_000;
|
||||||
let mut monster_entity_id = 30_000;
|
let mut monster_entity_id = 30_000;
|
||||||
|
|
||||||
for (group_id, group) in &group_config.group_items {
|
for (group_id, group) in &scene.scenes {
|
||||||
let mut group_info = SceneEntityGroupInfo {
|
let mut group_info = SceneEntityGroupInfo {
|
||||||
state: 0,
|
|
||||||
group_id: *group_id,
|
group_id: *group_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
// Load Props
|
// Load Props
|
||||||
for prop in &group.props {
|
for prop in &group.props {
|
||||||
let prop_state = if prop.prop_state_list.contains(&PropState::CheckPointEnable) {
|
|
||||||
PropState::CheckPointEnable
|
|
||||||
} else {
|
|
||||||
prop.state.clone()
|
|
||||||
};
|
|
||||||
|
|
||||||
prop_entity_id += 1;
|
prop_entity_id += 1;
|
||||||
|
|
||||||
let prop_position = Position {
|
let prop_position = Position {
|
||||||
x: (prop.pos_x * 1000f64) as i32,
|
x: (prop.pos.x),
|
||||||
y: (prop.pos_y * 1000f64) as i32,
|
y: (prop.pos.y),
|
||||||
z: (prop.pos_z * 1000f64) as i32,
|
z: (prop.pos.z),
|
||||||
rot_y: (prop.rot_y * 1000f64) as i32,
|
rot_y: (prop.rot.y),
|
||||||
};
|
};
|
||||||
|
|
||||||
let entity_info = SceneEntityInfo {
|
let entity_info = SceneEntityInfo {
|
||||||
inst_id: prop.id,
|
inst_id: prop.inst_id,
|
||||||
group_id: prop.group_id,
|
group_id: prop.group_id,
|
||||||
motion: Some(prop_position.to_motion()),
|
motion: Some(prop_position.to_motion()),
|
||||||
entity: Some(Entity::Prop(ScenePropInfo {
|
entity: Some(Entity::Prop(ScenePropInfo {
|
||||||
prop_state: prop_state as u32,
|
prop_state: prop.prop_state,
|
||||||
prop_id: prop.prop_id,
|
prop_id: prop.prop_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})),
|
})),
|
||||||
entity_id: prop_entity_id,
|
entity_id: prop_entity_id,
|
||||||
@@ -343,26 +291,26 @@ async fn load_scene(
|
|||||||
|
|
||||||
// Load NPCs
|
// Load NPCs
|
||||||
for npc in &group.npcs {
|
for npc in &group.npcs {
|
||||||
if loaded_npc.contains(&(npc.npcid)) || json.avatars.contains_key(&(npc.npcid)) {
|
if loaded_npc.contains(&(npc.npc_id)) || json.avatars.contains_key(&(npc.npc_id)) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
npc_entity_id += 1;
|
npc_entity_id += 1;
|
||||||
loaded_npc.push(npc.npcid);
|
loaded_npc.push(npc.npc_id);
|
||||||
|
|
||||||
let npc_position = Position {
|
let npc_position = Position {
|
||||||
x: (npc.pos_x * 1000f64) as i32,
|
x: (npc.pos.x) as i32,
|
||||||
y: (npc.pos_y * 1000f64) as i32,
|
y: (npc.pos.y) as i32,
|
||||||
z: (npc.pos_z * 1000f64) as i32,
|
z: (npc.pos.z) as i32,
|
||||||
rot_y: (npc.rot_y * 1000f64) as i32,
|
rot_y: (npc.rot.y) as i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
let info = SceneEntityInfo {
|
let info = SceneEntityInfo {
|
||||||
inst_id: npc.id,
|
inst_id: npc.inst_id,
|
||||||
group_id: npc.group_id,
|
group_id: npc.group_id,
|
||||||
entity_id: npc_entity_id,
|
entity_id: npc_entity_id,
|
||||||
motion: Some(npc_position.to_motion()),
|
motion: Some(npc_position.to_motion()),
|
||||||
entity: Some(Entity::Npc(SceneNpcInfo {
|
entity: Some(Entity::Npc(SceneNpcInfo {
|
||||||
npc_id: npc.npcid,
|
npc_id: npc.npc_id,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
})),
|
})),
|
||||||
};
|
};
|
||||||
@@ -374,21 +322,21 @@ async fn load_scene(
|
|||||||
for monster in &group.monsters {
|
for monster in &group.monsters {
|
||||||
monster_entity_id += 1;
|
monster_entity_id += 1;
|
||||||
let monster_position = Position {
|
let monster_position = Position {
|
||||||
x: (monster.pos_x * 1000f64) as i32,
|
x: (monster.pos.x) as i32,
|
||||||
y: (monster.pos_y * 1000f64) as i32,
|
y: (monster.pos.y) as i32,
|
||||||
z: (monster.pos_z * 1000f64) as i32,
|
z: (monster.pos.z) as i32,
|
||||||
rot_y: (monster.rot_y * 1000f64) as i32,
|
rot_y: (monster.rot.y) as i32,
|
||||||
};
|
};
|
||||||
|
|
||||||
let npc_monster = SceneNpcMonsterInfo {
|
let npc_monster = SceneNpcMonsterInfo {
|
||||||
monster_id: monster.npcmonster_id,
|
monster_id: monster.monster_id,
|
||||||
event_id: monster.event_id,
|
event_id: monster.event_id,
|
||||||
world_level: 6,
|
world_level: 6,
|
||||||
..Default::default()
|
..Default::default()
|
||||||
};
|
};
|
||||||
|
|
||||||
let info = SceneEntityInfo {
|
let info = SceneEntityInfo {
|
||||||
inst_id: monster.id,
|
inst_id: monster.inst_id,
|
||||||
group_id: monster.group_id,
|
group_id: monster.group_id,
|
||||||
entity_id: monster_entity_id,
|
entity_id: monster_entity_id,
|
||||||
motion: Some(monster_position.to_motion()),
|
motion: Some(monster_position.to_motion()),
|
||||||
@@ -398,7 +346,20 @@ async fn load_scene(
|
|||||||
group_info.entity_list.push(info);
|
group_info.entity_list.push(info);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO: for now don't load group that have nothing in it
|
||||||
|
if group.props.is_empty() && group.npcs.is_empty() && group.monsters.is_empty() {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
scene_info.entity_group_list.push(group_info);
|
scene_info.entity_group_list.push(group_info);
|
||||||
|
|
||||||
|
scene_info.group_id_list.push(*group_id);
|
||||||
|
|
||||||
|
scene_info.group_state_list.push(SceneGroupState {
|
||||||
|
group_id: *group_id,
|
||||||
|
is_default: true,
|
||||||
|
state: 0,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
// load player entity
|
// load player entity
|
||||||
@@ -411,20 +372,7 @@ async fn load_scene(
|
|||||||
player_group.entity_list.push(SceneEntityInfo {
|
player_group.entity_list.push(SceneEntityInfo {
|
||||||
inst_id: 0,
|
inst_id: 0,
|
||||||
entity_id: (*slot) + 1,
|
entity_id: (*slot) + 1,
|
||||||
motion: Some(MotionInfo {
|
motion: Some(player_pos.clone()),
|
||||||
// pos
|
|
||||||
pos: Some(Vector {
|
|
||||||
x: json.position.x,
|
|
||||||
y: json.position.y,
|
|
||||||
z: json.position.z,
|
|
||||||
}),
|
|
||||||
// rot
|
|
||||||
rot: Some(Vector {
|
|
||||||
x: 0,
|
|
||||||
y: json.position.rot_y,
|
|
||||||
z: 0,
|
|
||||||
}),
|
|
||||||
}),
|
|
||||||
entity: Some(Entity::Actor(SceneActorInfo {
|
entity: Some(Entity::Actor(SceneActorInfo {
|
||||||
avatar_type: AvatarType::AvatarFormalType.into(),
|
avatar_type: AvatarType::AvatarFormalType.into(),
|
||||||
base_avatar_id: *avatar_id,
|
base_avatar_id: *avatar_id,
|
||||||
@@ -436,37 +384,22 @@ async fn load_scene(
|
|||||||
}
|
}
|
||||||
scene_info.entity_group_list.push(player_group);
|
scene_info.entity_group_list.push(player_group);
|
||||||
|
|
||||||
if _save {
|
if save_scene {
|
||||||
session
|
session
|
||||||
.send(
|
.send(EnterSceneByServerScNotify {
|
||||||
CMD_ENTER_SCENE_BY_SERVER_SC_NOTIFY,
|
scene: Some(scene_info.clone()),
|
||||||
EnterSceneByServerScNotify {
|
lineup: Some(lineup_info),
|
||||||
scene: Some(scene_info.clone()),
|
..Default::default()
|
||||||
lineup: Some(lineup_info),
|
})
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
|
||||||
|
|
||||||
session
|
|
||||||
.send(
|
|
||||||
CMD_SCENE_ENTITY_MOVE_SC_NOTIFY,
|
|
||||||
SceneEntityMoveScNotify {
|
|
||||||
entity_id: 0,
|
|
||||||
motion: Some(player_pos),
|
|
||||||
entry_id,
|
|
||||||
..Default::default()
|
|
||||||
},
|
|
||||||
)
|
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
json.scene.entry_id = entry_id;
|
json.scene.entry_id = entry_id;
|
||||||
json.scene.floor_id = enterance.floor_id;
|
json.scene.floor_id = floor_id;
|
||||||
json.scene.plane_id = enterance.plane_id;
|
json.scene.plane_id = plane_id;
|
||||||
json.position.x = position.x;
|
json.position.x = json_pos.x;
|
||||||
json.position.y = position.y;
|
json.position.y = json_pos.y;
|
||||||
json.position.z = position.z;
|
json.position.z = json_pos.z;
|
||||||
json.position.rot_y = position.rot_y;
|
json.position.rot_y = json_pos.rot_y;
|
||||||
json.save().await;
|
json.save().await;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,117 +0,0 @@
|
|||||||
// use super::*;
|
|
||||||
|
|
||||||
// static TUTORIAL_IDS: [u32; 463] = [
|
|
||||||
// 1001, 1002, 1003, 1004, 1005, 1007, 1008, 1010, 2000, 2001, 2002, 2003, 2004, 2008, 2010, 2011,
|
|
||||||
// 2012, 2013, 3001, 3002, 3003, 3004, 3005, 3006, 3008, 3009, 3010, 3011, 3012, 3202, 4002, 4003,
|
|
||||||
// 4004, 4005, 4006, 4007, 4008, 4009, 4010, 4011, 4012, 4013, 4014, 4015, 4016, 4017, 4018, 4019,
|
|
||||||
// 4020, 4021, 4022, 4023, 4024, 4025, 4026, 4027, 4028, 4029, 4030, 4031, 4032, 4033, 4034, 4036,
|
|
||||||
// 4037, 4038, 4039, 4040, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012,
|
|
||||||
// 5013, 5014, 5015, 5016, 5017, 5018, 5019, 5021, 5022, 5023, 5024, 5025, 5026, 5027, 5028, 5029,
|
|
||||||
// 5030, 5031, 5032, 5033, 5034, 5035, 5036, 5038, 5039, 5041, 5044, 5045, 5046, 5047, 5048, 5049,
|
|
||||||
// 5050, 5051, 5052, 5053, 5054, 5055, 5056, 5057, 5058, 5059, 5060, 5061, 5062, 5063, 5064, 5065,
|
|
||||||
// 5070, 5071, 5072, 5073, 5074, 5075, 5077, 5078, 5079, 5081, 5082, 5083, 5084, 5085, 5086, 5087,
|
|
||||||
// 5088, 5089, 5090, 5091, 5092, 5093, 5094, 5095, 5096, 5097, 5098, 5099, 5100, 5101, 5102, 5103,
|
|
||||||
// 5104, 5105, 5106, 5107, 5108, 5109, 5110, 5111, 5112, 5113, 5114, 5115, 5116, 5130, 5131, 5132,
|
|
||||||
// 5133, 5134, 5135, 5140, 5141, 5142, 5143, 5144, 5145, 5146, 5150, 5151, 5152, 5153, 5154, 5155,
|
|
||||||
// 5156, 5157, 5158, 5159, 5160, 5161, 5162, 5172, 5173, 5174, 5175, 5176, 5177, 5178, 5179, 5180,
|
|
||||||
// 5181, 5182, 5183, 5184, 5185, 5186, 5187, 5188, 5189, 5190, 5191, 5192, 5193, 5194, 5195, 5196,
|
|
||||||
// 5197, 5198, 5199, 5200, 5201, 5202, 5301, 5302, 5303, 5304, 5305, 5306, 5308, 5309, 5310, 5322,
|
|
||||||
// 5326, 5312, 5311, 5313, 5307, 5314, 5315, 5316, 5317, 5318, 5319, 5320, 5321, 5323, 5324, 5325,
|
|
||||||
// 5350, 5387, 5352, 5388, 5355, 5360, 5361, 5356, 5357, 5358, 5359, 5351, 5365, 5366, 5367, 5368,
|
|
||||||
// 5375, 5376, 5377, 5389, 5374, 5369, 5370, 5371, 5372, 5373, 5390, 5380, 5381, 5400, 5382, 5383,
|
|
||||||
// 5392, 5378, 5384, 5393, 5408, 5394, 5395, 5391, 5385, 5397, 5398, 5399, 5386, 5401, 5402, 5403,
|
|
||||||
// 5404, 5405, 5406, 5407, 5409, 5410, 5510, 5511, 7001, 7002, 7003, 7004, 7005, 7007, 7008, 7009,
|
|
||||||
// 9001, 9002, 9003, 9004, 9005, 9006, 9007, 9008, 9009, 9010, 9011, 9012, 9013, 9014, 9015, 9016,
|
|
||||||
// 9017, 9018, 9019, 9020, 9021, 9022, 9023, 9024, 9025, 9026, 9027, 9028, 9029, 9030, 9031, 9032,
|
|
||||||
// 9033, 9034, 9035, 9036, 9037, 9038, 9039, 9040, 9041, 9042, 9043, 9044, 9045, 9046, 9047, 9048,
|
|
||||||
// 9049, 9050, 9051, 9052, 9053, 9201, 9202, 9203, 9204, 9205, 9206, 9207, 9208, 9209, 9210, 9211,
|
|
||||||
// 9212, 9213, 9214, 9301, 9302, 9303, 9304, 9305, 9306, 9307, 9308, 9309, 9310, 9311, 9313, 9314,
|
|
||||||
// 9315, 9316, 9317, 9318, 9319, 9321, 9322, 9323, 9324, 9325, 9801, 9802, 9803, 9804, 9805, 9806,
|
|
||||||
// 9807, 9808, 9809, 9810, 9811, 9812, 9813, 9814, 9816, 9817, 9818, 9819, 9815, 9820, 9901, 9903,
|
|
||||||
// 9904, 9905, 9906, 9907, 9908, 9610, 9611, 9612, 9613, 9614, 9615, 9616, 9617, 9618, 9619, 9620,
|
|
||||||
// 9621, 9622, 9623, 9624, 9625, 9626, 9627, 9628, 9629, 9630, 9631, 9701, 9702, 9703, 9704,
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// static GUIDE_IDS: [u32; 326] = [
|
|
||||||
// 1101, 1102, 1103, 1104, 1105, 1108, 1109, 1116, 1117, 1118, 2006, 2007, 2008, 2105, 2106, 2107,
|
|
||||||
// 2200, 2201, 2202, 2203, 2204, 2205, 2206, 2207, 2208, 2209, 2210, 2211, 2212, 2213, 2214, 2215,
|
|
||||||
// 2216, 2217, 2218, 2219, 2220, 2221, 2222, 3007, 3105, 3106, 3107, 3108, 3109, 3201, 3202, 3203,
|
|
||||||
// 3204, 3205, 3206, 3207, 3208, 3209, 3210, 3211, 3212, 3213, 3214, 3215, 4001, 4101, 4102, 4103,
|
|
||||||
// 4104, 4105, 4106, 4107, 4109, 4110, 5101, 5102, 5103, 5104, 5105, 5106, 6001, 6002, 6003, 6004,
|
|
||||||
// 6008, 6009, 6010, 6011, 6012, 6014, 6015, 6018, 6020, 6021, 6023, 6024, 6025, 6027, 6028, 6029,
|
|
||||||
// 6030, 6031, 6032, 6033, 6034, 6035, 6036, 6037, 6038, 6039, 6040, 6041, 6042, 6043, 6044, 6045,
|
|
||||||
// 6046, 6047, 6048, 6049, 6050, 6051, 6052, 6053, 6054, 6055, 6056, 6057, 6058, 6059, 6060, 6061,
|
|
||||||
// 6062, 6063, 6064, 6065, 6066, 6067, 6068, 6069, 6070, 6071, 6072, 6073, 6074, 6075, 6076, 6077,
|
|
||||||
// 6078, 6079, 6080, 6081, 6082, 6083, 6085, 6086, 6087, 6088, 6089, 6090, 6091, 6092, 6093, 6094,
|
|
||||||
// 6095, 6096, 6097, 6098, 6099, 6100, 6101, 6102, 6103, 6104, 6105, 6106, 6107, 6108, 6109, 6110,
|
|
||||||
// 6111, 7090, 7091, 7092, 7501, 7502, 7503, 7504, 7506, 7507, 7508, 7509, 7511, 7514, 7515, 8001,
|
|
||||||
// 8002, 8003, 8004, 8006, 8007, 8008, 8010, 8011, 8012, 8013, 8014, 8015, 8016, 8017, 8018, 8019,
|
|
||||||
// 8020, 8021, 8022, 8023, 8024, 8025, 8026, 8027, 8028, 8038, 8039, 8047, 8050, 8051, 8052, 8055,
|
|
||||||
// 8056, 8057, 8058, 8059, 8061, 8062, 8063, 8064, 8065, 8066, 8067, 8069, 8070, 8072, 8073, 8074,
|
|
||||||
// 8075, 8076, 8078, 8079, 8080, 8090, 8091, 8092, 8093, 8094, 8095, 8096, 8100, 8101, 8102, 8103,
|
|
||||||
// 8104, 8105, 8106, 8107, 8108, 8109, 8110, 8111, 8112, 8113, 8122, 8123, 8124, 8140, 8141, 8142,
|
|
||||||
// 8143, 8144, 8145, 8146, 9101, 9102, 9103, 9104, 9105, 9107, 9108, 9109, 9110, 9111, 9112, 9113,
|
|
||||||
// 9114, 9115, 9116, 9117, 9118, 9119, 9120, 9201, 9202, 9203, 9204, 9205, 9206, 9207, 9208, 9209,
|
|
||||||
// 9210, 9211, 9212, 9301, 9303, 9304, 9305, 9601, 9602, 9603, 9604, 9605, 9701, 9702, 31001,
|
|
||||||
// 31102, 31103, 31105, 31106, 31109, 31204, 31206,
|
|
||||||
// ];
|
|
||||||
|
|
||||||
// pub async fn on_get_tutorial_cs_req(
|
|
||||||
// session: &mut PlayerSession,
|
|
||||||
// _body: &GetTutorialCsReq,
|
|
||||||
// ) -> Result<()> {
|
|
||||||
// session
|
|
||||||
// .send(
|
|
||||||
// CMD_GET_TUTORIAL_SC_RSP,
|
|
||||||
// GetTutorialScRsp {
|
|
||||||
// retcode: 0,
|
|
||||||
// tutorial_list: TUTORIAL_IDS
|
|
||||||
// .iter()
|
|
||||||
// .map(|id| Tutorial {
|
|
||||||
// id: *id,
|
|
||||||
// status: TutorialStatus::TutorialFinish.into(),
|
|
||||||
// })
|
|
||||||
// .collect(),
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// .await
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub async fn on_get_tutorial_guide_cs_req(
|
|
||||||
// session: &mut PlayerSession,
|
|
||||||
// _body: &GetTutorialGuideCsReq,
|
|
||||||
// ) -> Result<()> {
|
|
||||||
// session
|
|
||||||
// .send(
|
|
||||||
// CMD_GET_TUTORIAL_GUIDE_SC_RSP,
|
|
||||||
// GetTutorialGuideScRsp {
|
|
||||||
// retcode: 0,
|
|
||||||
// tutorial_guide_list: GUIDE_IDS
|
|
||||||
// .iter()
|
|
||||||
// .map(|id| TutorialGuide {
|
|
||||||
// id: *id,
|
|
||||||
// status: TutorialStatus::TutorialFinish.into(),
|
|
||||||
// })
|
|
||||||
// .collect(),
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// .await
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub async fn on_unlock_tutorial_guide_cs_req(
|
|
||||||
// session: &mut PlayerSession,
|
|
||||||
// body: &UnlockTutorialGuideCsReq,
|
|
||||||
// ) -> Result<()> {
|
|
||||||
// session
|
|
||||||
// .send(
|
|
||||||
// CMD_UNLOCK_TUTORIAL_GUIDE_SC_RSP,
|
|
||||||
// UnlockTutorialGuideScRsp {
|
|
||||||
// retcode: 0,
|
|
||||||
// tutorial_guide: Some(TutorialGuide {
|
|
||||||
// id: body.group_id,
|
|
||||||
// status: TutorialStatus::TutorialUnlock.into(),
|
|
||||||
// }),
|
|
||||||
// },
|
|
||||||
// )
|
|
||||||
// .await
|
|
||||||
// }
|
|
||||||
@@ -4,8 +4,6 @@ mod handlers;
|
|||||||
mod packet;
|
mod packet;
|
||||||
mod session;
|
mod session;
|
||||||
mod tools;
|
mod tools;
|
||||||
mod tools_res;
|
|
||||||
|
|
||||||
|
|
||||||
pub use packet::NetPacket;
|
pub use packet::NetPacket;
|
||||||
pub use session::PlayerSession;
|
pub use session::PlayerSession;
|
||||||
|
|||||||
@@ -5,6 +5,28 @@ use tokio::net::TcpStream;
|
|||||||
use tracing::Instrument;
|
use tracing::Instrument;
|
||||||
|
|
||||||
use proto::*;
|
use proto::*;
|
||||||
|
#[allow(unused_imports)]
|
||||||
|
use proto::{
|
||||||
|
CmdActivityType::*, CmdAdventureType::*, CmdAetherDivideType::*, CmdAlleyType::*,
|
||||||
|
CmdArchiveType::*, CmdAvatarType::*, CmdBattleCollegeType::*, CmdBattlePassType::*,
|
||||||
|
CmdBattleType::*, CmdBoxingClubType::*, CmdChallengeType::*, CmdChatType::*,
|
||||||
|
CmdChessRogueType::*, CmdClockParkType::*, CmdContentPackageType::*, CmdDailyActiveType::*,
|
||||||
|
CmdDrinkMakerType::*, CmdExpeditionType::*, CmdFantasticStoryActivityType::*,
|
||||||
|
CmdFeverTimeActivityType::*, CmdFightActivityType::*, CmdFightMathc3Type::*, CmdFightType::*,
|
||||||
|
CmdFriendType::*, CmdGachaType::*, CmdHeartdialType::*, CmdHeliobusType::*, CmdItemType::*,
|
||||||
|
CmdJukeboxType::*, CmdLineupType::*, CmdLobbyType::*, CmdMailType::*, CmdMapRotationType::*,
|
||||||
|
CmdMatchThreeModuleType::*, CmdMatchType::*, CmdMessageType::*, CmdMiscModuleType::*,
|
||||||
|
CmdMissionType::*, CmdMonopolyType::*, CmdMultiplayerType::*, CmdMultipleDropType::*,
|
||||||
|
CmdMuseumType::*, CmdOfferingType::*, CmdPamMissionType::*, CmdPhoneType::*,
|
||||||
|
CmdPlayerBoardType::*, CmdPlayerReturnType::*, CmdPlayerSync::*, CmdPlayerType::*,
|
||||||
|
CmdPlotType::*, CmdPunkLordType::*, CmdQuestType::*, CmdRaidCollectionType::*, CmdRaidType::*,
|
||||||
|
CmdRedDotType::*, CmdReplayType::*, CmdRndOptionType::*, CmdRogueCommonType::*,
|
||||||
|
CmdRogueEndless::*, CmdRogueModifierType::*, CmdRogueTournType::*, CmdRogueType::*,
|
||||||
|
CmdRollShopType::*, CmdSceneType::*, CmdServerPrefsType::*, CmdShopType::*, CmdSpaceZooType::*,
|
||||||
|
CmdStarFightType::*, CmdStoryLineType::*, CmdStrongChallengeActivityType::*,
|
||||||
|
CmdTalkRewardType::*, CmdTelevisionActivityType::*, CmdTextJoinType::*, CmdTrainVisitorType::*,
|
||||||
|
CmdTreasureDungeonType::*, CmdTutorialType::*, CmdWaypointType::*, CmdWolfBroType::*,
|
||||||
|
};
|
||||||
|
|
||||||
use super::handlers::*;
|
use super::handlers::*;
|
||||||
use super::PlayerSession;
|
use super::PlayerSession;
|
||||||
@@ -58,12 +80,16 @@ impl NetPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
macro_rules! trait_handler {
|
macro_rules! trait_handler {
|
||||||
($($name:ident $cmd_type:expr;)*) => {
|
($($name:tt;)*) => {
|
||||||
pub trait CommandHandler {
|
pub trait CommandHandler {
|
||||||
$(
|
$(
|
||||||
paste! {
|
paste! {
|
||||||
async fn [<on_$name:snake>](session: &mut PlayerSession, body: &$name) -> Result<()> {
|
async fn [<on_$name:snake _cs_req>](session: &mut PlayerSession, request: &[<$name CsReq>]) -> Result<()> {
|
||||||
[<on_$name:snake>](session, body).await
|
let mut response = proto::[<$name ScRsp>]::default();
|
||||||
|
let _ = [<on_$name:snake _cs_req>](session, request, &mut response).await;
|
||||||
|
session.send(response).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
)*
|
)*
|
||||||
@@ -74,12 +100,14 @@ macro_rules! trait_handler {
|
|||||||
session.send_dummy_response(cmd_type).await?;
|
session.send_dummy_response(cmd_type).await?;
|
||||||
return Ok(());
|
return Ok(());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
match cmd_type {
|
match cmd_type {
|
||||||
$(
|
$(
|
||||||
$cmd_type => {
|
cmd_type if cmd_type == paste! { [<Cmd$name CsReq>] as u16 } => {
|
||||||
let body = $name::decode(&mut &payload[..])?;
|
let body = paste! { proto::[<$name CsReq>]::decode(&mut &payload[..])? };
|
||||||
paste! {
|
paste! {
|
||||||
Self::[<on_$name:snake>](session, &body)
|
Self::[<on_$name:snake _cs_req>](session, &body)
|
||||||
.instrument(tracing::info_span!(stringify!([<on_$name:snake>]), cmd_type = cmd_type))
|
.instrument(tracing::info_span!(stringify!([<on_$name:snake>]), cmd_type = cmd_type))
|
||||||
.await
|
.await
|
||||||
}
|
}
|
||||||
@@ -96,59 +124,54 @@ macro_rules! trait_handler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
trait_handler! {
|
trait_handler! {
|
||||||
PlayerGetTokenCsReq 56; // PlayerGetTokenScRsp
|
PlayerGetToken;
|
||||||
PlayerLoginCsReq 68; // PlayerLoginScRsp, PlayerBasicInfo
|
PlayerLogin;
|
||||||
GetMissionStatusCsReq 1224; // GetMissionStatusScRsp, Mission
|
GetMissionStatus;
|
||||||
GetBasicInfoCsReq 40; // GetBasicInfoScRsp, PlayerSettingInfo
|
GetBasicInfo;
|
||||||
GetMultiPathAvatarInfoCsReq 27;
|
GetMultiPathAvatarInfo;
|
||||||
GetAvatarDataCsReq 368; // GetAvatarDataScRsp, Avatar
|
GetAvatarData;
|
||||||
GetAllLineupDataCsReq 724; // GetAllLineupDataScRsp, LineupInfo, ExtraLineupType, LineupAvatar, AmountInfo
|
GetAllLineupData;
|
||||||
GetCurLineupDataCsReq 711; // GetCurLineupDataScRsp
|
GetCurLineupData;
|
||||||
GetCurSceneInfoCsReq 1439; // GetCurSceneInfoScRsp, SceneInfo
|
GetCurSceneInfo;
|
||||||
PlayerHeartBeatCsReq 31; // PlayerHeartBeatScRsp
|
PlayerHeartBeat;
|
||||||
|
|
||||||
// // Tutorial (dummy!)
|
|
||||||
// GetTutorialGuideCsReq 1691;
|
|
||||||
// UnlockTutorialGuideCsReq 1630;
|
|
||||||
// GetTutorialCsReq 1661;
|
|
||||||
|
|
||||||
// Entity move (dummy!)
|
// Entity move (dummy!)
|
||||||
SceneEntityMoveCsReq 1468;
|
SceneEntityMove;
|
||||||
|
|
||||||
// Inventory (dummy!)
|
// Inventory (dummy!)
|
||||||
GetBagCsReq 568;
|
GetBag;
|
||||||
GetArchiveDataCsReq 2368;
|
GetArchiveData;
|
||||||
DressAvatarCsReq 351;
|
DressAvatar;
|
||||||
TakeOffEquipmentCsReq 399;
|
TakeOffEquipment;
|
||||||
DressRelicAvatarCsReq 334;
|
DressRelicAvatar;
|
||||||
TakeOffRelicCsReq 398;
|
TakeOffRelic;
|
||||||
|
|
||||||
// Chat (dummy!)
|
// Chat (dummy!)
|
||||||
SendMsgCsReq 3968;
|
SendMsg;
|
||||||
GetPrivateChatHistoryCsReq 3956;
|
GetPrivateChatHistory;
|
||||||
GetFriendListInfoCsReq 2968;
|
GetFriendListInfo;
|
||||||
GetFriendLoginInfoCsReq 2969;
|
GetFriendLoginInfo;
|
||||||
|
|
||||||
// In-game lineup
|
// In-game lineup
|
||||||
JoinLineupCsReq 756;
|
JoinLineup;
|
||||||
ChangeLineupLeaderCsReq 748;
|
ChangeLineupLeader;
|
||||||
ReplaceLineupCsReq 790;
|
ReplaceLineup;
|
||||||
QuitLineupCsReq 739;
|
QuitLineup;
|
||||||
|
|
||||||
// Battle
|
// Battle
|
||||||
StartCocoonStageCsReq 1445;
|
StartCocoonStage;
|
||||||
PveBattleResultCsReq 168;
|
PveBattleResult;
|
||||||
SceneCastSkillCsReq 1456;
|
SceneCastSkill;
|
||||||
|
|
||||||
// Teleport
|
// Teleport
|
||||||
GetEnteredSceneCsReq 1427;
|
GetEnteredScene;
|
||||||
GetSceneMapInfoCsReq 1436;
|
GetSceneMapInfo;
|
||||||
EnterSceneCsReq 1486;
|
EnterScene;
|
||||||
|
|
||||||
// Optional
|
// Optional
|
||||||
GetMailCsReq 868;
|
GetMail;
|
||||||
GetGachaInfoCsReq 1968;
|
GetGachaInfo;
|
||||||
DoGachaCsReq 1911;
|
DoGacha;
|
||||||
// GetQuestDataCsReq 961;
|
PlayerLoginFinish;
|
||||||
PlayerLoginFinishCsReq 73;
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use prost::Message;
|
use prost::Message;
|
||||||
|
use proto::CmdID;
|
||||||
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||||
|
|
||||||
use super::{packet::CommandHandler, NetPacket};
|
use super::{packet::CommandHandler, NetPacket};
|
||||||
@@ -20,12 +21,12 @@ impl PlayerSession {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn send(&mut self, cmd_type: u16, body: impl Message) -> Result<()> {
|
pub async fn send(&mut self, body: impl Message + CmdID) -> Result<()> {
|
||||||
let mut buf = Vec::new();
|
let mut buf = Vec::new();
|
||||||
body.encode(&mut buf)?;
|
body.encode(&mut buf)?;
|
||||||
|
|
||||||
let payload: Vec<u8> = NetPacket {
|
let payload: Vec<u8> = NetPacket {
|
||||||
cmd_type,
|
cmd_type: body.get_cmd_id(),
|
||||||
head: Vec::new(),
|
head: Vec::new(),
|
||||||
body: buf,
|
body: buf,
|
||||||
}
|
}
|
||||||
|
|||||||
+34
-12
@@ -12,7 +12,6 @@ pub struct AvatarJson {
|
|||||||
pub data: AvatarData,
|
pub data: AvatarData,
|
||||||
pub level: u32,
|
pub level: u32,
|
||||||
pub promotion: u32,
|
pub promotion: u32,
|
||||||
// pub rank: u32,
|
|
||||||
#[serde(alias = "use_technique")]
|
#[serde(alias = "use_technique")]
|
||||||
#[serde(alias = "useTechnique")]
|
#[serde(alias = "useTechnique")]
|
||||||
pub techniques: Vec<u32>,
|
pub techniques: Vec<u32>,
|
||||||
@@ -32,7 +31,6 @@ impl AvatarJson {
|
|||||||
pub fn to_avatar_proto(&self, lightcone: Option<&Lightcone>, relics: Vec<&Relic>) -> Avatar {
|
pub fn to_avatar_proto(&self, lightcone: Option<&Lightcone>, relics: Vec<&Relic>) -> Avatar {
|
||||||
Avatar {
|
Avatar {
|
||||||
base_avatar_id: self.avatar_id,
|
base_avatar_id: self.avatar_id,
|
||||||
exp: 0,
|
|
||||||
level: self.level,
|
level: self.level,
|
||||||
promotion: self.promotion,
|
promotion: self.promotion,
|
||||||
rank: self.data.rank,
|
rank: self.data.rank,
|
||||||
@@ -68,7 +66,7 @@ impl AvatarJson {
|
|||||||
) -> (BattleAvatar, Vec<BattleBuff>) {
|
) -> (BattleAvatar, Vec<BattleBuff>) {
|
||||||
let battle_avatar = BattleAvatar {
|
let battle_avatar = BattleAvatar {
|
||||||
index,
|
index,
|
||||||
avatar_type: AvatarType::AvatarFormalType.into(),
|
avatar_type: AvatarType::AvatarUpgradeAvailableType.into(),
|
||||||
id: self.avatar_id,
|
id: self.avatar_id,
|
||||||
level: self.level,
|
level: self.level,
|
||||||
rank: self.data.rank,
|
rank: self.data.rank,
|
||||||
@@ -358,6 +356,8 @@ pub struct BattleConfig {
|
|||||||
pub cycle_count: u32,
|
pub cycle_count: u32,
|
||||||
pub path_resonance_id: u32,
|
pub path_resonance_id: u32,
|
||||||
pub custom_stats: Vec<SubAffix>,
|
pub custom_stats: Vec<SubAffix>,
|
||||||
|
#[serde(default)]
|
||||||
|
pub scepters: Vec<RogueMagicScepter>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Default for BattleConfig {
|
impl Default for BattleConfig {
|
||||||
@@ -374,6 +374,7 @@ impl Default for BattleConfig {
|
|||||||
cycle_count: Default::default(),
|
cycle_count: Default::default(),
|
||||||
path_resonance_id: Default::default(),
|
path_resonance_id: Default::default(),
|
||||||
custom_stats: Default::default(),
|
custom_stats: Default::default(),
|
||||||
|
scepters: Default::default(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -429,6 +430,29 @@ impl BattleBuffJson {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Eq, PartialEq, Default)]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum RogueMagicComponentType {
|
||||||
|
Passive = 3,
|
||||||
|
#[default]
|
||||||
|
Active = 4,
|
||||||
|
Attach = 5,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||||
|
pub struct RogueMagicScepter {
|
||||||
|
pub level: u32,
|
||||||
|
pub id: u32,
|
||||||
|
pub components: Vec<RogueMagicComponent>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Serialize, Deserialize, Clone, Default)]
|
||||||
|
pub struct RogueMagicComponent {
|
||||||
|
pub id: u32,
|
||||||
|
pub level: u32,
|
||||||
|
pub component_type: RogueMagicComponentType,
|
||||||
|
}
|
||||||
|
|
||||||
// SCENE
|
// SCENE
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct Scene {
|
pub struct Scene {
|
||||||
@@ -463,13 +487,11 @@ impl Position {
|
|||||||
|
|
||||||
pub fn to_motion(&self) -> MotionInfo {
|
pub fn to_motion(&self) -> MotionInfo {
|
||||||
MotionInfo {
|
MotionInfo {
|
||||||
// rot
|
|
||||||
rot: Some(Vector {
|
rot: Some(Vector {
|
||||||
x: 0,
|
x: 0,
|
||||||
y: self.rot_y,
|
y: self.rot_y,
|
||||||
z: 0,
|
z: 0,
|
||||||
}),
|
}),
|
||||||
// pos
|
|
||||||
pos: Some(Vector {
|
pos: Some(Vector {
|
||||||
x: self.x,
|
x: self.x,
|
||||||
y: self.y,
|
y: self.y,
|
||||||
@@ -488,15 +510,15 @@ pub struct FreesrData {
|
|||||||
#[serde(default)]
|
#[serde(default)]
|
||||||
pub battle_config: BattleConfig,
|
pub battle_config: BattleConfig,
|
||||||
|
|
||||||
#[serde(default)]
|
#[serde(default, skip_serializing)]
|
||||||
pub lineups: BTreeMap<u32, u32>,
|
pub lineups: BTreeMap<u32, u32>,
|
||||||
#[serde(default)]
|
#[serde(default, skip_serializing)]
|
||||||
pub position: Position,
|
pub position: Position,
|
||||||
#[serde(default)]
|
#[serde(default, skip_serializing)]
|
||||||
pub scene: Scene,
|
pub scene: Scene,
|
||||||
#[serde(default)]
|
#[serde(default, skip_serializing)]
|
||||||
pub main_character: MultiPathAvatar,
|
pub main_character: MultiPathAvatar,
|
||||||
#[serde(default)]
|
#[serde(default, skip_serializing)]
|
||||||
pub march_type: MultiPathAvatar,
|
pub march_type: MultiPathAvatar,
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -517,7 +539,7 @@ pub struct Persistent {
|
|||||||
impl Default for Persistent {
|
impl Default for Persistent {
|
||||||
fn default() -> Self {
|
fn default() -> Self {
|
||||||
let mut lineups = BTreeMap::<u32, u32>::new();
|
let mut lineups = BTreeMap::<u32, u32>::new();
|
||||||
lineups.insert(0, 8006);
|
lineups.insert(0, 8001);
|
||||||
lineups.insert(1, 0);
|
lineups.insert(1, 0);
|
||||||
lineups.insert(2, 0);
|
lineups.insert(2, 0);
|
||||||
lineups.insert(3, 0);
|
lineups.insert(3, 0);
|
||||||
@@ -624,7 +646,7 @@ impl FreesrData {
|
|||||||
|
|
||||||
async fn verify_lineup(&mut self) {
|
async fn verify_lineup(&mut self) {
|
||||||
if self.lineups.is_empty() {
|
if self.lineups.is_empty() {
|
||||||
self.lineups = BTreeMap::<u32, u32>::from([(0, 8006), (1, 0), (2, 0), (3, 0)])
|
self.lineups = BTreeMap::<u32, u32>::from([(0, 8001), (1, 0), (2, 0), (3, 0)])
|
||||||
} else if self.lineups.len() < 4 {
|
} else if self.lineups.len() < 4 {
|
||||||
for i in self.lineups.len()..4 {
|
for i in self.lineups.len()..4 {
|
||||||
self.lineups.insert(i as u32, 0);
|
self.lineups.insert(i as u32, 0);
|
||||||
|
|||||||
@@ -1,345 +0,0 @@
|
|||||||
use lazy_static::lazy_static;
|
|
||||||
use serde::{Deserialize, Serialize};
|
|
||||||
use serde_json::Value;
|
|
||||||
use std::collections::HashMap;
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelGroup {
|
|
||||||
#[serde(rename = "GroupGUID")]
|
|
||||||
pub group_guid: String,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "LoadSide")]
|
|
||||||
pub load_side: LoadSide,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "LoadOnInitial")]
|
|
||||||
pub load_on_initial: bool,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "AnchorList")]
|
|
||||||
pub anchor_list: Vec<LevelAnchor>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "MonsterList")]
|
|
||||||
pub monster_list: Vec<LevelMonster>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PropList")]
|
|
||||||
pub prop_list: Vec<LevelProp>,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "NPCList")]
|
|
||||||
pub npc_list: Vec<LevelNPC>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelProp {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32, // need
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "Category")]
|
|
||||||
pub category: String,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "GroupName")]
|
|
||||||
pub group_name: String,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "LoadSide")]
|
|
||||||
pub load_side: Option<LoadSide>, // need
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosX")]
|
|
||||||
pub pos_x: f64, // n
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosY")]
|
|
||||||
pub pos_y: f64, // n
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosZ")]
|
|
||||||
pub pos_z: f64, // n
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "RotY")]
|
|
||||||
pub rot_y: f64, // n
|
|
||||||
#[serde(rename = "PropID")]
|
|
||||||
pub prop_id: u32, // n
|
|
||||||
#[serde(rename = "AnchorID")]
|
|
||||||
pub anchor_id: Option<u32>, // n
|
|
||||||
#[serde(rename = "AnchorGroupID")]
|
|
||||||
pub anchor_group_id: Option<u32>, // n
|
|
||||||
#[serde(rename = "MappingInfoID")]
|
|
||||||
pub mapping_info_id: Option<u32>, // n
|
|
||||||
|
|
||||||
#[serde(rename = "InitLevelGraph")]
|
|
||||||
pub init_level_graph: Option<String>,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "State")]
|
|
||||||
pub state: PropState,
|
|
||||||
|
|
||||||
#[serde(default)]
|
|
||||||
pub prop_state_list: Vec<PropState>,
|
|
||||||
#[serde(default)]
|
|
||||||
pub group_id: u32,
|
|
||||||
#[serde(rename = "IsDelete")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub is_delete: bool, // n
|
|
||||||
#[serde(rename = "IsClientOnly")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub client_only: bool, // n
|
|
||||||
|
|
||||||
// #[serde(default)]
|
|
||||||
// pub is_door: bool,
|
|
||||||
// #[serde(default)]
|
|
||||||
// pub is_chest: bool,
|
|
||||||
#[serde(default)]
|
|
||||||
pub __test_field: String,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelAnchor {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosX")]
|
|
||||||
pub pos_x: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosY")]
|
|
||||||
pub pos_y: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosZ")]
|
|
||||||
pub pos_z: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "RotY")]
|
|
||||||
pub rot_y: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
pub group_id: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelNPC {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosX")]
|
|
||||||
pub pos_x: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosY")]
|
|
||||||
pub pos_y: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosZ")]
|
|
||||||
pub pos_z: f64,
|
|
||||||
#[serde(rename = "Name")]
|
|
||||||
pub name: String,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "RotY")]
|
|
||||||
pub rot_y: f64,
|
|
||||||
#[serde(rename = "NPCID")]
|
|
||||||
pub npcid: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
pub group_id: u32,
|
|
||||||
#[serde(rename = "IsDelete")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub is_delete: bool,
|
|
||||||
#[serde(rename = "IsClientOnly")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub client_only: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelMonster {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "RotY")]
|
|
||||||
pub rot_y: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosX")]
|
|
||||||
pub pos_x: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosY")]
|
|
||||||
pub pos_y: f64,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "PosZ")]
|
|
||||||
pub pos_z: f64,
|
|
||||||
#[serde(rename = "NPCMonsterID")]
|
|
||||||
pub npcmonster_id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "EventID")]
|
|
||||||
pub event_id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
pub group_id: u32,
|
|
||||||
#[serde(rename = "IsDelete")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub is_delete: bool,
|
|
||||||
#[serde(rename = "IsClientOnly")]
|
|
||||||
#[serde(default)]
|
|
||||||
pub client_only: bool,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Copy)]
|
|
||||||
pub enum LoadSide {
|
|
||||||
Client = 0,
|
|
||||||
Server = 1,
|
|
||||||
Unk = 2,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for LoadSide {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Client
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct LevelFloor {
|
|
||||||
pub floor_id: u32,
|
|
||||||
pub floor_name: String,
|
|
||||||
pub start_group_index: u32,
|
|
||||||
pub start_anchor_id: u32,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct MapEntrance {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32,
|
|
||||||
#[serde(default)]
|
|
||||||
#[serde(rename = "EntranceType")]
|
|
||||||
pub entrance_type: PlaneType,
|
|
||||||
#[serde(rename = "PlaneID")]
|
|
||||||
pub plane_id: u32,
|
|
||||||
#[serde(rename = "FloorID")]
|
|
||||||
pub floor_id: u32,
|
|
||||||
#[serde(rename = "BeginMainMissionList")]
|
|
||||||
pub begin_main_mission_list: Vec<Value>,
|
|
||||||
#[serde(rename = "FinishMainMissionList")]
|
|
||||||
pub finish_main_mission_list: Vec<Value>,
|
|
||||||
#[serde(rename = "FinishSubMissionList")]
|
|
||||||
pub finish_sub_mission_list: Vec<Value>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct MazePlane {
|
|
||||||
#[serde(rename = "PlaneID")]
|
|
||||||
pub plane_id: u32,
|
|
||||||
#[serde(rename = "PlaneType")]
|
|
||||||
pub plane_type: PlaneType,
|
|
||||||
#[serde(rename = "SubType")]
|
|
||||||
pub sub_type: u32,
|
|
||||||
#[serde(rename = "MazePoolType")]
|
|
||||||
pub maze_pool_type: u32,
|
|
||||||
#[serde(rename = "WorldID")]
|
|
||||||
pub world_id: u32,
|
|
||||||
#[serde(rename = "StartFloorID")]
|
|
||||||
pub start_floor_id: u32,
|
|
||||||
#[serde(rename = "FloorIDList")]
|
|
||||||
pub floor_idlist: Vec<u32>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone, PartialEq, Copy)]
|
|
||||||
pub enum PlaneType {
|
|
||||||
Unknown = 0,
|
|
||||||
Maze = 2,
|
|
||||||
Train = 3,
|
|
||||||
Challenge = 4,
|
|
||||||
Rogue = 5,
|
|
||||||
Raid = 6,
|
|
||||||
AetherDivide = 7,
|
|
||||||
TrialActivity = 8,
|
|
||||||
#[serde(other)]
|
|
||||||
Town = 1,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl Default for PlaneType {
|
|
||||||
fn default() -> Self {
|
|
||||||
Self::Maze
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Default, Debug, Clone, PartialEq, Serialize, Deserialize)]
|
|
||||||
#[serde(rename_all = "camelCase")]
|
|
||||||
pub struct MazeProp {
|
|
||||||
#[serde(rename = "ID")]
|
|
||||||
pub id: u32,
|
|
||||||
#[serde(rename = "PropType")]
|
|
||||||
pub prop_type: String,
|
|
||||||
#[serde(rename = "PropStateList")]
|
|
||||||
pub prop_state_list: Vec<PropState>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Clone, PartialEq, Serialize, Deserialize, Default)]
|
|
||||||
pub enum PropState {
|
|
||||||
#[default] Closed = 0,
|
|
||||||
Open = 1,
|
|
||||||
Locked = 2,
|
|
||||||
BridgeState1 = 3,
|
|
||||||
BridgeState2 = 4,
|
|
||||||
BridgeState3 = 5,
|
|
||||||
BridgeState4 = 6,
|
|
||||||
CheckPointDisable = 7,
|
|
||||||
CheckPointEnable = 8,
|
|
||||||
TriggerDisable = 9,
|
|
||||||
TriggerEnable = 10,
|
|
||||||
ChestLocked = 11,
|
|
||||||
ChestClosed = 12,
|
|
||||||
ChestUsed = 13,
|
|
||||||
Elevator1 = 14,
|
|
||||||
Elevator2 = 15,
|
|
||||||
Elevator3 = 16,
|
|
||||||
WaitActive = 17,
|
|
||||||
EventClose = 18,
|
|
||||||
EventOpen = 19,
|
|
||||||
Hidden = 20,
|
|
||||||
TeleportGate0 = 21,
|
|
||||||
TeleportGate1 = 22,
|
|
||||||
TeleportGate2 = 23,
|
|
||||||
TeleportGate3 = 24,
|
|
||||||
Destructed = 25,
|
|
||||||
CustomState01 = 101,
|
|
||||||
CustomState02 = 102,
|
|
||||||
CustomState03 = 103,
|
|
||||||
CustomState04 = 104,
|
|
||||||
CustomState05 = 105,
|
|
||||||
CustomState06 = 106,
|
|
||||||
CustomState07 = 107,
|
|
||||||
CustomState08 = 108,
|
|
||||||
CustomState09 = 109,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type IntMap<T> = HashMap<u32, T>;
|
|
||||||
pub type StringMap<T> = HashMap<String, T>;
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct SimpleLevelGroup {
|
|
||||||
pub teleports: IntMap<LevelProp>,
|
|
||||||
pub group_items: IntMap<LevelGroupItem>,
|
|
||||||
}
|
|
||||||
#[derive(Debug, Serialize, Deserialize, Clone)]
|
|
||||||
pub struct LevelGroupItem {
|
|
||||||
pub props: Vec<LevelProp>,
|
|
||||||
pub npcs: Vec<LevelNPC>,
|
|
||||||
pub monsters: Vec<LevelMonster>,
|
|
||||||
pub anchors: HashMap<u32, LevelAnchor>,
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug, Serialize, Deserialize)]
|
|
||||||
pub struct GameResources {
|
|
||||||
pub map_entrance: IntMap<MapEntrance>,
|
|
||||||
/// Key is P{PLANE_ID}_F{FLOOR_ID}
|
|
||||||
pub level_group: StringMap<SimpleLevelGroup>,
|
|
||||||
pub maze_prop: IntMap<MazeProp>,
|
|
||||||
pub maze_plane: IntMap<MazePlane>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl GameResources {
|
|
||||||
pub fn new() -> Self {
|
|
||||||
let str = std::fs::read_to_string("./resources.json")
|
|
||||||
.expect("resources.json is broken, pls redownload");
|
|
||||||
let res: Self =
|
|
||||||
serde_json::from_str(&str).expect("resources.json is broken, pls redownload");
|
|
||||||
res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
lazy_static! {
|
|
||||||
pub static ref GAME_RESOURCES: GameResources = GameResources::new();
|
|
||||||
}
|
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
pub mod resources;
|
||||||
@@ -0,0 +1,145 @@
|
|||||||
|
use serde::Deserialize;
|
||||||
|
use std::{collections::HashMap, fs, sync::LazyLock};
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct Vector {
|
||||||
|
pub x: i32, // or f32 depending on your needs
|
||||||
|
pub y: i32,
|
||||||
|
pub z: i32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Copy, PartialEq, Clone)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum PropState {
|
||||||
|
Closed = 0,
|
||||||
|
Open = 1,
|
||||||
|
Locked = 2,
|
||||||
|
BridgeState1 = 3,
|
||||||
|
BridgeState2 = 4,
|
||||||
|
BridgeState3 = 5,
|
||||||
|
BridgeState4 = 6,
|
||||||
|
CheckPointDisable = 7,
|
||||||
|
CheckPointEnable = 8,
|
||||||
|
TriggerDisable = 9,
|
||||||
|
TriggerEnable = 10,
|
||||||
|
ChestLocked = 11,
|
||||||
|
ChestClosed = 12,
|
||||||
|
ChestUsed = 13,
|
||||||
|
Elevator1 = 14,
|
||||||
|
Elevator2 = 15,
|
||||||
|
Elevator3 = 16,
|
||||||
|
WaitActive = 17,
|
||||||
|
EventClose = 18,
|
||||||
|
EventOpen = 19,
|
||||||
|
Hidden = 20,
|
||||||
|
TeleportGate0 = 21,
|
||||||
|
TeleportGate1 = 22,
|
||||||
|
TeleportGate2 = 23,
|
||||||
|
TeleportGate3 = 24,
|
||||||
|
Destructed = 25,
|
||||||
|
CustomState01 = 101,
|
||||||
|
CustomState02 = 102,
|
||||||
|
CustomState03 = 103,
|
||||||
|
CustomState04 = 104,
|
||||||
|
CustomState05 = 105,
|
||||||
|
CustomState06 = 106,
|
||||||
|
CustomState07 = 107,
|
||||||
|
CustomState08 = 108,
|
||||||
|
CustomState09 = 109,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Copy, Clone, PartialEq)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
#[repr(u32)]
|
||||||
|
pub enum PlaneType {
|
||||||
|
Unknown = 0,
|
||||||
|
Maze = 2,
|
||||||
|
Train = 3,
|
||||||
|
Challenge = 4,
|
||||||
|
Rogue = 5,
|
||||||
|
Raid = 6,
|
||||||
|
AetherDivide = 7,
|
||||||
|
TrialActivity = 8,
|
||||||
|
Town = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SceneMonsterInfo {
|
||||||
|
pub pos: Vector,
|
||||||
|
pub rot: Vector,
|
||||||
|
pub group_id: u32,
|
||||||
|
pub inst_id: u32,
|
||||||
|
pub monster_id: u32,
|
||||||
|
pub event_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SceneNpcInfo {
|
||||||
|
pub pos: Vector,
|
||||||
|
pub rot: Vector,
|
||||||
|
pub group_id: u32,
|
||||||
|
pub inst_id: u32,
|
||||||
|
pub npc_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct ScenePropInfo {
|
||||||
|
pub pos: Vector,
|
||||||
|
pub rot: Vector,
|
||||||
|
pub group_id: u32,
|
||||||
|
pub inst_id: u32,
|
||||||
|
pub prop_state: u32,
|
||||||
|
pub prop_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct TeleportInfo {
|
||||||
|
pub pos: Vector,
|
||||||
|
pub rot: Vector,
|
||||||
|
pub group_id: u32,
|
||||||
|
pub inst_id: u32,
|
||||||
|
pub anchor_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct SceneData {
|
||||||
|
pub npcs: Vec<SceneNpcInfo>,
|
||||||
|
pub props: Vec<ScenePropInfo>,
|
||||||
|
pub monsters: Vec<SceneMonsterInfo>,
|
||||||
|
pub teleports: HashMap<u32, TeleportInfo>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct LevelOutputConfig {
|
||||||
|
pub is_entered_scene_info: bool,
|
||||||
|
pub scenes: HashMap<u32, SceneData>,
|
||||||
|
pub plane_type: u32,
|
||||||
|
pub world_id: u32,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct AvatarConfig {
|
||||||
|
pub weakness_buff_id: u32,
|
||||||
|
pub technique_buff_ids: Vec<u32>,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Deserialize, Default)]
|
||||||
|
#[serde(rename_all = "camelCase")]
|
||||||
|
pub struct JsonConfig {
|
||||||
|
/// `entryid` -> `P[planeId]_F[floorId]` -> `groupId`
|
||||||
|
pub level_output_configs: HashMap<u32, HashMap<String, LevelOutputConfig>>,
|
||||||
|
pub avatar_configs: HashMap<u32, AvatarConfig>,
|
||||||
|
}
|
||||||
|
|
||||||
|
pub static GAME_RES: LazyLock<JsonConfig> = LazyLock::new(|| {
|
||||||
|
serde_json::from_str::<JsonConfig>(&fs::read_to_string("res.json").unwrap()).unwrap()
|
||||||
|
});
|
||||||
+12
-12
@@ -1,21 +1,21 @@
|
|||||||
{
|
{
|
||||||
"lineups": {
|
"lineups": {
|
||||||
"0": 1222,
|
"0": 1220,
|
||||||
"1": 1223,
|
"1": 1222,
|
||||||
"2": 1220,
|
"2": 1304,
|
||||||
"3": 1308
|
"3": 1309
|
||||||
},
|
},
|
||||||
"position": {
|
"position": {
|
||||||
"x": -3722,
|
"x": 64574,
|
||||||
"y": 56256,
|
"y": 1699,
|
||||||
"z": -87464,
|
"z": 258502,
|
||||||
"rot_y": 318488
|
"rot_y": 243401
|
||||||
},
|
},
|
||||||
"scene": {
|
"scene": {
|
||||||
"plane_id": 20321,
|
"plane_id": 20332,
|
||||||
"floor_id": 20321001,
|
"floor_id": 20332001,
|
||||||
"entry_id": 2032101
|
"entry_id": 2033201
|
||||||
},
|
},
|
||||||
"main_character": "FemaleHarmony",
|
"main_character": "FemaleHarmony",
|
||||||
"march_type": "MarchHunt"
|
"march_type": "FemaleHarmony"
|
||||||
}
|
}
|
||||||
@@ -6,6 +6,7 @@ version.workspace = true
|
|||||||
[dependencies]
|
[dependencies]
|
||||||
prost.workspace = true
|
prost.workspace = true
|
||||||
prost-types.workspace = true
|
prost-types.workspace = true
|
||||||
|
proto-derive.workspace = true
|
||||||
|
|
||||||
[build-dependencies]
|
[build-dependencies]
|
||||||
prost-build.workspace = true
|
prost-build.workspace = true
|
||||||
|
|||||||
@@ -1,3 +1,9 @@
|
|||||||
|
use std::{
|
||||||
|
fs,
|
||||||
|
io::{self, BufRead},
|
||||||
|
path::Path,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn main() {
|
pub fn main() {
|
||||||
let proto_file = "StarRail.proto";
|
let proto_file = "StarRail.proto";
|
||||||
if std::path::Path::new(proto_file).exists() {
|
if std::path::Path::new(proto_file).exists() {
|
||||||
@@ -5,7 +11,38 @@ pub fn main() {
|
|||||||
|
|
||||||
prost_build::Config::new()
|
prost_build::Config::new()
|
||||||
.out_dir("out/")
|
.out_dir("out/")
|
||||||
|
.type_attribute(".", "#[derive(proto_derive::CmdID)]")
|
||||||
.compile_protos(&[proto_file], &["."])
|
.compile_protos(&[proto_file], &["."])
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
|
impl_message_id(Path::new("out/_.rs")).unwrap();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn impl_message_id(path: &Path) -> io::Result<()> {
|
||||||
|
let file = fs::File::open(path)?;
|
||||||
|
let reader = io::BufReader::new(file);
|
||||||
|
let mut output = Vec::new();
|
||||||
|
|
||||||
|
let mut attr = None;
|
||||||
|
for line in reader.lines() {
|
||||||
|
let line = line?;
|
||||||
|
|
||||||
|
if line.contains("CmdID:") {
|
||||||
|
attr = Some(make_message_id_attr(&line).unwrap());
|
||||||
|
} else {
|
||||||
|
output.push(line);
|
||||||
|
if let Some(attr) = attr.take() {
|
||||||
|
output.push(attr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fs::write(path, output.join("\n").as_bytes())?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn make_message_id_attr(line: &str) -> Option<String> {
|
||||||
|
let id = line.trim_start().split(' ').nth(2)?.parse::<u16>().ok()?;
|
||||||
|
Some(format!("#[cmdid({id})]"))
|
||||||
|
}
|
||||||
|
|||||||
+50967
-11845
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
|||||||
|
[package]
|
||||||
|
name = "proto-derive"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
syn = "2.0.53"
|
||||||
|
quote = "1.0.35"
|
||||||
|
proc-macro2 = "1.0.79"
|
||||||
|
|
||||||
|
[lib]
|
||||||
|
proc-macro = true
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
use proc_macro::TokenStream;
|
||||||
|
use quote::{quote, ToTokens};
|
||||||
|
use syn::{parse_macro_input, DeriveInput, Meta, MetaList};
|
||||||
|
|
||||||
|
#[proc_macro_derive(CmdID, attributes(cmdid))]
|
||||||
|
pub fn message_id_derive(input: TokenStream) -> TokenStream {
|
||||||
|
let input = parse_macro_input!(input as DeriveInput);
|
||||||
|
let struct_name = input.ident;
|
||||||
|
|
||||||
|
let id = match input
|
||||||
|
.attrs
|
||||||
|
.iter()
|
||||||
|
.find(|attr| attr.path().is_ident("cmdid"))
|
||||||
|
{
|
||||||
|
Some(attr) => match attr.meta {
|
||||||
|
Meta::List(MetaList { ref tokens, .. }) => tokens.into_token_stream(),
|
||||||
|
_ => panic!("Invalid cmdid attribute value"),
|
||||||
|
},
|
||||||
|
_ => 0u16.into_token_stream(),
|
||||||
|
};
|
||||||
|
|
||||||
|
TokenStream::from(quote! {
|
||||||
|
impl crate::CmdID for #struct_name {
|
||||||
|
const CMD_ID: u16 = #id;
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
File diff suppressed because it is too large
Load Diff
+11
-3
@@ -1,4 +1,12 @@
|
|||||||
mod cmd_types;
|
|
||||||
pub use cmd_types::*;
|
|
||||||
|
|
||||||
include!("../out/_.rs");
|
include!("../out/_.rs");
|
||||||
|
|
||||||
|
pub use prost::DecodeError as ProtobufDecodeError;
|
||||||
|
pub use prost::Message as Protobuf;
|
||||||
|
|
||||||
|
pub trait CmdID {
|
||||||
|
const CMD_ID: u16;
|
||||||
|
|
||||||
|
fn get_cmd_id(&self) -> u16 {
|
||||||
|
Self::CMD_ID
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -42,7 +42,6 @@ pub async fn query_gateway(parameters: Query<QueryGatewayParameters>) -> String
|
|||||||
asset_bundle_url: config.asset_bundle_url.clone(),
|
asset_bundle_url: config.asset_bundle_url.clone(),
|
||||||
ex_resource_url: config.ex_resource_url.clone(),
|
ex_resource_url: config.ex_resource_url.clone(),
|
||||||
lua_url: config.lua_url.clone(),
|
lua_url: config.lua_url.clone(),
|
||||||
// lua_version: config.lua_version.clone(),
|
|
||||||
ifix_version: String::from("0"),
|
ifix_version: String::from("0"),
|
||||||
unk1: true,
|
unk1: true,
|
||||||
unk2: true,
|
unk2: true,
|
||||||
@@ -51,14 +50,8 @@ pub async fn query_gateway(parameters: Query<QueryGatewayParameters>) -> String
|
|||||||
unk5: true,
|
unk5: true,
|
||||||
unk6: true,
|
unk6: true,
|
||||||
unk7: true,
|
unk7: true,
|
||||||
mmcachlfjaa: true,
|
jgciiljehhe: true,
|
||||||
ncikdciigof: true,
|
|
||||||
efknbdlnakj: true,
|
|
||||||
gpjcfcjdmol: true,
|
|
||||||
jidbdekohdh: true,
|
|
||||||
pphbpgbnoem: true,
|
|
||||||
dhppkkgjldl: true,
|
|
||||||
jipjkleanbd: true,
|
|
||||||
..Default::default()
|
..Default::default()
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
+11
-11
@@ -1,14 +1,14 @@
|
|||||||
{
|
{
|
||||||
"CNBETAWin2.2.51": {
|
"CNBETAWin2.5.51": {
|
||||||
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_7037158_b67f5a6a68fb",
|
"asset_bundle_url": "",
|
||||||
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_7033392_aaca9c1b456b",
|
"ex_resource_url": "",
|
||||||
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_7050564_f05a0f949b10",
|
"lua_url": "",
|
||||||
"lua_version": "7050564"
|
"ifix_url": ""
|
||||||
},
|
},
|
||||||
"OSBETAWin2.2.51": {
|
"CNBETAWin2.5.52": {
|
||||||
"asset_bundle_url": "https://autopatchos.starrails.com/asb/BetaLive/output_7037158_b67f5a6a68fb",
|
"asset_bundle_url": "",
|
||||||
"ex_resource_url": "https://autopatchos.starrails.com/design_data/BetaLive/output_7033392_aaca9c1b456b",
|
"ex_resource_url": "",
|
||||||
"lua_url": "https://autopatchos.starrails.com/lua/BetaLive/output_7050564_f05a0f949b10",
|
"lua_url": "",
|
||||||
"lua_version": "7050564"
|
"ifix_url": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+11
-5
@@ -1,8 +1,14 @@
|
|||||||
{
|
{
|
||||||
"CNBETAWin2.4.51": {
|
"CNBETAWin2.5.51": {
|
||||||
"asset_bundle_url": "https://autopatchcn-ipv6.bhsr.com/asb/BetaLive/output_7663997_cd086af3f307",
|
"asset_bundle_url": "",
|
||||||
"ex_resource_url": "https://autopatchcn-ipv6.bhsr.com/design_data/BetaLive/output_7689868_456662b48277",
|
"ex_resource_url": "",
|
||||||
"lua_url": "https://autopatchcn-ipv6.bhsr.com/lua/BetaLive/output_7668875_0231727458ad",
|
"lua_url": "",
|
||||||
"ifix_url": "https://autopatchcn-ipv6.bhsr.com/ifix/BetaLive/output_0_40d2ce0253"
|
"ifix_url": ""
|
||||||
|
},
|
||||||
|
"CNBETAWin2.5.52": {
|
||||||
|
"asset_bundle_url": "",
|
||||||
|
"ex_resource_url": "",
|
||||||
|
"lua_url": "",
|
||||||
|
"ifix_url": ""
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user