First push
This commit is contained in:
parent
46a868ca85
commit
c0cdf91849
32 changed files with 39006 additions and 0 deletions
3
.gitignore
vendored
Normal file
3
.gitignore
vendored
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
target/
|
||||||
|
Cargo.lock
|
||||||
|
proto/StarRail.proto
|
62
Cargo.toml
Normal file
62
Cargo.toml
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
[workspace]
|
||||||
|
members = [ "gameserver", "proto", "sdkserver"]
|
||||||
|
resolver = "2"
|
||||||
|
|
||||||
|
[workspace.package]
|
||||||
|
version = "0.1.0"
|
||||||
|
|
||||||
|
[workspace.dependencies]
|
||||||
|
anyhow = "1.0.81"
|
||||||
|
ansi_term = "0.12.1"
|
||||||
|
atomic_refcell = "0.1.13"
|
||||||
|
lazy_static = "1.4.0"
|
||||||
|
|
||||||
|
axum = "0.7.4"
|
||||||
|
axum-server = "0.6.0"
|
||||||
|
|
||||||
|
env_logger = "0.11.3"
|
||||||
|
|
||||||
|
rbase64 = "2.0.3"
|
||||||
|
rand = "0.8.5"
|
||||||
|
rsa = { version = "0.9.6", features = [
|
||||||
|
"sha1",
|
||||||
|
"nightly",
|
||||||
|
"pkcs5",
|
||||||
|
"serde",
|
||||||
|
"sha2",
|
||||||
|
] }
|
||||||
|
|
||||||
|
prost = "0.12.3"
|
||||||
|
prost-types = "0.12.3"
|
||||||
|
prost-build = "0.12.3"
|
||||||
|
|
||||||
|
paste = "1.0.14"
|
||||||
|
sysinfo = "0.30.7"
|
||||||
|
|
||||||
|
hex = "0.4.3"
|
||||||
|
|
||||||
|
serde = { version = "1.0.197", features = ["derive"] }
|
||||||
|
serde_json = "1.0.114"
|
||||||
|
|
||||||
|
tokio = { version = "1.36.0", features = ["full"] }
|
||||||
|
tokio-util = { version = "0.7.10", features = ["io"] }
|
||||||
|
|
||||||
|
tracing = "0.1.40"
|
||||||
|
tracing-futures = "0.2.5"
|
||||||
|
tracing-log = { version = "0.2.0", features = ["std", "log-tracer"] }
|
||||||
|
tracing-subscriber = { version = "0.3.18", features = [
|
||||||
|
"env-filter",
|
||||||
|
"registry",
|
||||||
|
"std",
|
||||||
|
"tracing",
|
||||||
|
"tracing-log",
|
||||||
|
] }
|
||||||
|
tracing-bunyan-formatter = "0.3.9"
|
||||||
|
|
||||||
|
proto = { path = "proto/" }
|
||||||
|
|
||||||
|
[profile.release]
|
||||||
|
strip = true # Automatically strip symbols from the binary.
|
||||||
|
lto = true # Link-time optimization.
|
||||||
|
opt-level = 3 # Optimize for speed.
|
||||||
|
codegen-units = 1 # Maximum size reduction optimizations.
|
30
gameserver/Cargo.toml
Normal file
30
gameserver/Cargo.toml
Normal file
|
@ -0,0 +1,30 @@
|
||||||
|
[package]
|
||||||
|
name = "gameserver"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
ansi_term.workspace = true
|
||||||
|
anyhow.workspace = true
|
||||||
|
atomic_refcell.workspace = true
|
||||||
|
env_logger.workspace = true
|
||||||
|
hex.workspace = true
|
||||||
|
lazy_static.workspace = true
|
||||||
|
paste.workspace = true
|
||||||
|
rbase64.workspace = true
|
||||||
|
sysinfo.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
tracing.workspace = true
|
||||||
|
tracing-futures.workspace = true
|
||||||
|
tracing-log.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
tracing-bunyan-formatter.workspace = true
|
||||||
|
|
||||||
|
prost.workspace = true
|
||||||
|
proto.workspace = true
|
29
gameserver/src/logging.rs
Normal file
29
gameserver/src/logging.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_error {
|
||||||
|
($e:expr) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($context:expr, $e:expr $(,)?) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
let e = format!("{:?}", ::anyhow::anyhow!(e).context($context));
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($ok_context:expr, $err_context:expr, $e:expr $(,)?) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
let e = format!("{:?}", ::anyhow::anyhow!(e).context($err_context));
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
} else {
|
||||||
|
tracing::info!($ok_context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_tracing() {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
ansi_term::enable_ansi_support().unwrap();
|
||||||
|
|
||||||
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
}
|
15
gameserver/src/main.rs
Normal file
15
gameserver/src/main.rs
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
|
||||||
|
mod logging;
|
||||||
|
mod net;
|
||||||
|
mod util;
|
||||||
|
|
||||||
|
use logging::init_tracing;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
init_tracing();
|
||||||
|
net::gateway::listen("0.0.0.0", 23301).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
28
gameserver/src/net/gateway.rs
Normal file
28
gameserver/src/net/gateway.rs
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use tokio::net::TcpListener;
|
||||||
|
use tracing::{info_span, Instrument};
|
||||||
|
|
||||||
|
use crate::{log_error, net::PlayerSession};
|
||||||
|
|
||||||
|
pub async fn listen(host: &str, port: u16) -> Result<()> {
|
||||||
|
let listener = TcpListener::bind(format!("{host}:{port}")).await?;
|
||||||
|
tracing::info!("Listening at {host}:{port}");
|
||||||
|
|
||||||
|
loop {
|
||||||
|
let Ok((client_socket, client_addr)) = listener.accept().await else {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut session = PlayerSession::new(client_socket);
|
||||||
|
tokio::spawn(
|
||||||
|
async move {
|
||||||
|
log_error!(
|
||||||
|
"Session from {client_addr} disconnected",
|
||||||
|
format!("An error occurred while processing session ({client_addr})"),
|
||||||
|
Box::pin(session.run()).await
|
||||||
|
);
|
||||||
|
}
|
||||||
|
.instrument(info_span!("session", addr = %client_addr)),
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
44
gameserver/src/net/handlers/authentication.rs
Normal file
44
gameserver/src/net/handlers/authentication.rs
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use proto::*;
|
||||||
|
|
||||||
|
use crate::{net::PlayerSession, util};
|
||||||
|
|
||||||
|
pub async fn on_player_get_token_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &PlayerGetTokenCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_PLAYER_GET_TOKEN_SC_RSP,
|
||||||
|
PlayerGetTokenScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
msg: String::from("OK"),
|
||||||
|
uid: 1337,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_player_login_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &PlayerLoginCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_PLAYER_LOGIN_SC_RSP,
|
||||||
|
PlayerLoginScRsp {
|
||||||
|
login_random: body.login_random,
|
||||||
|
server_timestamp_ms: util::cur_timestamp_ms(),
|
||||||
|
stamina: 240,
|
||||||
|
basic_info: Some(PlayerBasicInfo {
|
||||||
|
nickname: String::from("xeondev"),
|
||||||
|
level: 5,
|
||||||
|
stamina: 240,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
34
gameserver/src/net/handlers/avatar.rs
Normal file
34
gameserver/src/net/handlers/avatar.rs
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static UNLOCKED_AVATARS: [u32; 49] = [
|
||||||
|
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,
|
||||||
|
1211, 1212, 1213, 1214, 1215, 1217, 1301, 1302, 1303, 1304, 1305, 1306, 1307, 1308, 1309, 1312,
|
||||||
|
1315,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub async fn on_get_avatar_data_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &GetAvatarDataCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_AVATAR_DATA_SC_RSP,
|
||||||
|
GetAvatarDataScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
is_all: body.is_get_all,
|
||||||
|
avatar_list: UNLOCKED_AVATARS
|
||||||
|
.iter()
|
||||||
|
.map(|id| Avatar {
|
||||||
|
base_avatar_id: *id,
|
||||||
|
level: 80,
|
||||||
|
promotion: 6,
|
||||||
|
rank: 6,
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
65
gameserver/src/net/handlers/battle.rs
Normal file
65
gameserver/src/net/handlers/battle.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static BATTLE_LINEUP: [u32; 4] = [1309, 1308, 1307, 1315];
|
||||||
|
|
||||||
|
pub async fn on_start_cocoon_stage_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &StartCocoonStageCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
let rsp = StartCocoonStageScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
prop_entity_id: body.prop_entity_id,
|
||||||
|
cocoon_id: body.cocoon_id,
|
||||||
|
wave: body.wave,
|
||||||
|
battle_info: Some(SceneBattleInfo {
|
||||||
|
stage_id: 201012311,
|
||||||
|
logic_random_seed: 4444,
|
||||||
|
battle_id: 1,
|
||||||
|
battle_avatar_list: BATTLE_LINEUP
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, id)| BattleAvatar {
|
||||||
|
index: idx as u32,
|
||||||
|
id: *id,
|
||||||
|
level: 80,
|
||||||
|
promotion: 6,
|
||||||
|
rank: 6,
|
||||||
|
hp: 10000,
|
||||||
|
avatar_type: 3,
|
||||||
|
sp: Some(AmountInfo {
|
||||||
|
cur_amount: 10000,
|
||||||
|
max_amount: 10000,
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
monster_wave_list: vec![SceneMonsterWave {
|
||||||
|
monster_list: vec![SceneMonsterParam {
|
||||||
|
monster_id: 3013010,
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
|
||||||
|
session.send(CMD_START_COCOON_STAGE_SC_RSP, rsp).await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_pve_battle_result_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &PveBattleResultCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_P_V_E_BATTLE_RESULT_SC_RSP,
|
||||||
|
PveBattleResultScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
end_status: body.end_status,
|
||||||
|
battle_id: body.battle_id,
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
89
gameserver/src/net/handlers/lineup.rs
Normal file
89
gameserver/src/net/handlers/lineup.rs
Normal file
|
@ -0,0 +1,89 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static STARTING_LINEUP: [u32; 4] = [1309, 1308, 1307, 1315];
|
||||||
|
|
||||||
|
pub async fn on_get_all_lineup_data_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &GetAllLineupDataCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_ALL_LINEUP_DATA_SC_RSP,
|
||||||
|
GetAllLineupDataScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
cur_index: 0,
|
||||||
|
lineup_list: vec![LineupInfo {
|
||||||
|
plane_id: 10001,
|
||||||
|
name: String::from("Lineup 1"),
|
||||||
|
index: 0,
|
||||||
|
avatar_list: STARTING_LINEUP
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, id)| LineupAvatar {
|
||||||
|
id: *id,
|
||||||
|
slot: idx as u32,
|
||||||
|
hp: 10000,
|
||||||
|
sp: Some(AmountInfo {
|
||||||
|
cur_amount: 10000,
|
||||||
|
max_amount: 10000,
|
||||||
|
}),
|
||||||
|
satiety: 100,
|
||||||
|
avatar_type: 3,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_get_cur_lineup_data_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &GetCurLineupDataCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_CUR_LINEUP_DATA_SC_RSP,
|
||||||
|
GetCurLineupDataScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
lineup: Some(LineupInfo {
|
||||||
|
plane_id: 10001,
|
||||||
|
name: String::from("Lineup 1"),
|
||||||
|
index: 0,
|
||||||
|
avatar_list: STARTING_LINEUP
|
||||||
|
.iter()
|
||||||
|
.enumerate()
|
||||||
|
.map(|(idx, id)| LineupAvatar {
|
||||||
|
id: *id,
|
||||||
|
slot: idx as u32,
|
||||||
|
hp: 10000,
|
||||||
|
sp: Some(AmountInfo {
|
||||||
|
cur_amount: 10000,
|
||||||
|
max_amount: 10000,
|
||||||
|
}),
|
||||||
|
satiety: 100,
|
||||||
|
avatar_type: 3,
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_change_lineup_leader_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &ChangeLineupLeaderCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_CHANGE_LINEUP_LEADER_SC_RSP,
|
||||||
|
ChangeLineupLeaderScRsp {
|
||||||
|
slot: body.slot,
|
||||||
|
retcode: 0,
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
72
gameserver/src/net/handlers/mission.rs
Normal file
72
gameserver/src/net/handlers/mission.rs
Normal file
|
@ -0,0 +1,72 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static FINISHED_MAIN_MISSIONS: [u32; 365] = [
|
||||||
|
1000101, 1000111, 1000112, 1000113, 1000114, 1000201, 1000202, 1000203, 1000204, 1000300,
|
||||||
|
1000301, 1000302, 1000303, 1000304, 1000400, 1000401, 1000402, 1000410, 1000500, 1000501,
|
||||||
|
1000502, 1000503, 1000504, 1000505, 1000510, 1000511, 1010001, 1010002, 1010101, 1010201,
|
||||||
|
1010202, 1010203, 1010204, 1010205, 1010206, 1010301, 1010302, 1010303, 1010401, 1010405,
|
||||||
|
1010402, 1010403, 1010500, 1010501, 1010502, 1010503, 1010601, 1010602, 1010700, 1010701,
|
||||||
|
1010801, 1010802, 1010901, 1010902, 1011001, 1011002, 1011003, 1011100, 1011101, 1011102,
|
||||||
|
1011103, 1011201, 1011202, 1011301, 1011400, 1011401, 1011402, 1011403, 1011501, 1011502,
|
||||||
|
1011503, 1020101, 1020201, 1020302, 1020301, 1020400, 1020401, 1020402, 1020403, 1020501,
|
||||||
|
1020601, 1020701, 1020702, 1020801, 1020901, 1021001, 1021101, 1021201, 1021301, 1021401,
|
||||||
|
1021501, 1021601, 1021702, 1021703, 1030101, 1030102, 1030201, 1030202, 1030301, 1030302,
|
||||||
|
1030303, 1030304, 1030401, 1030402, 1030403, 1030501, 1030601, 1030701, 1030702, 1030801,
|
||||||
|
2000001, 2000002, 2000003, 2000004, 2000100, 2000101, 2000131, 2000132, 2000133, 2000110,
|
||||||
|
2000111, 2000301, 2000103, 2000112, 2000108, 2000104, 2000102, 2000105, 2000106, 2000107,
|
||||||
|
2000313, 2000314, 2000109, 2000113, 2000116, 2000118, 2000119, 2000120, 2000122, 2000302,
|
||||||
|
2000303, 2000304, 2000305, 2000310, 2000311, 2000312, 2000320, 2000701, 2000702, 2000703,
|
||||||
|
2000704, 2000705, 2000706, 2000707, 2000801, 2000802, 2000803, 2000901, 2000902, 2000903,
|
||||||
|
2001001, 2001002, 2001003, 2010005, 2010301, 2010302, 2011103, 2011104, 2011409, 2010401,
|
||||||
|
2010402, 2010405, 2010502, 2010503, 2010701, 2010708, 2010709, 2010720, 2010730, 2010731,
|
||||||
|
2010732, 2010733, 2010734, 2010735, 2010904, 2011101, 2011102, 2011105, 2011301, 2011302,
|
||||||
|
2011303, 2011501, 2011502, 2010909, 2010910, 2011601, 2011701, 2011801, 2011901, 2011902,
|
||||||
|
2011903, 2011904, 2011905, 2011906, 2020301, 2020302, 2020304, 2020316, 2020317, 2020318,
|
||||||
|
2020319, 2020401, 2020402, 2020403, 2020404, 2020405, 2020406, 2020407, 2020303, 2020103,
|
||||||
|
2020104, 2020105, 2020106, 2020107, 2020108, 2020109, 2020110, 2020111, 2020201, 2020202,
|
||||||
|
2020203, 2020204, 2020205, 2000201, 2000202, 2000203, 2000204, 2000205, 2000206, 2000207,
|
||||||
|
2000208, 2000209, 2000211, 2000212, 2010201, 2010202, 2010203, 2010204, 2010205, 2010206,
|
||||||
|
2010500, 2010501, 2010705, 2010706, 2010901, 2010902, 2010903, 2010702, 2010703, 2011400,
|
||||||
|
2011401, 2011406, 2011402, 2011403, 2011404, 2011405, 2011407, 2011408, 2011410, 2011411,
|
||||||
|
2011412, 2011413, 2010905, 2010906, 2010907, 2010908, 2010911, 2010912, 2020305, 2020306,
|
||||||
|
2020309, 2020307, 2020308, 2020701, 2020702, 2020703, 2020313, 2020314, 2020315, 6020101,
|
||||||
|
6020201, 6020202, 2020501, 2020502, 2020503, 2020504, 2020505, 2020506, 2020507, 2020601,
|
||||||
|
2020602, 2020603, 2020604, 2020801, 2020802, 2020901, 2021001, 2021002, 2021009, 2021601,
|
||||||
|
2021602, 2021701, 2021702, 2021703, 2021704, 2021705, 2021801, 2021802, 2021803, 2030001,
|
||||||
|
2030002, 2030003, 2030101, 2030102, 2030201, 2030202, 2030203, 2030301, 2030302, 3000201,
|
||||||
|
3000202, 3000203, 3000211, 3000212, 3000213, 3000301, 3000302, 3000303, 3000522, 3000523,
|
||||||
|
3000524, 3000525, 3000526, 3000527, 3000601, 3000602, 3000603, 3000604, 3000701, 3000702,
|
||||||
|
3000703, 3000704, 3000705, 3000800, 3000801, 3000802, 3000803, 3010102, 3010103, 3010104,
|
||||||
|
3010105, 3010201, 3010202, 3010203, 3010204,
|
||||||
|
];
|
||||||
|
|
||||||
|
pub async fn on_get_mission_status_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &GetMissionStatusCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
let rsp = GetMissionStatusScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
finished_main_mission_id_list: FINISHED_MAIN_MISSIONS.to_vec(),
|
||||||
|
sub_mission_status_list: body
|
||||||
|
.main_mission_id_list
|
||||||
|
.iter()
|
||||||
|
.map(|id| Mission {
|
||||||
|
id: *id,
|
||||||
|
progress: 0,
|
||||||
|
status: MissionStatus::MissionFinish.into(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
mission_event_status_list: body
|
||||||
|
.mission_event_id_list
|
||||||
|
.iter()
|
||||||
|
.map(|id| Mission {
|
||||||
|
id: *id,
|
||||||
|
progress: 0,
|
||||||
|
status: MissionStatus::MissionFinish.into(),
|
||||||
|
})
|
||||||
|
.collect(),
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
session.send(CMD_GET_MISSION_STATUS_SC_RSP, rsp).await
|
||||||
|
}
|
119
gameserver/src/net/handlers/mod.rs
Normal file
119
gameserver/src/net/handlers/mod.rs
Normal file
|
@ -0,0 +1,119 @@
|
||||||
|
mod authentication;
|
||||||
|
mod avatar;
|
||||||
|
mod battle;
|
||||||
|
mod lineup;
|
||||||
|
mod mission;
|
||||||
|
mod player;
|
||||||
|
mod scene;
|
||||||
|
mod tutorial;
|
||||||
|
|
||||||
|
use anyhow::Result;
|
||||||
|
use paste::paste;
|
||||||
|
use proto::*;
|
||||||
|
use tokio::io::AsyncWriteExt;
|
||||||
|
|
||||||
|
use super::PlayerSession;
|
||||||
|
use crate::net::NetPacket;
|
||||||
|
|
||||||
|
pub use authentication::*;
|
||||||
|
pub use avatar::*;
|
||||||
|
pub use battle::*;
|
||||||
|
pub use lineup::*;
|
||||||
|
pub use mission::*;
|
||||||
|
pub use player::*;
|
||||||
|
pub use scene::*;
|
||||||
|
pub use tutorial::*;
|
||||||
|
|
||||||
|
use proto::{
|
||||||
|
Aaihejacdpk::*, Achkcddkkkj::*, Bancodieeof::*, CmdActivityType::*, CmdBattleType::*,
|
||||||
|
CmdItemType::*, CmdPlayerType::*, Cmpepmnekko::*, Cpbdjpocnai::*, Ddhbjcelmjp::*,
|
||||||
|
Eegmjpcijbc::*, Emhbkpkpjpa::*, Fdkapmfjgjl::*, Gaifgoihffa::*, Galijhmhgcg::*, Gdjpnkniijf::*,
|
||||||
|
Hfjpennlffa::*, Hmnbojnkleh::*, Ieoildlcdkb::*, Kfmpmaojchm::*, Lopidcokdih::*, Lpegmiilfjm::*,
|
||||||
|
Mbnnmfkffbo::*, Mkeclbphcol::*, Niinikapdpg::*, Pfokmnnfiap::*, Pjmghcfmmge::*, Pnjfenbhbhg::*,
|
||||||
|
Pnnbhogkeeh::*,
|
||||||
|
};
|
||||||
|
|
||||||
|
macro_rules! dummy {
|
||||||
|
($($cmd:ident),* $(,)*) => {
|
||||||
|
paste! {
|
||||||
|
impl PlayerSession {
|
||||||
|
pub const fn should_send_dummy_rsp(cmd_id: u16) -> bool {
|
||||||
|
match cmd_id {
|
||||||
|
$(
|
||||||
|
x if x == [<Cmd $cmd CsReq>] as u16 => true,
|
||||||
|
)*
|
||||||
|
_ => false,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send_dummy_response(&mut self, req_id: u16) -> Result<()> {
|
||||||
|
let cmd_type = match req_id {
|
||||||
|
$(
|
||||||
|
x if x == [<Cmd $cmd CsReq>] as u16 => [<Cmd $cmd ScRsp>] as u16,
|
||||||
|
)*
|
||||||
|
_ => return Err(anyhow::anyhow!("Invalid request id {req_id:?}")),
|
||||||
|
};
|
||||||
|
|
||||||
|
let payload: Vec<u8> = NetPacket {
|
||||||
|
cmd_type,
|
||||||
|
head: Vec::new(),
|
||||||
|
body: Vec::new(),
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
|
||||||
|
self.client_socket.write_all(&payload).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
dummy! {
|
||||||
|
SceneEntityMove,
|
||||||
|
GetLevelRewardTakenList,
|
||||||
|
GetRogueScoreRewardInfo,
|
||||||
|
GetGachaInfo,
|
||||||
|
QueryProductInfo,
|
||||||
|
GetQuestData,
|
||||||
|
GetQuestRecord,
|
||||||
|
GetFriendListInfo,
|
||||||
|
GetFriendApplyListInfo,
|
||||||
|
GetCurAssist,
|
||||||
|
GetRogueHandbookData,
|
||||||
|
GetDailyActiveInfo,
|
||||||
|
GetFightActivityData,
|
||||||
|
GetMultipleDropInfo,
|
||||||
|
GetPlayerReturnMultiDropInfo,
|
||||||
|
GetShareData,
|
||||||
|
GetTreasureDungeonActivityData,
|
||||||
|
PlayerReturnInfoQuery,
|
||||||
|
GetBag,
|
||||||
|
GetPlayerBoardData,
|
||||||
|
GetActivityScheduleConfig,
|
||||||
|
GetMissionData,
|
||||||
|
GetMissionEventData,
|
||||||
|
GetChallenge,
|
||||||
|
GetCurChallenge,
|
||||||
|
GetRogueInfo,
|
||||||
|
GetExpeditionData,
|
||||||
|
GetRogueDialogueEventData,
|
||||||
|
GetJukeboxData,
|
||||||
|
SyncClientResVersion,
|
||||||
|
DailyFirstMeetPam,
|
||||||
|
GetMuseumInfo,
|
||||||
|
GetLoginActivity,
|
||||||
|
GetRaidInfo,
|
||||||
|
GetTrialActivityData,
|
||||||
|
GetBoxingClubInfo,
|
||||||
|
GetNpcStatus,
|
||||||
|
TextJoinQuery,
|
||||||
|
GetSpringRecoverData,
|
||||||
|
GetChatFriendHistory,
|
||||||
|
GetSecretKeyInfo,
|
||||||
|
GetVideoVersionKey,
|
||||||
|
GetCurBattleInfo,
|
||||||
|
GetPhoneData,
|
||||||
|
PlayerLoginFinish,
|
||||||
|
}
|
61
gameserver/src/net/handlers/player.rs
Normal file
61
gameserver/src/net/handlers/player.rs
Normal file
|
@ -0,0 +1,61 @@
|
||||||
|
use crate::util;
|
||||||
|
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub async fn on_get_basic_info_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &GetBasicInfoCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_BASIC_INFO_SC_RSP,
|
||||||
|
GetBasicInfoScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
player_setting_info: Some(PlayerSettingInfo::default()),
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_get_hero_basic_type_info_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &GetHeroBasicTypeInfoCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_HERO_BASIC_TYPE_INFO_SC_RSP,
|
||||||
|
GetHeroBasicTypeInfoScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
gender: Gender::Man.into(),
|
||||||
|
cur_basic_type: HeroBasicType::BoyWarrior.into(),
|
||||||
|
basic_type_info_list: vec![HeroBasicTypeInfo {
|
||||||
|
basic_type: HeroBasicType::BoyWarrior.into(),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn on_player_heart_beat_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
body: &PlayerHeartBeatCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_PLAYER_HEART_BEAT_SC_RSP,
|
||||||
|
PlayerHeartBeatScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
client_time_ms: body.client_time_ms,
|
||||||
|
server_time_ms: util::cur_timestamp_ms(),
|
||||||
|
download_data: Some(ClientDownloadData {
|
||||||
|
version: 51,
|
||||||
|
time: util::cur_timestamp_ms() as i64,
|
||||||
|
data: rbase64::decode("G0x1YVMBGZMNChoKBAQICHhWAAAAAAAAAAAAAAAod0ABKEBDOlxVc2Vyc1x4ZW9uZGV2XERvd25sb2Fkc1xyYWJzdHZvLmx1YQAAAAAAAAAAAAEEEAAAACQAQAApQEAAKYBAACnAQABWAAEALIAAAR1AQQCkgEEA5ABAAOnAwQHpAMIB6UDCAawAAAEsgAAAH8BChRkAgAAMAAAABANDUwQMVW5pdHlFbmdpbmUEC0dhbWVPYmplY3QEBUZpbmQEKVVJUm9vdC9BYm92ZURpYWxvZy9CZXRhSGludERpYWxvZyhDbG9uZSkEF0dldENvbXBvbmVudEluQ2hpbGRyZW4EB3R5cGVvZgQEUlBHBAdDbGllbnQEDkxvY2FsaXplZFRleHQEBXRleHQURVJvYmluU1IgaXMgYSBmcmVlIGFuZCBvcGVuIHNvdXJjZSBzb2Z0d2FyZS4gZGlzY29yZC5nZy9yZXZlcnNlZHJvb21zAQAAAAEAAAAAABAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAFX0VOVg==").unwrap()
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
79
gameserver/src/net/handlers/scene.rs
Normal file
79
gameserver/src/net/handlers/scene.rs
Normal file
|
@ -0,0 +1,79 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
pub async fn on_get_cur_scene_info_cs_req(
|
||||||
|
session: &mut PlayerSession,
|
||||||
|
_body: &GetCurSceneInfoCsReq,
|
||||||
|
) -> Result<()> {
|
||||||
|
session
|
||||||
|
.send(
|
||||||
|
CMD_GET_CUR_SCENE_INFO_SC_RSP,
|
||||||
|
GetCurSceneInfoScRsp {
|
||||||
|
retcode: 0,
|
||||||
|
scene: Some(SceneInfo {
|
||||||
|
plane_id: 20101,
|
||||||
|
floor_id: 20101001,
|
||||||
|
entry_id: 2010101,
|
||||||
|
game_mode_type: 2,
|
||||||
|
chhmmbdhjpg: vec![
|
||||||
|
Dhkacjhaoid {
|
||||||
|
state: 1,
|
||||||
|
group_id: 0,
|
||||||
|
entity_list: vec![SceneEntityInfo {
|
||||||
|
group_id: 0,
|
||||||
|
inst_id: 0,
|
||||||
|
entity_id: 0,
|
||||||
|
actor: Some(SceneActorInfo {
|
||||||
|
avatar_type: 3,
|
||||||
|
base_avatar_id: 1309,
|
||||||
|
map_layer: 2,
|
||||||
|
uid: 1337,
|
||||||
|
}),
|
||||||
|
motion: Some(MotionInfo {
|
||||||
|
aomilajjmii: Some(Vector {
|
||||||
|
bagloppgnpb: 4480,
|
||||||
|
bemlopmcgch: 19364,
|
||||||
|
baimdminomk: -550,
|
||||||
|
}),
|
||||||
|
eiaoiankefd: Some(Vector {
|
||||||
|
bagloppgnpb: 4480,
|
||||||
|
bemlopmcgch: 19364,
|
||||||
|
baimdminomk: -550,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
Dhkacjhaoid {
|
||||||
|
state: 1,
|
||||||
|
group_id: 19,
|
||||||
|
entity_list: vec![SceneEntityInfo {
|
||||||
|
group_id: 19,
|
||||||
|
inst_id: 300001,
|
||||||
|
entity_id: 228,
|
||||||
|
prop: Some(ScenePropInfo {
|
||||||
|
prop_id: 808,
|
||||||
|
prop_state: 1,
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
motion: Some(MotionInfo {
|
||||||
|
aomilajjmii: Some(Vector {
|
||||||
|
bagloppgnpb: 4480,
|
||||||
|
bemlopmcgch: 19364,
|
||||||
|
baimdminomk: -570,
|
||||||
|
}),
|
||||||
|
eiaoiankefd: Some(Vector {
|
||||||
|
bagloppgnpb: 4480,
|
||||||
|
bemlopmcgch: 19364,
|
||||||
|
baimdminomk: -570,
|
||||||
|
}),
|
||||||
|
}),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
},
|
||||||
|
],
|
||||||
|
..Default::default()
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.await
|
||||||
|
}
|
62
gameserver/src/net/handlers/tutorial.rs
Normal file
62
gameserver/src/net/handlers/tutorial.rs
Normal file
|
@ -0,0 +1,62 @@
|
||||||
|
use super::*;
|
||||||
|
|
||||||
|
static TUTORIAL_IDS: [u32; 55] = [
|
||||||
|
1001, 1002, 1003, 1004, 1005, 1007, 1008, 1010, 1011, 2001, 2002, 2003, 2004, 2005, 2008, 2009,
|
||||||
|
2010, 2011, 2012, 2013, 2014, 2015, 3001, 3002, 3003, 3004, 3005, 3006, 4002, 4003, 4004, 4005,
|
||||||
|
4006, 4007, 4008, 4009, 5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010, 5011, 5012,
|
||||||
|
7001, 9001, 9002, 9003, 9004, 9005, 9006,
|
||||||
|
];
|
||||||
|
|
||||||
|
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: vec![],
|
||||||
|
},
|
||||||
|
)
|
||||||
|
.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
|
||||||
|
}
|
8
gameserver/src/net/mod.rs
Normal file
8
gameserver/src/net/mod.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
pub mod gateway;
|
||||||
|
|
||||||
|
mod handlers;
|
||||||
|
mod packet;
|
||||||
|
mod session;
|
||||||
|
|
||||||
|
pub use packet::NetPacket;
|
||||||
|
pub use session::PlayerSession;
|
1422
gameserver/src/net/packet.rs
Normal file
1422
gameserver/src/net/packet.rs
Normal file
File diff suppressed because it is too large
Load diff
40
gameserver/src/net/session.rs
Normal file
40
gameserver/src/net/session.rs
Normal file
|
@ -0,0 +1,40 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use prost::Message;
|
||||||
|
use tokio::{io::AsyncWriteExt, net::TcpStream};
|
||||||
|
|
||||||
|
use super::{packet::CommandHandler, NetPacket};
|
||||||
|
|
||||||
|
pub struct PlayerSession {
|
||||||
|
pub(crate) client_socket: TcpStream,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PlayerSession {
|
||||||
|
pub const fn new(client_socket: TcpStream) -> Self {
|
||||||
|
Self { client_socket }
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn run(&mut self) -> Result<()> {
|
||||||
|
loop {
|
||||||
|
let net_packet = NetPacket::read(&mut self.client_socket).await?;
|
||||||
|
Self::on_message(self, net_packet.cmd_type, net_packet.body).await?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub async fn send(&mut self, cmd_type: u16, body: impl Message) -> Result<()> {
|
||||||
|
let mut buf = Vec::new();
|
||||||
|
body.encode(&mut buf)?;
|
||||||
|
|
||||||
|
let payload: Vec<u8> = NetPacket {
|
||||||
|
cmd_type,
|
||||||
|
head: Vec::new(),
|
||||||
|
body: buf,
|
||||||
|
}
|
||||||
|
.into();
|
||||||
|
|
||||||
|
self.client_socket.write_all(&payload).await?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Auto implemented
|
||||||
|
impl CommandHandler for PlayerSession {}
|
8
gameserver/src/util.rs
Normal file
8
gameserver/src/util.rs
Normal file
|
@ -0,0 +1,8 @@
|
||||||
|
use std::time::{SystemTime, UNIX_EPOCH};
|
||||||
|
|
||||||
|
pub fn cur_timestamp_ms() -> u64 {
|
||||||
|
SystemTime::now()
|
||||||
|
.duration_since(UNIX_EPOCH)
|
||||||
|
.unwrap()
|
||||||
|
.as_millis() as u64
|
||||||
|
}
|
11
proto/Cargo.toml
Normal file
11
proto/Cargo.toml
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
[package]
|
||||||
|
name = "proto"
|
||||||
|
edition = "2021"
|
||||||
|
version.workspace = true
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
prost.workspace = true
|
||||||
|
prost-types.workspace = true
|
||||||
|
|
||||||
|
[build-dependencies]
|
||||||
|
prost-build.workspace = true
|
11
proto/build.rs
Normal file
11
proto/build.rs
Normal file
|
@ -0,0 +1,11 @@
|
||||||
|
pub fn main() {
|
||||||
|
let proto_file = "StarRail.proto";
|
||||||
|
if std::path::Path::new(proto_file).exists() {
|
||||||
|
println!("cargo:rerun-if-changed={proto_file}");
|
||||||
|
|
||||||
|
prost_build::Config::new()
|
||||||
|
.out_dir("out/")
|
||||||
|
.compile_protos(&[proto_file], &["."])
|
||||||
|
.unwrap();
|
||||||
|
}
|
||||||
|
}
|
0
proto/out/.gitkeep
Normal file
0
proto/out/.gitkeep
Normal file
35124
proto/out/_.rs
Normal file
35124
proto/out/_.rs
Normal file
File diff suppressed because it is too large
Load diff
1323
proto/src/cmd_types.rs
Normal file
1323
proto/src/cmd_types.rs
Normal file
File diff suppressed because it is too large
Load diff
4
proto/src/lib.rs
Normal file
4
proto/src/lib.rs
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
mod cmd_types;
|
||||||
|
pub use cmd_types::*;
|
||||||
|
|
||||||
|
include!("../out/_.rs");
|
28
sdkserver/Cargo.toml
Normal file
28
sdkserver/Cargo.toml
Normal file
|
@ -0,0 +1,28 @@
|
||||||
|
[package]
|
||||||
|
name = "sdkserver"
|
||||||
|
version = "0.1.0"
|
||||||
|
edition = "2021"
|
||||||
|
|
||||||
|
[dependencies]
|
||||||
|
anyhow.workspace = true
|
||||||
|
env_logger.workspace = true
|
||||||
|
|
||||||
|
axum.workspace = true
|
||||||
|
axum-server.workspace = true
|
||||||
|
|
||||||
|
serde.workspace = true
|
||||||
|
serde_json.workspace = true
|
||||||
|
|
||||||
|
tokio.workspace = true
|
||||||
|
tokio-util.workspace = true
|
||||||
|
|
||||||
|
tracing.workspace = true
|
||||||
|
tracing-futures.workspace = true
|
||||||
|
tracing-log.workspace = true
|
||||||
|
tracing-subscriber.workspace = true
|
||||||
|
tracing-bunyan-formatter.workspace = true
|
||||||
|
ansi_term.workspace = true
|
||||||
|
|
||||||
|
prost.workspace = true
|
||||||
|
rbase64.workspace = true
|
||||||
|
proto.workspace = true
|
29
sdkserver/src/logging.rs
Normal file
29
sdkserver/src/logging.rs
Normal file
|
@ -0,0 +1,29 @@
|
||||||
|
#[macro_export]
|
||||||
|
macro_rules! log_error {
|
||||||
|
($e:expr) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($context:expr, $e:expr $(,)?) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
let e = format!("{:?}", ::anyhow::anyhow!(e).context($context));
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
($ok_context:expr, $err_context:expr, $e:expr $(,)?) => {
|
||||||
|
if let Err(e) = $e {
|
||||||
|
let e = format!("{:?}", ::anyhow::anyhow!(e).context($err_context));
|
||||||
|
tracing::error!(error.message = %format!("{}", &e), "{:?}", e);
|
||||||
|
} else {
|
||||||
|
tracing::info!($ok_context);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn init_tracing() {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
ansi_term::enable_ansi_support().unwrap();
|
||||||
|
|
||||||
|
env_logger::init_from_env(env_logger::Env::new().default_filter_or("info"));
|
||||||
|
}
|
51
sdkserver/src/main.rs
Normal file
51
sdkserver/src/main.rs
Normal file
|
@ -0,0 +1,51 @@
|
||||||
|
use anyhow::Result;
|
||||||
|
use axum::routing::{get, post};
|
||||||
|
use axum::Router;
|
||||||
|
use logging::init_tracing;
|
||||||
|
use services::{auth, dispatch, errors};
|
||||||
|
use tracing::Level;
|
||||||
|
|
||||||
|
mod logging;
|
||||||
|
mod services;
|
||||||
|
|
||||||
|
const PORT: u16 = 21000;
|
||||||
|
|
||||||
|
#[tokio::main]
|
||||||
|
async fn main() -> Result<()> {
|
||||||
|
init_tracing();
|
||||||
|
|
||||||
|
let span = tracing::span!(Level::DEBUG, "main");
|
||||||
|
let _ = span.enter();
|
||||||
|
|
||||||
|
let router = Router::new()
|
||||||
|
.route(
|
||||||
|
dispatch::QUERY_DISPATCH_ENDPOINT,
|
||||||
|
get(dispatch::query_dispatch),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
dispatch::QUERY_GATEWAY_ENDPOINT,
|
||||||
|
get(dispatch::query_gateway),
|
||||||
|
)
|
||||||
|
.route(auth::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check))
|
||||||
|
.route(
|
||||||
|
auth::LOGIN_WITH_PASSWORD_ENDPOINT,
|
||||||
|
post(auth::login_with_password),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
auth::LOGIN_WITH_SESSION_TOKEN_ENDPOINT,
|
||||||
|
post(auth::login_with_session_token),
|
||||||
|
)
|
||||||
|
.route(
|
||||||
|
auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT,
|
||||||
|
post(auth::granter_login_verification),
|
||||||
|
)
|
||||||
|
.fallback(errors::not_found);
|
||||||
|
|
||||||
|
let addr = format!("0.0.0.0:{PORT}");
|
||||||
|
let server = axum_server::bind(addr.parse()?);
|
||||||
|
|
||||||
|
tracing::info!("sdkserver is listening at {addr}");
|
||||||
|
server.serve(router.into_make_service()).await?;
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
80
sdkserver/src/services/auth.rs
Normal file
80
sdkserver/src/services/auth.rs
Normal file
|
@ -0,0 +1,80 @@
|
||||||
|
use axum::Json;
|
||||||
|
use serde_json::json;
|
||||||
|
|
||||||
|
pub const LOGIN_WITH_PASSWORD_ENDPOINT: &str = "/:product_name/mdk/shield/api/login/";
|
||||||
|
pub const LOGIN_WITH_SESSION_TOKEN_ENDPOINT: &str = "/:product_name/mdk/shield/api/verify";
|
||||||
|
pub const GRANTER_LOGIN_VERIFICATION_ENDPOINT: &str = "/:product_name/combo/granter/login/v2/login";
|
||||||
|
pub const RISKY_API_CHECK_ENDPOINT: &str = "/account/risky/api/check";
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn login_with_password() -> Json<serde_json::Value> {
|
||||||
|
Json(json!({
|
||||||
|
"data": {
|
||||||
|
"account": {
|
||||||
|
"area_code": "**",
|
||||||
|
"email": "ReversedRooms",
|
||||||
|
"country": "RU",
|
||||||
|
"is_email_verify": "1",
|
||||||
|
"token": "mostsecuretokenever",
|
||||||
|
"uid": "1337"
|
||||||
|
},
|
||||||
|
"device_grant_required": false,
|
||||||
|
"reactivate_required": false,
|
||||||
|
"realperson_required": false,
|
||||||
|
"safe_mobile_required": false
|
||||||
|
},
|
||||||
|
"message": "OK",
|
||||||
|
"retcode": 0
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn login_with_session_token() -> Json<serde_json::Value> {
|
||||||
|
Json(json!({
|
||||||
|
"data": {
|
||||||
|
"account": {
|
||||||
|
"area_code": "**",
|
||||||
|
"email": "ReversedRooms",
|
||||||
|
"country": "RU",
|
||||||
|
"is_email_verify": "1",
|
||||||
|
"token": "mostsecuretokenever",
|
||||||
|
"uid": "1337"
|
||||||
|
},
|
||||||
|
"device_grant_required": false,
|
||||||
|
"reactivate_required": false,
|
||||||
|
"realperson_required": false,
|
||||||
|
"safe_mobile_required": false
|
||||||
|
},
|
||||||
|
"message": "OK",
|
||||||
|
"retcode": 0
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn granter_login_verification() -> Json<serde_json::Value> {
|
||||||
|
Json(json!({
|
||||||
|
"data": {
|
||||||
|
"account_type": 1,
|
||||||
|
"combo_id": "1337",
|
||||||
|
"combo_token": "9065ad8507d5a1991cb6fddacac5999b780bbd92",
|
||||||
|
"data": "{\"guest\":false}",
|
||||||
|
"heartbeat": false,
|
||||||
|
"open_id": "1337"
|
||||||
|
},
|
||||||
|
"message": "OK",
|
||||||
|
"retcode": 0
|
||||||
|
}))
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn risky_api_check() -> Json<serde_json::Value> {
|
||||||
|
Json(json!({
|
||||||
|
"data": {
|
||||||
|
"id": "06611ed14c3131a676b19c0d34c0644b",
|
||||||
|
"action": "ACTION_NONE",
|
||||||
|
"geetest": null
|
||||||
|
},
|
||||||
|
"message": "OK",
|
||||||
|
"retcode": 0
|
||||||
|
}))
|
||||||
|
}
|
65
sdkserver/src/services/dispatch.rs
Normal file
65
sdkserver/src/services/dispatch.rs
Normal file
|
@ -0,0 +1,65 @@
|
||||||
|
use prost::Message;
|
||||||
|
use proto::{Dispatch, Gateserver, RegionInfo};
|
||||||
|
|
||||||
|
pub const QUERY_DISPATCH_ENDPOINT: &str = "/query_dispatch";
|
||||||
|
pub const QUERY_GATEWAY_ENDPOINT: &str = "/query_gateway";
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn query_dispatch() -> String {
|
||||||
|
let rsp = Dispatch {
|
||||||
|
retcode: 0,
|
||||||
|
region_list: vec![RegionInfo {
|
||||||
|
name: String::from("RobinSR"),
|
||||||
|
title: String::from("RobinSR"),
|
||||||
|
env_type: String::from("9"),
|
||||||
|
dispatch_url: String::from("http://127.0.0.1:21000/query_gateway"),
|
||||||
|
..Default::default()
|
||||||
|
}],
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
rsp.encode(&mut buff).unwrap();
|
||||||
|
|
||||||
|
rbase64::encode(&buff)
|
||||||
|
}
|
||||||
|
|
||||||
|
#[tracing::instrument]
|
||||||
|
pub async fn query_gateway() -> String {
|
||||||
|
let rsp = Gateserver {
|
||||||
|
retcode: 0,
|
||||||
|
ip: String::from("127.0.0.1"),
|
||||||
|
port: 23301,
|
||||||
|
asset_bundle_url: String::from(
|
||||||
|
"https://autopatchcn.bhsr.com/asb/BetaLive/output_6744505_89b2f5dc973e",
|
||||||
|
),
|
||||||
|
lua_url: String::from(
|
||||||
|
"https://autopatchcn.bhsr.com/lua/BetaLive/output_6755976_3c46d7c46e2c",
|
||||||
|
),
|
||||||
|
ex_resource_url: String::from(
|
||||||
|
"https://autopatchcn.bhsr.com/design_data/BetaLive/output_6759713_b4e0e740f0da",
|
||||||
|
),
|
||||||
|
ifix_version: String::from("0"),
|
||||||
|
lua_version: String::from("6755976"),
|
||||||
|
jblkncaoiao: true,
|
||||||
|
hjdjakjkdbi: true,
|
||||||
|
ldknmcpffim: true,
|
||||||
|
feehapamfci: true,
|
||||||
|
eebfeohfpph: true,
|
||||||
|
dfmjjcfhfea: true,
|
||||||
|
najikcgjgan: true,
|
||||||
|
giddjofkndm: true,
|
||||||
|
fbnbbembcgn: false,
|
||||||
|
dedgfjhbnok: false,
|
||||||
|
use_tcp: true,
|
||||||
|
linlaijbboh: false,
|
||||||
|
ahmbfbkhmgh: false,
|
||||||
|
nmdccehcdcc: false,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
let mut buff = Vec::new();
|
||||||
|
rsp.encode(&mut buff).unwrap();
|
||||||
|
|
||||||
|
rbase64::encode(&buff)
|
||||||
|
}
|
7
sdkserver/src/services/errors.rs
Normal file
7
sdkserver/src/services/errors.rs
Normal file
|
@ -0,0 +1,7 @@
|
||||||
|
use axum::http::{StatusCode, Uri};
|
||||||
|
use axum::response::IntoResponse;
|
||||||
|
|
||||||
|
pub async fn not_found(uri: Uri) -> impl IntoResponse {
|
||||||
|
tracing::warn!("unhandled http request: {uri}");
|
||||||
|
StatusCode::NOT_FOUND
|
||||||
|
}
|
3
sdkserver/src/services/mod.rs
Normal file
3
sdkserver/src/services/mod.rs
Normal file
|
@ -0,0 +1,3 @@
|
||||||
|
pub mod auth;
|
||||||
|
pub mod dispatch;
|
||||||
|
pub mod errors;
|
Loading…
Reference in a new issue