diff options
39 files changed, 574 insertions, 383 deletions
@@ -4,9 +4,9 @@ version = 3 [[package]] name = "addr2line" -version = "0.22.0" +version = "0.24.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e4503c46a5c0c7844e948c9a4d6acd9f50cccb4de1c48eb9e291ea17470c678" +checksum = "f5fb1d8e4442bd405fdfd1dacb42792696b0cf9cb15882e5d097b742a676d375" dependencies = [ "gimli", ] @@ -18,6 +18,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f26201604c87b1e01bd3d98f8d5d9a8fcbb815e8cedb41ffccbeb4bf593a35fe" [[package]] +name = "adler2" +version = "2.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "512761e0bb2578dd7380c6baaa0f4ce03e84f95e960231d1dec8bf4d7d6e2627" + +[[package]] name = "aho-corasick" version = "1.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -221,9 +227,9 @@ dependencies = [ [[package]] name = "aws-lc-rs" -version = "1.8.1" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4ae74d9bd0a7530e8afd1770739ad34b36838829d6ad61818f9230f683f5ad77" +checksum = "2f95446d919226d587817a7d21379e6eb099b97b45110a7f272a444ca5c54070" dependencies = [ "aws-lc-sys", "mirai-annotations", @@ -233,9 +239,9 @@ dependencies = [ [[package]] name = "aws-lc-sys" -version = "0.20.1" +version = "0.21.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0f0e249228c6ad2d240c2dc94b714d711629d52bad946075d8e9b2f5391f0703" +checksum = "b3ddc4a5b231dd6958b140ff3151b6412b3f4321fab354f399eec8f14b06df62" dependencies = [ "bindgen", "cc", @@ -248,17 +254,17 @@ dependencies = [ [[package]] name = "backtrace" -version = "0.3.73" +version = "0.3.74" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cc23269a4f8976d0a4d2e7109211a419fe30e8d88d677cd60b6bc79c5732e0a" +checksum = "8d82cb332cdfaed17ae235a638438ac4d4839913cc2af585c3c6746e8f8bee1a" dependencies = [ "addr2line", - "cc", "cfg-if", "libc", - "miniz_oxide", + "miniz_oxide 0.8.0", "object", "rustc-demangle", + "windows-targets 0.52.6", ] [[package]] @@ -380,9 +386,9 @@ checksum = "8f1fe948ff07f4bd06c30984e69f5b4899c516a3ef74f34df92a2df2ab535495" [[package]] name = "bytes" -version = "1.7.1" +version = "1.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8318a53db07bb3f8dca91a600466bdb3f2eaadeedfdbcf02e1accbad9271ba50" +checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" [[package]] name = "c_linked_list" @@ -398,12 +404,13 @@ checksum = "fdd7a427adc0135366d99db65b36dae9237130997e560ed61118041fb72be6e8" [[package]] name = "cc" -version = "1.1.8" +version = "1.1.21" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "504bdec147f2cc13c8b57ed9401fd8a147cc66b67ad5cb241394244f2c947549" +checksum = "07b1695e2c7e8fc85310cde85aeaab7e3097f593c91d209d3f9df76c928100f0" dependencies = [ "jobserver", "libc", + "shlex", ] [[package]] @@ -444,9 +451,9 @@ dependencies = [ [[package]] name = "clap" -version = "4.5.16" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ed6719fffa43d0d87e5fd8caeab59be1554fb028cd30edc88fc4369b17971019" +checksum = "b0956a43b323ac1afaffc053ed5c4b7c1f1800bacd1683c353aabbb752515dd3" dependencies = [ "clap_builder", "clap_derive", @@ -454,9 +461,9 @@ dependencies = [ [[package]] name = "clap_builder" -version = "4.5.15" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "216aec2b177652e3846684cbfe25c9964d18ec45234f0f5da5157b207ed1aab6" +checksum = "4d72166dd41634086d5803a47eb71ae740e61d84709c36f3c34110173db3961b" dependencies = [ "anstream", "anstyle", @@ -466,9 +473,9 @@ dependencies = [ [[package]] name = "clap_derive" -version = "4.5.13" +version = "4.5.18" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "501d359d5f3dcaf6ecdeee48833ae73ec6e42723a1e52419c79abf9507eec0a0" +checksum = "4ac6a0c7b1a9e9a5186361f67dfa1b88213572f427fb9ab038efb2bd8c582dab" dependencies = [ "heck", "proc-macro2", @@ -484,9 +491,9 @@ checksum = "1462739cb27611015575c0c11df5df7601141071f07518d56fcc1be504cbec97" [[package]] name = "cmake" -version = "0.1.50" +version = "0.1.51" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a31c789563b815f77f4250caee12365734369f942439b7defd71e18a48197130" +checksum = "fb1e43aa7fd152b1f968787f7dbcdeb306d1867ff373c69955211876c053f91a" dependencies = [ "cc", ] @@ -535,15 +542,15 @@ dependencies = [ [[package]] name = "core-foundation-sys" -version = "0.8.6" +version = "0.8.7" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "06ea2b9bc92be3c2baa9334a323ebca2d6f074ff852cd1d7b11064035cd3868f" +checksum = "773648b94d0e5d620f64f280777445740e61fe701025087ec8b57f45c791888b" [[package]] name = "cpufeatures" -version = "0.2.12" +version = "0.2.14" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "53fe5e26ff1b7aef8bca9c6080520cfb8d9333c7568e1829cef191a9723e5504" +checksum = "608697df725056feaccfa42cffdaeeec3fccc4ffc38358ecd19b243e716a78e0" dependencies = [ "libc", ] @@ -726,7 +733,7 @@ dependencies = [ "flume", "half", "lebe", - "miniz_oxide", + "miniz_oxide 0.7.4", "rayon-core", "smallvec", "zune-inflate", @@ -768,7 +775,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f211bbe8e69bbd0cfdea405084f128ae8b4aaa6b0b522fc8f2b009084797920" dependencies = [ "crc32fast", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]] @@ -966,15 +973,15 @@ dependencies = [ [[package]] name = "gimli" -version = "0.29.0" +version = "0.31.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "40ecd4077b5ae9fd2e9e169b102c6c330d0605168eb0e8bf79952b256dbefffd" +checksum = "32085ea23f3234fc7846555e85283ba4de91e21016dc0455a16286d87a292d64" [[package]] name = "glam" -version = "0.28.0" +version = "0.29.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "779ae4bf7e8421cf91c0b3b64e7e8b40b862fba4d393f59150042de7c4965a94" +checksum = "c28091a37a5d09b555cb6628fd954da299b536433834f5b8e59eba78e0cbbf8a" dependencies = [ "serde", ] @@ -1421,9 +1428,9 @@ checksum = "44feda355f4159a7c757171a77de25daf6411e217b4cabd03bd6650690468126" [[package]] name = "indexmap" -version = "2.3.0" +version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "de3fc2e30ba82dd1b3911c8de1ffc143c74a914a14e99514d7637e3099df5ea0" +checksum = "68b900aa2f7301e21c36462b170ee99994de34dff39a4a6a528e80e7376d07e5" dependencies = [ "equivalent", "hashbrown", @@ -1529,9 +1536,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8" [[package]] name = "libc" -version = "0.2.155" +version = "0.2.158" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "97b3888a4aecf77e811145cadf6eef5901f4782c53886191b2f693f24761847c" +checksum = "d8adc4bb1803a324070e64a98ae98f38934d91957a99cfb3a43dcbc01bc56439" [[package]] name = "libfuzzer-sys" @@ -1556,9 +1563,13 @@ dependencies = [ [[package]] name = "libyml" -version = "0.0.4" +version = "0.0.5" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "64804cc6a5042d4f05379909ba25b503ec04e2c082151d62122d5dcaa274b961" +checksum = "3302702afa434ffa30847a83305f0a69d6abd74293b6554c18ec85c7ef30c980" +dependencies = [ + "anyhow", + "version_check", +] [[package]] name = "linux-raw-sys" @@ -1695,10 +1706,19 @@ dependencies = [ ] [[package]] +name = "miniz_oxide" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e2d80299ef12ff69b16a84bb182e3b9df68b5a91574d3d4fa6e41b65deec4df1" +dependencies = [ + "adler2", +] + +[[package]] name = "mio" -version = "1.0.1" +version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4569e456d394deccd22ce1c1913e6ea0e54519f577285001215d33557431afe4" +checksum = "80e04d1dcff3aae0704555fe5fee3bcfaf3d1fdf8a7e521d5b9d2b42acb52cec" dependencies = [ "hermit-abi 0.3.9", "libc", @@ -1831,9 +1851,9 @@ dependencies = [ [[package]] name = "object" -version = "0.36.3" +version = "0.36.4" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "27b64972346851a39438c60b341ebc01bba47464ae329e55cf343eb93964efd9" +checksum = "084f1a5821ac4c651660a94a7153d27ac9d8a53736203f58b31945ded098070a" dependencies = [ "memchr", ] @@ -1984,7 +2004,7 @@ dependencies = [ "crc32fast", "fdeflate", "flate2", - "miniz_oxide", + "miniz_oxide 0.7.4", ] [[package]] @@ -2026,9 +2046,9 @@ dependencies = [ [[package]] name = "prettyplease" -version = "0.2.20" +version = "0.2.22" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5f12335488a2f3b0a83b14edad48dca9879ce89b2edd10e80237e4e852dd645e" +checksum = "479cf940fbbb3426c32c5d5176f62ad57549a0bb84773423ba8be9d089f5faba" dependencies = [ "proc-macro2", "syn", @@ -2140,9 +2160,9 @@ dependencies = [ [[package]] name = "quote" -version = "1.0.36" +version = "1.0.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0fa76aaf39101c457836aec0ce2316dbdc3ab723cdda1c6bd4e6ad4208acaca7" +checksum = "b5b9d34b8991d19d98081b46eacdd8eb58c6f2b201139f7c5f643cc155a633af" dependencies = [ "proc-macro2", ] @@ -2377,7 +2397,7 @@ dependencies = [ "pin-project-lite", "quinn", "rustls", - "rustls-native-certs 0.7.1", + "rustls-native-certs 0.7.2", "rustls-pemfile", "rustls-pki-types", "serde", @@ -2520,9 +2540,9 @@ checksum = "583034fd73374156e66797ed8e5b0d5690409c9226b22d87cb7f19821c05d152" [[package]] name = "rustix" -version = "0.38.34" +version = "0.38.37" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70dc5ec042f7a43c4a73241207cecc9873a06d45debb38b329f8541d85c2730f" +checksum = "8acb788b847c24f28525660c4d7758620a7210875711f79e7f663cc152726811" dependencies = [ "bitflags 2.6.0", "errno", @@ -2533,9 +2553,9 @@ dependencies = [ [[package]] name = "rustls" -version = "0.23.12" +version = "0.23.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c58f8c84392efc0a126acce10fa59ff7b3d2ac06ab451a33f2741989b806b044" +checksum = "f2dabaac7466917e566adb06783a81ca48944c6898a1b08b9374106dd671f4c8" dependencies = [ "aws-lc-rs", "log", @@ -2549,9 +2569,9 @@ dependencies = [ [[package]] name = "rustls-native-certs" -version = "0.7.1" +version = "0.7.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a88d6d420651b496bdd98684116959239430022a115c1240e6c3993be0b15fba" +checksum = "04182dffc9091a404e0fc069ea5cd60e5b866c3adf881eff99a32d048242dffa" dependencies = [ "openssl-probe", "rustls-pemfile", @@ -2591,9 +2611,9 @@ checksum = "fc0a2ce646f8655401bb81e7927b812614bd5d91dbc968696be50603510fcaf0" [[package]] name = "rustls-webpki" -version = "0.102.6" +version = "0.102.8" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e6b52d4fda176fd835fdc55a835d4a89b8499cad995885a21149d5ad62f852e" +checksum = "64ca1bc8749bd4cf37b5ce386cc146580777b4e8572c7b97baf22c83f444bee9" dependencies = [ "aws-lc-rs", "ring", @@ -2737,19 +2757,17 @@ dependencies = [ [[package]] name = "serde_yml" -version = "0.0.11" +version = "0.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "48e76bab63c3fd98d27c17f9cbce177f64a91f5e69ac04cafe04e1bb25d1dc3c" +checksum = "59e2dd588bf1597a252c3b920e0143eb99b0f76e4e082f4c92ce34fbc9e71ddd" dependencies = [ "indexmap", "itoa", "libyml", - "log", "memchr", "ryu", "serde", - "serde_json", - "tempfile", + "version_check", ] [[package]] @@ -2868,9 +2886,9 @@ checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" [[package]] name = "syn" -version = "2.0.72" +version = "2.0.77" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dc4b9b9bf2add8093d3f2c0204471e951b2285580335de42f9d2534f3ae7a8af" +checksum = "9f35bcdf61fd8e7be6caf75f429fdca8beb3ed76584befb503b1569faee373ed" dependencies = [ "proc-macro2", "quote", @@ -3058,14 +3076,14 @@ dependencies = [ [[package]] name = "tokio-tungstenite" -version = "0.23.1" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c6989540ced10490aaf14e6bad2e3d33728a2813310a0c71d1574304c49631cd" +checksum = "edc5f74e248dc973e0dbb7b74c7e0d6fcc301c694ff50049504004ef4d0cdcd9" dependencies = [ "futures-util", "log", "rustls", - "rustls-native-certs 0.7.1", + "rustls-native-certs 0.8.0", "rustls-pki-types", "tokio", "tokio-rustls", @@ -3227,9 +3245,9 @@ checksum = "e421abadd41a4225275504ea4d6566923418b7f05506fbc9c0fe86ba7396114b" [[package]] name = "tungstenite" -version = "0.23.0" +version = "0.24.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e2e2ce1e47ed2994fd43b04c8f618008d4cabdd5ee34027cf14f9d918edd9c8" +checksum = "18e5b8366ee7a95b16d32197d0b2604b43a0be89dc5fac9f8e96ccafbaedda8a" dependencies = [ "byteorder", "bytes", @@ -3239,7 +3257,7 @@ dependencies = [ "log", "rand 0.8.5", "rustls", - "rustls-native-certs 0.7.1", + "rustls-native-certs 0.7.2", "rustls-pki-types", "sha1", "thiserror", @@ -3279,9 +3297,9 @@ checksum = "08f95100a766bf4f8f28f90d77e0a5461bbdb219042e7679bebe79004fed8d75" [[package]] name = "unicode-ident" -version = "1.0.12" +version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" +checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" [[package]] name = "unicode-normalization" @@ -3773,20 +3791,6 @@ name = "zeroize" version = "1.8.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ced3678a2879b30306d323f4542626697a464a97c0a07c9aebf7ebca65cd4dde" -dependencies = [ - "zeroize_derive", -] - -[[package]] -name = "zeroize_derive" -version = "1.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] [[package]] name = "zstd" diff --git a/client/game.gd b/client/game.gd index 76bb271a..fe1e9ba6 100644 --- a/client/game.gd +++ b/client/game.gd @@ -21,9 +21,8 @@ extends Node3D signal update_players(players: Dictionary) signal data_updated() signal in_lobby_updated(in_lobby: bool) +signal join_state_updated(state: JoinState) signal text_message(player: int, text: String, timeout_initial: float, timeout_remaining: float) -signal joined() -signal left() signal update_tutorial_running(running: bool) enum SpectatingMode { @@ -31,6 +30,12 @@ enum SpectatingMode { FREE, } +enum JoinState { + SPECTATING, + WAITING, + JOINED, +} + var player_id: int = -1 var item_names: Array = [] var item_index_by_name: Dictionary = {} @@ -42,10 +47,10 @@ var maps: Array = [] var bot_algos: Array var text_message_history: Array[Array] = [] +var join_state: JoinState = JoinState.SPECTATING + var in_lobby := false var is_replay := false -var is_joined := false -var join_sent := false var tutorial_running := false var tutorial_queue := [] var last_position := Vector2(0, 0) @@ -99,8 +104,7 @@ func handle_packet(p): in_lobby_updated.connect(player_instance.onscreen_controls.in_lobby_updated) player_instance.onscreen_controls.in_lobby_updated(in_lobby) camera.target = player_instance.movement_base - is_joined = true - joined.emit() + set_join_state(JoinState.JOINED) else: player_instance = Player.new(p.id, p.name, p.position, p.character, self) players[p.id] = player_instance @@ -114,8 +118,7 @@ func handle_packet(p): tutorial_queue.erase(player.current_item_message) pinned_items.clear_item(p.id) if p.id == player_id: - is_joined = false - left.emit() + set_join_state(JoinState.SPECTATING) camera.target = $Center if player.hand != null: player.hand.queue_free() @@ -244,18 +247,15 @@ func handle_packet(p): map.gi_bake() await get_parent()._menu_open() map.autobake = true - - if in_lobby: popup_message.lobby() - else: popup_message.ingame() + + in_lobby_updated.emit(in_lobby) else: map.autobake = false await get_parent()._menu_exit() - + lobby.visible = in_lobby - if lobby and not join_sent: - join() - - in_lobby_updated.emit(in_lobby) + if lobby and join_state == JoinState.SPECTATING: + toggle_join() "score": if p.time_remaining != null: overlay.update(p.demands_failed, p.demands_completed, p.points, p.time_remaining) @@ -291,7 +291,7 @@ func handle_packet(p): "server_message": var mstr := get_message_str(p.message) if p.error: - # popup_message.display_server_msg(tr("c.error.server").format([mstr])) + popup_message.display_server_msg(tr("c.error.server").format([mstr])) push_error(tr("c.error.server").format([mstr])) else: popup_message.display_server_msg(mstr) @@ -310,7 +310,7 @@ func handle_packet(p): else: # Positional hint message if message == null: - popup_message.clear_server_msg() + popup_message.clear_server_msg(position_) else: popup_message.display_server_msg_positional(get_message_str(message), position_, false) "environment": @@ -323,16 +323,20 @@ func handle_packet(p): _: push_error("Unrecognized packet type: %s" % p.type) -func join(): - if join_sent: - push_error("Join was already sent. Tried to join twice.") - return - join_sent = true - mp.send_join(Global.get_profile("username"), Global.get_profile("character")) +func set_join_state(state: JoinState): + join_state = state + join_state_updated.emit(state) -func leave(): - join_sent = false - mp.send_leave(player_id) +func toggle_join(): + match join_state: + JoinState.SPECTATING: + set_join_state(JoinState.WAITING) + mp.send_join(Global.get_profile("username"), Global.get_profile("character")) + JoinState.WAITING: + push_error("Join/Leave action already toggled.") + JoinState.JOINED: + set_join_state(JoinState.WAITING) + mp.send_leave(player_id) func _process(delta): update_center() @@ -359,7 +363,7 @@ func get_tile_interactive(pos: Vector2i) -> bool: func update_center(): - if is_joined: + if join_state != JoinState.SPECTATING: return if Input.get_vector("left", "right", "forwards", "backwards").normalized().length() > .1: spectating_mode = SpectatingMode.FREE diff --git a/client/map/tiles/floor.gd b/client/map/tiles/floor.gd index 8e75834b..dd51c928 100644 --- a/client/map/tiles/floor.gd +++ b/client/map/tiles/floor.gd @@ -16,11 +16,12 @@ class_name Floor extends Tile -var opt +var opt: bool + func _init(ctx: TileFactory.TileCC): opt = ctx.floor_mesher != null super(ctx) - if opt: ctx.floor_mesher.add_tile(ctx.position) + if not base_mesh: ctx.floor_mesher.add_tile(ctx.position) func get_base_mesh(): if opt: return null diff --git a/client/menu/blur_setup.gd b/client/menu/blur_setup.gd index 331d1f47..9d55a9d4 100644 --- a/client/menu/blur_setup.gd +++ b/client/menu/blur_setup.gd @@ -14,6 +14,7 @@ # along with this program. If not, see <https://www.gnu.org/licenses/>. # extends Control +class_name BlurSetup func _ready(): update(Global.get_setting("graphics.ui_blur")) diff --git a/client/menu/character.gd b/client/menu/character.gd index 6af30250..dd3bc5cd 100644 --- a/client/menu/character.gd +++ b/client/menu/character.gd @@ -18,7 +18,6 @@ extends Menu @onready var character: Character = $Node3D/Character -@onready var num_hairstyles := character.hairstyles.keys().size() @onready var back_button := $VBoxContainer/bottom_panel/back @onready var map: Map = $Node3D/Map @onready var username_edit = $VBoxContainer/top_panel/a/username @@ -26,7 +25,7 @@ extends Menu func _ready(): super() $VBoxContainer/top_panel/a/username.text = Global.get_profile("username") - character.select_hairstyle(Global.get_profile("character")) + character.set_style(Global.get_profile("character")) init_map() func init_map(): @@ -53,6 +52,7 @@ func init_map(): for y in tiles.size(): for x in tiles[y].size(): map.set_tile(Vector2i(x,y) - co, gt.call([x,y]), [[x,y-1],[x-1,y],[x,y+1],[x+1,y]].map(gt)) + map.flush() func _input(_event): if Input.is_action_just_pressed("ui_cancel"): @@ -68,9 +68,9 @@ func _on_back_pressed(): replace_menu("res://menu/main.tscn") func _on_character_back_pressed(): - Global.set_profile("character", (Global.get_profile("character") - 1) % num_hairstyles) - character.select_hairstyle(Global.get_profile("character")) + Global.set_profile("character", max(Global.get_profile("character") - 1, 0)) + character.set_style(Global.get_profile("character")) func _on_character_forward_pressed(): - Global.set_profile("character", (Global.get_profile("character") + 1) % num_hairstyles) - character.select_hairstyle(Global.get_profile("character")) + Global.set_profile("character", max(Global.get_profile("character") + 1, 0)) + character.set_style(Global.get_profile("character")) diff --git a/client/menu/communicate/popup_message/popup_message.gd b/client/menu/communicate/popup_message/popup_message.gd index 6c2c2c0e..98bd94e3 100644 --- a/client/menu/communicate/popup_message/popup_message.gd +++ b/client/menu/communicate/popup_message/popup_message.gd @@ -14,45 +14,34 @@ # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <https://www.gnu.org/licenses/>. # -extends MarginContainer +extends Control class_name PopupMessage +const SERVER_MESSAGE_SCENE = preload("res://menu/communicate/popup_message/server_message.tscn") + var is_ingame := false var is_joined := false -@onready var server_msg = $VBox/ServerMessage -@onready var server_msg_positional = $ServerMessagePositional -@onready var hint_msg = $VBox/HintMessage - -@onready var server_msg_timer: Timer = $ServerTimer -@onready var hint_msg_timer: Timer = $HintTimer - -@onready var server_msg_label: Label = $VBox/ServerMessage/CenterContainer/Label -@onready var server_msg_positional_label: Label = $ServerMessagePositional/ServerMessage/CenterContainer/Label -@onready var hint_msg_label: Label = $VBox/HintMessage/CenterContainer/Label +var positional_messages = {} -@onready var server_msg_positional_panel: PanelContainer = $ServerMessagePositional/ServerMessage +@onready var positional_messages_node: Control = $Positional +@onready var server_msg = $Static/VBox/ServerMessage +@onready var hint_msg = $Static/VBox/HintMessage -@onready var auto_hint_timers: Node = $AutoHintTimers +@onready var server_msg_label: Label = $Static/VBox/ServerMessage/CenterContainer/Label +@onready var hint_msg_label: Label = $Static/VBox/HintMessage/CenterContainer/Label -@onready var reset_timer = $Reset -@onready var join_while_running_timer = $JoinWhileRunning +@onready var auto_hint_timers: Node = $Timers/AutoHints +@onready var server_msg_timer: Timer = $Timers/Server +@onready var hint_msg_timer: Timer = $Timers/Hint +@onready var reset_timer = $Timers/Reset +@onready var join_while_running_timer = $Timers/JoinWhileRunning @onready var game: Game = $"../Game" -var server_message_position := Vector2.ZERO -var last_server_message_panel_size := Vector2.ZERO - func _ready(): - game.joined.connect( - func player_joined(): - is_joined = true - update_state() - ) - game.left.connect( - func player_joined(): - is_joined = false - update_state() + game.join_state_updated.connect(func(state: Game.JoinState): + is_joined = state == Game.JoinState.JOINED ) game.update_tutorial_running.connect( func a(running: bool): @@ -61,25 +50,26 @@ func _ready(): else: update_state() ) + game.in_lobby_updated.connect( + func a(in_lobby): + is_ingame = not in_lobby + update_state() + ) func _process(_delta: float): - if server_msg_positional.visible: - var pos_3d = Vector3(server_message_position.x + 0.5, 1.5, server_message_position.y + 0.5) + for pos: Vector2 in positional_messages.keys(): + var msg: PositionalMessage = positional_messages[pos] + var pos_3d = Vector3(pos.x + 0.5, 1.5, pos.y + 0.5) var pos_2d = get_viewport().get_camera_3d().unproject_position(pos_3d) - var server_message_panel_size = server_msg_positional_panel.size - server_msg_positional.position = pos_2d.clamp(Vector2.ZERO + 0.5 * server_message_panel_size, Vector2(get_viewport_rect().size) - 0.5 * server_message_panel_size) - if server_message_panel_size != last_server_message_panel_size: - last_server_message_panel_size = server_message_panel_size - server_msg_positional_panel.position = -0.5 * last_server_message_panel_size - -func ingame(): - is_ingame = true - update_state() - -func lobby(): - is_ingame = false - update_state() + msg.node_2d.position = pos_2d.clamp( + Vector2.ZERO + 0.5 * msg.node.size, + Vector2(get_viewport_rect().size) - 0.5 * msg.node.size + ) + + if msg.node.size != msg.last_size: + msg.last_size = msg.node.size + msg.node.position = -0.5 * msg.last_size func update_state(): if is_ingame and is_joined: @@ -91,30 +81,35 @@ func update_state(): stop_game_hints() func display_server_msg(msg: String, auto_remove := true): - clear_server_msg() server_msg.show() server_msg_label.text = msg if auto_remove: server_msg_timer.start() -func display_server_msg_positional(msg: String, pos: Vector2, auto_remove := true): +func _on_server_timeout() -> void: clear_server_msg() - server_msg_positional.show() - server_message_position = pos - server_msg_positional_label.text = msg - server_msg_positional_panel.size = Vector2.ZERO - - if auto_remove: - server_msg_timer.start() -func clear_server_msg(): - server_msg_timer.stop() - server_msg.hide() - server_msg_positional.hide() +func display_server_msg_positional(text: String, pos: Vector2, use_monospace: bool): + var msg := PositionalMessage.new() + msg.node = SERVER_MESSAGE_SCENE.instantiate() + msg.node_2d = Node2D.new() + positional_messages_node.add_child(msg.node_2d) + msg.node_2d.add_child(msg.node) + msg.node.set_text(text, use_monospace) + msg.node.size = Vector2.ZERO + msg.position = pos + positional_messages[pos] = msg -func _on_server_timer_timeout(): - clear_server_msg() +func clear_server_msg(position_ = null): + if position_ == null: + server_msg_timer.stop() + server_msg.hide() + else: + if position_ in positional_messages: + var msg: PositionalMessage = positional_messages[position_] + msg.node_2d.queue_free() + positional_messages.erase(position_) func display_hint_msg(msg: String): hint_msg.show() @@ -220,7 +215,7 @@ func _on_rotate_camera_timeout(): )])) func _on_join_while_running_timeout(): - if not game.is_joined and not Global.get_hint("has_seen_join_while_running"): + if not game.join_state == Game.JoinState.JOINED and not Global.get_hint("has_seen_join_while_running"): Global.set_hint("has_seen_join_while_running", true) display_hint_msg(tr("c.hint.join_while_running").format([display_keybind("menu")])) @@ -228,3 +223,9 @@ func _on_performance_timeout() -> void: if not Global.get_hint("has_seen_performance") and Engine.get_frames_per_second() < DisplayServer.screen_get_refresh_rate() * 0.75: Global.set_hint("has_seen_performance", true) display_hint_msg(tr("c.hint.framerate_low")) + +class PositionalMessage: + var node: ServerMessage + var node_2d: Node2D + var position: Vector2 + var last_size: Vector2 diff --git a/client/menu/communicate/popup_message/popup_message.tscn b/client/menu/communicate/popup_message/popup_message.tscn index 799712e1..880e8670 100644 --- a/client/menu/communicate/popup_message/popup_message.tscn +++ b/client/menu/communicate/popup_message/popup_message.tscn @@ -33,25 +33,35 @@ content_margin_top = 8.0 content_margin_right = 32.0 content_margin_bottom = 8.0 -[node name="PopupMessage" type="MarginContainer"] +[node name="PopupMessage" type="Control"] +layout_mode = 3 anchors_preset = 15 anchor_right = 1.0 anchor_bottom = 1.0 grow_horizontal = 2 grow_vertical = 2 mouse_filter = 2 -theme = ExtResource("1_a1566") script = ExtResource("2_sbew6") -[node name="VBox" type="VBoxContainer" parent="."] +[node name="Static" type="MarginContainer" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 +theme = ExtResource("1_a1566") + +[node name="VBox" type="VBoxContainer" parent="Static"] layout_mode = 2 mouse_filter = 2 -[node name="ServerMessage" parent="VBox" instance=ExtResource("3_m3rok")] +[node name="ServerMessage" parent="Static/VBox" instance=ExtResource("3_m3rok")] visible = false layout_mode = 2 -[node name="HintMessage" type="PanelContainer" parent="VBox"] +[node name="HintMessage" type="PanelContainer" parent="Static/VBox"] visible = false material = SubResource("ShaderMaterial_k0m35") layout_mode = 2 @@ -60,12 +70,12 @@ mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_vq4dg") script = ExtResource("4_pvwmw") -[node name="CenterContainer" type="HBoxContainer" parent="VBox/HintMessage"] +[node name="CenterContainer" type="HBoxContainer" parent="Static/VBox/HintMessage"] layout_mode = 2 mouse_filter = 2 alignment = 1 -[node name="MarginContainer" type="MarginContainer" parent="VBox/HintMessage/CenterContainer"] +[node name="MarginContainer" type="MarginContainer" parent="Static/VBox/HintMessage/CenterContainer"] layout_mode = 2 mouse_filter = 2 theme_override_constants/margin_left = 4 @@ -73,7 +83,7 @@ theme_override_constants/margin_top = 4 theme_override_constants/margin_right = 4 theme_override_constants/margin_bottom = 4 -[node name="TextureRect" type="TextureRect" parent="VBox/HintMessage/CenterContainer/MarginContainer"] +[node name="TextureRect" type="TextureRect" parent="Static/VBox/HintMessage/CenterContainer/MarginContainer"] custom_minimum_size = Vector2(28, 28) layout_mode = 2 mouse_filter = 2 @@ -81,7 +91,7 @@ texture = ExtResource("5_2dxsd") expand_mode = 1 stretch_mode = 4 -[node name="Label" type="Label" parent="VBox/HintMessage/CenterContainer"] +[node name="Label" type="Label" parent="Static/VBox/HintMessage/CenterContainer"] layout_mode = 2 size_flags_horizontal = 3 theme_override_fonts/font = SubResource("FontVariation_qfltj") @@ -89,60 +99,66 @@ theme_override_styles/normal = SubResource("StyleBoxEmpty_3rgop") text = "A hint is worth more than a thousand manuals" autowrap_mode = 3 -[node name="ServerTimer" type="Timer" parent="."] +[node name="Positional" type="Control" parent="."] +layout_mode = 1 +anchors_preset = 15 +anchor_right = 1.0 +anchor_bottom = 1.0 +grow_horizontal = 2 +grow_vertical = 2 +mouse_filter = 2 + +[node name="Timers" type="Node" parent="."] + +[node name="Server" type="Timer" parent="Timers"] wait_time = 5.0 one_shot = true -[node name="HintTimer" type="Timer" parent="."] +[node name="Hint" type="Timer" parent="Timers"] wait_time = 10.0 one_shot = true -[node name="AutoHintTimers" type="Node" parent="."] +[node name="AutoHints" type="Node" parent="Timers"] -[node name="Move" type="Timer" parent="AutoHintTimers"] +[node name="Move" type="Timer" parent="Timers/AutoHints"] wait_time = 2.0 one_shot = true -[node name="Performance" type="Timer" parent="AutoHintTimers"] +[node name="Performance" type="Timer" parent="Timers/AutoHints"] wait_time = 20.0 one_shot = true -[node name="Boost" type="Timer" parent="AutoHintTimers"] +[node name="Boost" type="Timer" parent="Timers/AutoHints"] wait_time = 90.0 one_shot = true -[node name="Interact" type="Timer" parent="AutoHintTimers"] +[node name="Interact" type="Timer" parent="Timers/AutoHints"] wait_time = 15.0 one_shot = true -[node name="RotateCamera" type="Timer" parent="AutoHintTimers"] +[node name="RotateCamera" type="Timer" parent="Timers/AutoHints"] wait_time = 120.0 one_shot = true -[node name="Zoom" type="Timer" parent="AutoHintTimers"] +[node name="Zoom" type="Timer" parent="Timers/AutoHints"] wait_time = 135.0 one_shot = true -[node name="Reset" type="Timer" parent="."] +[node name="Reset" type="Timer" parent="Timers"] wait_time = 10.0 one_shot = true -[node name="JoinWhileRunning" type="Timer" parent="."] +[node name="JoinWhileRunning" type="Timer" parent="Timers"] wait_time = 5.0 one_shot = true -[node name="ServerMessagePositional" type="Node2D" parent="."] -visible = false - -[node name="ServerMessage" parent="ServerMessagePositional" instance=ExtResource("3_m3rok")] - -[connection signal="timeout" from="ServerTimer" to="." method="_on_server_timer_timeout"] -[connection signal="timeout" from="HintTimer" to="." method="_on_hint_timer_timeout"] -[connection signal="timeout" from="AutoHintTimers/Move" to="." method="_on_move_timeout"] -[connection signal="timeout" from="AutoHintTimers/Performance" to="." method="_on_performance_timeout"] -[connection signal="timeout" from="AutoHintTimers/Boost" to="." method="_on_boost_timeout"] -[connection signal="timeout" from="AutoHintTimers/Interact" to="." method="_on_interact_timeout"] -[connection signal="timeout" from="AutoHintTimers/RotateCamera" to="." method="_on_rotate_camera_timeout"] -[connection signal="timeout" from="AutoHintTimers/Zoom" to="." method="_on_zoom_timeout"] -[connection signal="timeout" from="Reset" to="." method="_on_reset_timeout"] -[connection signal="timeout" from="JoinWhileRunning" to="." method="_on_join_while_running_timeout"] +[connection signal="timeout" from="Timers/Server" to="." method="_on_server_timeout"] +[connection signal="timeout" from="Timers/Hint" to="Static" method="_on_hint_timer_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Move" to="Static" method="_on_move_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Performance" to="Static" method="_on_performance_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Boost" to="Static" method="_on_boost_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Interact" to="Static" method="_on_interact_timeout"] +[connection signal="timeout" from="Timers/AutoHints/RotateCamera" to="Static" method="_on_rotate_camera_timeout"] +[connection signal="timeout" from="Timers/AutoHints/Zoom" to="Static" method="_on_zoom_timeout"] +[connection signal="timeout" from="Timers/Reset" to="Static" method="_on_reset_timeout"] +[connection signal="timeout" from="Timers/JoinWhileRunning" to="Static" method="_on_join_while_running_timeout"] diff --git a/client/menu/communicate/popup_message/server_message.gd b/client/menu/communicate/popup_message/server_message.gd new file mode 100644 index 00000000..fc12ee76 --- /dev/null +++ b/client/menu/communicate/popup_message/server_message.gd @@ -0,0 +1,13 @@ +extends BlurSetup +class_name ServerMessage + +const DEFAULT_FONT = preload("res://menu/theme/font-josefin-sans.woff2") +const MONOSPACE_FONT = preload("res://menu/theme/font-azaret-mono.woff2") + +@onready var label: Label = $CenterContainer/Label + +func set_text(text: String, use_monospace := true): + label.text = text + var font: FontVariation = label.get_theme_font("font") + font.base_font = MONOSPACE_FONT if use_monospace else DEFAULT_FONT + label.add_theme_font_size_override("font_size", 16 if use_monospace else 20) diff --git a/client/menu/communicate/popup_message/server_message.tscn b/client/menu/communicate/popup_message/server_message.tscn index 63160942..2a848419 100644 --- a/client/menu/communicate/popup_message/server_message.tscn +++ b/client/menu/communicate/popup_message/server_message.tscn @@ -1,7 +1,7 @@ [gd_scene load_steps=8 format=3 uid="uid://dq61p3a8og2b6"] [ext_resource type="Shader" path="res://menu/blur_mix.gdshader" id="1_qv8ew"] -[ext_resource type="Script" path="res://menu/blur_setup.gd" id="2_80a6b"] +[ext_resource type="Script" path="res://menu/communicate/popup_message/server_message.gd" id="2_csqo8"] [ext_resource type="FontFile" uid="uid://bk704sc5gkrb3" path="res://menu/theme/font-azaret-mono.woff2" id="3_dw20j"] [sub_resource type="ShaderMaterial" id="ShaderMaterial_q3bbd"] @@ -20,6 +20,7 @@ corner_radius_bottom_right = 16 corner_radius_bottom_left = 16 [sub_resource type="FontVariation" id="FontVariation_qfltj"] +resource_local_to_scene = true base_font = ExtResource("3_dw20j") variation_embolden = 0.75 @@ -35,7 +36,7 @@ size_flags_horizontal = 4 size_flags_vertical = 0 mouse_filter = 2 theme_override_styles/panel = SubResource("StyleBoxFlat_vq4dg") -script = ExtResource("2_80a6b") +script = ExtResource("2_csqo8") [node name="CenterContainer" type="CenterContainer" parent="."] layout_mode = 2 @@ -45,5 +46,6 @@ mouse_filter = 2 layout_mode = 2 theme_override_colors/font_color = Color(0, 0, 0, 1) theme_override_fonts/font = SubResource("FontVariation_qfltj") +theme_override_font_sizes/font_size = 16 theme_override_styles/normal = SubResource("StyleBoxEmpty_3rgop") text = "Server message" diff --git a/client/menu/hairstyle_preview.gd b/client/menu/hairstyle_preview.gd index 5a9cce68..08b6aab9 100644 --- a/client/menu/hairstyle_preview.gd +++ b/client/menu/hairstyle_preview.gd @@ -19,7 +19,7 @@ extends VBoxContainer signal selected(character: int) func setup(character: int, group: ButtonGroup): - $HairViewport/Node3D/Character.select_hairstyle(character) + $HairViewport/Node3D/Character.set_style(character) $Select.button_group = group $Select.text = tr("c.setup.uniform.value").format([character + 1]) $Select.pressed.connect(func(): selected.emit(character)) diff --git a/client/menu/ingame.gd b/client/menu/ingame.gd index 7052f237..ba365f8e 100644 --- a/client/menu/ingame.gd +++ b/client/menu/ingame.gd @@ -26,19 +26,16 @@ extends Menu var opened func _ready(): opened = Time.get_ticks_msec() - game.joined.connect(_on_game_joined) - game.left.connect(_on_game_left) - update_button_text() - game.joined.connect(update_lobby_button) - game.left.connect(update_lobby_button) + game.join_state_updated.connect(_on_game_join_state_changed) + _on_game_join_state_changed(game.join_state) update_lobby_button() super() func update_lobby_button(): - lobby_button.disabled = game.in_lobby or not game.is_joined + lobby_button.disabled = game.in_lobby or game.join_state == Game.JoinState.SPECTATING if game.in_lobby: lobby_button.tooltip_text = "Cannot cancel game since no game is running." - elif not game.is_joined: + elif not game.join_state == Game.JoinState.JOINED: lobby_button.tooltip_text = "You must join in order to be able to cancel the current game." else: lobby_button.tooltip_text = "" @@ -71,21 +68,15 @@ func _on_lobby_pressed(): exit() func _on_leave_pressed(): - if game.is_joined: - game.mp.send_leave(game.player_id) - elif not game.join_sent: - leave_button.disabled = true - game.join() + game.toggle_join() -func _on_game_joined(): - leave_button.disabled = false - update_button_text() - -func _on_game_left(): - update_button_text() - -func update_button_text(): - if game.is_joined: - leave_button.text = tr("c.menu.ingame.leave") - else: - leave_button.text = tr("c.menu.ingame.join") +func _on_game_join_state_changed(state: Game.JoinState): + match state: + Game.JoinState.JOINED: + leave_button.disabled = false + leave_button.text = tr("c.menu.ingame.leave") + Game.JoinState.SPECTATING: + leave_button.disabled = false + leave_button.text = tr("c.menu.ingame.join") + Game.JoinState.WAITING: + leave_button.disabled = true diff --git a/client/menu/lobby.gd b/client/menu/lobby.gd index 0dca6f4c..d595444e 100644 --- a/client/menu/lobby.gd +++ b/client/menu/lobby.gd @@ -52,8 +52,8 @@ func _ready(): game.update_players.connect(update_players) initialize() game.data_updated.connect(initialize) - game.joined.connect(_on_game_joined) - game.left.connect(_on_game_left) + game.join_state_updated.connect(_on_game_join_state_updated) + _on_game_join_state_updated(game.join_state) check_for_music() func initialize(): @@ -145,18 +145,6 @@ func _input(_event): elif Input.is_action_just_pressed("next") and not next_map.disabled: next_map.emit_signal("pressed") -func _on_game_joined(): - map_selector.show() - map_list.show() - bots_container.show() - start_button.disabled = false - -func _on_game_left(): - map_selector.hide() - map_list.hide() - bots_container.hide() - start_button.disabled = true - func _on_left_pressed(): selected_map = (selected_map - 1) % map_count select_map(selected_map) @@ -177,13 +165,27 @@ func _on_controller_button_pressed(): game.mp.send_chat(game.player_id, start_msg) Sound.play_music("stop") # TODO: Game music enter +func _on_game_join_state_updated(state: Game.JoinState): + match state: + Game.JoinState.JOINED: + map_selector.show() + map_list.show() + bots_container.show() + start_button.disabled = false + join_spectate.disabled = false + join_spectate.text = tr("c.menu.ingame.spectate") + Game.JoinState.SPECTATING: + map_selector.hide() + map_list.hide() + bots_container.hide() + start_button.disabled = true + join_spectate.disabled = false + join_spectate.text = tr("c.menu.ingame.join") + Game.JoinState.WAITING: + join_spectate.disabled = true + func _on_join_spectate_pressed(): - if game.is_joined: - game.leave() - join_spectate.text = tr("c.menu.ingame.join") - elif not game.join_sent: - game.join() - join_spectate.text = tr("c.menu.ingame.spectate") + game.toggle_join() func check_for_music(): if visible: diff --git a/client/menu/menu_background.gd b/client/menu/menu_background.gd index 33ec6e43..77fb123f 100644 --- a/client/menu/menu_background.gd +++ b/client/menu/menu_background.gd @@ -17,8 +17,8 @@ # extends Node3D -const NULLS = [null,null,null,null] -const BUCKETS = [[], ["floor","floor","floor","floor","tomato-crate", "steak-crate"], ["table", "chair", "counter"], ["sink", "stove"]] +const CRATES = ["tomato-crate", "steak-crate", "cheese-crate", "lettuce-crate", "flour-crate", "coconut-crate"] +const TOOLS = ["sink", "cuttingboard", "stove", "oven", "freezer"] @onready var environment: WorldEnvironment = $Environment @onready var map: Map = $Map @@ -27,12 +27,26 @@ func _ready(): if !Global.on_vulkan(): environment.environment.tonemap_exposure = 0.25 - for x in range(-10,11): - for y in range(-10,11): - var w = exp(-sqrt(x*x+y*y) * 0.15) + var tiles = {} + for x in range(-10, 11): + for y in range(-10, 11): + var w = exp(-sqrt(x * x + y * y) * 0.15) var k = randf() * w - var bucket = BUCKETS[int(floor(k * BUCKETS.size())) % BUCKETS.size()] - if bucket.size() == 0: continue - var tile_name = bucket[randi() % bucket.size()] - map.set_tile(Vector2i(x,y), tile_name) + var tn = null + if k > 0.25: tn = "floor" + if k > 0.4: tn = choose(CRATES) if randf() > 0.3 else "counter" + if k > 0.6: tn = choose(TOOLS) + if tn != null: tiles[str(Vector2i(x,y))] = [tn,[x,y]] + + var gt = func (cs): + var t = tiles.get(str(Vector2i(cs[0],cs[1]))) + return null if t == null else t[0] + for pk in tiles.keys(): + var x = tiles[pk][1][0] + var y = tiles[pk][1][1] + var t = gt.call([x,y]) + if t != null: map.set_tile(Vector2i(x,y), t, [[x,y-1],[x-1,y],[x,y+1],[x+1,y]].map(gt)) + map.flush() + +func choose(a): return a[floor(a.size() * randf())] diff --git a/client/menu/play.gd b/client/menu/play.gd index 1fe19224..b117d6a4 100644 --- a/client/menu/play.gd +++ b/client/menu/play.gd @@ -19,7 +19,6 @@ extends Menu var url_regex: RegEx = RegEx.new() -@onready var req: HTTPRequest = $HTTPRequest @onready var server_list: VBoxContainer = $side/margin/options/second/ScrollContainerCustom/ServerList @onready var server_list_loading: Label = $side/margin/options/second/Loading @onready var connect_uri = $side/margin/options/second/connect/uri diff --git a/client/player/character/character.gd b/client/player/character/character.gd index 66a3435b..65275549 100644 --- a/client/player/character/character.gd +++ b/client/player/character/character.gd @@ -42,11 +42,16 @@ var current_animation := "idle" @onready var tie = $Main/Tie @onready var knife = $Main/HandRight/Knife -@onready var hairstyles := { - "Brown": $Main/HeadDefault/Hair, - "Blond": $Main/HeadDefault/Hair2, - "E. Parsley": $Main/HeadDefault/Hair3 -} +const NUM_COLORS = 5; +const NUM_HAIRS = 3; +@onready var hairstyles := [$Main/HeadDefault/Hair, $Main/HeadDefault/Hair2, $Main/HeadDefault/Hair3] +var colors = [ + Color(0.204, 0.361, 0.624), + Color(0.568, 0.256, 0.602), + Color(0.575, 0.341, 0.117), + Color(0.3, 0.455, 0.221), + Color(0.101, 0.452, 0.521) +] @onready var head_default: MeshInstance3D = $Main/HeadDefault @onready var head_robot: MeshInstance3D = $Main/HeadRobot @@ -54,28 +59,41 @@ var current_animation := "idle" @onready var step_sounds: PlayRandom = $Steps @onready var boost_sounds: PlayRandom = $Boosts +class ParsedStyle: + var color: int + var hair: int + var robot: bool + var customer: bool + func _init(n: int) -> void: + customer = n < 0 + if customer: n *= -1 + if n == 51: robot = true + else: + hair = n % NUM_HAIRS + color = n / NUM_HAIRS % NUM_COLORS + func pack() -> int: + if robot: return 51 + return (hair + color * NUM_HAIRS) * (-1 if customer else 1) + func _ready(): play_animation("idle") var t := 0.0 func _process(delta): - if walking: - t += delta - main_height_target = default_height + sin(t * WALK_ANIM_SPEED) * WALK_ANIM_STRENGTH - else: - t = 0 + t += delta + if walking: main_height_target = default_height + sin(t * WALK_ANIM_SPEED) * WALK_ANIM_STRENGTH + else: t = 0 main.position.y = main_height_target # Update animation: var next_animation: String - if holding: - next_animation = "hold" - elif cutting: - next_animation = "cut" - elif walking: - next_animation = "walk" - else: - next_animation = "idle" + if holding: next_animation = "hold" + elif cutting: next_animation = "cut" + elif walking: next_animation = "walk" + else: next_animation = "idle" + + if current_animation != next_animation: + play_animation(next_animation) walking_particles.emitting = walking if boosting and walking and not was_boosting: @@ -85,47 +103,31 @@ func _process(delta): boosting_particles.emitting = false was_boosting = boosting and walking - if current_animation != next_animation: - play_animation(next_animation) - -func select_hairstyle(id: int): - if id == 51: - toggle_robot(true) - return - if id < 0: - to_customer() - id *= -1 - var hairstyle_count = hairstyles.keys().size() - id = id % hairstyle_count - var target = hairstyles.keys()[id] - for k in hairstyles.keys(): - if k == target: - hairstyles[k].show() - else: - hairstyles[k].hide() - -func to_customer(): - main.mesh = CUSTOMER_MAIN_MESH - tie.queue_free() +func set_style(id: int): + var p = ParsedStyle.new(id) + set_customer(p.customer) + set_robot(p.robot) + for h in hairstyles: h.hide() + hairstyles[p.hair].show() + $Main.get_active_material(0).albedo_color = colors[p.color] -func toggle_robot(b: bool): +func set_customer(b: bool): if b: - head_robot.show() - head_default.hide() - main.mesh = ROBOT_MAIN_MESH - else: - head_robot.hide() - head_default.show() - main.mesh = DEFAULT_MAIN_MESH + main.mesh = CUSTOMER_MAIN_MESH + tie.queue_free() + else: pass # TODO + +func set_robot(b: bool): + head_robot.visible = b + head_default.visible = not b + main.mesh = ROBOT_MAIN_MESH if b else DEFAULT_MAIN_MESH func play_animation(name_: String): current_animation = name_ hand_animations.play(name_) - if name_ == "walk": - step_sounds.start_autoplay() - else: - step_sounds.stop_autoplay() + if name_ == "walk": step_sounds.start_autoplay() + else: step_sounds.stop_autoplay() knife.visible = name_ == "cut" diff --git a/client/player/character/character.tscn b/client/player/character/character.tscn index a7c09c01..aca0658a 100644 --- a/client/player/character/character.tscn +++ b/client/player/character/character.tscn @@ -1,4 +1,4 @@ -[gd_scene load_steps=27 format=3 uid="uid://b3hhir2fvnunu"] +[gd_scene load_steps=28 format=3 uid="uid://b3hhir2fvnunu"] [ext_resource type="Script" path="res://player/character/character.gd" id="1_12lbh"] [ext_resource type="ArrayMesh" uid="uid://bnmm01yjwultj" path="res://player/character/default/main.res" id="2_uovyg"] @@ -18,6 +18,11 @@ [ext_resource type="AudioStream" uid="uid://1jsqpnk3igj3" path="res://player/sounds/woosh1.ogg" id="14_ikcec"] [ext_resource type="AudioStream" uid="uid://cwme7eatip0jc" path="res://player/sounds/woosh2.ogg" id="15_iv4wu"] +[sub_resource type="StandardMaterial3D" id="StandardMaterial3D_7ojaw"] +resource_local_to_scene = true +resource_name = "main" +cull_mode = 2 + [sub_resource type="Animation" id="Animation_tdhvg"] length = 0.001 tracks/0/type = "bezier" @@ -729,6 +734,7 @@ script = ExtResource("1_12lbh") transform = Transform3D(0.33, 0, 0, 0, 0.33, 0, 0, 0, 0.33, 0, 0.33, 0) mesh = ExtResource("2_uovyg") skeleton = NodePath("") +surface_material_override/0 = SubResource("StandardMaterial3D_7ojaw") [node name="HandRight" type="MeshInstance3D" parent="Main"] transform = Transform3D(0.287144, 0.2864, -1.17785e-06, 0.402357, -0.133775, 0.337554, 0.292329, -0.0971941, -0.464603, -1.302, -0.17, 0) diff --git a/client/player/controllable_player.gd b/client/player/controllable_player.gd index 0cabcb64..131bc55d 100644 --- a/client/player/controllable_player.gd +++ b/client/player/controllable_player.gd @@ -43,7 +43,7 @@ func _ready(): add_child(timer) timer.start() timer.connect("timeout", func(): - if game.mp != null and game.join_sent: + if game.mp != null and game.join_state == Game.JoinState.JOINED: game.mp.send_movement(game.player_id, position_, direction, boosting) ) add_child(onscreen_controls) @@ -60,13 +60,20 @@ func _process(delta): update_touch_scrolls() var moving_duration = 0 +var fps_rotation_target = 0 func _process_movement(delta): var input = Input.get_vector("left", "right", "forwards", "backwards") if is_input_enabled() else Vector2.ZERO if Global.get_setting("gameplay.first_person"): - input.x *= 0.1 + fps_rotation_target += input.x * delta * 3. + if abs(input.x) > 0.1: input.y -= 0.5 + input.x = 0. input.y = min(input.y, 0) + input = input.rotated(fps_rotation_target) + else: + input = input.rotated(input_rotation) + var boost = Input.is_action_pressed("boost") or (Global.get_setting("gameplay.latch_boost") and boosting) - input = input.rotated(input_rotation) + # if Input.is_action_pressed("interact") or Input.is_action_just_released("interact"): input *= 0 else: diff --git a/client/player/player.gd b/client/player/player.gd index 31a7a337..6ff28e81 100644 --- a/client/player/player.gd +++ b/client/player/player.gd @@ -79,7 +79,7 @@ func _init(_id: int, new_name: String, pos: Vector2, new_character_idx: int, new is_customer = character_idx < 0 func _ready(): - character.select_hairstyle(character_idx) + character.set_style(character_idx) clear_timer.timeout.connect(clear_message) Settings.hook_changed_init("gameplay.usernames", false, update_username_tag) diff --git a/data/index.yaml b/data/index.yaml index a4984d59..f1942d05 100644 --- a/data/index.yaml +++ b/data/index.yaml @@ -4,6 +4,7 @@ # Copyright 2024 Rusty Striker # Copyright 2024 BigBrotherNii # Copyright 2024 nokoe +# Copyright 2024 tpart # # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by @@ -37,6 +38,7 @@ maps: paris: { name: "Paris", players: 2, difficulty: 1 } line: { name: "Line", players: 2, difficulty: 1 } bbq: { name: "BBQ", players: 2, difficulty: 1 } + salad: { name: "Salad Store", players: 2, difficulty: 1 } sushibar: { name: "Sushi Bar", players: 2, difficulty: 2 } smallest: { name: "Smallest", players: 1, difficulty: 1 } teeny: { name: "Teeny", players: 3, difficulty: 2 } diff --git a/data/maps/salad.yaml b/data/maps/salad.yaml new file mode 100644 index 00000000..96bc1aca --- /dev/null +++ b/data/maps/salad.yaml @@ -0,0 +1,81 @@ +# Hurry Curry! - a game about cooking +# Copyright 2024 tpart +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, version 3 of the License only. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +# +score_baseline: 200 +map: + - "*'''''''*''''''*'*" + - "''''''*''''**'*'''" + - "'''''███▒▒███'''''" + - "*''''█⌷CCCC⌷█'''*'" + - "'''''█p....L█''''*" + - "*''''▒p....T▒'''''" + - "'''''▒p....L▒'''''" + - "*''''█s....T█''''*" + - "'''''█......█'''''" + - "'''''█w█dd█w█'''''" + - "'''''█tc..ct█'''''" + - "*''''▒c....c▒'''''" + - "'*'''█......█'''''" + - "'''''█c....c█''*''" + - "'''''▒tc.~ct▒'''''" + - "*''''█c....c█'''''" + - "'''''█▒█dd█▒█''''*" + - "'''''''X__''''''''" + - "*'*'''''!_'''**'''" + +tiles: + "⌷": counter + "f": counter + "p": counter + "t": table + "w": counter-window + "s": sink + "C": cuttingboard + "T": tomato-crate + "L": lettuce-crate + "X": trash + + "c": chair + "~": floor + ".": floor + "'": grass + "*": tree + "!": path + "_": path + "d": door + "▒": wall-window + "█": wall + +items: + "w": plate + "p": plate + +entities: + - !customers + +chef_spawn: "~" +customer_spawn: "!" + +walkable: + - door + - floor + - chair + - grass + - path + +collider: + - wall + - wall-window + - tree diff --git a/locale/en.ini b/locale/en.ini index 71fbd816..ea798258 100644 --- a/locale/en.ini +++ b/locale/en.ini @@ -180,18 +180,21 @@ s.bot.frank=Frank Miller s.tutorial.prevent_burning=Take this before it burns s.tutorial.take_now=Take this item quickly! s.tutorial.active=Interact here for {0}s +s.tutorial.active_cuttingboard=Cut the item to slices here s.tutorial.clear_tile=Clear this tile s.tutorial.error=Tutorial code handle this recipe yet. s.tutorial.finished=Tutorial finished! s.tutorial.hold_interact=Hold interact s.tutorial.interact_empty=Interact with an empty counter s.tutorial.interact=Interact here +s.tutorial.interact_plate=Add the item to this plate s.tutorial.pickup=Take this item. s.tutorial.put_away=Put away this item for later s.tutorial.put_on=Place on {0} s.tutorial.take=Take {0} from here s.tutorial.serve=Serve the meal here s.tutorial.wait_finish=... +s.tutorial.accept_order=Approach the customer take their order s.replay.cannot_join=Replays cannot be joined. s.campaign.unlock_condition=To unlock: %n%n{0} s.campaign.list_helper=- {0}%n - {1} diff --git a/locale/tools/Cargo.toml b/locale/tools/Cargo.toml index e8084b23..47f9e0d1 100644 --- a/locale/tools/Cargo.toml +++ b/locale/tools/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -clap = { version = "4.5.16", features = ["derive"] } -anyhow = "1.0.86" -serde_json = "1.0.127" +clap = { version = "4.5.18", features = ["derive"] } +anyhow = "1.0.89" +serde_json = "1.0.128" diff --git a/pixel-client/Cargo.toml b/pixel-client/Cargo.toml index 8104a384..4831f485 100644 --- a/pixel-client/Cargo.toml +++ b/pixel-client/Cargo.toml @@ -9,18 +9,18 @@ hurrycurry-protocol = { path = "../server/protocol" } hurrycurry-client-lib = { path = "../server/client-lib", default-features = false, features = [ "sync-network", ] } -tungstenite = { version = "0.23.0", features = ["rustls-tls-native-roots"] } -serde_json = "1.0.122" +tungstenite = { version = "0.24.0", features = ["rustls-tls-native-roots"] } +serde_json = "1.0.128" bincode = "2.0.0-rc.3" log = "0.4.22" env_logger = "0.11.5" -anyhow = "1.0.86" -clap = { version = "4.5.15", features = ["derive"] } -rustls = { version = "0.23.12", features = ["ring"] } +anyhow = "1.0.89" +clap = { version = "4.5.18", features = ["derive"] } +rustls = { version = "0.23.13", features = ["ring"] } rand = "0.9.0-alpha.2" xdg = "2.5.2" toml = "0.8.19" -serde = { version = "1.0.207", features = ["derive"] } +serde = { version = "1.0.210", features = ["derive"] } users = "0.11.0" [features] diff --git a/pixel-client/tools/Cargo.toml b/pixel-client/tools/Cargo.toml index 15dd0239..075ec24f 100644 --- a/pixel-client/tools/Cargo.toml +++ b/pixel-client/tools/Cargo.toml @@ -5,8 +5,8 @@ edition = "2021" [dependencies] image = "0.25.2" -anyhow = "1.0.86" +anyhow = "1.0.89" log = "0.4.22" env_logger = "0.11.5" -clap = { version = "4.5.15", features = ["derive"] } +clap = { version = "4.5.18", features = ["derive"] } sdl2 = { version = "0.37.0", features = ["image"] } diff --git a/protocol.md b/protocol.md index 4e5ab475..9562ab6f 100644 --- a/protocol.md +++ b/protocol.md @@ -45,9 +45,8 @@ sending a packet to update that of the other player. - 443: All uses with TLS - 27032: Game Server Websocket -- 27033: Registry API HTTP +- 27033: Registry API HTTP / Local dicovery service - 27034: Lobby Server Websocket -- 27035: Local discovery service API ## Binary Protocol diff --git a/server/Cargo.toml b/server/Cargo.toml index 978de4c6..38db0bdd 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -7,16 +7,16 @@ default-run = "hurrycurry-server" [dependencies] log = "0.4.22" env_logger = "0.11.5" -anyhow = "1.0.86" -serde = { version = "1.0.205", features = ["derive"] } -tokio = { version = "1.39.2", features = ["full"] } -serde_json = "1.0.122" -tokio-tungstenite = "0.23.1" +anyhow = "1.0.89" +serde = { version = "1.0.210", features = ["derive"] } +tokio = { version = "1.40.0", features = ["full"] } +serde_json = "1.0.128" +tokio-tungstenite = "0.24.0" futures-util = "0.3.30" -serde_yml = "0.0.11" +serde_yml = "0.0.12" rand = "0.9.0-alpha.2" shlex = "1.3.0" -clap = { version = "4.5.15", features = ["derive"] } +clap = { version = "4.5.18", features = ["derive"] } reqwest = { version = "0.12.7", optional = true, default-features = false, features = [ "json", "http2", diff --git a/server/bot/Cargo.toml b/server/bot/Cargo.toml index 3143ab55..c8d60270 100644 --- a/server/bot/Cargo.toml +++ b/server/bot/Cargo.toml @@ -7,8 +7,8 @@ edition = "2021" hurrycurry-client-lib = { path = "../client-lib", features = ["tokio-network"] } hurrycurry-protocol = { path = "../protocol" } log = "0.4.22" -anyhow = "1.0.86" +anyhow = "1.0.89" env_logger = "0.11.5" -rustls = { version = "0.23.12", features = ["ring"] } -clap = { version = "4.5.15", features = ["derive"] } +rustls = { version = "0.23.13", features = ["ring"] } +clap = { version = "4.5.18", features = ["derive"] } rand = "0.9.0-alpha.2" diff --git a/server/bot/src/algos/simple.rs b/server/bot/src/algos/simple.rs index dbe8bbfe..b275b522 100644 --- a/server/bot/src/algos/simple.rs +++ b/server/bot/src/algos/simple.rs @@ -145,6 +145,9 @@ impl<S> Context<'_, S> { .iter() .filter_map(|(_, pl)| match &pl.communicate_persist { Some((Message::Item(item), _)) => { + if self.game.data.item_name(*item) == "unknown-order" { + return None; + } let pos = pl.movement.position.as_ivec2(); [IVec2::X, IVec2::Y, -IVec2::X, -IVec2::Y] .into_iter() diff --git a/server/client-lib/Cargo.toml b/server/client-lib/Cargo.toml index 291c07f4..517dbba0 100644 --- a/server/client-lib/Cargo.toml +++ b/server/client-lib/Cargo.toml @@ -5,17 +5,17 @@ edition = "2021" [dependencies] hurrycurry-protocol = { path = "../protocol" } -tungstenite = { version = "0.23.0", optional = true, features = [ +tungstenite = { version = "0.24.0", optional = true, features = [ "rustls-tls-native-roots", ] } -tokio-tungstenite = { version = "0.23.1", optional = true, features = [ +tokio-tungstenite = { version = "0.24.0", optional = true, features = [ "rustls-tls-native-roots", ] } -tokio = { version = "1.39.2", features = ["net", "sync"], optional = true } -serde_json = "1.0.122" +tokio = { version = "1.40.0", features = ["net", "sync"], optional = true } +serde_json = "1.0.128" bincode = "2.0.0-rc.3" log = "0.4.22" -anyhow = "1.0.86" +anyhow = "1.0.89" futures-util = { version = "0.3.30", optional = true } [features] diff --git a/server/discover/src/main.rs b/server/discover/src/main.rs index 1c23de85..f1f2bb35 100644 --- a/server/discover/src/main.rs +++ b/server/discover/src/main.rs @@ -26,7 +26,7 @@ use hyper::{ use hyper_util::rt::TokioIo; use log::warn; use mdns_sd::{ServiceDaemon, ServiceEvent}; -use std::{cmp::Reverse, collections::HashMap, sync::Arc}; +use std::{cmp::Reverse, collections::HashMap, net::SocketAddr, sync::Arc}; use tokio::{net::TcpListener, spawn, sync::RwLock}; fn main() -> Result<()> { @@ -58,7 +58,9 @@ async fn async_main() -> Result<!> { address: service_info .get_addresses() .into_iter() - .map(|a| format!("ws://{a}:{}", service_info.get_port())) + .map(|a| { + format!("ws://{}", SocketAddr::new(*a, service_info.get_port())) + }) .collect(), players_online: service_info .get_property_val_str("players") @@ -83,7 +85,7 @@ async fn async_main() -> Result<!> { } }); - let listener = TcpListener::bind("127.0.0.1:27035").await?; + let listener = TcpListener::bind("127.0.0.1:27033").await?; loop { let (stream, _) = listener.accept().await?; let entries = entries.clone(); diff --git a/server/protocol/Cargo.toml b/server/protocol/Cargo.toml index 9c3f26e8..2a7a989c 100644 --- a/server/protocol/Cargo.toml +++ b/server/protocol/Cargo.toml @@ -4,6 +4,6 @@ version = "0.1.0" edition = "2021" [dependencies] -serde = { version = "1.0.205", features = ["derive"] } -glam = { version = "0.28.0", features = ["serde"] } +serde = { version = "1.0.210", features = ["derive"] } +glam = { version = "0.29.0", features = ["serde"] } bincode = { version = "2.0.0-rc.3", features = ["serde", "derive"] } diff --git a/server/registry/Cargo.toml b/server/registry/Cargo.toml index c616174f..49f58a46 100644 --- a/server/registry/Cargo.toml +++ b/server/registry/Cargo.toml @@ -6,16 +6,16 @@ edition = "2021" [dependencies] log = "0.4.22" env_logger = "0.11.5" -anyhow = "1.0.86" +anyhow = "1.0.89" rocket = { version = "0.5.1", features = ["json"] } -tokio = { version = "1.39.2", features = ["full"] } +tokio = { version = "1.40.0", features = ["full"] } serde_json = "1.0.128" markup = "0.15.0" serde = { version = "1.0.210", features = ["derive"] } -tokio-tungstenite = { version = "0.23.1", features = [ +tokio-tungstenite = { version = "0.24.0", features = [ "rustls-tls-native-roots", ] } -rustls = { version = "0.23.12", features = ["ring"] } +rustls = { version = "0.23.13", features = ["ring"] } hurrycurry-protocol = { path = "../protocol" } hurrycurry-client-lib = { path = "../client-lib" } diff --git a/server/registry/src/list.rs b/server/registry/src/list.rs index 1c2cd4a3..5684b473 100644 --- a/server/registry/src/list.rs +++ b/server/registry/src/list.rs @@ -20,9 +20,13 @@ use anyhow::Result; use hurrycurry_protocol::registry::Entry; use rocket::{ get, - http::MediaType, + http::{Header, MediaType}, request::{self, FromRequest, Outcome}, - response::content::{RawHtml, RawJson}, + response::{ + self, + content::{RawHtml, RawJson}, + Responder, + }, Either, Request, State, }; use std::sync::Arc; @@ -32,12 +36,12 @@ use tokio::sync::RwLock; pub(super) async fn r_list( registry: &State<Arc<RwLock<Registry>>>, json: AcceptJson, -) -> Either<RawJson<Arc<str>>, RawHtml<Arc<str>>> { - if json.0 { +) -> Cors<Either<RawJson<Arc<str>>, RawHtml<Arc<str>>>> { + Cors(if json.0 { Either::Left(RawJson(registry.read().await.json_response.clone())) } else { Either::Right(RawHtml(registry.read().await.html_response.clone())) - } + }) } pub(super) fn generate_json_list(entries: &[Entry]) -> Result<Arc<str>> { @@ -100,3 +104,13 @@ impl<'r> FromRequest<'r> for AcceptJson { }) } } + +pub struct Cors<T>(pub T); +#[rocket::async_trait] +impl<'r, T: Responder<'r, 'static>> Responder<'r, 'static> for Cors<T> { + fn respond_to(self, req: &'r Request<'_>) -> response::Result<'static> { + let mut b = self.0.respond_to(req)?; + b.set_header(Header::new("access-control-allow-origin", "*")); + Ok(b) + } +} diff --git a/server/registry/src/main.rs b/server/registry/src/main.rs index 5bb7a0a3..30fb8d66 100644 --- a/server/registry/src/main.rs +++ b/server/registry/src/main.rs @@ -26,7 +26,7 @@ use list::{generate_html_list, generate_json_list, r_list}; use lobby::lobby_wrapper; use log::{error, info}; use register::r_register; -use rocket::{get, routes, shield::Shield, Config}; +use rocket::{fairing::AdHoc, get, http::Header, routes, shield::Shield, Config}; use std::{ cmp::Reverse, collections::HashMap, @@ -73,6 +73,10 @@ fn main() { }) .attach(Shield::new()) .manage(registry) + .attach(AdHoc::on_response("set server header", |_req, res| { + res.set_header(Header::new("server", "hurrycurry-registry")); + Box::pin(async {}) + })) .mount("/", routes![r_index, r_list, r_register]) .ignite() .await diff --git a/server/replaytool/Cargo.toml b/server/replaytool/Cargo.toml index fb27ed4b..9d5ac20a 100644 --- a/server/replaytool/Cargo.toml +++ b/server/replaytool/Cargo.toml @@ -6,17 +6,17 @@ edition = "2021" [dependencies] log = "0.4.22" env_logger = "0.11.5" -anyhow = "1.0.86" -serde = { version = "1.0.205", features = ["derive"] } -tokio = { version = "1.39.2", features = ["full"] } -serde_json = "1.0.122" -tokio-tungstenite = { version = "0.23.1", features = [ +anyhow = "1.0.89" +serde = { version = "1.0.210", features = ["derive"] } +tokio = { version = "1.40.0", features = ["full"] } +serde_json = "1.0.128" +tokio-tungstenite = { version = "0.24.0", features = [ "rustls-tls-native-roots", ] } futures-util = "0.3.30" rand = "0.9.0-alpha.2" -clap = { version = "4.5.15", features = ["derive"] } +clap = { version = "4.5.18", features = ["derive"] } async-compression = { version = "0.4.12", features = ["zstd", "tokio"] } -rustls = { version = "0.23.12", features = ["ring"] } +rustls = { version = "0.23.13", features = ["ring"] } hurrycurry-protocol = { path = "../protocol" } diff --git a/server/src/commands.rs b/server/src/commands.rs index 06659161..478d88e3 100644 --- a/server/src/commands.rs +++ b/server/src/commands.rs @@ -70,7 +70,7 @@ enum Command { }, /// Reload the resource index ReloadIndex, - #[clap(alias = "summon-bot", alias = "spawn-bot")] + #[clap(alias = "summon", alias = "bot")] CreateBot { algo: String, name: Option<String>, diff --git a/server/src/entity/customers.rs b/server/src/entity/customers.rs index bb423e58..a9ddb6f1 100644 --- a/server/src/entity/customers.rs +++ b/server/src/entity/customers.rs @@ -54,7 +54,7 @@ impl Entity for Customers { self.spawn_cooldown = 10. + random::<f32>() * 10.; let bot = BotDriver::new( "".to_string(), - random::<u16>() as i32, + -1 - random::<u16>() as i32, PlayerClass::Customer, Customer::default(), ); diff --git a/server/src/entity/tutorial.rs b/server/src/entity/tutorial.rs index 3189687b..1d28f13e 100644 --- a/server/src/entity/tutorial.rs +++ b/server/src/entity/tutorial.rs @@ -211,6 +211,13 @@ impl<'a> StepContext<'a> { } } fn fulfil_demand(&mut self, item: ItemIndex) -> Result<(), (Option<IVec2>, Message)> { + if self.ent.game.data.item_name(item) == "unknown-order" { + return if let Some(pos) = self.find_demand(item) { + Err((Some(pos), trm!("s.tutorial.accept_order"))) + } else { + Ok(()) + }; + } if !*self.had_aquired_target { self.prevent_burning()?; self.aquire_item(item)?; @@ -264,7 +271,16 @@ impl<'a> StepContext<'a> { } => { let apos = self.aquire_placed_item(*a)?; self.aquire_item(*b)?; - return Err((Some(apos), trm!("s.tutorial.interact"))); + let aname = self.ent.game.data.item_name(*a); + let bname = self.ent.game.data.item_name(*b); + return Err(( + Some(apos), + if aname.starts_with("plate:") || bname.starts_with("plate:") { + trm!("s.tutorial.interact_plate") + } else { + trm!("s.tutorial.interact") + }, + )); } Recipe::Instant { tile: None, @@ -291,7 +307,11 @@ impl<'a> StepContext<'a> { self.aquire_item(*input)?; return Err(( Some(pos), - trm!("s.tutorial.active", s = format!("{:.01}", 1. / speed)), + if self.ent.game.data.tile_name(*tile) == "cuttingboard" { + trm!("s.tutorial.active_cuttingboard") + } else { + trm!("s.tutorial.active", s = format!("{:.01}", 1. / speed)) + }, )); } } diff --git a/server/src/network/register.rs b/server/src/network/register.rs index 8e0464fa..f75b8639 100644 --- a/server/src/network/register.rs +++ b/server/src/network/register.rs @@ -48,8 +48,8 @@ impl Register { port: u16, register_uri: Option<String>, state: Arc<RwLock<Server>>, - no6: bool, no4: bool, + no6: bool, ) -> Self { Self { name, |