This commit is contained in:
2026-02-23 18:42:35 +01:00
parent 768bbd239b
commit a0409c6763
4 changed files with 62 additions and 25 deletions
+28 -16
View File
@@ -1,18 +1,20 @@
use sqlx::SqlitePool;
use std::sync::Arc; use std::sync::Arc;
use sqlx::SqlitePool; use crate::{types::UUID, user};
use crate::{types::UUID, user::get_put};
pub const CLOAKS: &[&str] = &[ pub const CLOAKS: &[&str] = &[
"mercedes_flow",
"glitch", "glitch",
"mercedes_flow",
"crimson_mark", "crimson_mark",
"bmw", "bmw",
"amg", "amg",
"amg_petronas", "amg_petronas",
"ferrari", "ferrari",
"redbull", "redbull",
"black_hole_amethyst",
"black_hole_flame",
"black_hole_white",
]; ];
pub const HATS: &[&str] = &["horns_black", "horns_white", "halo", "halo_black"]; pub const HATS: &[&str] = &["horns_black", "horns_white", "halo", "halo_black"];
@@ -29,31 +31,36 @@ pub async fn buy(
item_id: String, item_id: String,
pool: Arc<SqlitePool>, pool: Arc<SqlitePool>,
) -> Result<String, String> { ) -> Result<String, String> {
let mut user = get_put(uuid.lock().await.as_str(), &pool).await?; // Lock once
let uuid = uuid.lock().await.clone();
let mut user = user::get(&uuid, &pool).await?;
match kind { match kind {
CosmeticKind::Hat => { CosmeticKind::Hat => {
if !HATS.contains(&item_id.as_str()) { if !HATS.contains(&item_id.as_str()) {
return Err("Hat does not exist".into()); return Err("Hat does not exist".into());
} }
if !user.hats.contains(&item_id.to_string()) {
user.hats.push(item_id.to_string()); if !user.hats.contains(&item_id) {
user.hats.push(item_id.clone());
} }
} }
CosmeticKind::Cloak => { CosmeticKind::Cloak => {
if !CLOAKS.contains(&item_id.as_str()) { if !CLOAKS.contains(&item_id.as_str()) {
return Err("Cloak does not exist".into()); return Err("Cloak does not exist".into());
} }
if !user.cloaks.contains(&item_id.to_string()) {
user.cloaks.push(item_id.to_string()); if !user.cloaks.contains(&item_id) {
user.cloaks.push(item_id.clone());
} }
} }
} }
sqlx::query("UPDATE users SET cloaks = ?, hats = ? WHERE uuid = ?") sqlx::query("UPDATE users SET cloaks = ?, hats = ? WHERE uuid = ?")
.bind(serde_json::to_string(&user.cloaks).unwrap()) .bind(serde_json::to_string(&user.cloaks).map_err(|e| e.to_string())?)
.bind(serde_json::to_string(&user.hats).unwrap()) .bind(serde_json::to_string(&user.hats).map_err(|e| e.to_string())?)
.bind(uuid.lock().await.as_str()) .bind(&uuid)
.execute(pool.as_ref()) .execute(pool.as_ref())
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
@@ -68,27 +75,32 @@ pub async fn equip(
item_id: String, item_id: String,
pool: Arc<SqlitePool>, pool: Arc<SqlitePool>,
) -> Result<String, String> { ) -> Result<String, String> {
let mut user = get_put(uuid.lock().await.as_str(), &pool).await?; // Lock once
let uuid = uuid.lock().await.clone();
let mut user = user::get(&uuid, &pool).await?;
match kind { match kind {
CosmeticKind::Hat => { CosmeticKind::Hat => {
if !user.hats.contains(&item_id) { if !user.hats.contains(&item_id) {
return Err("You don't own this hat".into()); return Err("You don't own this hat".into());
} }
user.hat = item_id.to_string();
user.hat = item_id.clone();
} }
CosmeticKind::Cloak => { CosmeticKind::Cloak => {
if !user.cloaks.contains(&item_id) { if !user.cloaks.contains(&item_id) {
return Err("You don't own this cloak".into()); return Err("You don't own this cloak".into());
} }
user.cloak = item_id.to_string();
user.cloak = item_id.clone();
} }
} }
sqlx::query("UPDATE users SET cloak = ?, hat = ? WHERE uuid = ?") sqlx::query("UPDATE users SET cloak = ?, hat = ? WHERE uuid = ?")
.bind(&user.cloak) .bind(&user.cloak)
.bind(&user.hat) .bind(&user.hat)
.bind(uuid.lock().await.as_str()) .bind(&uuid)
.execute(pool.as_ref()) .execute(pool.as_ref())
.await .await
.map_err(|e| e.to_string())?; .map_err(|e| e.to_string())?;
+11 -4
View File
@@ -36,10 +36,17 @@ pub async fn authenticate(
)); ));
} }
let auth: crate::types::MinecraftAuthResponse = response let auth = response
.json() .json::<crate::types::MinecraftAuthResponse>()
.await .await
.map_err(|_| "Unable to parse auth response".to_string())?; .map_err(|_| "Unable to parse auth response".to_string())
.and_then(|auth| {
let id = crate::types::format_uuid(&auth.id)?;
Ok(crate::types::MinecraftAuthResponse {
name: auth.name,
id,
})
})?;
*uuid.lock().await = auth.id.clone(); *uuid.lock().await = auth.id.clone();
*name.lock().await = auth.name.clone(); *name.lock().await = auth.name.clone();
@@ -51,7 +58,7 @@ pub async fn authenticate(
.or_default() .or_default()
.insert(session); .insert(session);
println!("Authenticated as {:?}", auth); println!("{:?}", auth);
crate::user::get_put(&auth.id, &pool).await crate::user::get_put(&auth.id, &pool).await
} }
+8 -5
View File
@@ -27,15 +27,16 @@ pub async fn send_user(
targets: Vec<String>, targets: Vec<String>,
pool: Arc<SqlitePool>, pool: Arc<SqlitePool>,
) -> Result<(), String> { ) -> Result<(), String> {
println!("send player {targets:?}");
let uuid = uuid.lock().await.to_string();
let user = PlayerStream { let user = PlayerStream {
player: crate::user::get(&uuid.lock().await, pool.as_ref()).await?, player: crate::user::get(&uuid, pool.as_ref()).await?,
uuid: uuid.lock().await.clone(), uuid: uuid.clone(),
name: name.lock().await.clone(), name: name.lock().await.clone(),
}; };
println!("{user:?}"); println!("ready {targets:?}");
println!("{targets:?}");
for target in targets { for target in targets {
if let Some(sessions) = sessions.lock().await.get_mut(&target) { if let Some(sessions) = sessions.lock().await.get_mut(&target) {
@@ -53,5 +54,7 @@ pub async fn send_user(
} }
} }
println!("sent");
Ok(()) Ok(())
} }
+15
View File
@@ -38,3 +38,18 @@ pub struct PlayerStream {
pub uuid: String, pub uuid: String,
pub name: String, pub name: String,
} }
pub fn format_uuid(input: &str) -> Result<String, &'static str> {
if input.len() != 32 {
return Err("Input must be exactly 32 hex characters");
}
Ok(format!(
"{}-{}-{}-{}-{}",
&input[0..8],
&input[8..12],
&input[12..16],
&input[16..20],
&input[20..32],
))
}