From a18928c673635a24f708fc1320798b41a0c9cec6 Mon Sep 17 00:00:00 2001 From: deadvey Date: Thu, 14 May 2026 21:24:28 +0100 Subject: [PATCH] added CHANGE command --- server/report.odt | Bin 13997 -> 0 bytes server/src/api.rs | 19 +++++++++++++++++-- server/src/character.rs | 28 ++++++++++++++++++++++++++++ server/src/main.rs | 1 + server/src/parsing.rs | 32 +++++++++++++++++++++++++++++--- stories/characters.json | 12 ++++++------ stories/no-characters.zip | Bin 265 -> 0 bytes stories/no-story.zip | Bin 344 -> 0 bytes stories/nothing.zip | Bin 373 -> 0 bytes stories/story.ha | 1 + stories/test.zip | Bin 587 -> 635 bytes 11 files changed, 82 insertions(+), 11 deletions(-) delete mode 100644 server/report.odt delete mode 100644 stories/no-characters.zip delete mode 100644 stories/no-story.zip delete mode 100644 stories/nothing.zip diff --git a/server/report.odt b/server/report.odt deleted file mode 100644 index eefef77e132f23724f7ecf0e45530c7b2e3344c3..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 13997 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 diff --git a/server/src/api.rs b/server/src/api.rs index f38b73a..5bee681 100644 --- a/server/src/api.rs +++ b/server/src/api.rs @@ -4,6 +4,7 @@ use crate:: // internal code character, // libraries + json, HashMap, Arc, Mutex, @@ -11,6 +12,7 @@ use crate:: mpsc::Sender, info, debug, + warn, Serialize, Deserialize, }; @@ -60,8 +62,21 @@ pub async fn api_process .and(characters_filter) .map(|name: String, characters: Arc>>| { - let map = characters.lock().unwrap(); // TODO eh - let reply = map.get(&name).unwrap(); // TODO eh + let characters = match characters.lock() + { + Ok(data) => data, + Err(poisoned) => + { + warn!("Character Mutex is poisoned"); + poisoned.into_inner() + }, + }; + let Some(reply) = characters.get(&name) + else + { + warn!("Client requested character that does not exist"); + return warp::reply::json(&json!({"reply": "invalid character"})); + }; debug!("GET: name: {name}"); warp::reply::json(&reply) }).boxed(); diff --git a/server/src/character.rs b/server/src/character.rs index 2fd8e8e..2b7d601 100644 --- a/server/src/character.rs +++ b/server/src/character.rs @@ -31,6 +31,34 @@ pub struct Character bottom_clothing: String, shoes: String, } +impl Character { + pub fn set_field(&mut self, field: &str, value: &str) -> Result<(), ()> { + match field { + "name" => self.name = value.to_string(), + "gender" => self.gender = value.to_string(), + "eye_color" => self.eye_color = value.to_string(), + "pronoun_subject" => self.pronoun_subject = value.to_string(), + "pronoun_object" => self.pronoun_object = value.to_string(), + "pronoun_deppos" => self.pronoun_deppos = value.to_string(), + "pronoun_indpos" => self.pronoun_indpos = value.to_string(), + "pronoun_reflex" => self.pronoun_reflex = value.to_string(), + "animation" => self.animation = value.to_string(), + "head" => self.head = value.to_string(), + "hair" => self.hair = value.to_string(), + "torso" => self.torso = value.to_string(), + "arm" => self.arm = value.to_string(), + "leg" => self.leg = value.to_string(), + "hair_color" => self.hair_color = value.to_string(), + "top_clothing" => self.top_clothing = value.to_string(), + "bottom_clothing" => self.bottom_clothing = value.to_string(), + "shoes" => self.shoes = value.to_string(), + + _ => return Err(()), + } + + Ok(()) + } +} pub fn character_parse(archive: &mut ZipArchive) -> Result>>,String> diff --git a/server/src/main.rs b/server/src/main.rs index cad2003..e1a6658 100644 --- a/server/src/main.rs +++ b/server/src/main.rs @@ -19,6 +19,7 @@ use serde:: Deserialize, Serialize }; +use serde_json::json; use zip:: { ZipArchive, diff --git a/server/src/parsing.rs b/server/src/parsing.rs index d8888c7..8670c3e 100644 --- a/server/src/parsing.rs +++ b/server/src/parsing.rs @@ -165,7 +165,7 @@ fn character_parse // Ensure the index is valid (the index is not beyond the vector) let token = tokens .get(sum_index) - .ok_or_else(|| "File reached termination point".to_string())?; + .ok_or_else(|| "File unexpectedly reached termination point".to_string())?; match token.to_lowercase().as_str() { // The character is saying something, so grab the text and pass it @@ -173,7 +173,7 @@ fn character_parse "says" => { info!("SAYS command with character {character_name}"); - match strings::extract_quoted(&tokens[sum_index+1..]) // TODO increment to after the string + match strings::extract_quoted(&tokens[sum_index+1..]) { Some((output_string, counter)) => { @@ -185,9 +185,35 @@ fn character_parse data.character = character_name; data.choices = vec![]; }, - None => return Err(String::from("Unable to read string")), + None => return Err("Unable to read output string".to_string()), } }, + // Change the property of the selected character eg @tim CHANGE name "Bill Buffins" + // will change the character with ID tim to "Bill Buffins"; a character's ID cannot change + "change" => + { + sum_index += 1; + let feature = tokens + .get(sum_index) + .ok_or_else(|| "File unexpectedly reached termination point".to_string())?; + let output_string: String; + (output_string, sum_index) = match strings::extract_quoted(&tokens[sum_index+1..]) + { + Some((string,counter)) => (string,sum_index+counter), + None => return Err("Unable to parse property to change character".to_string()), + }; + info!("CHANGE command with character {character_name} feature {feature}"); + let mut characters = characters.lock().expect("Data cannot be unlocked"); + if let Some(character) = characters.get_mut(&character_name) + { + if character.set_field(feature, &output_string) + .is_err() { warn!("Feature {feature} does not exist") }; + } + let mut data = data_to_send.lock().unwrap(); + data.action_type = String::from("change"); + data.content = String::new(); + data.character = character_name; + }, // Catch all condition, if the instruction is unrecognised as a // character command _ => return Err(format!("Invalid command: {token}")), diff --git a/stories/characters.json b/stories/characters.json index a5ec8d4..c120f30 100644 --- a/stories/characters.json +++ b/stories/characters.json @@ -1,14 +1,14 @@ { "tim": { "name": "Timothy Sharpshooter", - "gender": "", + "gender": "Male", "skin_color": "", "eye_color": "", - "pronoun_subject": "", - "pronoun_object": "", - "pronoun_deppos": "", - "pronoun_indpos": "", - "pronoun_reflex": "", + "pronoun_subject": "He", + "pronoun_object": "Him", + "pronoun_deppos": "His", + "pronoun_indpos": "His", + "pronoun_reflex": "Himself", "animation": "", "head": "", "hair": "", diff --git a/stories/no-characters.zip b/stories/no-characters.zip deleted file mode 100644 index dd9ff219232122092146856903e11b150a0a3ddb..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 265 zcmWIWW@Zs#U|`^2@ZYl{=1CJzN-_fj!*sBS3`22Aeo>`fMq+3PCj;}hlz*Ap|5>t1 zE4UdLSza(RFo20-jgx0WHT>4-gaw@PID7JBxW;+?Q=S(CPv`{dhk1l}oImd$=;660 zXbukWW@Q7ZV`N}t@MBS}Wg7iw$ttbjW?*D_!OXw_CQ2tb@--_6xLz;dI=oB$h3T!mjx)J*&j?6NmU?{G z`?1riGV}ju|DXIbb7{bvrd?*6MVuD$1*DahH{S3&d-j#cX4NE*SD#9G8kU_oy7|?g zq8s0ytV}XED0kGwLwQ@}n|T*L7dqDOXq3>D-|1X@O4!C`kNLWbtY`ZQoW-`RoKkjm zu8(H$RKG-FxwiW^_NfHtRL9Fb-%wO`#OGm3;6JWxW=*l3C-?)r8JXmmad}sQ0R$Ks k7#Nl`f>;=yXN7nk&Eo;ytZX3Vj0}tnp$rTRZ$TUe0IZ06Gynhq diff --git a/stories/nothing.zip b/stories/nothing.zip deleted file mode 100644 index 670361456d97a258599dcede8a75ce5857fc134a..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 373 zcmWIWW@Zs#U|`^2aM-jaW<}`q=SLYB7(y8t7g_y|R z>Rr5DrOH2EfB)Ma{B_mNm15axq3wT8JY4ikZtce0XA|9251ryJ71bqJ9Gk4v;-}^Nd>+YCc_1O}{+V_YP diff --git a/stories/story.ha b/stories/story.ha index a8799fb..84a6ac7 100644 --- a/stories/story.ha +++ b/stories/story.ha @@ -1,4 +1,5 @@ @tim says "hello world, it's a good day" +@tim change name "Timothy Fineshooter" choice "choice numero uno" { @tim says "super sad" } diff --git a/stories/test.zip b/stories/test.zip index 3575183923da886b1bbd8404b991d016e6afbd27..2fed764632d65b7a182ff60b759d3f44bb1db9bb 100644 GIT binary patch literal 635 zcmWIWW@Zs#U|`^2__cUl%+;)ai+3?FFf3wZVBlwvVMxwMEJ{o+Ni8bY%PP*#3k~69 zU{+UV%ZgEE%POtlW?*D_!OXw_CQ2tb@--_6xLz;nYAf}>AY5`ebhr76#g`88G#ain zyth}wSLE`$XaBz|)~5-zrsO_-YSOuA!U~-uk#<{D-yOfaH~e1fypDsXKTmqWFx%qz z8DB|{xQa}jY@;o|PBshnP5azpk|5dkiqlm80hi^X-XlShSqCh+I9p{hbN(svuWkJP z{V>Ba--w0Vx=bHlTgQI&&6G>KpZVBbP@B4aw!wv`=limacWyHKI7h1dWY>(7{}?{r z+VD=v)v!CVh5-=-Oe@yKEZQw3QOm%u|EAe>Z^uW0$Q9ni!tI-JE;+txtY{HzSiAGp;z4U;qI|1_p*DjUX0AjIu&v6wOD- ohGK>avZ2h33`k+b%D{{zd;+{#*+7;vF)%SKW?*1A1ac1p086gmZ2$lO literal 587 zcmWIWW@Zs#U|`^2@ZYl{=BebCiX{vT3_Xkt4Ezi-49OXZMTyBJsYS(lS;hHzp&^_M z%->S}Wg7iw$ttbjW?*D_!OXw_CQ2tb@--_6xLz;dI=oB$h3T!mjx)J*&j?6NmU?{G z`?1riGV}ju|DXIbb7{bvrd?*6MVuD$1*DahH{S3&d-j#cX4NE*SD#9G8kU_oy7|?g zq8s0ytV}XED0kGwLwQ@}n|T*L7dqDOXq3>D-|1X@O4!C`kNLWbtY`ZQoW-`RoKkjm zu8(H$RKG-FxwiW^_NfHtRL9Fb-%wO`#OGm3;6JWxW=*l3C-_l4`=p5{C7FSNVLI6R zG7QBf`9+m_8HsRTYGeAcSmWfGPz}E|I$;5)JkFjx8Ln|&|CHy&z!N%w`e7a+9_P>d z2YPs}33=po?!g~= c0|Qb>;4+Ps4P-eJ0~5ny1_p*nAonl;0E(5%`2YX_