diff --git a/Cargo.lock b/Cargo.lock index f2aa994..29f3627 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -26,12 +26,6 @@ version = "1.0.100" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" -[[package]] -name = "anymap2" -version = "0.13.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d301b3b94cb4b2f23d7917810addbbaff90738e0ca2be692bd027e70d7e0330c" - [[package]] name = "atomic-waker" version = "1.1.2" @@ -160,12 +154,6 @@ dependencies = [ "generic-array", ] -[[package]] -name = "boolinator" -version = "2.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfa8873f51c92e232f9bac4065cddef41b714152812bfc5f7672ba16d6ef8cd9" - [[package]] name = "bumpalo" version = "3.19.0" @@ -255,18 +243,18 @@ dependencies = [ [[package]] name = "convert_case" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "baaaa0ecca5b51987b9423ccdc971514dd8b0bb7b4060b983d3664dad3f1f89f" +checksum = "db05ffb6856bf0ecdf6367558a76a0e8a77b1713044eb92845c692100ed50190" dependencies = [ "unicode-segmentation", ] [[package]] name = "convert_case" -version = "0.9.0" +version = "0.10.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "db05ffb6856bf0ecdf6367558a76a0e8a77b1713044eb92845c692100ed50190" +checksum = "633458d4ef8c78b72454de2d54fd6ab2e60f9e02be22f3c6104cdc8a4e0fceb9" dependencies = [ "unicode-segmentation", ] @@ -507,74 +495,23 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gloo" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28999cda5ef6916ffd33fb4a7b87e1de633c47c0dc6d97905fee1cdaa142b94d" -dependencies = [ - "gloo-console 0.2.3", - "gloo-dialogs 0.1.1", - "gloo-events 0.1.2", - "gloo-file 0.2.3", - "gloo-history 0.1.5", - "gloo-net 0.3.1", - "gloo-render 0.1.1", - "gloo-storage 0.2.2", - "gloo-timers 0.2.6", - "gloo-utils 0.1.7", - "gloo-worker 0.2.1", -] - -[[package]] -name = "gloo" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd35526c28cc55c1db77aed6296de58677dbab863b118483a27845631d870249" -dependencies = [ - "gloo-console 0.3.0", - "gloo-dialogs 0.2.0", - "gloo-events 0.2.0", - "gloo-file 0.3.0", - "gloo-history 0.2.2", - "gloo-net 0.4.0", - "gloo-render 0.2.0", - "gloo-storage 0.3.0", - "gloo-timers 0.3.0", - "gloo-utils 0.2.0", - "gloo-worker 0.4.0", -] - [[package]] name = "gloo" version = "0.11.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d15282ece24eaf4bd338d73ef580c6714c8615155c4190c781290ee3fa0fd372" dependencies = [ - "gloo-console 0.3.0", - "gloo-dialogs 0.2.0", - "gloo-events 0.2.0", - "gloo-file 0.3.0", - "gloo-history 0.2.2", - "gloo-net 0.5.0", - "gloo-render 0.2.0", - "gloo-storage 0.3.0", - "gloo-timers 0.3.0", - "gloo-utils 0.2.0", - "gloo-worker 0.5.0", -] - -[[package]] -name = "gloo-console" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82b7ce3c05debe147233596904981848862b068862e9ec3e34be446077190d3f" -dependencies = [ - "gloo-utils 0.1.7", - "js-sys", - "serde", - "wasm-bindgen", - "web-sys", + "gloo-console", + "gloo-dialogs", + "gloo-events", + "gloo-file", + "gloo-history", + "gloo-net", + "gloo-render", + "gloo-storage", + "gloo-timers", + "gloo-utils", + "gloo-worker", ] [[package]] @@ -583,23 +520,13 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2a17868f56b4a24f677b17c8cb69958385102fa879418052d60b50bc1727e261" dependencies = [ - "gloo-utils 0.2.0", + "gloo-utils", "js-sys", "serde", "wasm-bindgen", "web-sys", ] -[[package]] -name = "gloo-dialogs" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "67062364ac72d27f08445a46cab428188e2e224ec9e37efdba48ae8c289002e6" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-dialogs" version = "0.2.0" @@ -610,16 +537,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-events" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "68b107f8abed8105e4182de63845afcc7b69c098b7852a813ea7462a320992fc" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-events" version = "0.2.0" @@ -630,18 +547,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-file" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8d5564e570a38b43d78bdc063374a0c3098c4f0d64005b12f9bbe87e869b6d7" -dependencies = [ - "gloo-events 0.1.2", - "js-sys", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-file" version = "0.3.0" @@ -649,28 +554,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "97563d71863fb2824b2e974e754a81d19c4a7ec47b09ced8a0e6656b6d54bd1f" dependencies = [ "futures-channel", - "gloo-events 0.2.0", + "gloo-events", "js-sys", "wasm-bindgen", "web-sys", ] -[[package]] -name = "gloo-history" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "85725d90bf0ed47063b3930ef28e863658a7905989e9929a8708aab74a1d5e7f" -dependencies = [ - "gloo-events 0.1.2", - "gloo-utils 0.1.7", - "serde", - "serde-wasm-bindgen 0.5.0", - "serde_urlencoded", - "thiserror 1.0.69", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-history" version = "0.2.2" @@ -678,58 +567,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "903f432be5ba34427eac5e16048ef65604a82061fe93789f2212afc73d8617d6" dependencies = [ "getrandom 0.2.16", - "gloo-events 0.2.0", - "gloo-utils 0.2.0", + "gloo-events", + "gloo-utils", "serde", - "serde-wasm-bindgen 0.6.5", + "serde-wasm-bindgen", "serde_urlencoded", "thiserror 1.0.69", "wasm-bindgen", "web-sys", ] -[[package]] -name = "gloo-net" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a66b4e3c7d9ed8d315fd6b97c8b1f74a7c6ecbbc2320e65ae7ed38b7068cc620" -dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils 0.1.7", - "http 0.2.12", - "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "gloo-net" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8ac9e8288ae2c632fa9f8657ac70bfe38a1530f345282d7ba66a1f70b72b7dc4" -dependencies = [ - "futures-channel", - "futures-core", - "futures-sink", - "gloo-utils 0.2.0", - "http 0.2.12", - "js-sys", - "pin-project", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "gloo-net" version = "0.5.0" @@ -739,7 +586,7 @@ dependencies = [ "futures-channel", "futures-core", "futures-sink", - "gloo-utils 0.2.0", + "gloo-utils", "http 0.2.12", "js-sys", "pin-project", @@ -751,16 +598,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-render" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2fd9306aef67cfd4449823aadcd14e3958e0800aa2183955a309112a84ec7764" -dependencies = [ - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-render" version = "0.2.0" @@ -771,28 +608,13 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-storage" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d6ab60bf5dbfd6f0ed1f7843da31b41010515c745735c970e821945ca91e480" -dependencies = [ - "gloo-utils 0.1.7", - "js-sys", - "serde", - "serde_json", - "thiserror 1.0.69", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-storage" version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "fbc8031e8c92758af912f9bc08fbbadd3c6f3cfcbf6b64cdf3d6a81f0139277a" dependencies = [ - "gloo-utils 0.2.0", + "gloo-utils", "js-sys", "serde", "serde_json", @@ -801,16 +623,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-timers" -version = "0.2.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9b995a66bb87bebce9a0f4a95aed01daca4872c050bfcb21653361c03bc35e5c" -dependencies = [ - "js-sys", - "wasm-bindgen", -] - [[package]] name = "gloo-timers" version = "0.3.0" @@ -823,19 +635,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "gloo-utils" -version = "0.1.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "037fcb07216cb3a30f7292bd0176b050b7b9a052ba830ef7d5d65f6dc64ba58e" -dependencies = [ - "js-sys", - "serde", - "serde_json", - "wasm-bindgen", - "web-sys", -] - [[package]] name = "gloo-utils" version = "0.2.0" @@ -849,42 +648,6 @@ dependencies = [ "web-sys", ] -[[package]] -name = "gloo-worker" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13471584da78061a28306d1359dd0178d8d6fc1c7c80e5e35d27260346e0516a" -dependencies = [ - "anymap2", - "bincode", - "gloo-console 0.2.3", - "gloo-utils 0.1.7", - "js-sys", - "serde", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - -[[package]] -name = "gloo-worker" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76495d3dd87de51da268fa3a593da118ab43eb7f8809e17eb38d3319b424e400" -dependencies = [ - "bincode", - "futures", - "gloo-utils 0.2.0", - "gloo-worker-macros", - "js-sys", - "pinned", - "serde", - "thiserror 1.0.69", - "wasm-bindgen", - "wasm-bindgen-futures", - "web-sys", -] - [[package]] name = "gloo-worker" version = "0.5.0" @@ -893,7 +656,7 @@ checksum = "085f262d7604911c8150162529cefab3782e91adb20202e8658f7275d2aefe5d" dependencies = [ "bincode", "futures", - "gloo-utils 0.2.0", + "gloo-utils", "gloo-worker-macros", "js-sys", "pinned", @@ -1190,9 +953,9 @@ dependencies = [ [[package]] name = "implicit-clone" -version = "0.4.9" +version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f8a9aa791c7b5a71b636b7a68207fdebf171ddfc593d9c8506ec4cbc527b6a84" +checksum = "1689b939ee35e3a075b0834b5672efd43aec8a6e81a1c6002b76a5ca2f211ae0" dependencies = [ "implicit-clone-derive", "indexmap", @@ -1511,23 +1274,6 @@ dependencies = [ "unicode-ident", ] -[[package]] -name = "prokio" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "03b55e106e5791fa5a13abd13c85d6127312e8e09098059ca2bc9b03ca4cf488" -dependencies = [ - "futures", - "gloo 0.8.1", - "num_cpus", - "once_cell", - "pin-project", - "pinned", - "tokio", - "tokio-stream", - "wasm-bindgen-futures", -] - [[package]] name = "quote" version = "1.0.42" @@ -1656,17 +1402,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f3b143e2833c57ab9ad3ea280d21fd34e285a42837aeb0ee301f4f41890fa00e" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - [[package]] name = "serde-wasm-bindgen" version = "0.6.5" @@ -1936,6 +1671,23 @@ dependencies = [ "tungstenite", ] +[[package]] +name = "tokise" +version = "0.2.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "decf97738ce15b9e9cc1671ea29b0f6c56538719e1a092d19cc2134bf144e40e" +dependencies = [ + "futures", + "gloo", + "num_cpus", + "once_cell", + "pin-project", + "pinned", + "tokio", + "tokio-stream", + "wasm-bindgen-futures", +] + [[package]] name = "toml_datetime" version = "0.6.11" @@ -2209,10 +1961,10 @@ version = "0.1.0" dependencies = [ "chrono", "ciborium", - "convert_case 0.8.0", + "convert_case 0.10.0", "futures", "getrandom 0.3.4", - "gloo 0.11.0", + "gloo", "instant", "log", "once_cell", @@ -2537,22 +2289,22 @@ checksum = "cfe53a6657fd280eaa890a3bc59152892ffa3e30101319d168b781ed6529b049" [[package]] name = "yew" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f1a03f255c70c7aa3e9c62e15292f142ede0564123543c1cc0c7a4f31660cac" +checksum = "3346273ed61b636f5d84e6c696d40f380045b5565b36c5c47f8fc634b8bf5be6" dependencies = [ "console_error_panic_hook", "futures", - "gloo 0.10.0", + "gloo", "implicit-clone", "indexmap", "js-sys", - "prokio", "rustversion", "serde", "slab", - "thiserror 1.0.69", + "thiserror 2.0.17", "tokio", + "tokise", "tracing", "wasm-bindgen", "wasm-bindgen-futures", @@ -2562,26 +2314,26 @@ dependencies = [ [[package]] name = "yew-macro" -version = "0.21.0" +version = "0.22.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "02fd8ca5166d69e59f796500a2ce432ff751edecbbb308ca59fd3fe4d0343de2" +checksum = "479e94d645dde3749e81d488c1d32987509dd3b8c31650fcf6e3af1f370e913b" dependencies = [ - "boolinator", "once_cell", "prettyplease", "proc-macro-error", "proc-macro2", "quote", + "rustversion", "syn 2.0.111", ] [[package]] name = "yew-router" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ca1d5052c96e6762b4d6209a8aded597758d442e6c479995faf0c7b5538e0c6" +checksum = "415cb628900ddf1eaf55ebd04163adf1ea80d3f5a9832a876554f9c0fdd4c282" dependencies = [ - "gloo 0.10.0", + "gloo", "js-sys", "route-recognizer", "serde", @@ -2596,9 +2348,9 @@ dependencies = [ [[package]] name = "yew-router-macro" -version = "0.18.0" +version = "0.19.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "42bfd190a07ca8cfde7cd4c52b3ac463803dc07323db8c34daa697e86365978c" +checksum = "9e87a3ce33434ab66a700edbaf2cc8a417d9b89f00a6fd8216fd6ac83b0e7b1c" dependencies = [ "proc-macro2", "quote", diff --git a/werewolves-proto/src/game/mod.rs b/werewolves-proto/src/game/mod.rs index 11afef6..d97e094 100644 --- a/werewolves-proto/src/game/mod.rs +++ b/werewolves-proto/src/game/mod.rs @@ -19,6 +19,7 @@ pub mod story; mod village; use core::{ + cmp::Ordering, fmt::{Debug, Display}, num::NonZeroU8, ops::{Deref, Range, RangeBounds}, @@ -379,6 +380,35 @@ pub enum GameTime { Night { number: u8 }, } +impl PartialOrd for GameTime { + fn partial_cmp(&self, other: &Self) -> Option { + Some(self.cmp(other)) + } +} + +impl Ord for GameTime { + fn cmp(&self, other: &Self) -> Ordering { + match (self, other) { + (GameTime::Day { number: l }, GameTime::Day { number: r }) => l.cmp(r), + (GameTime::Day { number: l }, GameTime::Night { number: r }) => { + if *r >= l.get() { + Ordering::Less + } else { + Ordering::Greater + } + } + (GameTime::Night { number: l }, GameTime::Day { number: r }) => { + if *l > r.get() { + Ordering::Greater + } else { + Ordering::Less + } + } + (GameTime::Night { number: l }, GameTime::Night { number: r }) => l.cmp(r), + } + } +} + impl Display for GameTime { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { diff --git a/werewolves-proto/src/game/story.rs b/werewolves-proto/src/game/story.rs index beaba05..423a70f 100644 --- a/werewolves-proto/src/game/story.rs +++ b/werewolves-proto/src/game/story.rs @@ -209,12 +209,17 @@ pub enum StoryActionPrompt { character_id: CharacterId, chosen: CharacterId, }, + BeholderWakes { + character_id: CharacterId, + }, } impl StoryActionPrompt { pub fn new(prompt: ActionPrompt) -> Option { Some(match prompt { - ActionPrompt::BeholderWakes { .. } => return None, // TODO: rework story anyway + ActionPrompt::BeholderWakes { character_id } => Self::BeholderWakes { + character_id: character_id.character_id, + }, ActionPrompt::Bloodletter { character_id, marked: Some(marked), @@ -425,6 +430,35 @@ impl StoryActionPrompt { | ActionPrompt::CoverOfDarkness => return None, }) } + + pub const fn character_id(&self) -> Option { + match self { + StoryActionPrompt::MasonsWake { .. } | StoryActionPrompt::WolfPackKill { .. } => None, + StoryActionPrompt::Seer { character_id, .. } + | StoryActionPrompt::Protector { character_id, .. } + | StoryActionPrompt::Arcanist { character_id, .. } + | StoryActionPrompt::Gravedigger { character_id, .. } + | StoryActionPrompt::Hunter { character_id, .. } + | StoryActionPrompt::Militia { character_id, .. } + | StoryActionPrompt::MapleWolf { character_id, .. } + | StoryActionPrompt::Guardian { character_id, .. } + | StoryActionPrompt::Adjudicator { character_id, .. } + | StoryActionPrompt::PowerSeer { character_id, .. } + | StoryActionPrompt::Mortician { character_id, .. } + | StoryActionPrompt::Beholder { character_id, .. } + | StoryActionPrompt::MasonLeaderRecruit { character_id, .. } + | StoryActionPrompt::Empath { character_id, .. } + | StoryActionPrompt::Vindicator { character_id, .. } + | StoryActionPrompt::PyreMaster { character_id, .. } + | StoryActionPrompt::Shapeshifter { character_id, .. } + | StoryActionPrompt::AlphaWolf { character_id, .. } + | StoryActionPrompt::DireWolf { character_id, .. } + | StoryActionPrompt::LoneWolfKill { character_id, .. } + | StoryActionPrompt::Insomniac { character_id, .. } + | StoryActionPrompt::Bloodletter { character_id, .. } + | StoryActionPrompt::BeholderWakes { character_id, .. } => Some(*character_id), + } + } } #[derive(Debug, Clone, PartialEq, Serialize, Deserialize)] diff --git a/werewolves/Cargo.toml b/werewolves/Cargo.toml index 1219dda..a2b48d6 100644 --- a/werewolves/Cargo.toml +++ b/werewolves/Cargo.toml @@ -13,14 +13,16 @@ web-sys = { version = "0.3", features = [ "HtmlImageElement", "HtmlDivElement", "HtmlSelectElement", + "HtmlDialogElement", + "DomRect", ] } wasm-bindgen = { version = "=0.2.100" } log = "0.4" rand = { version = "0.9", features = ["small_rng"] } getrandom = { version = "0.3", features = ["wasm_js"] } uuid = { version = "*", features = ["js"] } -yew = { version = "0.21", features = ["csr"] } -yew-router = "0.18" +yew = { version = "0.22", features = ["csr"] } +yew-router = "0.19" serde = { version = "1.0", features = ["derive"] } serde_json = { version = "1.0", optional = true } gloo = "0.11" @@ -33,7 +35,7 @@ werewolves-proto = { path = "../werewolves-proto" } futures = "0.3" wasm-bindgen-futures = "0.4" thiserror = { version = "2" } -convert_case = { version = "0.8" } +convert_case = { version = "0.10" } ciborium = { version = "0.2", optional = true } [features] diff --git a/werewolves/index.scss b/werewolves/index.scss index 1b658df..446249d 100644 --- a/werewolves/index.scss +++ b/werewolves/index.scss @@ -208,8 +208,8 @@ nav.host-nav { block-size: max-content; &>button { - width: 100%; - height: 100%; + width: 160px; + height: 75px; border: 1px solid $disconnected_color; background-color: color.change($disconnected_color, $alpha: 0.15); color: $disconnected_color; @@ -977,17 +977,30 @@ error { } -input { - background-color: rgba(255, 255, 255, 0.1); +// input { +// background-color: rgba(255, 255, 255, 0.1); +// color: white; +// border: 2px solid rgba(255, 255, 255, 0.2); +// margin: 10px; +// } +input, +select { + border: 1px solid rgba(255, 255, 255, 0.7); + background-color: rgba(255, 255, 255, 0.07); color: white; - border: 2px solid rgba(255, 255, 255, 0.2); - margin: 10px; + font-size: 1em; + + &:focus { + outline: 1px solid white; + background-color: white; + color: black; + } } .info-update { border: 1px solid rgba(255, 255, 255, 0.5); padding: 30px 0px 30px 0px; - font-size: 2rem; + // font-size: 2rem; align-content: stretch; margin: 0; position: fixed; @@ -1799,25 +1812,52 @@ li.choice { } .signin { - @extend .row-list; + display: flex; + flex-direction: column; + flex-wrap: nowrap; justify-content: center; - text-align: center; - - & label { - font-size: 1.5rem; - } &.full-height { height: 100vh; + max-width: 100vw; } - & input { - height: 2rem; - text-align: center; + .signin-box { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-items: center; + gap: 3px; + // justify-content: center; + // text-align: center; - #number { - font-size: 2rem; - max-width: 50vw; + .field { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + align-items: center; + width: 100%; + } + + & label { + font-size: 1.25em; + } + + & input { + height: 2em; + // max-width: 80%; + width: 70%; + + &#number { + text-align: center; + // font-size: 2rem; + // width: 20%; + width: 3ch; + } + } + + &>button { + margin-top: 7px; } } } @@ -1832,67 +1872,67 @@ li.choice { } -.story { - .cast { - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 10px; - justify-content: center; - } +// .story { +// .cast { +// display: flex; +// flex-direction: row; +// flex-wrap: wrap; +// gap: 10px; +// justify-content: center; +// } - .time-period { - user-select: text; +// .time-period { +// user-select: text; - .day { - display: flex; - flex-direction: column; - flex-wrap: wrap; - align-items: center; +// .day { +// display: flex; +// flex-direction: column; +// flex-wrap: wrap; +// align-items: center; - .executed { - display: flex; - flex-direction: row; - flex-wrap: wrap; - gap: 10px; - } - } +// .executed { +// display: flex; +// flex-direction: row; +// flex-wrap: wrap; +// gap: 10px; +// } +// } - .night { - &>label { - margin-left: 10vw; - font-size: 2rem; - font-weight: lighter; - } +// .night { +// &>label { +// margin-left: 10vw; +// font-size: 2rem; +// font-weight: lighter; +// } - ul.changes, - ul.choices { - display: flex; - flex-direction: column; - flex-wrap: nowrap; - gap: 10px; +// ul.changes, +// ul.choices { +// display: flex; +// flex-direction: column; +// flex-wrap: nowrap; +// gap: 10px; - &>li { - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; +// &>li { +// display: flex; +// flex-direction: row; +// flex-wrap: wrap; +// align-items: center; - gap: 10px; - } +// gap: 10px; +// } - & span { - display: flex; - flex-direction: row; - flex-wrap: wrap; - align-items: center; - gap: 10px; - } - } - } - } -} +// & span { +// display: flex; +// flex-direction: row; +// flex-wrap: wrap; +// align-items: center; +// gap: 10px; +// } +// } +// } +// } +// } .attribute-span { display: flex; @@ -2209,13 +2249,6 @@ li.choice { gap: 10px; } -.add-player { - background-color: black; - border: 1px solid white; - padding: 20px; - margin: 0px; -} - .joined { $joined_color: rgba(0, 255, 0, 0.7); $joined_border: color.change($joined_color, $alpha: 1); @@ -2370,6 +2403,7 @@ li.choice { left: 0; align-items: center; justify-content: center; + color: white; .dialog-box { border: 1px solid white; @@ -2395,6 +2429,22 @@ li.choice { } } } + + .close-dialog { + align-self: flex-end; + width: 100%; + margin: 0; + border: 1px solid $wolves_border; + color: $wolves_border; + + &:hover { + background-color: $wolves_border_faint; + } + } +} + +dialog::backdrop { + background-color: rgba(0, 0, 0, 0.7); } .about { @@ -2648,3 +2698,110 @@ li.choice { flex-wrap: nowrap; gap: 5px; } + + +.story { + display: flex; + flex-direction: row; + flex-wrap: wrap; + // width: 100vw; + justify-content: space-evenly; + row-gap: 5px; + margin: 5vh 10vw 0px 10vw; + + .character-headline { + display: flex; + flex-direction: row; + gap: 3px; + align-items: center; + + .icon-spacer { + height: 32px; + width: 32px; + } + + padding: 0.2em 1em 0.2em 1em; + min-width: 5cm; + + .identity { + text-align: center; + flex-grow: 1; + } + } + + .character-details { + display: none; + + &.shown { + display: flex; + } + + border-top: none; + flex-direction: column; + flex-wrap: nowrap; + gap: 3px; + padding: 2px 3px 2px 3px; + + } + + .story-time { + width: 100%; + + .time { + width: 100%; + font-size: 1.5em; + font-weight: bold; + padding: 3px 0px 3px 0px; + display: block; + + &:hover { + backdrop-filter: brightness(150%); + } + } + + .details { + display: none; + + &.shown { + display: flex; + } + + flex-direction: column; + flex-wrap: nowrap; + } + } +} + +dialog { + background-color: transparent; + border: none; +} + +.object-submenu { + display: flex; + flex-direction: column; + align-items: center; + gap: 5px; + + .object { + width: 100%; + background-color: black; + } + + menu { + display: flex; + flex-direction: column; + flex-wrap: nowrap; + gap: 3px; + align-items: center; + width: 100%; + margin: 0; + padding: 0; + + &>button, + &>div, + &>div>button { + width: 100%; + } + } +} diff --git a/werewolves/src/clients/client/client.rs b/werewolves/src/clients/client/client.rs index f28f1e5..ed64aad 100644 --- a/werewolves/src/clients/client/client.rs +++ b/werewolves/src/clients/client/client.rs @@ -29,8 +29,9 @@ use yew::prelude::*; use crate::{ clients::client::connection::{Connection2, ConnectionError}, components::{ - Button, CoverOfDarkness, Footer, Identity, Story, + Button, CoverOfDarkness, Footer, Identity, client::{ClientNav, Signin}, + story::Story, }, storage::StorageKey, }; @@ -39,6 +40,7 @@ use crate::WerewolfError; #[derive(PartialEq, Debug, Clone)] pub enum ClientEvent2 { + Signin, Disconnected, Connecting, ShowRole(RoleTitle), @@ -54,7 +56,6 @@ pub enum ClientEvent2 { #[derive(Default, Clone, PartialEq)] pub struct ClientContext { pub error_cb: Callback>, - pub forced_identity: Option, } static LOST_FOCUS: AtomicI64 = AtomicI64::new(0); @@ -73,6 +74,8 @@ pub(super) fn time_spent_unfocused() -> Option { #[function_component] pub fn Client2(ClientProps { auto_join }: &ClientProps) -> Html { + let ident_state = use_state(|| Option::<(PlayerId, PublicIdentity)>::None); + if gloo::utils::window().onfocus().is_none() { let on_focus = { Closure::wrap(Box::new(move || { @@ -93,45 +96,67 @@ pub fn Client2(ClientProps { auto_join }: &ClientProps) -> Html { } let client_state = use_state(|| ClientEvent2::Connecting); - let ClientContext { - error_cb, - forced_identity, - } = use_context::().unwrap_or_default(); - let force = use_force_update(); + let ClientContext { error_cb } = use_context::().unwrap_or_default(); + // let force = use_force_update(); + let (send, recv) = yew::platform::pinned::mpsc::unbounded(); + let send = use_state(|| send); + let recv = use_mut_ref(|| recv); + let connection = + use_mut_ref(|| Connection2::new(client_state.setter(), ident_state.clone(), recv)); - let ident = if let Some(Identification { player_id, public }) = forced_identity { - (player_id, public) + let on_signin = { + let current_ident = ident_state.setter(); + let client_state = client_state.setter(); + Callback::from(move |ident: PublicIdentity| { + let pid = PlayerId::new(); + pid.save_to_storage().expect("saving player id"); + ident.save_to_storage().expect("saving ident"); + + current_ident.set(Some((pid, ident))); + client_state.set(ClientEvent2::Connecting); + }) + }; + if let ClientEvent2::Signin = &*client_state { + return html! { + + }; + } + let ident = if let Some(current_ident) = ident_state.as_ref() { + current_ident.clone() } else { match PlayerId::load_from_storage() .and_then(|pid| PublicIdentity::load_from_storage().map(|ident| (pid, ident))) { - Ok((pid, ident)) => (pid, ident), + Ok((pid, ident)) => { + ident_state.set(Some((pid, ident.clone()))); + (pid, ident) + } Err(StorageError::KeyNotFound(_)) => { - let on_signin = Callback::from(move |ident: PublicIdentity| { - PlayerId::new().save_to_storage().expect("saving player id"); - ident.save_to_storage().expect("saving ident"); - force.force_update(); - }); + client_state.set(ClientEvent2::Signin); return html! { - + // }; } Err(err) => { + log::error!("storage error: {err}"); error_cb.emit(Some(err.into())); PlayerId::delete(); PublicIdentity::delete(); - force.force_update(); - return html! {}; + // force.force_update(); + + // client_state.set(ClientEvent2::Connecting); + client_state.set(ClientEvent2::Signin); + return html! { + // + }; } } }; - let ident = use_state(|| ident); - let (send, recv) = yew::platform::pinned::mpsc::unbounded(); - let send = use_state(|| send); - let recv = use_mut_ref(|| recv); - let connection = use_mut_ref(|| Connection2::new(client_state.setter(), ident.clone(), recv)); let content = match &*client_state { + ClientEvent2::Signin => html! { + + }, ClientEvent2::GameInProgress => html! { }, @@ -245,7 +270,7 @@ pub fn Client2(ClientProps { auto_join }: &ClientProps) -> Html { } }; html! { - + } }; diff --git a/werewolves/src/clients/client/connection.rs b/werewolves/src/clients/client/connection.rs index 3305c6c..9fea555 100644 --- a/werewolves/src/clients/client/connection.rs +++ b/werewolves/src/clients/client/connection.rs @@ -45,7 +45,7 @@ fn url() -> String { #[derive(Clone)] pub struct Connection2 { state: UseStateSetter, - ident: UseStateHandle<(PlayerId, PublicIdentity)>, + ident: UseStateHandle>, receiver: Rc>>, active: Rc>, } @@ -53,7 +53,7 @@ pub struct Connection2 { impl Connection2 { pub fn new( state: UseStateSetter, - ident: UseStateHandle<(PlayerId, PublicIdentity)>, + ident: UseStateHandle>, receiver: Rc>>, ) -> Self { Self { @@ -64,9 +64,19 @@ impl Connection2 { } } fn identification(&self) -> Identification { - Identification { - player_id: self.ident.0, - public: self.ident.1.clone(), + match self.ident.as_ref() { + Some(ident) => Identification { + player_id: ident.0, + public: ident.1.clone(), + }, + None => Identification { + player_id: PlayerId::from_u128(0), + public: PublicIdentity { + name: String::new(), + pronouns: None, + number: None, + }, + }, } } async fn connect_ws() -> WebSocket { @@ -108,7 +118,10 @@ impl Connection2 { yew::platform::spawn_local(async move { let active = conn.active.clone(); conn.active = Rc::new(RefCell::new(())); - let active_borrow = active.borrow_mut(); + let Ok(active_borrow) = active.try_borrow_mut() else { + log::warn!("active connection already borrowed; exiting"); + return; + }; conn.run().await; core::mem::drop(active_borrow); }); @@ -274,9 +287,11 @@ impl Connection2 { return None; } ServerMessage::Update(PlayerUpdate::Number(new_num)) => { - let (pid, mut ident) = (*self.ident).clone(); + let Some((pid, mut ident)) = (*self.ident).clone() else { + return None; + }; ident.number = Some(new_num); - self.ident.set((pid, ident)); + self.ident.set(Some((pid, ident))); return None; } ServerMessage::GameInProgress => ClientEvent2::GameInProgress, diff --git a/werewolves/src/clients/host/host.rs b/werewolves/src/clients/host/host.rs index bfb46e8..590bc4e 100644 --- a/werewolves/src/clients/host/host.rs +++ b/werewolves/src/clients/host/host.rs @@ -42,10 +42,11 @@ use yew::{html::Scope, prelude::*}; use crate::{ callback, components::{ - Button, Footer, Lobby, LobbyPlayerAction, RoleReveal, Story, Victory, + Button, Footer, Lobby, LobbyPlayerAction, RoleReveal, Victory, action::{ActionResultView, Prompt}, host::{CharacterStatesReadOnly, DaytimePlayerList, Setup}, settings::Settings, + story::Story, }, pages::RolePage, storage::StorageKey, diff --git a/werewolves/src/clients/mod.rs b/werewolves/src/clients/mod.rs index a3fbca0..34886e9 100644 --- a/werewolves/src/clients/mod.rs +++ b/werewolves/src/clients/mod.rs @@ -26,3 +26,11 @@ const BASE_URL: &str = match option_env!("BASE_URL") { Some(base_url) => base_url, None => "ws://192.168.1.162:8080", }; + +use yew::prelude::*; +#[function_component] +pub fn StoryTest() -> Html { + html! { + + } +} diff --git a/werewolves/src/components/client/nav.rs b/werewolves/src/components/client/nav.rs index 021f055..fe38e49 100644 --- a/werewolves/src/components/client/nav.rs +++ b/werewolves/src/components/client/nav.rs @@ -27,7 +27,7 @@ use crate::{ #[derive(Debug, Clone, PartialEq, Properties)] pub struct ClientNavProps { - pub identity: UseStateHandle<(PlayerId, PublicIdentity)>, + pub identity: UseStateHandle>, pub message_callback: Callback, } @@ -38,18 +38,19 @@ pub fn ClientNav( message_callback, }: &ClientNavProps, ) -> Html { + const MUST_HAVE_IDENTITY: &str = "client nav must have identity"; let pronouns = identity - .1 - .pronouns .as_ref() - .map(|pronouns| { - html! { -
{"("}{pronouns.as_str()}{")"}
- } + .and_then(|identity| { + identity.1.pronouns.as_ref().map(|pronouns| { + html! { + {"("}{pronouns.as_str()}{")"} + } + }) }) .unwrap_or_else(|| { html! { -
{"(None)"}
+ {"(None)"} } }); @@ -62,10 +63,13 @@ pub fn ClientNav( let submit_ident = identity.clone(); let current_num = identity - .1 - .number - .map(|v| v.to_string()) - .unwrap_or_else(|| String::from("???")); + .as_ref() + .and_then(|identity| identity.1.number.map(|v| html! {{v.to_string()}})) + .unwrap_or_else(|| { + html! { + {"???"} + } + }); let open_set = number_open.setter(); let on_submit = { let val = current_value.clone(); @@ -74,13 +78,16 @@ pub fn ClientNav( Some(num) => num, None => return, }; + let Some(submit_ident_ref) = submit_ident.as_ref() else { + return; + }; message_callback.emit(ClientMessage::UpdateSelf(UpdateSelf::Number(num))); let new_ident = PublicIdentity { - name: submit_ident.1.name.clone(), - pronouns: submit_ident.1.pronouns.clone(), + name: submit_ident_ref.1.name.clone(), + pronouns: submit_ident_ref.1.pronouns.clone(), number: Some(num), }; - submit_ident.set((submit_ident.0, new_ident.clone())); + submit_ident.set(Some((submit_ident_ref.0, new_ident.clone()))); if let Err(err) = new_ident.save_to_storage() { log::error!("saving public identity after change: {err}"); } @@ -114,6 +121,7 @@ pub fn ClientNav( let ident = identity.clone(); let message_callback = message_callback.clone(); Callback::from(move |value: String| -> Option { + let ident = ident.as_ref().expect(MUST_HAVE_IDENTITY); value.trim().is_empty().not().then(|| { let name = value.trim().to_string(); message_callback @@ -134,6 +142,12 @@ pub fn ClientNav( pronouns_open.set(false); }) }; + let name_str = identity + .as_ref() + .map(|i| html! {{i.1.name.to_string()}}) + .unwrap_or(html! { + {"???"} + }); html! { -
{identity.1.name.as_str()}
+
{name_str}
} }; @@ -154,15 +168,18 @@ pub fn ClientNav( let on_submit = { let ident = identity.clone(); let message_callback = message_callback.clone(); + let pronuns_state = pronuns_state.clone(); Callback::from(move |value: String| -> Option { let pronouns = value.trim().is_empty().not().then_some(value); message_callback.emit(ClientMessage::UpdateSelf(UpdateSelf::Pronouns( pronouns.clone(), ))); - Some(PublicIdentity { - pronouns, - name: ident.1.name.clone(), - number: ident.1.number, + pronuns_state.set(String::new()); + ident.as_ref().map(|id| { + let mut public = id.1.clone(); + public.pronouns = pronouns; + ident.set(Some((id.0, public.clone()))); + public }) }) }; @@ -196,14 +213,10 @@ pub fn ClientNav( cb.emit(ClientMessage::Goodbye); let _ = gloo::utils::window().location().reload(); }; - let host_click = Callback::from(|_| { - if let Some(loc) = gloo::utils::document().location() { - let _ = loc.replace("/host"); - } - }); + html! { <> - + } @@ -223,7 +236,7 @@ struct ClickableTextEditProps { #[prop_or_default] pub children: Html, pub value: UseStateHandle, - pub submit_ident: UseStateHandle<(PlayerId, PublicIdentity)>, + pub submit_ident: UseStateHandle>, pub on_submit: Callback>, pub field_name: &'static str, pub state: UseStateHandle, @@ -257,8 +270,10 @@ fn ClickableTextEdit( let submit = { let submit_ident = submit_ident.clone(); move |_| { - if let Some(new_ident) = message_callback.emit(value.trim().to_string()) { - submit_ident.set((submit_ident.0, new_ident.clone())); + if let Some(new_ident) = message_callback.emit(value.trim().to_string()) + && let Some(ident) = submit_ident.as_ref() + { + submit_ident.set(Some((ident.0, new_ident.clone()))); if let Err(err) = new_ident.save_to_storage() { log::error!("saving public identity after change: {err}"); } diff --git a/werewolves/src/components/client/signin.rs b/werewolves/src/components/client/signin.rs index 9b3fbb2..b44d780 100644 --- a/werewolves/src/components/client/signin.rs +++ b/werewolves/src/components/client/signin.rs @@ -23,6 +23,8 @@ use crate::components::Button; #[derive(Debug, PartialEq, Properties)] pub struct SigninProps { pub callback: Callback, + #[prop_or(true)] + pub full_height: bool, } #[function_component] @@ -60,15 +62,34 @@ pub fn Signin(props: &SigninProps) -> Html { }); let on_change = crate::components::input_element_number_oninput(num_value); + let full_height = props.full_height.then_some("full-height"); html! { -