- Replace bank payment flow with a checkout mutation using explicit source context - Return backend errors to players instead of silently falling back to local state - Queue hot state persistence for actors, garages, lockers, orgs, and owned assets
705 lines
22 KiB
Rust
705 lines
22 KiB
Rust
//! Garage management operations for the Arma 3 server extension.
|
|
//!
|
|
//! Provides Arma 3 extension commands for vehicle storage, retrieval, and updates.
|
|
|
|
use arma_rs::{CallContext, Group};
|
|
use forge_models::Vehicle;
|
|
use forge_repositories::{InMemoryGarageHotRepository, RedisGarageRepository};
|
|
use forge_services::{GarageHotStateService, GarageService};
|
|
use std::collections::HashMap;
|
|
use std::sync::LazyLock;
|
|
|
|
use crate::adapters::ExtensionRedisClient;
|
|
use crate::enqueue_persistence_task;
|
|
use crate::helpers::resolve_uid;
|
|
use crate::log::log;
|
|
|
|
/// Global garage service instance.
|
|
static GARAGE_SERVICE: LazyLock<GarageService<RedisGarageRepository<ExtensionRedisClient>>> =
|
|
LazyLock::new(|| {
|
|
let redis_client = ExtensionRedisClient::new();
|
|
let repository = RedisGarageRepository::new(redis_client);
|
|
GarageService::new(repository)
|
|
});
|
|
static HOT_GARAGE_SERVICE: LazyLock<
|
|
GarageHotStateService<RedisGarageRepository<ExtensionRedisClient>, InMemoryGarageHotRepository>,
|
|
> = LazyLock::new(|| {
|
|
let redis_client = ExtensionRedisClient::new();
|
|
let repository = RedisGarageRepository::new(redis_client);
|
|
let hot_repository = InMemoryGarageHotRepository::new();
|
|
GarageHotStateService::new(repository, hot_repository)
|
|
});
|
|
|
|
/// Creates the Arma 3 command group for garage operations.
|
|
///
|
|
/// Registers commands: `create`, `get`, `add`, `update`, `remove`, `delete`, `exists`.
|
|
pub fn group() -> Group {
|
|
Group::new()
|
|
.command("create", create_garage)
|
|
.command("get", get_garage)
|
|
.command("add", add_vehicle)
|
|
.command("update", update_garage)
|
|
.command("patch", patch_vehicle)
|
|
.command("remove", remove_vehicle)
|
|
.command("delete", delete_garage)
|
|
.command("exists", garage_exists)
|
|
.group(
|
|
"hot",
|
|
Group::new()
|
|
.command("init", init_hot_garage)
|
|
.command("get", get_hot_garage)
|
|
.command("override", override_hot_garage)
|
|
.command("save", save_hot_garage)
|
|
.command("remove", remove_hot_garage)
|
|
.command("add", add_hot_vehicle)
|
|
.command("remove_vehicle", remove_hot_vehicle),
|
|
)
|
|
}
|
|
|
|
fn serialize_hot_vehicles(garage: forge_models::garage::Garage) -> String {
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(error) => format!("Error: Failed to serialize hot garage: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn init_hot_garage(call_context: CallContext, key: String) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.init_garage(resolved_uid) {
|
|
Ok(garage) => serialize_hot_vehicles(garage),
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn get_hot_garage(call_context: CallContext, key: String) -> String {
|
|
init_hot_garage(call_context, key)
|
|
}
|
|
|
|
pub(crate) fn override_hot_garage(
|
|
call_context: CallContext,
|
|
key: String,
|
|
json_data: String,
|
|
) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
let vehicles: HashMap<String, Vehicle> = match serde_json::from_str(&json_data) {
|
|
Ok(data) => data,
|
|
Err(error) => return format!("Error: Invalid JSON data: {}", error),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.override_garage(resolved_uid, vehicles) {
|
|
Ok(garage) => serialize_hot_vehicles(garage),
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn save_hot_garage(call_context: CallContext, key: String) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.get_garage(resolved_uid.clone()) {
|
|
Ok(garage) => {
|
|
enqueue_persistence_task("garage", move || {
|
|
HOT_GARAGE_SERVICE.save_garage(resolved_uid).map(|_| ())
|
|
});
|
|
serialize_hot_vehicles(garage)
|
|
}
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn remove_hot_garage(call_context: CallContext, key: String) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.remove_garage(resolved_uid) {
|
|
Ok(_) => "OK".to_string(),
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn add_hot_vehicle(call_context: CallContext, key: String, json_data: String) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
let data: serde_json::Value = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(error) => return format!("Error: Invalid JSON data: {}", error),
|
|
};
|
|
|
|
let classname = match data.get("classname").and_then(|v| v.as_str()) {
|
|
Some(c) => c.to_string(),
|
|
None => return "Error: Missing or invalid classname".to_string(),
|
|
};
|
|
let fuel = match data.get("fuel").and_then(|v| v.as_f64()) {
|
|
Some(f) => f,
|
|
None => return "Error: Missing or invalid fuel".to_string(),
|
|
};
|
|
let damage = match data.get("damage").and_then(|v| v.as_f64()) {
|
|
Some(d) => d,
|
|
None => return "Error: Missing or invalid damage".to_string(),
|
|
};
|
|
let hit_points_json = match data.get("hit_points") {
|
|
Some(hp) => match serde_json::to_string(hp) {
|
|
Ok(s) => s,
|
|
Err(error) => return format!("Error: Failed to serialize hit_points: {}", error),
|
|
},
|
|
None => return "Error: Missing hit_points".to_string(),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.add_vehicle(resolved_uid, classname, fuel, damage, hit_points_json) {
|
|
Ok(garage) => serialize_hot_vehicles(garage),
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
pub(crate) fn remove_hot_vehicle(
|
|
call_context: CallContext,
|
|
key: String,
|
|
json_data: String,
|
|
) -> String {
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => uid,
|
|
None => return format!("Error: Failed to resolve UID for key: {}", key),
|
|
};
|
|
|
|
let data: serde_json::Value = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(error) => return format!("Error: Invalid JSON data: {}", error),
|
|
};
|
|
|
|
let plate = match data.get("plate").and_then(|v| v.as_str()) {
|
|
Some(p) => p.to_string(),
|
|
None => return "Error: Missing or invalid plate".to_string(),
|
|
};
|
|
|
|
match HOT_GARAGE_SERVICE.remove_vehicle(resolved_uid, plate) {
|
|
Ok(garage) => serialize_hot_vehicles(garage),
|
|
Err(error) => format!("Error: {}", error),
|
|
}
|
|
}
|
|
|
|
/// Creates a new empty garage for a player.
|
|
///
|
|
/// Parameters: key
|
|
pub fn create_garage(call_context: CallContext, key: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Creating garage for key: {}", key),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.create_garage(resolved_uid.clone()) {
|
|
Ok(empty_garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully created garage for: {}", resolved_uid),
|
|
);
|
|
match serde_json::to_string(&empty_garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to create garage '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Retrieves a player's garage by key/UID.
|
|
///
|
|
/// Returns JSON object with garage data including all vehicles.
|
|
pub fn get_garage(call_context: CallContext, key: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Getting garage for key: {}", key),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.get_garage(resolved_uid.clone()) {
|
|
Ok(garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!(
|
|
"Successfully retrieved garage with {} vehicles",
|
|
garage.vehicles.len()
|
|
),
|
|
);
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Serialized garage to JSON: {}", json),
|
|
);
|
|
json
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to get garage '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Adds a new vehicle to a player's garage.
|
|
///
|
|
/// Parameters: key, json_data
|
|
pub fn add_vehicle(call_context: CallContext, key: String, json_data: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Adding vehicle for key: {} with data: {}", key, json_data),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
// Parse JSON data
|
|
let data: serde_json::Value = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Invalid JSON data: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
// Extract fields
|
|
let classname = match data.get("classname").and_then(|v| v.as_str()) {
|
|
Some(c) => c.to_string(),
|
|
None => {
|
|
let error_msg = "Error: Missing or invalid classname".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let fuel = match data.get("fuel").and_then(|v| v.as_f64()) {
|
|
Some(f) => f,
|
|
None => {
|
|
let error_msg = "Error: Missing or invalid fuel".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let damage = match data.get("damage").and_then(|v| v.as_f64()) {
|
|
Some(d) => d,
|
|
None => {
|
|
let error_msg = "Error: Missing or invalid damage".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let hit_points_json = match data.get("hit_points") {
|
|
Some(hp) => match serde_json::to_string(hp) {
|
|
Ok(s) => s,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize hit_points: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
},
|
|
None => {
|
|
let error_msg = "Error: Missing hit_points".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.add_vehicle(
|
|
resolved_uid.clone(),
|
|
classname,
|
|
fuel,
|
|
damage,
|
|
hit_points_json,
|
|
) {
|
|
Ok(garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully added vehicle to garage: {}", resolved_uid),
|
|
);
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to add vehicle '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Updates the entire garage state.
|
|
///
|
|
/// Parameters: key, json_data (Map of vehicles)
|
|
pub fn update_garage(call_context: CallContext, key: String, json_data: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Updating garage for key: {} with data: {}", key, json_data),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
// Parse JSON data
|
|
let vehicles: HashMap<String, Vehicle> = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Invalid JSON data: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.update_garage(resolved_uid.clone(), vehicles) {
|
|
Ok(garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully updated garage for: {}", resolved_uid),
|
|
);
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to update garage '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Patches a specific vehicle in the garage.
|
|
///
|
|
/// Parameters: key, json_data (Map with plate and optional fields)
|
|
pub fn patch_vehicle(call_context: CallContext, key: String, json_data: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Patching vehicle for key: {} with data: {}", key, json_data),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let data: serde_json::Value = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Invalid JSON data: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let plate = match data.get("plate").and_then(|v| v.as_str()) {
|
|
Some(s) => s.to_string(),
|
|
None => {
|
|
let error_msg = "Error: Missing plate".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
let fuel = data.get("fuel").and_then(|v| v.as_f64());
|
|
let damage = data.get("damage").and_then(|v| v.as_f64());
|
|
let hit_points_json = data
|
|
.get("hit_points")
|
|
.and_then(|v| serde_json::to_string(v).ok());
|
|
|
|
match GARAGE_SERVICE.patch_vehicle(resolved_uid.clone(), plate, damage, fuel, hit_points_json) {
|
|
Ok(garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully patched vehicle for: {}", resolved_uid),
|
|
);
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to patch vehicle '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Removes a vehicle from the garage.
|
|
///
|
|
/// Parameters: key, json_data
|
|
pub fn remove_vehicle(call_context: CallContext, key: String, json_data: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!(
|
|
"Removing vehicle from garage for key: {} with data: {}",
|
|
key, json_data
|
|
),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
// Parse JSON data
|
|
let data: serde_json::Value = match serde_json::from_str(&json_data) {
|
|
Ok(d) => d,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Invalid JSON data: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
// Extract plate
|
|
let plate = match data.get("plate").and_then(|v| v.as_str()) {
|
|
Some(p) => p.to_string(),
|
|
None => {
|
|
let error_msg = "Error: Missing or invalid plate".to_string();
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.remove_vehicle(resolved_uid.clone(), plate) {
|
|
Ok(garage) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully removed vehicle from garage: {}", resolved_uid),
|
|
);
|
|
match serde_json::to_string(&garage.vehicles) {
|
|
Ok(json) => json,
|
|
Err(e) => {
|
|
let error_msg = format!("Error: Failed to serialize garage: {}", e);
|
|
log("garage", "ERROR", &error_msg);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to remove vehicle '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Permanently deletes a player's garage.
|
|
pub fn delete_garage(call_context: CallContext, key: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Deleting garage for key: {}", key),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
let error_msg = format!("Error: Failed to resolve UID for key: {}", key);
|
|
log("garage", "ERROR", &error_msg);
|
|
return error_msg;
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.delete_garage(resolved_uid.clone()) {
|
|
Ok(_) => {
|
|
log(
|
|
"garage",
|
|
"INFO",
|
|
&format!("Successfully deleted garage: {}", resolved_uid),
|
|
);
|
|
"OK".to_string()
|
|
}
|
|
Err(e) => {
|
|
let error_msg = format!("Error: {}", e);
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to delete garage '{}': {}", resolved_uid, e),
|
|
);
|
|
error_msg
|
|
}
|
|
}
|
|
}
|
|
|
|
/// Checks if a player has a garage.
|
|
pub fn garage_exists(call_context: CallContext, key: String) -> String {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Checking garage existence for key: {}", key),
|
|
);
|
|
|
|
let resolved_uid = match resolve_uid(&key, &call_context) {
|
|
Some(uid) => {
|
|
log("garage", "DEBUG", &format!("Resolved UID: {}", uid));
|
|
uid
|
|
}
|
|
None => {
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to resolve UID for key: {}", key),
|
|
);
|
|
return "false".to_string();
|
|
}
|
|
};
|
|
|
|
match GARAGE_SERVICE.garage_exists(resolved_uid.clone()) {
|
|
Ok(exists) => {
|
|
log(
|
|
"garage",
|
|
"DEBUG",
|
|
&format!("Garage '{}' exists: {}", resolved_uid, exists),
|
|
);
|
|
exists.to_string()
|
|
}
|
|
Err(e) => {
|
|
log(
|
|
"garage",
|
|
"ERROR",
|
|
&format!("Failed to check if garage '{}' exists: {}", resolved_uid, e),
|
|
);
|
|
"false".to_string()
|
|
}
|
|
}
|
|
}
|