online system

This commit is contained in:
2025-04-02 20:08:14 +02:00
parent 6b01a37ec6
commit 5731e193c8
5 changed files with 107 additions and 72 deletions
+1
View File
@@ -7,6 +7,7 @@ pub struct Player {
pub cloak: String,
pub hats: Vec<String>,
pub hat: String,
pub online: bool,
}
pub struct Database {
+4 -1
View File
@@ -32,7 +32,10 @@ fn main() -> std::io::Result<()> {
loop {
let mut request_string = String::new();
match reader.read_line(&mut request_string).unwrap() {
0 => break,
0 => {
methods::player::logout(&session).unwrap();
println!("[MOJANG] {} went offline", session.local_player.name);
}
_ => {
let (method, params) = parser::parse(&request_string).unwrap();
let response = session.handle_request(&method, &params);
+26 -12
View File
@@ -1,4 +1,4 @@
mod player;
pub mod player;
mod set_cloak;
mod set_hat;
@@ -6,10 +6,9 @@ use std::{
collections::HashMap,
io::{BufRead, BufReader},
net::TcpStream,
sync::Arc,
sync::{mpsc, Arc},
};
use player::create;
use serde::{Deserialize, Serialize};
use crate::{
@@ -34,12 +33,25 @@ impl Session {
reader: &mut BufReader<TcpStream>,
database: Arc<crate::database::Database>,
) -> Result<(Self, Response)> {
// Read the session token
let mut session_token = String::new();
reader
.read_line(&mut session_token)
.map_err(|_| crate::response::Error::InvalidHandshake)?;
let (token_send, token_recv) =
mpsc::channel::<std::result::Result<String, crate::response::Error>>();
let reader_clone = reader
.get_ref()
.try_clone()
.map_err(|_| crate::response::Error::InvalidHandshake)?;
std::thread::spawn(move || {
let mut reader = BufReader::new(reader_clone);
let mut session_token = String::new();
if reader.read_line(&mut session_token).is_ok() {
token_send.send(Ok(session_token))
} else {
token_send.send(Err(crate::response::Error::InvalidHandshake))
}
});
match token_recv.recv_timeout(std::time::Duration::from_secs(20)) {
Ok(Ok(session_token)) => {
// Validate session id
let response = minreq::get("https://api.minecraftservices.com/minecraft/profile")
.with_header("Authorization", &format!("Bearer {session_token}"))
@@ -56,6 +68,8 @@ impl Session {
.json()
.map_err(|_| crate::response::Error::InvalidSession)?;
println!("[MOJANG] {} successfully logged on", &local_player.name);
let session = Self {
session_token,
database,
@@ -65,13 +79,13 @@ impl Session {
// Capture the player
match player::login(&session) {
Ok(player) => Ok((session, player)),
Err(crate::response::Error::DatabaseError) => {
let player = create(&session)?;
Ok((session, player))
}
Err(e) => Err(e),
}
}
Err(mpsc::RecvTimeoutError::Timeout) => Err(crate::response::Error::Timeout),
_ => Err(crate::response::Error::InvalidHandshake),
}
}
pub fn handle_request(&self, method: &str, params: &HashMap<String, String>) -> Result {
match method {
+43 -28
View File
@@ -16,22 +16,27 @@ pub fn player(session: &Session, uuid: String) -> Result {
.run()?;
// Check if there's a document in the cursor
match cursor.next() {
Ok(match cursor.next() {
Some(Ok(player)) => {
// Player exists, deserialize and return their data
Ok(Response::Player(crate::response::PlayerResponse::Player {
if player.online {
Response::Player(crate::response::PlayerResponse::Player {
cloak: player.cloak,
uuid,
cloaks: player.cloaks,
hats: player.hats,
hat: player.hat,
}))
})
} else {
crate::response::Response::Player(crate::response::PlayerResponse::NonSaturnPlayer(
uuid,
))
}
}
_ => Ok(crate::response::Response::Player(
crate::response::PlayerResponse::NonSaturnPlayer(uuid),
_ => crate::response::Response::Player(crate::response::PlayerResponse::NonSaturnPlayer(
uuid,
)),
}
})
}
pub fn create(session: &Session) -> Result {
@@ -43,6 +48,7 @@ pub fn create(session: &Session) -> Result {
cloak: "".to_string(),
hats: Vec::new(),
hat: String::new(),
online: true,
};
session.database.players.insert_one(player.clone()).run()?;
@@ -68,7 +74,18 @@ pub fn login(session: &Session) -> Result {
// Check if there's a document in the cursor
match cursor.next() {
Some(Ok(player)) => {
Some(Ok(mut player)) => {
// Update player's online status
player.online = true;
session
.database
.players
.update_one(
doc! { "uuid": uuid.clone() },
doc! { "$set": { "online": true } },
)
.run()?;
// Player exists, deserialize and return their data
Ok(Response::Player(crate::response::PlayerResponse::Player {
cloak: player.cloak,
@@ -80,26 +97,24 @@ pub fn login(session: &Session) -> Result {
}
// No document found or deserialization error
_ => {
let player = Player {
uuid: uuid.clone(),
cloaks: Vec::new(),
cloak: "".to_string(),
hats: Vec::new(),
hat: String::new(),
};
_ => create(session),
}
}
// Insert the new player
session.database.players.insert_one(player.clone()).run()?;
pub fn logout(session: &Session) -> Result {
let uuid = session.local_player.id.clone();
// Return the newly created player's data
Ok(Response::Player(crate::response::PlayerResponse::Player {
cloak: player.cloak,
uuid,
cloaks: player.cloaks,
hats: player.hats,
hat: player.hat,
}))
}
}
// Update player's online status to false
session
.database
.players
.update_one(
doc! { "uuid": uuid.clone() },
doc! { "$set": { "online": false } },
)
.run()?;
Ok(Response::Player(
crate::response::PlayerResponse::NonSaturnPlayer(uuid),
))
}
+2
View File
@@ -70,6 +70,7 @@ pub enum Error {
InvalidHandshake,
DatabaseError,
SomethingWentWrong,
Timeout,
}
impl std::fmt::Display for Error {
@@ -83,6 +84,7 @@ impl std::fmt::Display for Error {
Error::InvalidHandshake => write!(f, "Invalid handshake"),
Error::DatabaseError => write!(f, "Database error"),
Error::SomethingWentWrong => write!(f, "Something went wrong"),
Error::Timeout => write!(f, "Timeout"),
}
}
}