Client is approx 5% done

This commit is contained in:
2026-05-20 21:51:09 +01:00
parent 556185e095
commit 29565949b0
9 changed files with 2229 additions and 4 deletions
+1
View File
@@ -1,4 +1,5 @@
/server/target /server/target
/client/target
*.swp *.swp
.venv .venv
.~* .~*
+2059
View File
File diff suppressed because it is too large Load Diff
+11
View File
@@ -0,0 +1,11 @@
[package]
name = "happening-client"
version = "0.1.0"
edition = "2024"
[dependencies]
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"
+155
View File
@@ -0,0 +1,155 @@
use macroquad::prelude::*;
use reqwest::*;
use reqwest::blocking;
use std::collections::HashMap;
use phf::phf_map;
use std::{thread, time::Duration};
use serde::
{
Serialize,
Deserialize,
};
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
pub struct Data {
pub action_type: String,
pub content: String,
pub character: String,
pub choices: Vec<String>,
}
#[derive(Debug, Deserialize, Serialize, Clone, Default)]
#[serde(default)]
pub struct Character
{
name: String,
gender: String,
eye_color: Colour,
hair_color: Colour,
skin_color: Colour,
pronoun_subject: String,
pronoun_object: String,
pronoun_deppos: String,
pronoun_indpos: String,
pronoun_reflex: String,
head_shape: String,
hair_style: String,
torso_shape: String,
arm_shape: String,
leg_shape: String,
clothing: Clothing,
}
#[derive(Debug,Deserialize,Serialize,Clone,Default)]
#[serde(default)]
pub struct Clothing
{
top: String,
bottom: String,
shoes: String,
}
#[derive(Debug,Deserialize,Serialize,Clone,Default)]
#[serde(default)]
pub struct Colour
{
red: u8,
green: u8,
blue: u8,
}
static POSITIONS: phf::Map<&'static str, [f32;2]> = phf_map! [
"fl" => [0.0,500.0],
"bl" => [0.0,0.0],
"fr" => [500.0,500.0],
"br" => [500.0,0.0],
];
#[macroquad::main("happening")]
async fn main()
{
let mut characters: HashMap<String, (Character, Texture2D)> = HashMap::new();
let mut textures: Vec<(Texture2D, f32, f32, Color)> = Vec::new();
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)
{
let new_character = get_character(character_name).await;
characters.insert(character_name.to_string(), new_character);
}
// Matchbox for all the commands
match data.action_type.to_lowercase().as_str()
{
"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);
},
"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
}
_ => println!("Unknown action"),
}
for (texture, x, y, colour) in &textures
{
draw_texture(&texture, *x, *y, *colour);
}
thread::sleep(Duration::from_millis(1000));
next_frame().await;
}
}
fn next_happening()
-> Data
{
let data: Data = reqwest::blocking::get(format!("http://127.0.0.1:20264/happening")).unwrap().json().unwrap();
println!("{data:?}");
data
}
async fn get_character(name: &str)
-> (Character, Texture2D)
{
let character: Character = reqwest::blocking::get(format!("http://127.0.0.1:20264/character/{name}")).unwrap().json().unwrap();
println!("{character:?}");
let skin_colour = character.skin_color.clone();
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: Texture2D = change_colour(&mut load_image(head_path.as_str()).await.unwrap(), &skin, &hair);
(character, head)
}
fn change_colour(image: &mut Image, skin: &Color, hair: &Color)
-> Texture2D
{
let target = Color::from_rgba(255,0,255,255);
for y in 0..image.height() {
for x in 0..image.width() {
let pixel = image.get_pixel(x as u32, y as u32);
if pixel == target {
image.set_pixel(x as u32, y as u32, *skin);
}
}
}
let target = Color::from_rgba(0,255,255,255);
for y in 0..image.height() {
for x in 0..image.width() {
let pixel = image.get_pixel(x as u32, y as u32);
if pixel == target {
image.set_pixel(x as u32, y as u32, *hair);
}
}
}
Texture2D::from_image(&image)
}
Binary file not shown.

After

Width:  |  Height:  |  Size: 981 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1011 B

+1 -2
View File
@@ -43,8 +43,6 @@ pub async fn api_process
let tx_filter1 = warp::any().map(move || tx.clone()); let tx_filter1 = warp::any().map(move || tx.clone());
let tx_filter2 = tx_filter1.clone(); let tx_filter2 = tx_filter1.clone();
info!("Running server");
// The server route is loaded at address:port/happening // The server route is loaded at address:port/happening
let main = warp::path("happening") let main = warp::path("happening")
.and(warp::get()) .and(warp::get())
@@ -109,6 +107,7 @@ pub async fn api_process
let routes = main.or(characters).or(choice).or(input); let routes = main.or(characters).or(choice).or(input);
// Start the server // Start the server
info!("Running server");
warp::serve(routes) warp::serve(routes)
.run(([127, 0, 0, 1],config::API_PORT)) .run(([127, 0, 0, 1],config::API_PORT))
.await; .await;
+1 -2
View File
@@ -121,8 +121,7 @@ async fn main()
Ok(()) => Ok(()) =>
{ {
api::modify_data(&happening_stack, "end".to_string(), String::new(), String::new(), vec![]); api::modify_data(&happening_stack, "end".to_string(), String::new(), String::new(), vec![]);
// TODO fix quitting instantly let _ = rx.recv();
let _ = rx.recv(); // Wait for the client to respond
info!("Program exited successfully"); info!("Program exited successfully");
exit(0); exit(0);
}, },
+1
View File
@@ -26,6 +26,7 @@ def main():
continue continue
case "end": case "end":
print("Exitting successfully") print("Exitting successfully")
requests.post("127.0.0.1:20264", json=0);
os._exit(0) os._exit(0)
except: except:
print("Server not up or cannot be reached") print("Server not up or cannot be reached")