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
+51 -37
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,42 +33,57 @@ 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)
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)?;
// Validate session id
let response = minreq::get("https://api.minecraftservices.com/minecraft/profile")
.with_header("Authorization", &format!("Bearer {session_token}"))
.send()
.map_err(|_| crate::response::Error::InvalidSession)?;
// If the session is invalid, return an error
if response.status_code != 200 {
return Err(crate::response::Error::InvalidSession);
}
// Parse the player data
let local_player: LocalPlayer = response
.json()
.map_err(|_| crate::response::Error::InvalidSession)?;
let session = Self {
session_token,
database,
local_player,
};
// Capture the player
match player::login(&session) {
Ok(player) => Ok((session, player)),
Err(crate::response::Error::DatabaseError) => {
let player = create(&session)?;
Ok((session, player))
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))
}
Err(e) => Err(e),
});
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}"))
.send()
.map_err(|_| crate::response::Error::InvalidSession)?;
// If the session is invalid, return an error
if response.status_code != 200 {
return Err(crate::response::Error::InvalidSession);
}
// Parse the player data
let local_player: LocalPlayer = response
.json()
.map_err(|_| crate::response::Error::InvalidSession)?;
println!("[MOJANG] {} successfully logged on", &local_player.name);
let session = Self {
session_token,
database,
local_player,
};
// Capture the player
match player::login(&session) {
Ok(player) => Ok((session, player)),
Err(e) => Err(e),
}
}
Err(mpsc::RecvTimeoutError::Timeout) => Err(crate::response::Error::Timeout),
_ => Err(crate::response::Error::InvalidHandshake),
}
}
+49 -34
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 {
cloak: player.cloak,
uuid,
cloaks: player.cloaks,
hats: player.hats,
hat: player.hat,
}))
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(),
};
// Insert the new player
session.database.players.insert_one(player.clone()).run()?;
// 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,
}))
}
_ => create(session),
}
}
pub fn logout(session: &Session) -> Result {
let uuid = session.local_player.id.clone();
// 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),
))
}