Added a character route for requesting character data from the server

This commit is contained in:
2026-04-30 14:53:04 +01:00
parent 800bee13da
commit 93c09290cd
11 changed files with 139 additions and 23 deletions
+1 -1
View File
@@ -1 +1 @@
,deadvey,linux-pc,07.04.2026 00:08,file:///home/deadvey/.config/libreoffice/4; ,deadvey,linux-pc,30.04.2026 12:49,file:///home/deadvey/.config/libreoffice/4;
Generated
+1
View File
@@ -248,6 +248,7 @@ dependencies = [
"env_logger", "env_logger",
"log", "log",
"serde", "serde",
"serde_json",
"tokio", "tokio",
"warp", "warp",
] ]
+1
View File
@@ -7,5 +7,6 @@ edition = "2024"
env_logger = "0.11.10" env_logger = "0.11.10"
log = "0.4.29" log = "0.4.29"
serde = { version = "1.0.228", features = ["derive"] } serde = { version = "1.0.228", features = ["derive"] }
serde_json = "1.0.149"
tokio = { version = "1.51.0", features = ["rt-multi-thread","macros"] } tokio = { version = "1.51.0", features = ["rt-multi-thread","macros"] }
warp = { version = "0.4.2", features = ["server"] } warp = { version = "0.4.2", features = ["server"] }
BIN
View File
Binary file not shown.
Binary file not shown.
Binary file not shown.
+30 -7
View File
@@ -1,14 +1,18 @@
use serde::{Deserialize, Serialize};
use warp::Filter; use warp::Filter;
use crate:: use crate::
{ {
// internal code
character,
// libraries
HashMap,
Arc, Arc,
Mutex, Mutex,
config, config,
mpsc::Sender, mpsc::Sender,
info, info,
warn,
debug, debug,
Serialize,
Deserialize,
}; };
#[derive(Debug, Deserialize, Serialize, Clone)] #[derive(Debug, Deserialize, Serialize, Clone)]
@@ -21,29 +25,48 @@ pub struct DataToSend {
// Async function that runs the api server in the background. // Async function that runs the api server in the background.
// Waits for the client to load it, at which point it sends a 1 over // Waits for the client to load it, at which point it sends a 1 over
// tx to allow the program executor to move onto the next bit of code // tx to allow the program executor to move onto the next bit of code
pub async fn api_process(data_to_send: Arc<Mutex<DataToSend>>, tx: Sender<u8>) pub async fn api_process
(
data_to_send: Arc<Mutex<DataToSend>>,
characters: Arc<Mutex<HashMap::<String,character::Character>>>,
tx: Sender<u8>,
)
{ {
// This data must be passed through to the api route in order to be used // This data must be passed through to the api route in order to be used
let data_filter = warp::any().map(move || Arc::clone(&data_to_send)); let data_filter = warp::any().map(move || Arc::clone(&data_to_send));
let characters_filter = warp::any().map(move || Arc::clone(&characters));
let tx_filter = warp::any().map(move || tx.clone()); let tx_filter = warp::any().map(move || tx.clone());
debug!("Running server"); info!("Running server");
// The server route is loaded at address:port/happening // The server route is loaded at address:port/happening
let route = warp::path("happening") let main = warp::path("happening")
.and(warp::get()) .and(warp::get())
.and(data_filter) .and(data_filter)
.and(tx_filter) .and(tx_filter)
// Perform this code on a GET request // Perform this code on a GET request
.map(|state: Arc<Mutex<DataToSend>>, tx_handle: Sender<u8>| { .map(|state: Arc<Mutex<DataToSend>>, tx_handle: Sender<u8>|
{
info!("GET: {:?}", state); info!("GET: {:?}", state);
let reply = state.as_ref(); let reply = state.as_ref();
let _ = tx_handle.send(1); let _ = tx_handle.send(1);
warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON) warp::reply::json(&reply) // Send the reply data (data_to_send formatted as JSON)
}).boxed(); }).boxed();
let characters = warp::path("character")
.and(warp::get())
.and(warp::path::param::<String>())
.and(characters_filter)
.map(|name: String, characters: Arc<Mutex<HashMap<String, character::Character>>>|
{
let map = characters.lock().unwrap(); // TODO remove unwrap
let reply = map.get(&name).unwrap();
debug!("GET: name: {}, data: {:?}", name, reply);
warp::reply::json(&reply)
}).boxed();
let routes = main.or(characters);
// Start the server // Start the server
warp::serve(route) warp::serve(routes)
.run(([127, 0, 0, 1],config::API_PORT)) .run(([127, 0, 0, 1],config::API_PORT))
.await; .await;
} }
+59
View File
@@ -1,6 +1,33 @@
use crate::{
HashMap,
fs,
debug,
Deserialize,
Serialize,
Mutex,
Arc,
};
#[derive(Debug, Deserialize, Serialize)]
pub struct Character pub struct Character
{ {
name: String, name: String,
gender: String,
eye_color: String,
pronoun_subject: String,
pronoun_object: String,
pronoun_deppos: String,
pronoun_indpos: String,
pronoun_reflex: String,
animation: String,
head: String,
hair: String,
torso: String,
arm: String,
leg: String,
hair_color: String,
top_clothing: String,
bottom_clothing: String,
shoes: String,
} }
impl Character impl Character
{ {
@@ -9,6 +36,38 @@ impl Character
Character Character
{ {
name: new_name, name: new_name,
gender: "".to_string(),
eye_color: "".to_string(),
pronoun_subject: "".to_string(),
pronoun_object: "".to_string(),
pronoun_deppos: "".to_string(),
pronoun_indpos: "".to_string(),
pronoun_reflex: "".to_string(),
animation: "".to_string(),
head: "".to_string(),
hair: "".to_string(),
torso: "".to_string(),
arm: "".to_string(),
leg: "".to_string(),
hair_color: "".to_string(),
top_clothing: "".to_string(),
bottom_clothing: "".to_string(),
shoes: "".to_string(),
} }
} }
} }
pub async fn character_parse()
-> Result<Arc<Mutex<HashMap<String, Character>>>,String>
{
// Get the JSON file to a string
let file_contents: String = fs::read_to_string("stories/characters.json")
.unwrap_or_else(|err| { return err.to_string() });
// Serialise this to a HashMap
let characters: HashMap<String, Character> =
serde_json::from_str(&file_contents)
.expect("JSON was not well-formatted");
debug!("{:?}",characters);
Ok(Arc::new(Mutex::new(characters)))
}
+21 -5
View File
@@ -10,6 +10,8 @@ use log::
warn, warn,
debug, debug,
}; };
use serde_json::from_str;
use serde::{Deserialize, Serialize};
mod parsing; mod parsing;
mod character; mod character;
@@ -30,24 +32,33 @@ async fn main()
content: "".to_string(), content: "".to_string(),
character: "".to_string(), character: "".to_string(),
})); }));
// Setup the characters hashmap which will store each character in it as a Character struct
let mut characters: Arc<Mutex<HashMap::<String, character::Character>>> = Default::default();
match character::character_parse().await
{
Ok(result) => characters = result, //let mut characters = character,
Err(error) =>
{
eprintln!("{}",error);
std::process::exit(3);
},
};
// setup the api stuff // // setup the api stuff //
// Make clones of the data Arc for the two processes // Make clones of the data Arc for the two processes
let data_clone1 = Arc::clone(&data_to_send); let data_clone1 = Arc::clone(&data_to_send);
let characters_clone1 = Arc::clone(&characters);
let tx_clone = tx.clone(); let tx_clone = tx.clone();
// Spawn a thread for warp api server // Spawn a thread for warp api server
tokio::spawn( tokio::spawn(
async move { async move {
api::api_process(data_clone1, tx_clone).await; api::api_process(data_clone1, characters_clone1, tx_clone).await;
}); });
// setup the parsing stuff // // setup the parsing stuff //
// Setup the characters hashmap which will store each character in it as a Character struct
let mut characters = HashMap::<String, character::Character>::new();
// Read the file and split it into tokens // Read the file and split it into tokens
let file_contents: String = fs::read_to_string("stories/story.ha") // TODO make this a command line argument let file_contents: String = fs::read_to_string("stories/story.ha") // TODO make this a command line argument
.unwrap_or_else(|err| .unwrap_or_else(|err|
@@ -58,10 +69,15 @@ async fn main()
let tokens: Vec<&str> = file_contents let tokens: Vec<&str> = file_contents
.split_whitespace() .split_whitespace()
.collect(); .collect();
if ! tokens.contains(&"END")
{
warn!("No END statement, story may exit unexpectedly");
}
let data_clone2 = Arc::clone(&data_to_send); let data_clone2 = Arc::clone(&data_to_send);
let characters_clone2 = Arc::clone(&characters);
// Run the parsing process // Run the parsing process
match parsing::token_parse(&tokens, &mut characters, data_clone2, &rx).await match parsing::token_parse(&tokens, characters_clone2, data_clone2, &rx).await
{ {
// Exit with error or success // Exit with error or success
Ok(()) => Ok(()) =>
+3 -10
View File
@@ -11,7 +11,6 @@ use crate::
Arc, Arc,
Mutex, Mutex,
info, info,
warn,
debug, debug,
}; };
@@ -20,7 +19,7 @@ use crate::
// Returns success or an error string // Returns success or an error string
pub async fn token_parse( pub async fn token_parse(
tokens: &Vec<&str>, tokens: &Vec<&str>,
mut characters: &mut HashMap::<String, character::Character>, mut characters: Arc<Mutex<HashMap::<String, character::Character>>>,
data_to_send: Arc<Mutex<api::DataToSend>>, data_to_send: Arc<Mutex<api::DataToSend>>,
rx: &Receiver<u8>, rx: &Receiver<u8>,
) -> Result<(),String> ) -> Result<(),String>
@@ -43,15 +42,9 @@ pub async fn token_parse(
if token.starts_with('@') if token.starts_with('@')
{ {
let character_name: String = token.chars().skip(1).collect(); let character_name: String = token.chars().skip(1).collect();
// If the character doesn't exist, then create it
if ! characters.contains_key(&character_name)
{
let new_character = character::Character::new(character_name.clone());
characters.insert(character_name.clone(),new_character);
}
info!("Doing something with a character: {}", character_name); info!("Doing something with a character: {}", character_name);
// The index is incremented to after the character's instructions // The index is incremented to after the character's instructions
index += match character_parse(index+1, &tokens, character_name, &mut characters, &data_to_send, &rx).await index += match character_parse(index+1, &tokens, character_name, &characters, &data_to_send, &rx).await
{ {
Ok(increment) => increment, Ok(increment) => increment,
Err(error) => return Err(error), Err(error) => return Err(error),
@@ -73,7 +66,7 @@ async fn character_parse
index: usize, index: usize,
tokens: &Vec<&str>, tokens: &Vec<&str>,
character_name: String, character_name: String,
characters: &mut HashMap::<String, character::Character>, characters: &Arc<Mutex<HashMap::<String, character::Character>>>,
data_to_send: &Arc<Mutex<api::DataToSend>>, data_to_send: &Arc<Mutex<api::DataToSend>>,
rx: &Receiver<u8>, rx: &Receiver<u8>,
) -> Result<usize,String> ) -> Result<usize,String>
+23
View File
@@ -0,0 +1,23 @@
{
"tim": {
"name": "Timothy Sharpshooter",
"gender": "",
"skin_color": "",
"eye_color": "",
"pronoun_subject": "",
"pronoun_object": "",
"pronoun_deppos": "",
"pronoun_indpos": "",
"pronoun_reflex": "",
"animation": "",
"head": "",
"hair": "",
"torso": "",
"arm": "",
"leg": "",
"hair_color": "",
"top_clothing": "",
"bottom_clothing": "",
"shoes": ""
}
}