From 9f491c0e7cc3820d0ca63004afb32c7702c62e81 Mon Sep 17 00:00:00 2001 From: techmetx11 Date: Wed, 26 Jun 2024 21:57:03 +0100 Subject: [PATCH] Added new opcode: `PLAYER_STATUS` --- README.md | 16 +++++++++++++- src/jobs.rs | 60 ++++++++++++++++++++++++++++++++++++++++++++++----- src/main.rs | 12 ++++++++++- src/opcode.rs | 10 ++++++++- src/player.rs | 1 + 5 files changed, 91 insertions(+), 8 deletions(-) diff --git a/README.md b/README.md index 997f072..0571848 100644 --- a/README.md +++ b/README.md @@ -61,7 +61,7 @@ Decrypt a provided `s` signature using the server's current `sig` function code, |string| *`size`* | The decrypted signature | ### `GET_SIGNATURE_TIMESTAMP` (0x03) -Get the signature timestamp from the server's current player, and return it in the form of a 64-bit integer +Get the signature timestamp from the server's current player, and return it in the form of a 64-bit integer. If there's no player, it will return 0 in the `timestamp` (Please check with `PLAYER_STATUS` if the server has a player) #### Request No additional data required @@ -70,3 +70,17 @@ No additional data required | Name | Size (bytes) | Description | |---------|--------------|----------------------------------------------------------| |timestamp| 8 | The signature timestamp from the server's current player | + +### `PLAYER_STATUS` (0x04) +Get the server's information about the current player. + +#### Request +No additional data required + +#### Response + +| Name | Size (bytes) | Description | +|----------|--------------|-------------| +|has_player| 1 | If the server has a player, this variable will be `0xFF`, or else, it will be `0x00`| +|player_id | 4 | The server's current player ID, If the server has no player, this will always be `0x00000000`| + diff --git a/src/jobs.rs b/src/jobs.rs index 187b87b..bb1f9c8 100644 --- a/src/jobs.rs +++ b/src/jobs.rs @@ -15,6 +15,7 @@ pub enum JobOpcode { DecryptNSignature, DecryptSignature, GetSignatureTimestamp, + PlayerStatus, UnknownOpcode, } @@ -25,6 +26,7 @@ impl std::fmt::Display for JobOpcode { Self::DecryptNSignature => write!(f, "DecryptNSignature"), Self::DecryptSignature => write!(f, "DecryptSignature"), Self::GetSignatureTimestamp => write!(f, "GetSignatureTimestamp"), + Self::PlayerStatus => write!(f, "PlayerStatus"), Self::UnknownOpcode => write!(f, "UnknownOpcode"), } } @@ -36,6 +38,7 @@ impl From for JobOpcode { 0x01 => Self::DecryptNSignature, 0x02 => Self::DecryptSignature, 0x03 => Self::GetSignatureTimestamp, + 0x04 => Self::PlayerStatus, _ => Self::UnknownOpcode, } } @@ -47,6 +50,7 @@ pub struct PlayerInfo { pub sig_function_name: String, pub signature_timestamp: u64, pub player_id: u32, + pub has_player: u8, } pub struct JavascriptInterpreter { @@ -105,6 +109,7 @@ impl GlobalState { sig_function_name: Default::default(), player_id: Default::default(), signature_timestamp: Default::default(), + has_player: 0x00, }), js_runtime_pool: runtime_pool, } @@ -130,6 +135,8 @@ pub async fn process_fetch_update( update_status: status, signature: Default::default(), signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }) .await; } @@ -169,7 +176,9 @@ pub async fn process_decrypt_n_signature( request_id, update_status: Ok(Default::default()), signature: String::new(), - signature_timestamp: Default::default() + signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; return; } @@ -198,7 +207,9 @@ pub async fn process_decrypt_n_signature( request_id, update_status: Ok(Default::default()), signature: String::new(), - signature_timestamp: Default::default() + signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; return; } @@ -211,7 +222,9 @@ pub async fn process_decrypt_n_signature( request_id, update_status: Ok(Default::default()), signature: decrypted_string, - signature_timestamp: Default::default() + signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; }) .await; @@ -251,7 +264,9 @@ pub async fn process_decrypt_signature( request_id, update_status: Ok(Default::default()), signature: String::new(), - signature_timestamp: Default::default() + signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; return; } @@ -283,7 +298,9 @@ pub async fn process_decrypt_signature( request_id, update_status: Ok(Default::default()), signature: String::new(), - signature_timestamp: Default::default() + signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; return; } @@ -297,6 +314,8 @@ pub async fn process_decrypt_signature( update_status: Ok(Default::default()), signature: decrypted_string, signature_timestamp: Default::default(), + has_player: Default::default(), + player_id: Default::default(), }).await; }) .await; @@ -323,6 +342,37 @@ pub async fn process_get_signature_timestamp( update_status: Ok(Default::default()), signature: String::new(), signature_timestamp: timestamp, + has_player: Default::default(), + player_id: Default::default(), + }) + .await; +} + +pub async fn process_player_status( + state: Arc, + stream: Arc>, + request_id: u32, +) where + W: SinkExt + Unpin + Send, +{ + let cloned_writer = stream.clone(); + let global_state = state.clone(); + + let player_info = global_state.player_info.lock().await; + let has_player = player_info.has_player; + let player_id = player_info.player_id; + + let mut writer = cloned_writer.lock().await; + + writer + .send(OpcodeResponse { + opcode: JobOpcode::PlayerStatus, + request_id, + update_status: Ok(Default::default()), + signature: String::new(), + signature_timestamp: Default::default(), + has_player, + player_id, }) .await; } diff --git a/src/main.rs b/src/main.rs index 9bf0fc2..aafc8a4 100644 --- a/src/main.rs +++ b/src/main.rs @@ -21,7 +21,9 @@ use tokio::{ }; use tokio_util::codec::{Decoder, Framed, FramedRead, FramedWrite}; -use crate::jobs::{process_decrypt_signature, process_get_signature_timestamp}; +use crate::jobs::{ + process_decrypt_signature, process_get_signature_timestamp, process_player_status, +}; macro_rules! break_fail { ($res:expr) => { @@ -147,6 +149,14 @@ async fn process_socket(state: Arc, socket: UnixStream) { .await; }); } + JobOpcode::PlayerStatus => { + let cloned_state = state.clone(); + let cloned_sink = arc_sink.clone(); + tokio::spawn(async move { + process_player_status(cloned_state, cloned_sink, opcode.request_id) + .await; + }); + } _ => { continue; } diff --git a/src/opcode.rs b/src/opcode.rs index 34e58de..1aa4c61 100644 --- a/src/opcode.rs +++ b/src/opcode.rs @@ -24,6 +24,9 @@ pub struct OpcodeResponse { pub update_status: Result<(), FetchUpdateStatus>, pub signature: String, pub signature_timestamp: u64, + + pub has_player: u8, + pub player_id: u32, } impl Decoder for OpcodeDecoder { @@ -44,7 +47,7 @@ impl Decoder for OpcodeDecoder { let request_id: u32 = u32::from_be_bytes(src[1..5].try_into().unwrap()); match opcode { - JobOpcode::ForceUpdate | JobOpcode::GetSignatureTimestamp => { + JobOpcode::ForceUpdate | JobOpcode::GetSignatureTimestamp | JobOpcode::PlayerStatus => { src.advance(5); Ok(Some(Opcode { opcode, @@ -115,6 +118,11 @@ impl Encoder for OpcodeDecoder { dst.put_u32(8); dst.put_u64(item.signature_timestamp); } + JobOpcode::PlayerStatus => { + dst.put_u32(5); + dst.put_u8(item.has_player); + dst.put_u32(item.player_id); + } _ => {} } Ok(()) diff --git a/src/player.rs b/src/player.rs index 95c3b19..8698e2d 100644 --- a/src/player.rs +++ b/src/player.rs @@ -173,6 +173,7 @@ pub async fn fetch_update(state: Arc) -> Result<(), FetchUpdateStat current_player_info.sig_function_code = sig_code; current_player_info.sig_function_name = sig_function_name.to_string(); current_player_info.signature_timestamp = signature_timestamp; + current_player_info.has_player = 0xFF; Ok(()) }