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