From 21bf6597182cb87c3518dde5e53aed3d042a6308 Mon Sep 17 00:00:00 2001 From: deadvey Date: Sun, 24 May 2026 15:09:59 +0100 Subject: [PATCH] Began adding support for variables --- client/Cargo.lock | 92 +++++++++++++++++++++ client/Cargo.toml | 2 + client/src/main.rs | 110 ++++++++++++++++++++----- server/src/parsing.rs | 14 ++++ server/src/parsing/identifier_parse.rs | 29 +++++++ server/src/tokenise.rs | 62 +++++++++++++- stories/story.ha | 2 + stories/test.zip | Bin 924 -> 936 bytes 8 files changed, 287 insertions(+), 24 deletions(-) create mode 100644 server/src/parsing/identifier_parse.rs diff --git a/client/Cargo.lock b/client/Cargo.lock index 23eb449..f1e2643 100644 --- a/client/Cargo.lock +++ b/client/Cargo.lock @@ -206,6 +206,16 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "877a4ace8713b0bcf2a4e7eec82529c029f1d0619886d18145fea96c3ffe5c0f" +[[package]] +name = "errno" +version = "0.3.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "39cab71617ae0d63f51a36d69f866391735b51691dbda63cf6f96d042b63efeb" +dependencies = [ + "libc", + "windows-sys 0.52.0", +] + [[package]] name = "fastrand" version = "2.4.1" @@ -379,11 +389,13 @@ dependencies = [ name = "happening-client" version = "0.1.0" dependencies = [ + "home", "macroquad", "phf", "reqwest", "serde", "serde_json", + "tokio", ] [[package]] @@ -403,6 +415,15 @@ version = "0.17.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ed5909b6e89a2db4456e54cd5f673791d7eca6732202bbf2a9cc504fe2f9b84a" +[[package]] +name = "home" +version = "0.5.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cc627f471c528ff0c4a49e1d5e60450c8f6461dd6d10ba9dcd3a61d3dff7728d" +dependencies = [ + "windows-sys 0.61.2", +] + [[package]] name = "http" version = "1.4.0" @@ -724,6 +745,15 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "92daf443525c4cce67b150400bc2316076100ce0b3686209eb8cf3c31612e6f0" +[[package]] +name = "lock_api" +version = "0.4.14" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "224399e74b87b5f3557511d98dff8b14089b3dadafcab6bb93eab67d3aace965" +dependencies = [ + "scopeguard", +] + [[package]] name = "log" version = "0.4.29" @@ -846,6 +876,29 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7c87def4c32ab89d880effc9e097653c8da5d6ef28e6b539d313baaacfbafcbe" +[[package]] +name = "parking_lot" +version = "0.12.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "93857453250e3077bd71ff98b6a65ea6621a19bb0f559a85248955ac12c45a1a" +dependencies = [ + "lock_api", + "parking_lot_core", +] + +[[package]] +name = "parking_lot_core" +version = "0.9.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2621685985a2ebf1c516881c026032ac7deafcda1a2c9b7850dc81e3dfcb64c1" +dependencies = [ + "cfg-if", + "libc", + "redox_syscall", + "smallvec", + "windows-link", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -1047,6 +1100,15 @@ dependencies = [ "getrandom 0.3.4", ] +[[package]] +name = "redox_syscall" +version = "0.5.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed2bf2547551a7053d6fdfafda3f938979645c44812fbfcda098faae3f1a362d" +dependencies = [ + "bitflags 2.11.1", +] + [[package]] name = "reqwest" version = "0.13.3" @@ -1217,6 +1279,12 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "scopeguard" +version = "1.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49" + [[package]] name = "security-framework" version = "3.7.0" @@ -1295,6 +1363,16 @@ version = "1.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0fda2ff0d084019ba4d7c6f371c95d8fd75ce3524c3cb8fb653a3023f6323e64" +[[package]] +name = "signal-hook-registry" +version = "1.4.8" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c4db69cba1110affc0e9f7bcd48bbf87b3f4fc7c61fc9155afd4c469eb3d6c1b" +dependencies = [ + "errno", + "libc", +] + [[package]] name = "simd-adler32" version = "0.3.9" @@ -1463,11 +1541,25 @@ dependencies = [ "bytes", "libc", "mio", + "parking_lot", "pin-project-lite", + "signal-hook-registry", "socket2", + "tokio-macros", "windows-sys 0.61.2", ] +[[package]] +name = "tokio-macros" +version = "2.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "385a6cb71ab9ab790c5fe8d67f1645e6c450a7ce006a33de03daa956cf70a496" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + [[package]] name = "tokio-rustls" version = "0.26.4" diff --git a/client/Cargo.toml b/client/Cargo.toml index c183e13..be168de 100644 --- a/client/Cargo.toml +++ b/client/Cargo.toml @@ -4,8 +4,10 @@ version = "0.1.0" edition = "2024" [dependencies] +home = "0.5.12" macroquad = "0.4.15" phf = {version="0.13.1",features=["macros"]} reqwest = {version="0.13.3",features=["blocking","json"]} serde = {version="1.0.228",features=["derive"]} serde_json = "1.0.149" +tokio = {version="1.52.3",features=["full"]} diff --git a/client/src/main.rs b/client/src/main.rs index 4d58a1d..bbd29d1 100644 --- a/client/src/main.rs +++ b/client/src/main.rs @@ -1,14 +1,24 @@ use macroquad::prelude::*; use reqwest::*; use reqwest::blocking; -use std::collections::HashMap; use phf::phf_map; -use std::{thread, time::Duration}; +use std:: +{ + thread, + time::Duration, + collections:: + { + HashMap, + HashSet, + }, + process::exit, +}; use serde:: { Serialize, Deserialize, }; +use home::home_dir; #[derive(Debug, Deserialize, Serialize, Clone, Default)] pub struct Data { @@ -69,45 +79,92 @@ static POSITIONS: phf::Map<&'static str, [f32;2]> = phf_map! [ async fn main() { let mut characters: HashMap = HashMap::new(); - let mut textures: Vec<(Texture2D, f32, f32, Color)> = Vec::new(); + characters.insert("narrator".to_string(), (Character { name: "Narrator".to_string(), ..Default::default() }, Texture2D::empty())); + let mut textures: HashMap = HashMap::new(); + let mut text: String = String::new(); + let mut checking_for_choice: bool = false; + let mut data: Data = next_happening(); // First one should be begin loop { clear_background(RED); - // Get the next character - let data = next_happening(); - let character_name: &str = data.character.as_str(); - // Add the character to the HashMap if it's not already - if character_name != "" && !characters.contains_key(character_name) + for (name, (texture, x, y, colour)) in &textures { - let new_character = get_character(character_name).await; - characters.insert(character_name.to_string(), new_character); + draw_texture(&texture, *x, *y, *colour); + } + draw_multiline_text(&text, 50.0,30.0,40.0,None,WHITE); + if !is_any_key_down() + { + next_frame().await; + continue + } + let keys: HashSet = get_keys_pressed(); + if checking_for_choice + { + for key in &keys + { + let keycode = *key as u16; + let length: u16 = data.choices.len() as u16; + println!("key: {key:?} {keycode}"); + if keycode > 48 && keycode <= length+48 + { + checking_for_choice = false; + println!("Sending POST: {}",keycode-49); + let value = keycode - 49; + send_choice(value); + } + else { continue } + } + } + // Get the next character + data = next_happening(); + let character_name: String = data.character.to_lowercase(); + // Add the character to the HashMap if it's not already + if character_name != "" && !characters.contains_key(&character_name) + { + println!("Fetching {character_name}"); + let new_character = get_character(&character_name).await; + characters.insert(character_name.clone(), new_character); } // Matchbox for all the commands match data.action_type.to_lowercase().as_str() { + "choice" => + { + for (index, choice) in data.choices.iter().enumerate() + { + text += format!("\n{}. {}",index+1, choice).as_str(); + } + checking_for_choice = true; + }, "output" => { println!("SAYING"); - draw_text(characters[character_name].0.name.clone(), 50.0,20.0,40.0,WHITE); - draw_text(data.content.as_str(), 50.0,40.0,30.0,WHITE); + text = format!("{}: {}", characters[&character_name].0.name.clone(),wrap_text(&data.content).as_str()); }, "to" => { let position = POSITIONS.get(&data.content).cloned().unwrap(); - let texture = &characters[character_name].1; - textures.push((texture.clone(), position[0], position[1], WHITE)); // Heavy + let texture = &characters[&character_name].1; + textures.insert(character_name.clone(),(texture.clone(), position[0], position[1], WHITE)); // Heavy } - _ => println!("Unknown action"), + "begin" => (), + "end" => exit(0), + _ => println!("Unknown action, {}", data.action_type), } - for (texture, x, y, colour) in &textures - { - draw_texture(&texture, *x, *y, *colour); - } - thread::sleep(Duration::from_millis(1000)); next_frame().await; } } +fn wrap_text(text: &str) -> String +{ + text.chars() + .collect::>() + .chunks(30) + .map(|chunk| chunk.iter().collect::()) + .collect::>() + .join("\n") +} + fn next_happening() -> Data { @@ -116,6 +173,17 @@ fn next_happening() data } +#[tokio::main] +async fn send_choice(index: u16) +{ + + let client = reqwest::Client::new(); + let res = client.post("http://localhost:20264/choice") + .json(&index) + .send() + .await; +} + async fn get_character(name: &str) -> (Character, Texture2D) { @@ -125,7 +193,7 @@ async fn get_character(name: &str) let skin: Color = Color::from_rgba(skin_colour.red,skin_colour.green,skin_colour.blue,255); let hair_colour = character.hair_color.clone(); let hair: Color = Color::from_rgba(hair_colour.red,hair_colour.green,hair_colour.blue,255); - let head_path: String = format!("../images/head/{}.png",character.head_shape); + let head_path: String = format!("/home/deadvey/.local/share/happening/images/head/{}.png",character.head_shape); let head: Texture2D = change_colour(&mut load_image(head_path.as_str()).await.unwrap(), &skin, &hair); (character, head) } diff --git a/server/src/parsing.rs b/server/src/parsing.rs index 841931d..8ae25a6 100644 --- a/server/src/parsing.rs +++ b/server/src/parsing.rs @@ -18,6 +18,7 @@ use crate:: mod character_parse; mod keyword_parse; +mod identifier_parse; // Parse the tokens in a file // Returns success or an error string @@ -66,6 +67,19 @@ pub fn token_parse( }, }; } + // Identifier + Some(tokenise::Token::Identifier(name)) => + { + index = match identifier_parse::identifier_parse(index+1,tokens) + { + Ok(increment) => increment, + Err((err,increment)) => + { + warn!("{err}"); + increment + }, + }; + } Some(_) => { warn!("Unexpected token"); diff --git a/server/src/parsing/identifier_parse.rs b/server/src/parsing/identifier_parse.rs new file mode 100644 index 0000000..2f9140b --- /dev/null +++ b/server/src/parsing/identifier_parse.rs @@ -0,0 +1,29 @@ +use crate:: +{ + // Internal code + character, + api, + tokenise, + UnwrapOrExit, + //Libs + Mutex, + Arc, + HashMap, + VecDeque, + info, + warn, + debug, +}; + +#[allow(unused_variables)] +pub fn identifier_parse +( + index: usize, + tokens: &[tokenise::Token], +) -> Result +{ + let mut sum_index: usize = index; + sum_index += 1; + Ok(sum_index) +} + diff --git a/server/src/tokenise.rs b/server/src/tokenise.rs index 66897bd..d273129 100644 --- a/server/src/tokenise.rs +++ b/server/src/tokenise.rs @@ -7,19 +7,40 @@ use crate:: pub enum Token { String(String), + #[allow(dead_code)] + Integer(i64), // idk someone might want to do a big number + #[allow(dead_code)] + Bool(bool), + + #[allow(dead_code)] + Operator(Operator), Keyword(String), // Keywords aren't checked for validity in this stage - #[allow(dead_code)] // This is unused rn, but am going to add it later Identifier(String), Bracket((Bracket,usize)), // Stores the index of the matching deliminator Character(String), } -#[derive(Debug,Clone,PartialEq, Eq)] -pub enum Bracket +#[derive(Debug,Clone,PartialEq,Eq)] +pub enum Bracket { Opening, Closing, } +#[derive(Debug, Clone)] +pub enum Operator +{ + // Changing a value + Assignment, + Add, + Sub, + // Comparing a value + Comparison, + Greater, + Less, + GreaterOrEqual, + LessOrEqual, +} + pub fn get_string_token(tokens: &[Token], index: usize) -> Result { @@ -64,6 +85,29 @@ pub fn tokenise(file_contents: &str) while index < space_seperated.len() { let mut item = space_seperated[index].to_string(); + // Operator + let op: Option = match item.as_str() + { + "=" => Some(Operator::Assignment), + "+" => Some(Operator::Add), + "-" => Some(Operator::Sub), + "==" => Some(Operator::Comparison), + ">" => Some(Operator::Greater), + "<" => Some(Operator::Less), + ">=" => Some(Operator::GreaterOrEqual), + "<=" => Some(Operator::LessOrEqual), + _ => None, + }; + match op + { + Some(op) => + { + tokenised_data.push(Token::Operator(op)); + index += 1; + continue // skip the rest of this loop + }, + None => (), + } // Characters if item.starts_with('@') { @@ -80,6 +124,18 @@ pub fn tokenise(file_contents: &str) item = new_item; tokenised_data.push(Token::String(item)); } + // variable/identifier + else if item.starts_with("$") + { + let mut chars = item.chars(); + chars.next(); + tokenised_data.push(Token::Identifier(chars.as_str().to_string())); + } + // Integer + else if item.parse::().is_ok() + { + tokenised_data.push(Token::Integer(item.parse::().unwrap())); + } // Labels else if item.ends_with(':') { diff --git a/stories/story.ha b/stories/story.ha index ded3738..22c20df 100644 --- a/stories/story.ha +++ b/stories/story.ha @@ -1,5 +1,7 @@ @tim says "hello world, it's a good day" @tim change name "Timothy Fineshooter" +$x = 3 +$x + 1 label: choice "choice numero uno" { @tim says "super sad" diff --git a/stories/test.zip b/stories/test.zip index 089a22da5f9139ca62203e7472dd99dad94333db..b93251a7e30ace7f56ab2b11c704c31bc9f82972 100644 GIT binary patch delta 287 zcmbQkzJk3zz?+#xgn@y9gMqVRM@-wn^$klI7#PGEK_W5?#U=Sgm3kS8p&^_M%tb81 zSs+|m!Og(P@`9Ox0Zf#h+snmdD8TaIR&AFehuE!-xe750r-kiv*rPMuVbat;3)+9Y zyVt286Jr|v#@r`3#^G9R+om^rA1I!j%^Q;unVM0e#OC(BYu3k&Tdm4^Rxmrq#!g78 zo)h~d$CXRn^|U(QjoyvNrtR6c@qTdj(XGutQr9$2Uf>p3adFX4{}W%&W$x%*WbQeO zD>&Vyck?opbHOP`vsu_>W7H!rE}E?Lqfge#Z@O|V!^Yc37rkME5w{K=LFfed3f<$B(ic9i~D)llFLqj+jn1BD~ z$^zli3T_5QmKV$n3}B+PZ!Z^_gvp7d`h~Cb~BJ zgfiFi1CyGZO-(FJK74<3sc@IfOWuvok1+D0cx&