diff --git a/src/cosmetics.rs b/src/cosmetics.rs index a2b0c06..2664f75 100644 --- a/src/cosmetics.rs +++ b/src/cosmetics.rs @@ -1,4 +1,7 @@ +use std::sync::Arc; + use sqlx::SqlitePool; +use tokio::sync::Mutex; use crate::user::get_put; @@ -15,7 +18,7 @@ pub const CLOAKS: &[&str] = &[ pub const HATS: &[&str] = &["horns_black", "horns_white", "halo", "halo_black"]; -enum CosmeticKind { +pub enum CosmeticKind { Hat, Cloak, } @@ -23,27 +26,27 @@ enum CosmeticKind { // Buy a cosmetic pub async fn buy( kind: CosmeticKind, - uuid: &str, - id: &str, - pool: &SqlitePool, + uuid: Arc>, + item_id: String, + pool: Arc, ) -> Result { - let mut user = get_put(uuid, pool).await?; + let mut user = get_put(uuid.lock().await.as_str(), &pool).await?; match kind { CosmeticKind::Hat => { - if !HATS.contains(&id) { + if !HATS.contains(&item_id.as_str()) { return Err("Hat does not exist".into()); } - if !user.hats.contains(&id.to_string()) { - user.hats.push(id.to_string()); + if !user.hats.contains(&item_id.to_string()) { + user.hats.push(item_id.to_string()); } } CosmeticKind::Cloak => { - if !CLOAKS.contains(&id) { + if !CLOAKS.contains(&item_id.as_str()) { return Err("Cloak does not exist".into()); } - if !user.cloaks.contains(&id.to_string()) { - user.cloaks.push(id.to_string()); + if !user.cloaks.contains(&item_id.to_string()) { + user.cloaks.push(item_id.to_string()); } } } @@ -51,45 +54,45 @@ pub async fn buy( sqlx::query("UPDATE users SET cloaks = ?, hats = ? WHERE uuid = ?") .bind(serde_json::to_string(&user.cloaks).unwrap()) .bind(serde_json::to_string(&user.hats).unwrap()) - .bind(uuid) - .execute(pool) + .bind(uuid.lock().await.as_str()) + .execute(pool.as_ref()) .await .map_err(|e| e.to_string())?; - Ok(format!("Item {} bought successfully!", id)) + Ok(format!("Item {} bought successfully!", item_id)) } // Equip a cosmetic pub async fn equip( kind: CosmeticKind, - uuid: &str, - id: &str, - pool: &SqlitePool, + uuid: Arc>, + item_id: String, + pool: Arc, ) -> Result { - let mut user = get_put(uuid, pool).await?; + let mut user = get_put(uuid.lock().await.as_str(), &pool).await?; match kind { CosmeticKind::Hat => { - if !user.hats.contains(&id.to_string()) { + if !user.hats.contains(&item_id) { return Err("You don't own this hat".into()); } - user.hat = id.to_string(); + user.hat = item_id.to_string(); } CosmeticKind::Cloak => { - if !user.cloaks.contains(&id.to_string()) { + if !user.cloaks.contains(&item_id) { return Err("You don't own this cloak".into()); } - user.cloak = id.to_string(); + user.cloak = item_id.to_string(); } } sqlx::query("UPDATE users SET cloak = ?, hat = ? WHERE uuid = ?") .bind(&user.cloak) .bind(&user.hat) - .bind(uuid) - .execute(pool) + .bind(uuid.lock().await.as_str()) + .execute(pool.as_ref()) .await .map_err(|e| e.to_string())?; - Ok(format!("Item {} equipped successfully!", id)) + Ok(format!("Item {} equipped successfully!", item_id)) } diff --git a/src/main.rs b/src/main.rs index 08f798d..abb4bbc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -7,13 +7,14 @@ use std::{pin::Pin, sync::Arc}; use serde::{Deserialize, Serialize}; use session_rs::server::SessionServer; use sqlx::SqlitePool; +use tokio::sync::Mutex; use ureq::http::StatusCode; use crate::user::User; #[tokio::main(flavor = "current_thread")] async fn main() -> session_rs::Result<()> { - let pool = Arc::new(init_db().await); + let pool = Arc::new(user::init_db().await); let server = SessionServer::bind("127.0.0.1:8080").await?; server @@ -24,13 +25,90 @@ async fn main() -> session_rs::Result<()> { Box::pin(async move { println!("Connected"); + let uuid: Arc> = Arc::new(Mutex::new(String::new())); session - .on::(move |req_id, token| { - let req_id = req_id.clone(); - let token = token.clone(); + .on::({ + let pool = Arc::clone(&pool); + let uuid = Arc::clone(&uuid); - authenticate(req_id.clone(), token, Arc::clone(&pool)) + move |_, token| authenticate(uuid.clone(), token, pool.clone()) + }) + .await; + + session + .on::({ + let uuid = Arc::clone(&uuid); + let pool = Arc::clone(&pool); + + move |_, item_id| { + let pool = Arc::clone(&pool); + let item_id = item_id.clone(); + + cosmetics::buy( + cosmetics::CosmeticKind::Cloak, + uuid.clone(), + item_id, + pool, + ) + } + }) + .await; + + session + .on::({ + let uuid = Arc::clone(&uuid); + let pool = Arc::clone(&pool); + + move |_, item_id| { + let pool = Arc::clone(&pool); + let item_id = item_id.clone(); + + cosmetics::buy( + cosmetics::CosmeticKind::Hat, + uuid.clone(), + item_id, + pool, + ) + } + }) + .await; + + session + .on::({ + let uuid = Arc::clone(&uuid); + let pool = Arc::clone(&pool); + + move |_, item_id| { + let pool = Arc::clone(&pool); + let item_id = item_id.clone(); + + cosmetics::equip( + cosmetics::CosmeticKind::Cloak, + uuid.clone(), + item_id, + pool, + ) + } + }) + .await; + + session + .on::({ + let uuid = Arc::clone(&uuid); + let pool = Arc::clone(&pool); + + move |_, item_id| { + let pool = Arc::clone(&pool); + let item_id = item_id.clone(); + + cosmetics::equip( + cosmetics::CosmeticKind::Hat, + uuid.clone(), + item_id, + pool, + ) + } }) .await; @@ -48,7 +126,7 @@ struct MinecraftAuthResponse { } async fn authenticate( - _req_id: u32, + uuid: Arc>, session_token: String, pool: Arc, ) -> Result { @@ -69,14 +147,7 @@ async fn authenticate( .read_json() .map_err(|_| "Unable to parse auth response".to_string())?; + *uuid.lock().await = auth.id.clone(); + user::get_put(&auth.id, &pool).await } - -async fn init_db() -> SqlitePool { - let pool = SqlitePool::connect("sqlite:cosmetics.db").await.unwrap(); - sqlx::query(include_str!("schema.sql")) - .execute(&pool) - .await - .unwrap(); - pool -} diff --git a/src/methods.rs b/src/methods.rs index 0098637..dcafb2e 100644 --- a/src/methods.rs +++ b/src/methods.rs @@ -27,7 +27,7 @@ impl Method for SetCloak { pub struct SetHat; impl Method for SetHat { - const NAME: &'static str = "set_cloak"; + const NAME: &'static str = "set_hat"; type Request = String; type Response = String; type Error = String; @@ -37,7 +37,7 @@ impl Method for SetHat { pub struct BuyCloak; impl Method for BuyCloak { - const NAME: &'static str = "set_cloak"; + const NAME: &'static str = "buy_cloak"; type Request = String; type Response = String; type Error = String; @@ -47,7 +47,7 @@ impl Method for BuyCloak { pub struct BuyHat; impl Method for BuyHat { - const NAME: &'static str = "set_cloak"; + const NAME: &'static str = "buy_hat"; type Request = String; type Response = String; type Error = String; diff --git a/src/user.rs b/src/user.rs index ebd4248..133f7d1 100644 --- a/src/user.rs +++ b/src/user.rs @@ -9,27 +9,9 @@ pub struct User { pub hats: Vec, } -pub const CLOAKS: &[&str] = &[ - "mercedes_flow", - "glitch", - "crimson_mark", - "bmw", - "amg", - "amg_petronas", - "ferrari", - "redbull", -]; - -pub const HATS: &[&str] = &["horns_black", "horns_white", "halo", "halo_black"]; - -pub enum CosmeticKind { - Hat, - Cloak, -} - // Initialize SQLite connection pool -pub async fn init_db(db_path: &str) -> SqlitePool { - let pool = SqlitePool::connect(db_path).await.unwrap(); +pub async fn init_db() -> SqlitePool { + let pool = SqlitePool::connect("sqlite:users.db").await.unwrap(); sqlx::query(include_str!("schema.sql")) .execute(&pool) .await