Compare commits

..

No commits in common. "master" and "0.1.2" have entirely different histories.

47 changed files with 294 additions and 4964 deletions

View file

@ -1,2 +0,0 @@
[alias]
xtask = "run --package xtask --"

1
.gitignore vendored
View file

@ -1,4 +1,3 @@
target/ target/
Cargo.lock Cargo.lock
proto/StarRail.proto proto/StarRail.proto
/*.json

View file

@ -1,5 +1,5 @@
[workspace] [workspace]
members = ["common", "dispatch", "gameserver", "proto", "sdkserver", "xtask"] members = [ "gameserver", "proto", "sdkserver"]
resolver = "2" resolver = "2"
[workspace.package] [workspace.package]
@ -13,10 +13,6 @@ lazy_static = "1.4.0"
axum = "0.7.4" axum = "0.7.4"
axum-server = "0.6.0" axum-server = "0.6.0"
tower = "0.4.13"
tower-http = { version = "0.5.2", features = ["normalize-path"] }
hyper = { version = "1.3.0", features = [ "client" ] }
hyper-util = { version = "0.1.3", features = [ "client-legacy" ] }
dirs = "5.0.1" dirs = "5.0.1"
dotenv = "0.15.0" dotenv = "0.15.0"
@ -53,7 +49,6 @@ tracing-subscriber = { version = "0.3.18", features = [
] } ] }
tracing-bunyan-formatter = "0.3.9" tracing-bunyan-formatter = "0.3.9"
common = { path = "common/" }
proto = { path = "proto/" } proto = { path = "proto/" }
[profile.release] [profile.release]

View file

@ -208,7 +208,7 @@ If you develop a new program, and you want it to be of the greatest possible use
To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found. To do so, attach the following notices to the program. It is safest to attach them to the start of each source file to most effectively state the exclusion of warranty; and each file should have at least the “copyright” line and a pointer to where the full notice is found.
AcheronSR RobinSR
Copyright (C) 2024 reversedrooms Copyright (C) 2024 reversedrooms
This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version.
@ -221,7 +221,7 @@ Also add information on how to contact you by electronic and paper mail.
If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode: If the program does terminal interaction, make it output a short notice like this when it starts in an interactive mode:
AcheronSR Copyright (C) 2024 reversedrooms RobinSR Copyright (C) 2024 reversedrooms
This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'. This program comes with ABSOLUTELY NO WARRANTY; for details type `show w'.
This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details. This is free software, and you are welcome to redistribute it under certain conditions; type `show c' for details.

View file

@ -1,7 +1,7 @@
# AcheronSR # RobinSR
A Server emulator for the game [`Honkai: Star Rail`](https://hsr.hoyoverse.com/en-us/) A Server emulator for the game [`Honkai: Star Rail`](https://hsr.hoyoverse.com/en-us/)
![screenshot](https://git.xeondev.com/reversedrooms/AcheronSR/raw/branch/master/screenshot.png) ![screenshot](https://git.xeondev.com/reversedrooms/RobinSR/raw/branch/master/screenshot.png)
## Installation ## Installation
@ -11,56 +11,52 @@ A Server emulator for the game [`Honkai: Star Rail`](https://hsr.hoyoverse.com/e
- [Rust](https://www.rust-lang.org/tools/install) - [Rust](https://www.rust-lang.org/tools/install)
**NOTE**: Nightly Rust is required to build the project. To install it, first install
Rust itself, then run the following command:
```sh
rustup toolchain install nightly
rustup default nightly
```
#### Building #### Building
##### Manually
```sh ```sh
git clone https://git.xeondev.com/reversedrooms/AcheronSR.git git clone https://git.xeondev.com/reversedrooms/RobinSR.git
cd AcheronSR cd RobinSR
cargo build --bin gameserver cargo install --path gameserver
cargo build --bin dispatch cargo install --path sdkserver
cargo build --bin sdkserver
```
##### Using xtasks (use this if stupid)
```sh
cargo xtask run
```
##### To run it with automatic recompilation when any Rust files are changed
```sh
cargo xtask watch
``` ```
### From Pre-built Binaries ### From Pre-built Binaries
Navigate to the [Releases](https://git.xeondev.com/reversedrooms/AcheronSR/releases) Navigate to the [Releases](https://git.xeondev.com/reversedrooms/RobinSR/releases)
page and download the latest release for your platform. page and download the latest release for your platform.
## Usage ## Usage
To begin using the server, you need to run both the SDK server and the game server. To begin using the server, you need to run both the SDK server and the game server.
If you installed from source, Rust's installer should have added .cargo/bin to your
path, so simply run the following:
```sh
gameserver
sdkserver
```
If you installed from pre-built binaries, navigate to the directory where you downloaded If you installed from pre-built binaries, navigate to the directory where you downloaded
the binaries and either a) double-click on the following executable names or b) the binaries and either a) double-click on the following executable names or b)
run the following in a terminal: run the following in a terminal:
```sh ```sh
./gameserver ./gameserver
./dispatch
./sdkserver ./sdkserver
``` ```
##### Note: the `assets` folder should be in the same directory with the `gameserver`, otherwise it will panic.
## Connecting ## Connecting
[Get 2.2 beta client](https://bhrpg-prod.oss-accelerate.aliyuncs.com/client/beta/20240322124944_scfGE0xJXlWtoJ1r/StarRail_2.1.51.zip), [Get 2.2 beta client](https://bhrpg-prod.oss-accelerate.aliyuncs.com/client/beta/20240322124944_scfGE0xJXlWtoJ1r/StarRail_2.1.51.zip),
replace [mhypbase.dll](https://git.xeondev.com/reversedrooms/AcheronSR/raw/branch/master/mhypbase.dll) replace [mhypbase.dll](https://git.xeondev.com/reversedrooms/RobinSR/raw/branch/master/mhypbase.dll) file in your game folder, it will redirect game traffic (and also disable in-game censorship)
file in your game folder, it will redirect game traffic (and disable in-game censorship)
## Contributing ## Contributing

File diff suppressed because it is too large Load diff

View file

@ -1,13 +0,0 @@
[package]
name = "common"
edition = "2021"
version.workspace = true
[dependencies]
anyhow.workspace = true
ansi_term.workspace = true
env_logger.workspace = true
tracing.workspace = true
lazy_static.workspace = true
serde.workspace = true
serde_json.workspace = true

View file

@ -1,20 +0,0 @@
use serde::Deserialize;
#[derive(Default, Deserialize)]
#[serde(rename_all = "PascalCase")]
#[serde(default)]
pub struct MapEntranceConfig {
#[serde(rename = "BeginMainMissionIDList")]
pub begin_main_mission_idlist: Vec<u32>,
pub entrance_type: String,
#[serde(rename = "FinishMainMissionIDList")]
pub finish_main_mission_idlist: Vec<u32>,
#[serde(rename = "FinishSubMissionIDList")]
pub finish_sub_mission_idlist: Vec<u32>,
#[serde(rename = "FloorID")]
pub floor_id: u32,
#[serde(rename = "ID")]
pub id: u32,
#[serde(rename = "PlaneID")]
pub plane_id: u32,
}

View file

@ -1,37 +0,0 @@
mod excels;
pub use excels::*;
use lazy_static::lazy_static;
use serde_json::from_str;
pub fn init_assets() {
tracing::info!("Loaded {} excel tables", EXCEL_COLLECTION.table_count());
}
lazy_static! {
pub static ref EXCEL_COLLECTION: ExcelCollection = ExcelCollection::new();
}
pub struct ExcelCollection {
pub map_entrance_configs: Vec<MapEntranceConfig>,
}
impl ExcelCollection {
fn new() -> Self {
Self {
map_entrance_configs: from_str(&load_asset(
"assets/ExcelOutput/MapEntranceConfig.json",
))
.unwrap(),
}
}
#[must_use]
pub const fn table_count(&self) -> usize {
1
}
}
fn load_asset(path: &str) -> String {
std::fs::read_to_string(path).unwrap()
}

View file

@ -1,3 +0,0 @@
pub mod data;
pub mod logging;
pub mod util;

View file

@ -1,7 +0,0 @@
#[must_use]
pub fn load_or_create_config(path: &str, defaults: &str) -> String {
std::fs::read_to_string(path).unwrap_or_else(|_| {
std::fs::write(path, defaults).unwrap();
defaults.to_string()
})
}

View file

@ -1,34 +0,0 @@
[package]
name = "dispatch"
edition = "2021"
version.workspace = true
[dependencies]
common.workspace = true
anyhow.workspace = true
env_logger.workspace = true
axum.workspace = true
axum-server.workspace = true
lazy_static.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
tower.workspace = true
tower-http.workspace = true

View file

@ -1,34 +0,0 @@
{
"http_port": 21041,
"game_servers": {
"acheron_sr": {
"name": "AcheronSR",
"title": "AcheronSR",
"dispatch_url": "http://127.0.0.1:21041/query_gateway/acheron_sr",
"env_type": "2",
"gateserver_ip": "127.0.0.1",
"gateserver_port": 23301,
"gateserver_protocol": "Tcp"
}
},
"versions": {
"CNBETAWin2.1.51": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6744505_89b2f5dc973e",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6759713_b4e0e740f0da",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6755976_3c46d7c46e2c",
"lua_version": "6755976"
},
"CNBETAWin2.1.52": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6785106_15237df2ef89",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6787319_5f3f1dae4769",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6785460_26c4b6c61a8b",
"lua_version": "6785460"
},
"CNBETAWin2.1.53": {
"asset_bundle_url": "https://autopatchcn.bhsr.com/asb/BetaLive/output_6828321_72f2df86102b",
"ex_resource_url": "https://autopatchcn.bhsr.com/design_data/BetaLive/output_6834225_44836493b261",
"lua_url": "https://autopatchcn.bhsr.com/lua/BetaLive/output_6828764_f749b48347fd",
"lua_version": "6828764"
}
}
}

View file

@ -1,51 +0,0 @@
use std::collections::HashMap;
use common::util::load_or_create_config;
use lazy_static::lazy_static;
use serde::Deserialize;
use serde_json::from_str;
const DEFAULT_CONFIG: &str = include_str!("../dispatch.json");
pub fn init_config() {
let _configuration = &*CONFIGURATION;
}
#[derive(Deserialize)]
pub struct DispatchServerConfiguration {
pub http_port: u16,
pub game_servers: HashMap<String, GameServerConfig>,
pub versions: HashMap<String, VersionConfig>,
}
#[derive(Deserialize)]
pub struct VersionConfig {
pub asset_bundle_url: String,
pub ex_resource_url: String,
pub lua_url: String,
pub lua_version: String,
}
#[derive(Deserialize)]
pub struct GameServerConfig {
pub name: String,
pub title: String,
pub dispatch_url: String,
pub env_type: String,
pub gateserver_ip: String,
pub gateserver_port: u16,
pub gateserver_protocol: GatewayProtocolType,
}
#[derive(Deserialize, Eq, PartialEq)]
pub enum GatewayProtocolType {
Tcp,
Kcp,
}
lazy_static! {
pub static ref CONFIGURATION: DispatchServerConfiguration = {
let data = load_or_create_config("dispatch.json", DEFAULT_CONFIG);
from_str(&data).unwrap()
};
}

View file

@ -1,85 +0,0 @@
use crate::config::*;
use axum::extract::{Path, Query};
use prost::Message;
use proto::{Dispatch, Gateserver, RegionInfo};
use serde::Deserialize;
pub const QUERY_DISPATCH_PATH: &str = "/query_dispatch";
pub const QUERY_GATEWAY_PATH: &str = "/query_gateway/:region_name";
#[tracing::instrument]
pub async fn query_dispatch() -> String {
let rsp = Dispatch {
retcode: 0,
region_list: CONFIGURATION
.game_servers
.values()
.map(|c| RegionInfo {
name: c.name.clone(),
title: c.title.clone(),
env_type: c.env_type.clone(),
dispatch_url: c.dispatch_url.clone(),
..Default::default()
})
.collect(),
..Default::default()
};
let mut buff = Vec::new();
rsp.encode(&mut buff).unwrap();
rbase64::encode(&buff)
}
#[derive(Deserialize, Debug)]
pub struct QueryGatewayParameters {
pub version: String,
}
#[tracing::instrument]
pub async fn query_gateway(
Path(region_name): Path<String>,
parameters: Query<QueryGatewayParameters>,
) -> String {
let rsp = if let Some(server_config) = CONFIGURATION.game_servers.get(&region_name) {
if let Some(version_config) = CONFIGURATION.versions.get(&parameters.version) {
Gateserver {
retcode: 0,
ip: server_config.gateserver_ip.clone(),
port: u32::from(server_config.gateserver_port),
asset_bundle_url: version_config.asset_bundle_url.clone(),
ex_resource_url: version_config.ex_resource_url.clone(),
lua_url: version_config.lua_url.clone(),
lua_version: version_config.lua_version.clone(),
ifix_version: String::from("0"),
jblkncaoiao: true,
hjdjakjkdbi: true,
ldknmcpffim: true,
feehapamfci: true,
eebfeohfpph: true,
dfmjjcfhfea: true,
najikcgjgan: true,
giddjofkndm: true,
use_tcp: server_config.gateserver_protocol == GatewayProtocolType::Tcp,
..Default::default()
}
} else {
Gateserver {
retcode: 9,
msg: format!("forbidden version: {} or invalid bind", parameters.version),
..Default::default()
}
}
} else {
Gateserver {
retcode: 9,
msg: format!("server config for {region_name} not found"),
..Default::default()
}
};
let mut buff = Vec::new();
rsp.encode(&mut buff).unwrap();
rbase64::encode(&buff)
}

View file

@ -1,35 +0,0 @@
use anyhow::Result;
use axum::{extract::Request, routing::get, Router, ServiceExt};
use common::logging::init_tracing;
use tokio::net::TcpListener;
use tower::Layer;
use tower_http::normalize_path::NormalizePathLayer;
use tracing::Level;
mod config;
mod handlers;
use config::{init_config, CONFIGURATION};
#[tokio::main]
async fn main() -> Result<()> {
init_tracing();
init_config();
let span = tracing::span!(Level::DEBUG, "main");
let _ = span.enter();
let app = Router::new()
.route(handlers::QUERY_DISPATCH_PATH, get(handlers::query_dispatch))
.route(handlers::QUERY_GATEWAY_PATH, get(handlers::query_gateway));
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
let addr = format!("0.0.0.0:{}", CONFIGURATION.http_port);
let server = TcpListener::bind(&addr).await?;
tracing::info!("dispatch is listening at {addr}");
axum::serve(server, ServiceExt::<Request>::into_make_service(app)).await?;
Ok(())
}

View file

@ -4,8 +4,6 @@ edition = "2021"
version.workspace = true version.workspace = true
[dependencies] [dependencies]
common.workspace = true
ansi_term.workspace = true ansi_term.workspace = true
anyhow.workspace = true anyhow.workspace = true
atomic_refcell.workspace = true atomic_refcell.workspace = true

View file

@ -1,5 +1,5 @@
{ {
"lineup": [1308, 1309, 1307, 1315], "lineup": [1309, 1308, 1307, 1315],
"monster_wave_list": "monster_wave_list":
[ [
[3013010, 3013010], [3013010, 3013010],

View file

@ -1,4 +1,3 @@
use common::util::load_or_create_config;
use lazy_static::lazy_static; use lazy_static::lazy_static;
use serde::Deserialize; use serde::Deserialize;
use serde_json::from_str; use serde_json::from_str;
@ -7,7 +6,25 @@ const DEFAULT_GLOBALS: &str = include_str!("../../globals.json");
lazy_static! { lazy_static! {
pub static ref INSTANCE: Globals = { pub static ref INSTANCE: Globals = {
let data = load_or_create_config("globals.json", DEFAULT_GLOBALS); let local_config = std::path::Path::new("globals.json");
let data = if local_config.exists() {
std::fs::read_to_string("globals.json").unwrap()
} else {
let config = dirs::config_dir()
.expect("No config directory found")
.join("hkrpg-gameserver");
std::fs::create_dir_all(&config).unwrap();
let env = config.join("globals.json");
if !env.exists() {
std::fs::write(&env, DEFAULT_GLOBALS).unwrap();
}
std::fs::read_to_string(&env).unwrap()
};
from_str(&data).unwrap() from_str(&data).unwrap()
}; };
} }

View file

@ -3,7 +3,3 @@ mod player_info;
pub use global_config::INSTANCE as globals; pub use global_config::INSTANCE as globals;
pub use player_info::PlayerInfo; pub use player_info::PlayerInfo;
pub fn init_config() {
let _globals = &*globals; // this will initialize the static (and create default config)
}

View file

@ -5,14 +5,12 @@ use anyhow::Result;
use proto::*; use proto::*;
pub struct PlayerInfo { pub struct PlayerInfo {
pub uid: u32,
pub lineup: LineupInfo, pub lineup: LineupInfo,
} }
impl PlayerInfo { impl PlayerInfo {
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
uid: 1337,
lineup: default_lineup(), lineup: default_lineup(),
} }
} }

View file

@ -1,19 +1,15 @@
use anyhow::Result; use anyhow::Result;
mod game; mod game;
mod logging;
mod net; mod net;
mod util; mod util;
use common::data::init_assets; use logging::init_tracing;
use common::logging::init_tracing;
use game::init_config;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
init_tracing(); init_tracing();
init_config();
init_assets();
net::gateway::listen("0.0.0.0", 23301).await?; net::gateway::listen("0.0.0.0", 23301).await?;
Ok(()) Ok(())

View file

@ -1,9 +1,8 @@
use anyhow::Result; use anyhow::Result;
use common::log_error;
use tokio::net::TcpListener; use tokio::net::TcpListener;
use tracing::{info_span, Instrument}; use tracing::{info_span, Instrument};
use crate::net::PlayerSession; use crate::{log_error, net::PlayerSession};
pub async fn listen(host: &str, port: u16) -> Result<()> { pub async fn listen(host: &str, port: u16) -> Result<()> {
let listener = TcpListener::bind(format!("{host}:{port}")).await?; let listener = TcpListener::bind(format!("{host}:{port}")).await?;

View file

@ -13,7 +13,7 @@ pub async fn on_player_get_token_cs_req(
PlayerGetTokenScRsp { PlayerGetTokenScRsp {
retcode: 0, retcode: 0,
msg: String::from("OK"), msg: String::from("OK"),
uid: session.player_uid(), uid: 1337,
..Default::default() ..Default::default()
}, },
) )
@ -32,7 +32,7 @@ pub async fn on_player_login_cs_req(
server_timestamp_ms: util::cur_timestamp_ms(), server_timestamp_ms: util::cur_timestamp_ms(),
stamina: 240, stamina: 240,
basic_info: Some(PlayerBasicInfo { basic_info: Some(PlayerBasicInfo {
nickname: String::from("AcheronSR"), nickname: String::from("xeondev"),
level: 5, level: 5,
stamina: 240, stamina: 240,
..Default::default() ..Default::default()

View file

@ -137,8 +137,7 @@ pub async fn on_quit_lineup_cs_req(session: &PlayerSession, body: &QuitLineupCsR
.await .await
} }
#[must_use] fn lineup_avatar(id: u32, slot: u32) -> LineupAvatar {
const fn lineup_avatar(id: u32, slot: u32) -> LineupAvatar {
LineupAvatar { LineupAvatar {
id, id,
slot, slot,

View file

@ -1,27 +0,0 @@
use super::*;
pub async fn on_get_scene_map_info_cs_req(
session: &PlayerSession,
body: &GetSceneMapInfoCsReq,
) -> Result<()> {
session
.send(
CMD_GET_SCENE_MAP_INFO_SC_RSP,
GetSceneMapInfoScRsp {
entry_id: body.entry_id,
cur_map_entry_id: body.entry_id,
scene_map_info: body
.entry_id_list
.iter()
.map(|id| SceneMapInfo {
cur_map_entry_id: body.entry_id,
entry_id: *id,
..Default::default()
})
.collect(),
retcode: 0,
..Default::default()
},
)
.await
}

View file

@ -2,7 +2,6 @@ mod authentication;
mod avatar; mod avatar;
mod battle; mod battle;
mod lineup; mod lineup;
mod map;
mod mission; mod mission;
mod player; mod player;
mod scene; mod scene;
@ -20,7 +19,6 @@ pub use authentication::*;
pub use avatar::*; pub use avatar::*;
pub use battle::*; pub use battle::*;
pub use lineup::*; pub use lineup::*;
pub use map::*;
pub use mission::*; pub use mission::*;
pub use player::*; pub use player::*;
pub use scene::*; pub use scene::*;

View file

@ -53,7 +53,7 @@ pub async fn on_player_heart_beat_cs_req(
download_data: Some(ClientDownloadData { download_data: Some(ClientDownloadData {
version: 51, version: 51,
time: util::cur_timestamp_ms() as i64, time: util::cur_timestamp_ms() as i64,
data: rbase64::decode("G0x1YVMBGZMNChoKBAQICHhWAAAAAAAAAAAAAAAod0ABKEBDOlxVc2Vyc1x4ZW9uZGV2XERvd25sb2Fkc1xhY2hlcm9uLmx1YQAAAAAAAAAAAAEEHwAAACQAQAApQEAAKYBAACnAQABWAAEALIAAAR1AQQCkgEEA5ABAAOnAwQHpAMIB6UDCAawAAAEsgAAAH8BChSQAQAApQEAAKYBAACnAQABWAAMALIAAAR1AQQCkgEEA5ABAAOnAwQHpAMIB6UDCAawAAAEsgAAAH0BDhRkAgAAOAAAABANDUwQMVW5pdHlFbmdpbmUEC0dhbWVPYmplY3QEBUZpbmQEKVVJUm9vdC9BYm92ZURpYWxvZy9CZXRhSGludERpYWxvZyhDbG9uZSkEF0dldENvbXBvbmVudEluQ2hpbGRyZW4EB3R5cGVvZgQEUlBHBAdDbGllbnQEDkxvY2FsaXplZFRleHQEBXRleHQULUFjaGVyb25TUiBpcyBhIGZyZWUgYW5kIG9wZW4gc291cmNlIHNvZnR3YXJlBAxWZXJzaW9uVGV4dBQuVmlzaXQgZGlzY29yZC5nZy9yZXZlcnNlZHJvb21zIGZvciBtb3JlIGluZm8hAQAAAAEAAAAAAB8AAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAgAAAAIAAAACAAAAAAAAAAEAAAAFX0VOVg==").unwrap() data: rbase64::decode("G0x1YVMBGZMNChoKBAQICHhWAAAAAAAAAAAAAAAod0ABKEBDOlxVc2Vyc1x4ZW9uZGV2XERvd25sb2Fkc1xyYWJzdHZvLmx1YQAAAAAAAAAAAAEEEAAAACQAQAApQEAAKYBAACnAQABWAAEALIAAAR1AQQCkgEEA5ABAAOnAwQHpAMIB6UDCAawAAAEsgAAAH8BChRkAgAAMAAAABANDUwQMVW5pdHlFbmdpbmUEC0dhbWVPYmplY3QEBUZpbmQEKVVJUm9vdC9BYm92ZURpYWxvZy9CZXRhSGludERpYWxvZyhDbG9uZSkEF0dldENvbXBvbmVudEluQ2hpbGRyZW4EB3R5cGVvZgQEUlBHBAdDbGllbnQEDkxvY2FsaXplZFRleHQEBXRleHQURVJvYmluU1IgaXMgYSBmcmVlIGFuZCBvcGVuIHNvdXJjZSBzb2Z0d2FyZS4gZGlzY29yZC5nZy9yZXZlcnNlZHJvb21zAQAAAAEAAAAAABAAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAQAAAAEAAAABAAAAAAAAAAEAAAAFX0VOVg==").unwrap()
}), }),
}, },
) )

View file

@ -1,36 +1,5 @@
use common::data::EXCEL_COLLECTION;
use super::*; use super::*;
pub async fn on_enter_scene_cs_req(session: &PlayerSession, body: &EnterSceneCsReq) -> Result<()> {
session
.send(CMD_ENTER_SCENE_SC_RSP, EnterSceneScRsp::default())
.await?;
let entrance_config = EXCEL_COLLECTION
.map_entrance_configs
.iter()
.find(|c| c.id == body.entry_id)
.unwrap();
let player = session.player_info();
let enter_scene_by_server = EnterSceneByServerScNotify {
reason: EnterSceneReason::None.into(),
lineup: Some(player.lineup.clone()),
scene: Some(SceneInfo {
plane_id: entrance_config.plane_id,
floor_id: entrance_config.floor_id,
entry_id: entrance_config.id,
game_mode_type: 2, // TODO: EntranceType -> enum repr(u32)
..Default::default()
}),
};
session
.send(CMD_ENTER_SCENE_BY_SERVER_SC_NOTIFY, enter_scene_by_server)
.await
}
pub async fn on_get_cur_scene_info_cs_req( pub async fn on_get_cur_scene_info_cs_req(
session: &PlayerSession, session: &PlayerSession,
_body: &GetCurSceneInfoCsReq, _body: &GetCurSceneInfoCsReq,
@ -57,7 +26,7 @@ pub async fn on_get_cur_scene_info_cs_req(
avatar_type: 3, avatar_type: 3,
base_avatar_id: 1309, base_avatar_id: 1309,
map_layer: 2, map_layer: 2,
uid: session.player_uid(), uid: 1337,
}), }),
motion: Some(MotionInfo { motion: Some(MotionInfo {
aomilajjmii: Some(Vector { aomilajjmii: Some(Vector {

View file

@ -1241,7 +1241,7 @@ trait_handler! {
// SetCurInteractEntityScRsp 1497; // SetCurInteractEntityScRsp 1497;
// SceneCastSkillCsReq 1402; // SceneCastSkillCsReq 1402;
StartCocoonStageCsReq 1408; StartCocoonStageCsReq 1408;
GetSceneMapInfoCsReq 1470; // GetSceneMapInfoCsReq 1470;
// SceneEntityMoveScRsp 1448; // SceneEntityMoveScRsp 1448;
// DeactivateFarmElementScRsp 1467; // DeactivateFarmElementScRsp 1467;
// SetCurInteractEntityCsReq 1491; // SetCurInteractEntityCsReq 1491;
@ -1263,7 +1263,7 @@ trait_handler! {
// GetSpringRecoverDataCsReq 1466; // GetSpringRecoverDataCsReq 1466;
// SceneEntityTeleportScRsp 1415; // SceneEntityTeleportScRsp 1415;
// SetClientPausedScRsp 1465; // SetClientPausedScRsp 1465;
EnterSceneCsReq 1472; // EnterSceneCsReq 1472;
// GetAllServerPrefsDataScRsp 6148; // GetAllServerPrefsDataScRsp 6148;
// GetServerPrefsDataCsReq 6162; // GetServerPrefsDataCsReq 6162;
// UpdateServerPrefsDataScRsp 6109; // UpdateServerPrefsDataScRsp 6109;

View file

@ -51,10 +51,6 @@ impl PlayerSession {
self.client_socket.lock().await self.client_socket.lock().await
} }
pub fn player_uid(&self) -> u32 {
self.player_info().uid
}
pub fn player_info(&self) -> AtomicRef<PlayerInfo> { pub fn player_info(&self) -> AtomicRef<PlayerInfo> {
self.player_info.borrow() self.player_info.borrow()
} }

View file

@ -1,8 +1,6 @@
use std::path::Path;
pub fn main() { pub fn main() {
let proto_file = "StarRail.proto"; let proto_file = "StarRail.proto";
if Path::new(proto_file).exists() { if std::path::Path::new(proto_file).exists() {
println!("cargo:rerun-if-changed={proto_file}"); println!("cargo:rerun-if-changed={proto_file}");
prost_build::Config::new() prost_build::Config::new()

View file

@ -207,7 +207,7 @@ pub struct Cldjmhdelhn {
#[prost(uint32, tag = "2")] #[prost(uint32, tag = "2")]
pub monster_id: u32, pub monster_id: u32,
#[prost(uint32, tag = "3")] #[prost(uint32, tag = "3")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(uint32, tag = "4")] #[prost(uint32, tag = "4")]
pub world_level: u32, pub world_level: u32,
#[prost(int64, tag = "5")] #[prost(int64, tag = "5")]
@ -4549,7 +4549,7 @@ pub struct Acageokchob {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct Hgnpppadonl { pub struct Hgnpppadonl {
#[prost(enumeration = "Pdgndfeojif", tag = "2")] #[prost(enumeration = "Pdgndfeojif", tag = "2")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(enumeration = "Leieahhhhmi", tag = "3")] #[prost(enumeration = "Leieahhhhmi", tag = "3")]
pub jdgielljojd: i32, pub jdgielljojd: i32,
} }
@ -4748,7 +4748,7 @@ pub struct Codlhohjmag {
#[prost(enumeration = "Lcmlaclkndi", tag = "6")] #[prost(enumeration = "Lcmlaclkndi", tag = "6")]
pub hfbfdnemjed: i32, pub hfbfdnemjed: i32,
#[prost(enumeration = "Jgjcjhmakka", tag = "11")] #[prost(enumeration = "Jgjcjhmakka", tag = "11")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
pub jageglcnmjj: u32, pub jageglcnmjj: u32,
#[prost(message, repeated, tag = "3")] #[prost(message, repeated, tag = "3")]
@ -10955,7 +10955,7 @@ pub struct Cnmoppanlgc {
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub iabdegkmaom: u32, pub iabdegkmaom: u32,
#[prost(uint32, tag = "8")] #[prost(uint32, tag = "8")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(uint32, tag = "5")] #[prost(uint32, tag = "5")]
pub ippleljgojk: u32, pub ippleljgojk: u32,
#[prost(message, optional, tag = "14")] #[prost(message, optional, tag = "14")]
@ -12593,7 +12593,7 @@ pub struct AnnounceData {
#[prost(uint32, tag = "3")] #[prost(uint32, tag = "3")]
pub dfbogdogcpp: u32, pub dfbogdogcpp: u32,
#[prost(uint32, tag = "12")] #[prost(uint32, tag = "12")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(string, tag = "6")] #[prost(string, tag = "6")]
pub chjojjlobei: ::prost::alloc::string::String, pub chjojjlobei: ::prost::alloc::string::String,
#[prost(int64, tag = "14")] #[prost(int64, tag = "14")]
@ -13530,7 +13530,7 @@ pub struct Ingnmgnigfo {
#[prost(message, optional, tag = "11")] #[prost(message, optional, tag = "11")]
pub mdnlmmamejd: ::core::option::Option<PunkLordBattleRecord>, pub mdnlmmamejd: ::core::option::Option<PunkLordBattleRecord>,
#[prost(enumeration = "PunkLordMonsterInfoNotifyReason", tag = "13")] #[prost(enumeration = "PunkLordMonsterInfoNotifyReason", tag = "13")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(message, optional, tag = "15")] #[prost(message, optional, tag = "15")]
pub basic_info: ::core::option::Option<Cldjmhdelhn>, pub basic_info: ::core::option::Option<Cldjmhdelhn>,
} }
@ -13590,7 +13590,7 @@ pub struct Kjeaaledkib {
#[prost(int64, tag = "8")] #[prost(int64, tag = "8")]
pub phhhfhobhmk: i64, pub phhhfhobhmk: i64,
#[prost(uint32, tag = "5")] #[prost(uint32, tag = "5")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(uint32, tag = "3")] #[prost(uint32, tag = "3")]
pub blipenmcnbg: u32, pub blipenmcnbg: u32,
#[prost(bool, tag = "4")] #[prost(bool, tag = "4")]
@ -14035,7 +14035,7 @@ pub struct Mipgopjanij {
#[prost(message, optional, tag = "3")] #[prost(message, optional, tag = "3")]
pub lineup: ::core::option::Option<LineupInfo>, pub lineup: ::core::option::Option<LineupInfo>,
#[prost(enumeration = "Mldgocoemih", tag = "1")] #[prost(enumeration = "Mldgocoemih", tag = "1")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(message, optional, tag = "9")] #[prost(message, optional, tag = "9")]
pub scene: ::core::option::Option<SceneInfo>, pub scene: ::core::option::Option<SceneInfo>,
} }
@ -17196,7 +17196,7 @@ pub struct SceneInfo {
#[prost(message, repeated, tag = "497")] #[prost(message, repeated, tag = "497")]
pub chhmmbdhjpg: ::prost::alloc::vec::Vec<Dhkacjhaoid>, pub chhmmbdhjpg: ::prost::alloc::vec::Vec<Dhkacjhaoid>,
#[prost(uint32, repeated, tag = "9")] #[prost(uint32, repeated, tag = "9")]
pub lighten_section_list: ::prost::alloc::vec::Vec<u32>, pub phicefeaigb: ::prost::alloc::vec::Vec<u32>,
#[prost(message, repeated, tag = "7")] #[prost(message, repeated, tag = "7")]
pub env_buff_list: ::prost::alloc::vec::Vec<BuffInfo>, pub env_buff_list: ::prost::alloc::vec::Vec<BuffInfo>,
#[prost(uint32, tag = "8")] #[prost(uint32, tag = "8")]
@ -17813,7 +17813,7 @@ pub struct Eogjjcbdadn {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct EnterSceneCsReq { pub struct Lckgkdehclb {
#[prost(bool, tag = "4")] #[prost(bool, tag = "4")]
pub bfpgcodlocf: bool, pub bfpgcodlocf: bool,
#[prost(uint32, tag = "2")] #[prost(uint32, tag = "2")]
@ -17826,7 +17826,7 @@ pub struct EnterSceneCsReq {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct EnterSceneScRsp { pub struct Ehhfgomdfkd {
#[prost(bool, tag = "9")] #[prost(bool, tag = "9")]
pub bfpgcodlocf: bool, pub bfpgcodlocf: bool,
#[prost(bool, tag = "15")] #[prost(bool, tag = "15")]
@ -17837,11 +17837,11 @@ pub struct EnterSceneScRsp {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct EnterSceneByServerScNotify { pub struct Jdokmmikidp {
#[prost(message, optional, tag = "11")] #[prost(message, optional, tag = "11")]
pub lineup: ::core::option::Option<LineupInfo>, pub lineup: ::core::option::Option<LineupInfo>,
#[prost(enumeration = "EnterSceneReason", tag = "8")] #[prost(enumeration = "Ffnhcbelgpd", tag = "8")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(message, optional, tag = "15")] #[prost(message, optional, tag = "15")]
pub scene: ::core::option::Option<SceneInfo>, pub scene: ::core::option::Option<SceneInfo>,
} }
@ -17859,9 +17859,9 @@ pub struct Bkpebkeapjh {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetSceneMapInfoCsReq { pub struct Fkjoeabiioe {
#[prost(uint32, repeated, tag = "1")] #[prost(uint32, repeated, tag = "1")]
pub entry_id_list: ::prost::alloc::vec::Vec<u32>, pub dmkkkfnkofh: ::prost::alloc::vec::Vec<u32>,
#[prost(uint32, tag = "11")] #[prost(uint32, tag = "11")]
pub entry_id: u32, pub entry_id: u32,
#[prost(bool, tag = "6")] #[prost(bool, tag = "6")]
@ -17872,20 +17872,20 @@ pub struct GetSceneMapInfoCsReq {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct MazePropState { pub struct Kangcibfhee {
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
pub group_id: u32, pub group_id: u32,
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(uint32, tag = "12")] #[prost(uint32, tag = "12")]
pub state: u32, pub state: u32,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct MazeGroup { pub struct Gecjjlmabhp {
#[prost(int64, tag = "14")] #[prost(int64, tag = "14")]
pub modify_time: i64, pub opmnklhfdch: i64,
#[prost(uint32, tag = "8")] #[prost(uint32, tag = "8")]
pub group_id: u32, pub group_id: u32,
#[prost(bool, tag = "5")] #[prost(bool, tag = "5")]
@ -17896,7 +17896,7 @@ pub struct MazeGroup {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct ChestInfo { pub struct Gbiimoglajl {
#[prost(enumeration = "Kihbdaniehp", tag = "3")] #[prost(enumeration = "Kihbdaniehp", tag = "3")]
pub gommoeicmjg: i32, pub gommoeicmjg: i32,
#[prost(uint32, tag = "11")] #[prost(uint32, tag = "11")]
@ -17918,48 +17918,48 @@ pub struct Kbbeoemcdhi {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct SceneMapInfo { pub struct Fjniajephmj {
#[prost(uint32, repeated, tag = "13")] #[prost(uint32, repeated, tag = "13")]
pub unlock_teleport_list: ::prost::alloc::vec::Vec<u32>, pub ojlnmnehgai: ::prost::alloc::vec::Vec<u32>,
#[prost(message, repeated, tag = "11")] #[prost(message, repeated, tag = "11")]
pub aechnhklpkp: ::prost::alloc::vec::Vec<Kbbeoemcdhi>, pub aechnhklpkp: ::prost::alloc::vec::Vec<Kbbeoemcdhi>,
#[prost(message, repeated, tag = "15")] #[prost(message, repeated, tag = "15")]
pub maze_prop_list: ::prost::alloc::vec::Vec<MazePropState>, pub cgkfbhoadpc: ::prost::alloc::vec::Vec<Kangcibfhee>,
#[prost(message, repeated, tag = "6")] #[prost(message, repeated, tag = "6")]
pub dcbdhkkkpgd: ::prost::alloc::vec::Vec<ChestInfo>, pub dcbdhkkkpgd: ::prost::alloc::vec::Vec<Gbiimoglajl>,
#[prost(uint32, tag = "4")] #[prost(uint32, tag = "4")]
pub retcode: u32, pub retcode: u32,
#[prost(message, repeated, tag = "2")] #[prost(message, repeated, tag = "2")]
pub pmolfbcbfpe: ::prost::alloc::vec::Vec<MazeGroup>, pub pmolfbcbfpe: ::prost::alloc::vec::Vec<Gecjjlmabhp>,
#[prost(uint32, tag = "12")] #[prost(uint32, tag = "12")]
pub entry_id: u32, pub entry_id: u32,
#[prost(uint32, tag = "14")] #[prost(uint32, tag = "14")]
pub cur_map_entry_id: u32, pub kjlbpaefaff: u32,
#[prost(uint32, tag = "7")] #[prost(uint32, tag = "7")]
pub cngakkcmonh: u32, pub cngakkcmonh: u32,
#[prost(uint32, repeated, tag = "10")] #[prost(uint32, repeated, tag = "10")]
pub lighten_section_list: ::prost::alloc::vec::Vec<u32>, pub phicefeaigb: ::prost::alloc::vec::Vec<u32>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetSceneMapInfoScRsp { pub struct Cegeebldbke {
#[prost(uint32, tag = "6")] #[prost(uint32, tag = "6")]
pub entry_id: u32, pub entry_id: u32,
#[prost(uint32, repeated, tag = "3")] #[prost(uint32, repeated, tag = "3")]
pub unlock_teleport_list: ::prost::alloc::vec::Vec<u32>, pub ojlnmnehgai: ::prost::alloc::vec::Vec<u32>,
#[prost(message, repeated, tag = "8")] #[prost(message, repeated, tag = "8")]
pub maze_prop_list: ::prost::alloc::vec::Vec<MazePropState>, pub cgkfbhoadpc: ::prost::alloc::vec::Vec<Kangcibfhee>,
#[prost(uint32, tag = "10")] #[prost(uint32, tag = "10")]
pub cur_map_entry_id: u32, pub kjlbpaefaff: u32,
#[prost(message, repeated, tag = "14")] #[prost(message, repeated, tag = "14")]
pub dcbdhkkkpgd: ::prost::alloc::vec::Vec<ChestInfo>, pub dcbdhkkkpgd: ::prost::alloc::vec::Vec<Gbiimoglajl>,
#[prost(uint32, repeated, tag = "9")] #[prost(uint32, repeated, tag = "9")]
pub lighten_section_list: ::prost::alloc::vec::Vec<u32>, pub phicefeaigb: ::prost::alloc::vec::Vec<u32>,
#[prost(message, repeated, tag = "13")] #[prost(message, repeated, tag = "13")]
pub pmolfbcbfpe: ::prost::alloc::vec::Vec<MazeGroup>, pub pmolfbcbfpe: ::prost::alloc::vec::Vec<Gecjjlmabhp>,
#[prost(message, repeated, tag = "2")] #[prost(message, repeated, tag = "2")]
pub scene_map_info: ::prost::alloc::vec::Vec<SceneMapInfo>, pub mhefdgcamjl: ::prost::alloc::vec::Vec<Fjniajephmj>,
#[prost(bool, tag = "5")] #[prost(bool, tag = "5")]
pub dhdoicckifl: bool, pub dhdoicckifl: bool,
#[prost(uint32, tag = "4")] #[prost(uint32, tag = "4")]
@ -17970,11 +17970,11 @@ pub struct GetSceneMapInfoScRsp {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct SyncServerSceneChangeNotify {} pub struct Glknjjgjgjn {}
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GameplayCounterCountDownCsReq { pub struct Onfclaedboj {
#[prost(uint32, tag = "7")] #[prost(uint32, tag = "7")]
pub baokagnfnab: u32, pub baokagnfnab: u32,
#[prost(uint32, tag = "11")] #[prost(uint32, tag = "11")]
@ -17983,16 +17983,16 @@ pub struct GameplayCounterCountDownCsReq {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GameplayCounterCountDownScRsp { pub struct Ppjlpfbfbhd {
#[prost(uint32, tag = "13")] #[prost(uint32, tag = "13")]
pub retcode: u32, pub retcode: u32,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GameplayCounterUpdateScNotify { pub struct Dceecobdeko {
#[prost(enumeration = "Oigihagkoib", tag = "14")] #[prost(enumeration = "Oigihagkoib", tag = "14")]
pub reason: i32, pub bpodijpdnnk: i32,
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub baokagnfnab: u32, pub baokagnfnab: u32,
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
@ -18001,7 +18001,7 @@ pub struct GameplayCounterUpdateScNotify {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GameplayCounterRecoverCsReq { pub struct Lmkkjhdeaph {
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub ifmmefaoeoa: u32, pub ifmmefaoeoa: u32,
#[prost(uint32, tag = "6")] #[prost(uint32, tag = "6")]
@ -18010,35 +18010,32 @@ pub struct GameplayCounterRecoverCsReq {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GameplayCounterRecoverScRsp { pub struct Ijpkjflgcgn {
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
pub retcode: u32, pub retcode: u32,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct UpdateFloorSavedValueNotify { pub struct Fhjnibeddad {
#[prost(map = "string, int32", tag = "6")] #[prost(map = "string, int32", tag = "6")]
pub saved_value_map: ::std::collections::HashMap< pub mbpmoihjnfi: ::std::collections::HashMap<::prost::alloc::string::String, i32>,
::prost::alloc::string::String,
i32,
>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetUnlockTeleportCsReq { pub struct Nmbdnhoimim {
#[prost(uint32, repeated, tag = "1")] #[prost(uint32, repeated, tag = "1")]
pub entry_id_list: ::prost::alloc::vec::Vec<u32>, pub dmkkkfnkofh: ::prost::alloc::vec::Vec<u32>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GetUnlockTeleportScRsp { pub struct Pokegknhbga {
#[prost(uint32, tag = "12")] #[prost(uint32, tag = "12")]
pub retcode: u32, pub retcode: u32,
#[prost(uint32, repeated, tag = "8")] #[prost(uint32, repeated, tag = "8")]
pub unlock_teleport_list: ::prost::alloc::vec::Vec<u32>, pub ojlnmnehgai: ::prost::alloc::vec::Vec<u32>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
@ -18054,22 +18051,22 @@ pub struct Gffbkjofnad {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct GroupRefreshInfo { pub struct Jnofbbanolk {
#[prost(uint32, tag = "4")] #[prost(uint32, tag = "4")]
pub state: u32, pub state: u32,
#[prost(uint32, tag = "1")] #[prost(uint32, tag = "1")]
pub group_id: u32, pub group_id: u32,
#[prost(message, repeated, tag = "14")] #[prost(message, repeated, tag = "14")]
pub fiiciciambe: ::prost::alloc::vec::Vec<Gffbkjofnad>, pub fiiciciambe: ::prost::alloc::vec::Vec<Gffbkjofnad>,
#[prost(enumeration = "SceneGroupRefreshType", tag = "7")] #[prost(enumeration = "Njdmhcchfdj", tag = "7")]
pub group_refresh_type: i32, pub kppckepfpce: i32,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct SceneGroupRefreshScNotify { pub struct Ljihfeagpcl {
#[prost(message, repeated, tag = "14")] #[prost(message, repeated, tag = "14")]
pub group_refresh_list: ::prost::alloc::vec::Vec<GroupRefreshInfo>, pub kpfomkdmoce: ::prost::alloc::vec::Vec<Jnofbbanolk>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
@ -18194,7 +18191,7 @@ pub struct Diplgalkehc {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct Kkbapmgmmcb { pub struct Kkbapmgmmcb {
#[prost(uint32, repeated, tag = "8")] #[prost(uint32, repeated, tag = "8")]
pub entry_id_list: ::prost::alloc::vec::Vec<u32>, pub dmkkkfnkofh: ::prost::alloc::vec::Vec<u32>,
} }
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[allow(clippy::derive_partial_eq_without_eq)] #[allow(clippy::derive_partial_eq_without_eq)]
@ -20231,7 +20228,7 @@ pub struct Loldclbcgpd {
#[derive(Clone, PartialEq, ::prost::Message)] #[derive(Clone, PartialEq, ::prost::Message)]
pub struct Nihdpcfoidb { pub struct Nihdpcfoidb {
#[prost(uint32, tag = "6")] #[prost(uint32, tag = "6")]
pub config_id: u32, pub ifjocipnpgd: u32,
#[prost(uint32, tag = "15")] #[prost(uint32, tag = "15")]
pub group_id: u32, pub group_id: u32,
} }
@ -35476,32 +35473,44 @@ impl Aggoobcfjlh {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)] #[repr(i32)]
pub enum EnterSceneReason { pub enum Ffnhcbelgpd {
None = 0, EnterSceneReasonNone = 0,
ChallengeTimeout = 1, EnterSceneReasonChallengeTimeout = 1,
RogueTimeout = 2, EnterSceneReasonRogueTimeout = 2,
ChangeStoryline = 3, EnterSceneReasonChangeStoryline = 3,
} }
impl EnterSceneReason { impl Ffnhcbelgpd {
/// String value of the enum field names used in the ProtoBuf definition. /// String value of the enum field names used in the ProtoBuf definition.
/// ///
/// The values are not transformed in any way and thus are considered stable /// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use. /// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str { pub fn as_str_name(&self) -> &'static str {
match self { match self {
EnterSceneReason::None => "ENTER_SCENE_REASON_NONE", Ffnhcbelgpd::EnterSceneReasonNone => "ENTER_SCENE_REASON_NONE",
EnterSceneReason::ChallengeTimeout => "ENTER_SCENE_REASON_CHALLENGE_TIMEOUT", Ffnhcbelgpd::EnterSceneReasonChallengeTimeout => {
EnterSceneReason::RogueTimeout => "ENTER_SCENE_REASON_ROGUE_TIMEOUT", "ENTER_SCENE_REASON_CHALLENGE_TIMEOUT"
EnterSceneReason::ChangeStoryline => "ENTER_SCENE_REASON_CHANGE_STORYLINE", }
Ffnhcbelgpd::EnterSceneReasonRogueTimeout => {
"ENTER_SCENE_REASON_ROGUE_TIMEOUT"
}
Ffnhcbelgpd::EnterSceneReasonChangeStoryline => {
"ENTER_SCENE_REASON_CHANGE_STORYLINE"
}
} }
} }
/// Creates an enum from field names used in the ProtoBuf definition. /// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> { pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value { match value {
"ENTER_SCENE_REASON_NONE" => Some(Self::None), "ENTER_SCENE_REASON_NONE" => Some(Self::EnterSceneReasonNone),
"ENTER_SCENE_REASON_CHALLENGE_TIMEOUT" => Some(Self::ChallengeTimeout), "ENTER_SCENE_REASON_CHALLENGE_TIMEOUT" => {
"ENTER_SCENE_REASON_ROGUE_TIMEOUT" => Some(Self::RogueTimeout), Some(Self::EnterSceneReasonChallengeTimeout)
"ENTER_SCENE_REASON_CHANGE_STORYLINE" => Some(Self::ChangeStoryline), }
"ENTER_SCENE_REASON_ROGUE_TIMEOUT" => {
Some(Self::EnterSceneReasonRogueTimeout)
}
"ENTER_SCENE_REASON_CHANGE_STORYLINE" => {
Some(Self::EnterSceneReasonChangeStoryline)
}
_ => None, _ => None,
} }
} }
@ -35591,29 +35600,29 @@ impl Oigihagkoib {
#[derive(serde::Serialize, serde::Deserialize)] #[derive(serde::Serialize, serde::Deserialize)]
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)] #[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, PartialOrd, Ord, ::prost::Enumeration)]
#[repr(i32)] #[repr(i32)]
pub enum SceneGroupRefreshType { pub enum Njdmhcchfdj {
None = 0, SceneGroupRefreshTypeNone = 0,
Loaded = 1, SceneGroupRefreshTypeLoaded = 1,
Unload = 2, SceneGroupRefreshTypeUnload = 2,
} }
impl SceneGroupRefreshType { impl Njdmhcchfdj {
/// String value of the enum field names used in the ProtoBuf definition. /// String value of the enum field names used in the ProtoBuf definition.
/// ///
/// The values are not transformed in any way and thus are considered stable /// The values are not transformed in any way and thus are considered stable
/// (if the ProtoBuf definition does not change) and safe for programmatic use. /// (if the ProtoBuf definition does not change) and safe for programmatic use.
pub fn as_str_name(&self) -> &'static str { pub fn as_str_name(&self) -> &'static str {
match self { match self {
SceneGroupRefreshType::None => "SCENE_GROUP_REFRESH_TYPE_NONE", Njdmhcchfdj::SceneGroupRefreshTypeNone => "SCENE_GROUP_REFRESH_TYPE_NONE",
SceneGroupRefreshType::Loaded => "SCENE_GROUP_REFRESH_TYPE_LOADED", Njdmhcchfdj::SceneGroupRefreshTypeLoaded => "SCENE_GROUP_REFRESH_TYPE_LOADED",
SceneGroupRefreshType::Unload => "SCENE_GROUP_REFRESH_TYPE_UNLOAD", Njdmhcchfdj::SceneGroupRefreshTypeUnload => "SCENE_GROUP_REFRESH_TYPE_UNLOAD",
} }
} }
/// Creates an enum from field names used in the ProtoBuf definition. /// Creates an enum from field names used in the ProtoBuf definition.
pub fn from_str_name(value: &str) -> ::core::option::Option<Self> { pub fn from_str_name(value: &str) -> ::core::option::Option<Self> {
match value { match value {
"SCENE_GROUP_REFRESH_TYPE_NONE" => Some(Self::None), "SCENE_GROUP_REFRESH_TYPE_NONE" => Some(Self::SceneGroupRefreshTypeNone),
"SCENE_GROUP_REFRESH_TYPE_LOADED" => Some(Self::Loaded), "SCENE_GROUP_REFRESH_TYPE_LOADED" => Some(Self::SceneGroupRefreshTypeLoaded),
"SCENE_GROUP_REFRESH_TYPE_UNLOAD" => Some(Self::Unload), "SCENE_GROUP_REFRESH_TYPE_UNLOAD" => Some(Self::SceneGroupRefreshTypeUnload),
_ => None, _ => None,
} }
} }

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.7 MiB

After

Width:  |  Height:  |  Size: 4.7 MiB

4
sdkserver/.env Normal file
View file

@ -0,0 +1,4 @@
ASSET_BUNDLE_URL=https://autopatchcn.bhsr.com/asb/BetaLive/output_6744505_89b2f5dc973e
EX_RESOURCE_URL=https://autopatchcn.bhsr.com/design_data/BetaLive/output_6759713_b4e0e740f0da
LUA_URL=https://autopatchcn.bhsr.com/lua/BetaLive/output_6755976_3c46d7c46e2c
LUA_VERSION=6755976

View file

@ -4,21 +4,15 @@ version = "0.1.0"
edition = "2021" edition = "2021"
[dependencies] [dependencies]
common.workspace = true
anyhow.workspace = true anyhow.workspace = true
env_logger.workspace = true env_logger.workspace = true
axum.workspace = true axum.workspace = true
axum-server.workspace = true axum-server.workspace = true
hyper.workspace = true
hyper-util.workspace = true
dirs.workspace = true dirs.workspace = true
dotenv.workspace = true dotenv.workspace = true
lazy_static.workspace = true
serde.workspace = true serde.workspace = true
serde_json.workspace = true serde_json.workspace = true
@ -32,6 +26,6 @@ tracing-subscriber.workspace = true
tracing-bunyan-formatter.workspace = true tracing-bunyan-formatter.workspace = true
ansi_term.workspace = true ansi_term.workspace = true
tower.workspace = true prost.workspace = true
tower-http.workspace = true rbase64.workspace = true
proto.workspace = true

View file

@ -1,4 +0,0 @@
{
"http_port": 21000,
"dispatch_endpoint": "http://127.0.0.1:21041"
}

View file

@ -1,23 +0,0 @@
use common::util::load_or_create_config;
use lazy_static::lazy_static;
use serde::Deserialize;
use serde_json::from_str;
const DEFAULT_CONFIG: &str = include_str!("../sdkserver.json");
pub fn init_config() {
let _configuration = &*CONFIGURATION;
}
#[derive(Deserialize)]
pub struct SDKServerConfiguration {
pub http_port: u16,
pub dispatch_endpoint: String,
}
lazy_static! {
pub static ref CONFIGURATION: SDKServerConfiguration = {
let data = load_or_create_config("sdkserver.json", DEFAULT_CONFIG);
from_str(&data).unwrap()
};
}

29
sdkserver/src/logging.rs Normal file
View 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"));
}

View file

@ -1,43 +1,33 @@
use anyhow::Result; use anyhow::Result;
use axum::body::Body;
use axum::extract::Request;
use axum::routing::{get, post}; use axum::routing::{get, post};
use axum::{Router, ServiceExt}; use axum::Router;
use hyper_util::{client::legacy::connect::HttpConnector, rt::TokioExecutor}; use logging::init_tracing;
use services::{auth, errors}; use services::{auth, dispatch, errors};
use tokio::net::TcpListener; use std::path::Path;
use tower::Layer;
use tower_http::normalize_path::NormalizePathLayer;
use tracing::Level; use tracing::Level;
type Client = hyper_util::client::legacy::Client<HttpConnector, Body>; mod logging;
mod config;
mod services; mod services;
use common::logging::init_tracing; const PORT: u16 = 21000;
const DEFAULT_DOTENV: &str = include_str!("../.env");
use config::{init_config, CONFIGURATION};
use services::reverse_proxy;
#[tokio::main] #[tokio::main]
async fn main() -> Result<()> { async fn main() -> Result<()> {
init_tracing(); init_tracing();
init_config(); init_config()?;
let span = tracing::span!(Level::DEBUG, "main"); let span = tracing::span!(Level::DEBUG, "main");
let _ = span.enter(); let _ = span.enter();
// For dispatch reverse proxy let router = Router::new()
let client: Client =
hyper_util::client::legacy::Client::<(), ()>::builder(TokioExecutor::new())
.build(HttpConnector::new());
let app = Router::new()
.route("/query_dispatch", get(reverse_proxy::forward_to_dispatch))
.route( .route(
"/query_gateway/:region_name", dispatch::QUERY_DISPATCH_ENDPOINT,
get(reverse_proxy::forward_to_dispatch), 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::RISKY_API_CHECK_ENDPOINT, post(auth::risky_api_check))
.route( .route(
@ -52,16 +42,36 @@ async fn main() -> Result<()> {
auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT, auth::GRANTER_LOGIN_VERIFICATION_ENDPOINT,
post(auth::granter_login_verification), post(auth::granter_login_verification),
) )
.fallback(errors::not_found) .fallback(errors::not_found);
.with_state(client);
let app = NormalizePathLayer::trim_trailing_slash().layer(app); let addr = format!("0.0.0.0:{PORT}");
let server = axum_server::bind(addr.parse()?);
let addr = format!("0.0.0.0:{}", CONFIGURATION.http_port);
let server = TcpListener::bind(&addr).await?;
tracing::info!("sdkserver is listening at {addr}"); tracing::info!("sdkserver is listening at {addr}");
axum::serve(server, ServiceExt::<Request>::into_make_service(app)).await?; server.serve(router.into_make_service()).await?;
Ok(())
}
fn init_config() -> Result<()> {
let local_dotenv = Path::new(".env");
if local_dotenv.exists() {
dotenv::dotenv()?;
} else {
let config = dirs::config_dir()
.ok_or_else(|| anyhow::anyhow!("No config directory found"))?
.join("hkrpg-sdkserver");
std::fs::create_dir_all(&config)?;
let env = config.join(".env");
if !env.exists() {
std::fs::write(&env, DEFAULT_DOTENV)?;
}
dotenv::from_path(&env)?;
}
Ok(()) Ok(())
} }

View file

@ -1,7 +1,7 @@
use axum::Json; use axum::Json;
use serde_json::json; use serde_json::json;
pub const LOGIN_WITH_PASSWORD_ENDPOINT: &str = "/:product_name/mdk/shield/api/login"; 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 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 GRANTER_LOGIN_VERIFICATION_ENDPOINT: &str = "/:product_name/combo/granter/login/v2/login";
pub const RISKY_API_CHECK_ENDPOINT: &str = "/account/risky/api/check"; pub const RISKY_API_CHECK_ENDPOINT: &str = "/account/risky/api/check";
@ -12,7 +12,7 @@ pub async fn login_with_password() -> Json<serde_json::Value> {
"data": { "data": {
"account": { "account": {
"area_code": "**", "area_code": "**",
"email": "AcheronSR", "email": "ReversedRooms",
"country": "RU", "country": "RU",
"is_email_verify": "1", "is_email_verify": "1",
"token": "mostsecuretokenever", "token": "mostsecuretokenever",
@ -34,7 +34,7 @@ pub async fn login_with_session_token() -> Json<serde_json::Value> {
"data": { "data": {
"account": { "account": {
"area_code": "**", "area_code": "**",
"email": "AcheronSR", "email": "ReversedRooms",
"country": "RU", "country": "RU",
"is_email_verify": "1", "is_email_verify": "1",
"token": "mostsecuretokenever", "token": "mostsecuretokenever",

View file

@ -0,0 +1,61 @@
use std::env;
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: env::var("ASSET_BUNDLE_URL").unwrap(),
ex_resource_url: env::var("EX_RESOURCE_URL").unwrap(),
lua_url: env::var("LUA_URL").unwrap(),
lua_version: env::var("LUA_VERSION").unwrap(),
ifix_version: String::from("0"),
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)
}

View file

@ -1,3 +1,3 @@
pub mod auth; pub mod auth;
pub mod dispatch;
pub mod errors; pub mod errors;
pub mod reverse_proxy;

View file

@ -1,33 +0,0 @@
use axum::{
body::Body,
extract::{Request, State},
http::uri::{PathAndQuery, Uri},
response::{IntoResponse, Response},
};
use hyper::StatusCode;
use hyper_util::client::legacy::connect::HttpConnector;
use crate::config::CONFIGURATION;
type Client = hyper_util::client::legacy::Client<HttpConnector, Body>;
pub async fn forward_to_dispatch(
State(client): State<Client>,
mut req: Request,
) -> Result<Response, StatusCode> {
let path = req.uri().path();
let path_query = req
.uri()
.path_and_query()
.map_or(path, PathAndQuery::as_str);
let uri = format!("{}{}", CONFIGURATION.dispatch_endpoint, path_query);
*req.uri_mut() = Uri::try_from(uri).unwrap();
Ok(client
.request(req)
.await
.map_err(|_| StatusCode::BAD_REQUEST)?
.into_response())
}

View file

@ -1,7 +0,0 @@
[package]
name = "xtask"
edition = "2021"
version.workspace = true
[dependencies]
notify = "6.1.1"

View file

@ -1,112 +0,0 @@
use std::{io, process::Command, sync::mpsc, thread};
fn print_help() {
println!(
"
xtask must specify a task to run.
Usage: `cargo xtask <task>`
Tasks:
run
Run the gameserver and sdkserver.
watch
Watch for changes in the project and restart the servers if any file changes.
"
);
}
// run gameserver and sdkserver, wait till any of them exit
fn spawn_servers(release: bool) -> Result<(), Box<dyn std::error::Error>> {
let (tx, rx) = mpsc::channel();
let tx1 = tx.clone();
let handle1 = thread::spawn(move || {
let mut gameserver = Command::new("cargo")
.arg("run")
.arg("--bin")
.arg("gameserver")
.args(if release { vec!["--release"] } else { vec![] })
.spawn()
.expect("failed to start gameserver");
gameserver.wait()?;
tx1.send(()).expect("failed to send completion signal");
Ok::<(), io::Error>(())
});
let tx2 = tx.clone();
let handle2 = thread::spawn(move || {
let mut sdkserver = Command::new("cargo")
.arg("run")
.arg("--bin")
.arg("sdkserver")
.args(if release { vec!["--release"] } else { vec![] })
.spawn()
.expect("failed to start sdkserver");
let _ = sdkserver.wait()?;
tx2.send(()).expect("failed to send completion signal");
Ok::<(), io::Error>(())
});
let handle3 = thread::spawn(move || {
let mut dispatch = Command::new("cargo")
.arg("run")
.arg("--bin")
.arg("dispatch")
.args(if release { vec!["--release"] } else { vec![] })
.spawn()
.expect("failed to start dispatch");
let _ = dispatch.wait()?;
tx.send(()).expect("failed to send completion signal");
Ok::<(), io::Error>(())
});
rx.recv().expect("failed to receive from channel");
handle1.join().expect("failed to join gameserver thread")?;
handle2.join().expect("failed to join sdkserver thread")?;
handle3.join().expect("failed to join dispatch thread")?;
Ok(())
}
// watch for changes in the project and restart the servers if any file changes
fn watch(release: bool) -> Result<(), Box<dyn std::error::Error>> {
let mut cmd = std::process::Command::new("cargo");
cmd.arg("watch").arg("-x").arg(format!(
"xtask run {}",
if release { "--release" } else { "" }
));
let mut child = cmd.spawn()?;
child.wait()?;
Ok(())
}
fn main() -> Result<(), Box<dyn std::error::Error>> {
let Some(task) = std::env::args().nth(1) else {
print_help();
std::process::exit(0);
};
let release = std::env::args().any(|arg| arg == "--release");
match task.as_str() {
"run" => spawn_servers(release)?,
"watch" => watch(release)?,
_ => {
println!("invalid task: `{task}`, run `cargo xtask` for a list of tasks");
std::process::exit(1);
}
}
Ok(())
}