Working code

This commit is contained in:
2026-02-23 02:49:03 +01:00
parent cdb40f64f4
commit 02985ce60a
4 changed files with 119 additions and 63 deletions
+28 -25
View File
@@ -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<Mutex<String>>,
item_id: String,
pool: Arc<SqlitePool>,
) -> Result<String, String> {
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<Mutex<String>>,
item_id: String,
pool: Arc<SqlitePool>,
) -> Result<String, String> {
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))
}
+86 -15
View File
@@ -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<Mutex<String>> = Arc::new(Mutex::new(String::new()));
session
.on::<methods::Auth, _>(move |req_id, token| {
let req_id = req_id.clone();
let token = token.clone();
.on::<methods::Auth, _>({
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::<methods::BuyCloak, _>({
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::<methods::BuyHat, _>({
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::<methods::SetCloak, _>({
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::<methods::SetHat, _>({
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<Mutex<String>>,
session_token: String,
pool: Arc<SqlitePool>,
) -> Result<User, String> {
@@ -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
}
+3 -3
View File
@@ -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;
+2 -20
View File
@@ -9,27 +9,9 @@ pub struct User {
pub hats: Vec<String>,
}
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