diff --git a/Cargo.lock b/Cargo.lock index 63fda22145..d81bc947c2 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -2,16 +2,6 @@ # It is not intended for manual editing. version = 3 -[[package]] -name = "Inflector" -version = "0.11.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fe438c63458706e03479442743baae6c88256498e6431708f6dfc520a26515d3" -dependencies = [ - "lazy_static", - "regex", -] - [[package]] name = "ab_glyph" version = "0.2.18" @@ -185,20 +175,6 @@ dependencies = [ "libloading", ] -[[package]] -name = "ast_node" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cf94863c5fdfee166d0907c44e5fee970123b2b7307046d35d1e671aa93afbba" -dependencies = [ - "darling", - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - [[package]] name = "async-channel" version = "1.7.1" @@ -310,27 +286,12 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base64" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b41b7ea54a0c9d92199de89e20e58d49f02f8e699814ef3fdf266f6f748d15c7" - [[package]] name = "base64" version = "0.13.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e1b586273c5702936fe7b7d6896644d8be71e6314cfe09d3167c95f712589e8" -[[package]] -name = "better_scoped_tls" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b73e8ecdec39e98aa3b19e8cd0b8ed8f77ccb86a6b0b2dc7cd86d105438a2123" -dependencies = [ - "scoped-tls", -] - [[package]] name = "bevy" version = "0.8.1" @@ -733,38 +694,6 @@ dependencies = [ "glam", ] -[[package]] -name = "bevy_mod_js_scripting" -version = "0.1.0" -source = "git+https://github.com/zicklag/bevy_mod_js_scripting.git?branch=jumpy#9781be0f8035ba43fa4498d88f1efba658ab4ed5" -dependencies = [ - "anyhow", - "bevy", - "bevy_ecs_dynamic", - "bevy_reflect", - "bevy_reflect_fns", - "deno_core", - "fixedbitset", - "indexmap", - "js-sys", - "pollster", - "serde", - "serde-wasm-bindgen", - "serde_json", - "serde_v8", - "slotmap", - "swc_atoms", - "swc_common", - "swc_ecma_codegen", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_typescript", - "swc_ecma_visit", - "type-map 0.5.0", - "wasm-bindgen", - "wasm_mutex", -] - [[package]] name = "bevy_pbr" version = "0.8.1" @@ -835,15 +764,6 @@ dependencies = [ "uuid", ] -[[package]] -name = "bevy_reflect_fns" -version = "0.1.0" -source = "git+https://github.com/jakobhellermann/bevy_reflect_fns?rev=22e85021851e0cfe27b87e428f6313dd8c26abde#22e85021851e0cfe27b87e428f6313dd8c26abde" -dependencies = [ - "bevy_reflect", - "thiserror", -] - [[package]] name = "bevy_render" version = "0.8.1" @@ -1170,15 +1090,6 @@ version = "0.1.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0d8c1fef690941d3e7788d328517591fecc684c084084702d6ff1641e993699a" -[[package]] -name = "block-buffer" -version = "0.10.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "69cce20737498f97b993470a6e536b8523f0af7892a4f928cceb1ac5e52ebe7e" -dependencies = [ - "generic-array", -] - [[package]] name = "blocking" version = "1.2.0" @@ -1444,12 +1355,6 @@ version = "0.2.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9ed2b28323eee4fb66bb824401daa3e46bd445b9a9298a3d382b320710ba69dd" -[[package]] -name = "convert_case" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6245d59a3e82a7fc217c5828a6692dbc6dfb63a0c8c90495621f7b9d79704a0e" - [[package]] name = "copyless" version = "0.1.5" @@ -1583,15 +1488,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "cpufeatures" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "28d997bd5e24a5928dd43e46dc529867e207907fe0b239c3477d924f7f2ca320" -dependencies = [ - "libc", -] - [[package]] name = "crc32fast" version = "1.3.2" @@ -1620,16 +1516,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "crypto-common" -version = "0.1.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1bfb12502f3fc46cca1bb51ac28df9d618d813cdc3d2f25b9fe775a34af26bb3" -dependencies = [ - "generic-array", - "typenum", -] - [[package]] name = "cty" version = "0.2.2" @@ -1682,28 +1568,6 @@ dependencies = [ "syn", ] -[[package]] -name = "dashmap" -version = "5.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "907076dfda823b0b36d2a1bb5f90c96660a5bbcd7729e10727f07858f22c4edc" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown", - "lock_api", - "once_cell", - "parking_lot_core 0.9.4", -] - -[[package]] -name = "debug_unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a032eac705ca39214d169f83e3d3da290af06d8d1d344d1baad2fd002dca4b3" -dependencies = [ - "unreachable", -] - [[package]] name = "deflate" version = "0.8.6" @@ -1714,66 +1578,17 @@ dependencies = [ "byteorder", ] -[[package]] -name = "deno_core" -version = "0.146.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "88475da37fe0544b7372fd4705560df496498eb5eeb40ce19bfe7787ed0600ca" -dependencies = [ - "anyhow", - "deno_ops", - "futures", - "indexmap", - "libc", - "log", - "once_cell", - "parking_lot 0.12.1", - "pin-project", - "serde", - "serde_json", - "serde_v8", - "sourcemap", - "url", - "v8", -] - -[[package]] -name = "deno_ops" -version = "0.24.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e217fd2f9a61bc581f6b13868a46ef800efb7532348fd86cc4fe49204d203ea6" -dependencies = [ - "once_cell", - "proc-macro-crate", - "proc-macro2", - "quote", - "regex", - "syn", -] - [[package]] name = "derive_more" version = "0.99.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4fb810d30a7c1953f91334de7244731fc3f3c10d7fe163338a35b9f640960321" dependencies = [ - "convert_case", "proc-macro2", "quote", - "rustc_version 0.4.0", "syn", ] -[[package]] -name = "digest" -version = "0.10.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8168378f4e5023e7218c89c891c0fd8ecdb5e5e4f18cb78f38cf245dd021e76f" -dependencies = [ - "block-buffer", - "crypto-common", -] - [[package]] name = "directories" version = "4.0.1" @@ -1893,18 +1708,6 @@ dependencies = [ "cfg-if 1.0.0", ] -[[package]] -name = "enum_kind" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "78b940da354ae81ef0926c5eaa428207b8f4f091d3956c891dfbd124162bed99" -dependencies = [ - "pmutil", - "proc-macro2", - "swc_macros_common", - "syn", -] - [[package]] name = "env_logger" version = "0.8.4" @@ -2112,18 +1915,6 @@ dependencies = [ "percent-encoding", ] -[[package]] -name = "from_variant" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f0981e470d2ab9f643df3921d54f1952ea100c39fdb6a3fdc820e20d2291df6c" -dependencies = [ - "pmutil", - "proc-macro2", - "swc_macros_common", - "syn", -] - [[package]] name = "fsevent-sys" version = "4.1.0" @@ -2133,16 +1924,6 @@ dependencies = [ "libc", ] -[[package]] -name = "fslock" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "57eafdd0c16f57161105ae1b98a1238f97645f2f588438b2949c99a2af9616bf" -dependencies = [ - "libc", - "winapi", -] - [[package]] name = "futures" version = "0.3.25" @@ -2151,7 +1932,6 @@ checksum = "38390104763dc37a5145a53c29c63c1290b5d316d6086ec32c293f6736051bb0" dependencies = [ "futures-channel", "futures-core", - "futures-executor", "futures-io", "futures-sink", "futures-task", @@ -2174,17 +1954,6 @@ version = "0.3.25" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "04909a7a7e4633ae6c4a9ab280aeb86da1236243a77b694a49eacd659a4bd3ac" -[[package]] -name = "futures-executor" -version = "0.3.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7acc85df6714c176ab5edf386123fafe217be88c0840ec11f199441134a074e2" -dependencies = [ - "futures-core", - "futures-task", - "futures-util", -] - [[package]] name = "futures-io" version = "0.3.25" @@ -2256,16 +2025,6 @@ dependencies = [ "byteorder", ] -[[package]] -name = "generic-array" -version = "0.14.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bff49e947297f3312447abdca79f45f4738097cc82b06e72054d2223f601f1b9" -dependencies = [ - "typenum", - "version_check", -] - [[package]] name = "gethostname" version = "0.2.3" @@ -2528,12 +2287,6 @@ dependencies = [ "unicode-normalization", ] -[[package]] -name = "if_chain" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cb56e1aa765b4b4f3aadfab769793b7087bb03a4ea4920644a6d238e2df5b9ed" - [[package]] name = "image" version = "0.23.14" @@ -2625,7 +2378,7 @@ version = "0.5.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c310433e4a310918d6ed9243542a6b83ec1183df95dff8f23f87bb88a264a66f" dependencies = [ - "type-map 0.4.0", + "type-map", "unic-langid", ] @@ -2648,19 +2401,6 @@ dependencies = [ "mach", ] -[[package]] -name = "is-macro" -version = "0.2.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c068d4c6b922cd6284c609cfa6dec0e41615c9c5a1a4ba729a970d8daba05fb" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "itertools" version = "0.10.5" @@ -2738,7 +2478,7 @@ version = "0.4.3" dependencies = [ "anyhow", "async-channel", - "base64 0.13.1", + "base64", "bevy", "bevy-has-load-progress", "bevy-inspector-egui", @@ -2749,7 +2489,6 @@ dependencies = [ "bevy_fluent", "bevy_ggrs", "bevy_kira_audio", - "bevy_mod_js_scripting", "bevy_prototype_lyon", "bevy_tweening", "bitfield", @@ -2778,6 +2517,7 @@ dependencies = [ "rand", "rustls", "serde", + "serde_json", "serde_yaml", "sys-locale", "thiserror", @@ -2905,79 +2645,6 @@ dependencies = [ "syn", ] -[[package]] -name = "lexical" -version = "6.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c7aefb36fd43fef7003334742cbf77b243fcd36418a1d1bdd480d613a67968f6" -dependencies = [ - "lexical-core", -] - -[[package]] -name = "lexical-core" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2cde5de06e8d4c2faabc400238f9ae1c74d5412d03a7bd067645ccbc47070e46" -dependencies = [ - "lexical-parse-float", - "lexical-parse-integer", - "lexical-util", - "lexical-write-float", - "lexical-write-integer", -] - -[[package]] -name = "lexical-parse-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "683b3a5ebd0130b8fb52ba0bdc718cc56815b6a097e28ae5a6997d0ad17dc05f" -dependencies = [ - "lexical-parse-integer", - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-parse-integer" -version = "0.8.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d0994485ed0c312f6d965766754ea177d07f9c00c9b82a5ee62ed5b47945ee9" -dependencies = [ - "lexical-util", - "static_assertions", -] - -[[package]] -name = "lexical-util" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5255b9ff16ff898710eb9eb63cb39248ea8a5bb036bea8085b1a767ff6c4e3fc" -dependencies = [ - "static_assertions", -] - -[[package]] -name = "lexical-write-float" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "accabaa1c4581f05a3923d1b4cfd124c329352288b7b9da09e766b0668116862" -dependencies = [ - "lexical-util", - "lexical-write-integer", - "static_assertions", -] - -[[package]] -name = "lexical-write-integer" -version = "0.8.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1b6f3d1f4422866b68192d62f77bc5c700bee84f3069f2469d7bc8c77852446" -dependencies = [ - "lexical-util", - "static_assertions", -] - [[package]] name = "libc" version = "0.2.137" @@ -3296,12 +2963,6 @@ dependencies = [ "jni-sys", ] -[[package]] -name = "new_debug_unreachable" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e4a24736216ec316047a1fc4252e27dabb04218aa4a3f37c6e7ddbf1f9782b54" - [[package]] name = "nix" version = "0.22.3" @@ -3389,18 +3050,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "num-bigint" -version = "0.4.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f93ab6289c7b344a8a9f60f88d80aa20032336fe78da341afc91c8a2341fc75f" -dependencies = [ - "autocfg", - "num-integer", - "num-traits", - "serde", -] - [[package]] name = "num-derive" version = "0.3.3" @@ -3671,7 +3320,7 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "03c64931a1a212348ec4f3b4362585eca7159d0d09cbdf4a7f74f02173596fd4" dependencies = [ - "base64 0.13.1", + "base64", ] [[package]] @@ -3700,74 +3349,30 @@ dependencies = [ ] [[package]] -name = "phf" -version = "0.10.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fabbf1ead8a5bcbc20f5f8b939ee3f5b0f6f281b6ad3468b84656b658b455259" -dependencies = [ - "phf_macros", - "phf_shared", - "proc-macro-hack", -] - -[[package]] -name = "phf_generator" -version = "0.10.0" +name = "pin-project" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5d5285893bb5eb82e6aaf5d59ee909a06a16737a8970984dd7746ba9283498d6" +checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" dependencies = [ - "phf_shared", - "rand", + "pin-project-internal", ] [[package]] -name = "phf_macros" -version = "0.10.0" +name = "pin-project-internal" +version = "1.0.12" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fdf3184dd560f160dd73922bea2d5cd6e8f064bf4b13110abd81b03697b4e0" +checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro-hack", "proc-macro2", "quote", "syn", ] [[package]] -name = "phf_shared" -version = "0.10.0" +name = "pin-project-lite" +version = "0.2.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b6796ad771acdc0123d2a88dc428b5e38ef24456743ddb1744ed628f9815c096" -dependencies = [ - "siphasher 0.3.10", -] - -[[package]] -name = "pin-project" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ad29a609b6bcd67fee905812e544992d216af9d755757c05ed2d0e15a74c6ecc" -dependencies = [ - "pin-project-internal", -] - -[[package]] -name = "pin-project-internal" -version = "1.0.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "069bdb1e05adc7a8990dce9cc75370895fbe4e3d58b9b73bf1aee56359344a55" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "pin-project-lite" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" +checksum = "e0a7ae3ac2f1173085d398531c705756c94a4c56843785df85a60c1a0afac116" [[package]] name = "pin-utils" @@ -3781,17 +3386,6 @@ version = "0.3.26" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "6ac9a59f73473f1b8d852421e59e64809f025994837ef743615c6d0c5b305160" -[[package]] -name = "pmutil" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3894e5d549cccbe44afecf72922f277f603cd4bb0219c8342631ef18fffbe004" -dependencies = [ - "proc-macro2", - "quote", - "syn", -] - [[package]] name = "png" version = "0.16.8" @@ -3830,12 +3424,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "pollster" -version = "0.2.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5da3b0203fd7ee5720aa0b5e790b591aa5d3f41c3ed2c34a3a393382198af2f7" - [[package]] name = "postcard" version = "1.0.2" @@ -3870,12 +3458,6 @@ version = "0.2.17" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5b40af805b3121feab8a3c29f04d8ad262fa8e0561883e7653e024ae4479e6de" -[[package]] -name = "precomputed-hash" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "925383efa346730478fb4838dbe9137d2a47675ad789c546d150a6e1dd4ab31c" - [[package]] name = "pretty-type-name" version = "1.0.0" @@ -3917,12 +3499,6 @@ dependencies = [ "version_check", ] -[[package]] -name = "proc-macro-hack" -version = "0.5.19" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dbf0c48bc1d91375ae5c3cd81e3722dff1abcf81a30960240640d223f59fe0e5" - [[package]] name = "proc-macro2" version = "1.0.47" @@ -4163,7 +3739,7 @@ version = "0.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88073939a61e5b7680558e6be56b419e208420c2adb92be54921fa6b72283f1a" dependencies = [ - "base64 0.13.1", + "base64", "bitflags", "serde", ] @@ -4180,24 +3756,6 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2" -[[package]] -name = "rustc_version" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "138e3e0acb6c9fb258b19b67cb8abd63c00679d2851805ea151465464fe9030a" -dependencies = [ - "semver 0.9.0", -] - -[[package]] -name = "rustc_version" -version = "0.4.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bfa0f585226d2e68097d4f95d113b15b83a82e819ab25717ec0590d9584ef366" -dependencies = [ - "semver 1.0.14", -] - [[package]] name = "rustls" version = "0.20.7" @@ -4228,7 +3786,7 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0864aeff53f8c05aa08d86e5ef839d3dfcf07aeba2db32f12db0ef716e87bd55" dependencies = [ - "base64 0.13.1", + "base64", ] [[package]] @@ -4276,12 +3834,6 @@ dependencies = [ "windows-sys 0.36.1", ] -[[package]] -name = "scoped-tls" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e1cf6437eb19a8f4a6cc0f7dca544973b0b78843adbfeb3683d1a94a0024a294" - [[package]] name = "scopeguard" version = "1.1.0" @@ -4327,27 +3879,6 @@ version = "0.10.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1ef965a420fe14fdac7dd018862966a4c14094f900e1650bbc71ddd7d580c8af" -[[package]] -name = "semver" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1d7eb9ef2c18661902cc47e535f9bc51b78acd254da71d375c2f6720d9a40403" -dependencies = [ - "semver-parser", -] - -[[package]] -name = "semver" -version = "1.0.14" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e25dfac463d778e353db5be2449d1cce89bd6fd23c9f1ea21310ce6e5a1b29c4" - -[[package]] -name = "semver-parser" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "388a1df253eca08550bef6c72392cfe7c30914bf41df5269b68cbd6ff8f570a3" - [[package]] name = "serde" version = "1.0.147" @@ -4357,26 +3888,6 @@ dependencies = [ "serde_derive", ] -[[package]] -name = "serde-wasm-bindgen" -version = "0.4.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e3b4c031cd0d9014307d82b8abf653c0290fbdaeb4c02d00c63cf52f728628bf" -dependencies = [ - "js-sys", - "serde", - "wasm-bindgen", -] - -[[package]] -name = "serde_bytes" -version = "0.11.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cfc50e8183eeeb6178dcb167ae34a8051d63535023ae38b5d8d12beae193d37b" -dependencies = [ - "serde", -] - [[package]] name = "serde_derive" version = "1.0.147" @@ -4390,30 +3901,15 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.88" +version = "1.0.89" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8e8b3801309262e8184d9687fb697586833e939767aea0dda89f5a8e650e8bd7" +checksum = "020ff22c755c2ed3f8cf162dbb41a7268d934702f3ed3631656ea597e08fc3db" dependencies = [ - "indexmap", "itoa", "ryu", "serde", ] -[[package]] -name = "serde_v8" -version = "0.57.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b3c3efa9cff97d5a543df0508c37af619e422fb92eb525f38d255d46df7a0eb7" -dependencies = [ - "bytes", - "derive_more", - "serde", - "serde_bytes", - "smallvec", - "v8", -] - [[package]] name = "serde_yaml" version = "0.9.14" @@ -4427,17 +3923,6 @@ dependencies = [ "unsafe-libyaml", ] -[[package]] -name = "sha-1" -version = "0.10.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "028f48d513f9678cda28f6e4064755b3fbb2af6acd672f2c209b62323f7aea0f" -dependencies = [ - "cfg-if 1.0.0", - "cpufeatures", - "digest", -] - [[package]] name = "sha1_smol" version = "1.0.0" @@ -4474,12 +3959,6 @@ version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -[[package]] -name = "siphasher" -version = "0.3.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7bd3e3206899af3f8b12af284fafc038cc1dc2b41d1b89dd17297221c5d225de" - [[package]] name = "slab" version = "0.4.7" @@ -4495,7 +3974,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e1e08e261d0e8f5c43123b7adf3e4ca1690d655377ac93a03b2c9d3e98de1342" dependencies = [ - "serde", "version_check", ] @@ -4518,22 +3996,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "sourcemap" -version = "6.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6e031f2463ecbdd5f34c950f89f5c1e1032f22c0f8e3dc4bdb2e8b6658cf61eb" -dependencies = [ - "base64 0.11.0", - "if_chain", - "lazy_static", - "regex", - "rustc_version 0.2.3", - "serde", - "serde_json", - "url", -] - [[package]] name = "spin" version = "0.5.2" @@ -4550,18 +4012,6 @@ dependencies = [ "num-traits", ] -[[package]] -name = "stable_deref_trait" -version = "1.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" - -[[package]] -name = "static_assertions" -version = "1.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" - [[package]] name = "stdweb" version = "0.1.3" @@ -4574,45 +4024,6 @@ version = "1.0.6" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9e08d8363704e6c71fc928674353e6b7c23dcea9d82d7012c8faf2a3a025f8d0" -[[package]] -name = "string_cache" -version = "0.8.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213494b7a2b503146286049378ce02b482200519accc31872ee8be91fa820a08" -dependencies = [ - "new_debug_unreachable", - "once_cell", - "parking_lot 0.12.1", - "phf_shared", - "precomputed-hash", - "serde", -] - -[[package]] -name = "string_cache_codegen" -version = "0.5.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6bb30289b722be4ff74a408c3cc27edeaad656e06cb1fe8fa9231fa59c728988" -dependencies = [ - "phf_generator", - "phf_shared", - "proc-macro2", - "quote", -] - -[[package]] -name = "string_enum" -version = "0.3.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "994453cd270ad0265796eb24abf5540091ed03e681c5f3c12bc33e4db33253e1" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - [[package]] name = "strsim" version = "0.10.0" @@ -4632,297 +4043,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c536faaff1a10837cfe373142583f6e27d81e96beba339147e77b67c9f260ff" dependencies = [ "float-cmp", - "siphasher 0.2.3", -] - -[[package]] -name = "swc_atoms" -version = "0.4.25" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "63b8033a868fbebf5829797ac0c543499622b657e2d33a08ca6ab12547b8bafc" -dependencies = [ - "once_cell", - "rustc-hash", - "serde", - "string_cache", - "string_cache_codegen", - "triomphe", -] - -[[package]] -name = "swc_common" -version = "0.27.16" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "49b0b6107e44797d0549bdb5b47a97682c3b914140269c01d2acdb16a1b885f6" -dependencies = [ - "ahash 0.7.6", - "ast_node", - "better_scoped_tls", - "cfg-if 1.0.0", - "debug_unreachable", - "either", - "from_variant", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "siphasher 0.3.10", - "string_cache", - "swc_atoms", - "swc_eq_ignore_macros", - "swc_visit", - "tracing", - "unicode-width", - "url", -] - -[[package]] -name = "swc_config" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4de36224eb9498fccd4e68971f0b83326ccf8592c2d424f257f3a1c76b2b211" -dependencies = [ - "indexmap", - "serde", - "serde_json", - "swc_config_macro", -] - -[[package]] -name = "swc_config_macro" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb64bc03d90fd5c90d6ab917bb2b1d7fbd31957df39e31ea24a3f554b4372251" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_ast" -version = "0.90.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f712949db06518bec7b7e050aa3bcde749a74fbf79f4f520ab179d0445b63593" -dependencies = [ - "bitflags", - "is-macro", - "num-bigint", - "scoped-tls", - "serde", - "string_enum", - "swc_atoms", - "swc_common", - "unicode-id", -] - -[[package]] -name = "swc_ecma_codegen" -version = "0.121.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fa47424bed05de6077eda3271d6764f87c2735a8f3798dea23c95898e5e0deb" -dependencies = [ - "memchr", - "num-bigint", - "once_cell", - "rustc-hash", - "serde", - "sourcemap", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_codegen_macros", - "tracing", -] - -[[package]] -name = "swc_ecma_codegen_macros" -version = "0.7.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0159c99f81f52e48fe692ef7af1b0990b45d3006b14c6629be0b1ffee1b23aea" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_parser" -version = "0.117.7" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d88ffca99514bc8bfa8bf4f2d74fb673caa844e521b55035b8cfd10472b801d4" -dependencies = [ - "either", - "enum_kind", - "lexical", - "num-bigint", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "tracing", - "typed-arena", -] - -[[package]] -name = "swc_ecma_transforms_base" -version = "0.103.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4aad7af4a1ae307e547a0f5ab6b081ffa6a22af89abe2f8a953a735a398ba9d" -dependencies = [ - "better_scoped_tls", - "bitflags", - "num_cpus", - "once_cell", - "phf", - "rustc-hash", - "serde", - "smallvec", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_utils", - "swc_ecma_visit", - "tracing", -] - -[[package]] -name = "swc_ecma_transforms_macros" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ebf907935ec5492256b523ae7935a824d9fdc0368dcadc41375bad0dca91cd8b" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", -] - -[[package]] -name = "swc_ecma_transforms_react" -version = "0.141.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b57461fea819904faf5aeac39e49229995701a31fa5041929b7909885a69cc0a" -dependencies = [ - "ahash 0.7.6", - "base64 0.13.1", - "dashmap", - "indexmap", - "once_cell", - "regex", - "serde", - "sha-1", - "string_enum", - "swc_atoms", - "swc_common", - "swc_config", - "swc_ecma_ast", - "swc_ecma_parser", - "swc_ecma_transforms_base", - "swc_ecma_transforms_macros", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_transforms_typescript" -version = "0.145.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ecc0cba6d14b04900e5068d69c7492149c4e9320a9fcf79fca0e7224811c1d14" -dependencies = [ - "serde", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_transforms_base", - "swc_ecma_transforms_react", - "swc_ecma_utils", - "swc_ecma_visit", -] - -[[package]] -name = "swc_ecma_utils" -version = "0.99.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d92cff624945ded0b2bb07e9dfb44d57745abcc415b6025c6c3d2dc3a7af5396" -dependencies = [ - "indexmap", - "once_cell", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_ecma_visit", - "tracing", - "unicode-id", -] - -[[package]] -name = "swc_ecma_visit" -version = "0.76.10" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7da9fbd418ce4dc3c7b10e74a919ecc6f56c376d63a6a03766655c6c2283475d" -dependencies = [ - "num-bigint", - "swc_atoms", - "swc_common", - "swc_ecma_ast", - "swc_visit", - "tracing", -] - -[[package]] -name = "swc_eq_ignore_macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0c20468634668c2bbab581947bb8c75c97158d5a6959f4ba33df20983b20b4f6" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_macros_common" -version = "0.3.6" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a4be988307882648d9bc7c71a6a73322b7520ef0211e920489a98f8391d8caa2" -dependencies = [ - "pmutil", - "proc-macro2", - "quote", - "syn", -] - -[[package]] -name = "swc_visit" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "82f2bcb7223e185c4c7cbf5e0c1207dec6d2bfd5e72e3fb7b3e8d179747e9130" -dependencies = [ - "either", - "swc_visit_macros", -] - -[[package]] -name = "swc_visit_macros" -version = "0.5.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8fb1f3561674d84947694d41fb6d5737d19539222779baeac1b3a071a2b29428" -dependencies = [ - "Inflector", - "pmutil", - "proc-macro2", - "quote", - "swc_macros_common", - "syn", + "siphasher", ] [[package]] @@ -5247,16 +4368,6 @@ dependencies = [ "wasm-bindgen", ] -[[package]] -name = "triomphe" -version = "0.1.8" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f1ee9bd9239c339d714d657fac840c6d2a4f9c45f4f9ec7b0975113458be78db" -dependencies = [ - "serde", - "stable_deref_trait", -] - [[package]] name = "ttf-parser" version = "0.17.1" @@ -5283,21 +4394,6 @@ dependencies = [ "rustc-hash", ] -[[package]] -name = "type-map" -version = "0.5.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "deb68604048ff8fa93347f02441e4487594adc20bb8a084f9e564d2b827a0a9f" -dependencies = [ - "rustc-hash", -] - -[[package]] -name = "typed-arena" -version = "2.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0685c84d5d54d1c26f7d3eb96cd41550adb97baed141a761cf335d3d33bcd0ae" - [[package]] name = "typenum" version = "1.15.0" @@ -5339,12 +4435,6 @@ version = "0.3.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "099b7128301d285f79ddd55b9a83d5e6b9e97c92e0ea0daebee7263e932de992" -[[package]] -name = "unicode-id" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d70b6494226b36008c8366c288d77190b3fad2eb4c10533139c1c1f461127f1a" - [[package]] name = "unicode-ident" version = "1.0.5" @@ -5372,15 +4462,6 @@ version = "0.2.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f962df74c8c05a667b5ee8bcf162993134c104e96440b663c8daa176dc772d8c" -[[package]] -name = "unreachable" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1f2ae5ddb18e1c92664717616dd9549dde73f539f01bd7b77c2edb2446bdff91" -dependencies = [ - "void", -] - [[package]] name = "unsafe-libyaml" version = "0.2.4" @@ -5402,7 +4483,6 @@ dependencies = [ "form_urlencoded", "idna", "percent-encoding", - "serde", ] [[package]] @@ -5416,19 +4496,6 @@ dependencies = [ "sha1_smol", ] -[[package]] -name = "v8" -version = "0.47.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "be156dece7a023d5959a72dc0d398d6c95100ec601a2cea10d868da143e85166" -dependencies = [ - "bitflags", - "fslock", - "lazy_static", - "libc", - "which", -] - [[package]] name = "valuable" version = "0.1.0" @@ -5453,12 +4520,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "void" -version = "1.0.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6a02e4885ed3bc0f2de90ea6dd45ebcbb66dacffe03547fadbb0eeae2770887d" - [[package]] name = "waker-fn" version = "1.1.0" @@ -5548,15 +4609,6 @@ version = "0.2.83" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1c38c045535d93ec4f0b4defec448e4291638ee608530863b1e2ba115d4fff7f" -[[package]] -name = "wasm_mutex" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "efbdddc3b163fc2d639800b3411a5428d1e151ba2a400a560b1545e39f1e68cd" -dependencies = [ - "serde", -] - [[package]] name = "web-sys" version = "0.3.60" @@ -5616,7 +4668,7 @@ dependencies = [ "js-sys", "log", "naga", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "raw-window-handle", "smallvec", "wasm-bindgen", @@ -5642,7 +4694,7 @@ dependencies = [ "fxhash", "log", "naga", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "raw-window-handle", "smallvec", @@ -5679,7 +4731,7 @@ dependencies = [ "metal", "naga", "objc", - "parking_lot 0.11.2", + "parking_lot 0.12.1", "profiling", "range-alloc", "raw-window-handle", @@ -5700,17 +4752,6 @@ dependencies = [ "bitflags", ] -[[package]] -name = "which" -version = "4.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c831fbbee9e129a8cf93e7747a82da9d95ba8e16621cae60ec2cdc849bacb7b" -dependencies = [ - "either", - "libc", - "once_cell", -] - [[package]] name = "widestring" version = "0.5.1" diff --git a/Cargo.toml b/Cargo.toml index b45225b1ae..7af5685346 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -36,7 +36,7 @@ bevy_egui = "0.16.1" bevy_fluent = "0.4.0" bevy_ggrs = { git = "https://github.com/zicklag/bevy_ggrs.git", branch = "jumpy" } bevy_kira_audio = { version = "0.12.0", features = ["ogg"], default-features = false } -bevy_mod_js_scripting = { git = "https://github.com/zicklag/bevy_mod_js_scripting.git", branch = "jumpy" } +# bevy_mod_js_scripting = { git = "https://github.com/zicklag/bevy_mod_js_scripting.git", branch = "jumpy" } bevy_prototype_lyon = "0.6.0" bevy_tweening = { version = "0.5", default-features = false } bitfield = "0.14.0" @@ -69,6 +69,7 @@ thiserror = "1.0.31" tracing = { version = "0.1.37", features = ["release_max_level_debug"] } turborand = { version = "0.8.0", features = ["atomic", "serialize"] } unic-langid = "0.9.0" +serde_json = "1.0.89" [dependencies.bevy] version = "0.8" diff --git a/assets/default.game.yaml b/assets/default.game.yaml index d68516142c..4e93003ccb 100644 --- a/assets/default.game.yaml +++ b/assets/default.game.yaml @@ -45,10 +45,6 @@ playlist: - music/krill_or_be_krilled.ogg - music/whale_theme.ogg -scripts: - - map/scripts/kill_out_of_bounds.ts - - ui/menu-background-zoom.ts - main_menu: title_font: family: fairfax diff --git a/assets/game/camera_controller.ts b/assets/game/camera_controller.ts deleted file mode 100644 index bc791740c6..0000000000 --- a/assets/game/camera_controller.ts +++ /dev/null @@ -1,46 +0,0 @@ -const lerpFactor = 0.1; - -export default { - postUpdateInGame() { - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) return; - - const playerComponents = world - .query(PlayerIdx, Transform) - .map((x) => x.components); - - const [_, cameraTransform, projection] = world.query( - GameCamera, - Transform, - OrthographicProjection - )[0].components; - - let middlePoint = { x: 0, y: 0 }; - let min = { x: 100000, y: 100000 }; - let max = { x: -100000, y: -100000 }; - - const player_count = playerComponents.length; - - for (const [_, playerTransform] of playerComponents) { - const playerPos = playerTransform.translation; - middlePoint.x += playerPos.x; - middlePoint.y += playerPos.y; - - min.x = Math.min(playerPos.x, min.x); - min.y = Math.min(playerPos.y, min.y); - max.x = Math.max(playerPos.x, max.x); - max.y = Math.max(playerPos.y, max.y); - } - - middlePoint.x /= Math.max(player_count, 1); - middlePoint.y /= Math.max(player_count, 1); - - for (const dim of ["x", "y"]) { - let delta = cameraTransform.translation[dim] - middlePoint[dim]; - let dist = delta * lerpFactor; - cameraTransform.translation[dim] -= dist; - } - - projection.scale = 1.25; - }, -}; diff --git a/assets/map/elements/decoration/anemones/anemones.ts b/assets/map/elements/decoration/anemones/anemones.ts deleted file mode 100644 index b1e20e89b8..0000000000 --- a/assets/map/elements/decoration/anemones/anemones.ts +++ /dev/null @@ -1,18 +0,0 @@ -export default { - preUpdate() { - for (const entity of MapElement.getSpawnedEntities()) { - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 4, - repeat: true, - fps: 6, - atlas: { - id: Assets.getHandleId("./anemones.atlas.yaml"), - }, - }) - ); - } - }, -}; diff --git a/assets/map/elements/decoration/seaweed/seaweed.ts b/assets/map/elements/decoration/seaweed/seaweed.ts deleted file mode 100644 index 87829d1b9f..0000000000 --- a/assets/map/elements/decoration/seaweed/seaweed.ts +++ /dev/null @@ -1,17 +0,0 @@ -export default { - preUpdate() { - for (const entity of MapElement.getSpawnedEntities()) { - let animated_sprite = Value.create(AnimatedSprite, { - start: 0, - end: 4, - repeat: true, - fps: 6, - atlas: { - id: Assets.getHandleId("./seaweed.atlas.yaml"), - }, - }); - - world.insert(entity, animated_sprite); - } - }, -}; diff --git a/assets/map/elements/environment/crab/crab.element.yaml b/assets/map/elements/environment/crab/crab.element.yaml index 8e818d5ea9..8a1e147d23 100644 --- a/assets/map/elements/environment/crab/crab.element.yaml +++ b/assets/map/elements/environment/crab/crab.element.yaml @@ -1,7 +1,5 @@ name: Crab category: Critters -scripts: - # - ./crab.ts editor_size: [17, 12] preload_assets: - ./crab.atlas.yaml diff --git a/assets/map/elements/environment/crab/crab.ts b/assets/map/elements/environment/crab/crab.ts deleted file mode 100644 index 9b0448186a..0000000000 --- a/assets/map/elements/environment/crab/crab.ts +++ /dev/null @@ -1,84 +0,0 @@ -const MapMeta: BevyType = { - typeName: "jumpy::metadata::map::MapMeta", -}; - -let i = 0; - -const CRABS = "crabs"; - -export default { - preUpdateInGame() { - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) { - Script.clearEntityList(CRABS); - return; - } - - const spawnedEntities = MapElement.getSpawnedEntities(); - if (spawnedEntities.length > 0) { - Script.clearEntityList(CRABS); - } - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the crab and copy the transform and visibility from the map element - const entity = WorldTemp.spawn(); - Script.addEntityToList(CRABS, entity); - - world.insert(entity, Value.create(EntityName, ["Critter: Crab"])); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 1, - repeat: true, - fps: 3, - atlas: { - id: Assets.getHandleId("crab.atlas.yaml"), - }, - }) - ); - - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 18, - y: 12, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - }, - - updateInGame() { - i++; - const query = world.query(KinematicBody); - - for (const crab of Script.getEntityList(CRABS)) { - const components = query.get(crab); - if (!components) continue; - const [kinematicBody] = components; - - if (i % 100 == 0) { - i = 0; - kinematicBody.velocity.x = - Random.gen() * 3 * (Random.gen() >= 0.5 ? -1 : 1); - } - } - }, -}; diff --git a/assets/map/elements/environment/fish_school/fish_school.element.yaml b/assets/map/elements/environment/fish_school/fish_school.element.yaml index b40f5763aa..7a1fee617d 100644 --- a/assets/map/elements/environment/fish_school/fish_school.element.yaml +++ b/assets/map/elements/environment/fish_school/fish_school.element.yaml @@ -1,4 +1,2 @@ name: Fish School category: Critters -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/environment/fish_school/sproinger.ts b/assets/map/elements/environment/fish_school/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/environment/fish_school/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/environment/player_spawner/player_spawner.ts b/assets/map/elements/environment/player_spawner/player_spawner.ts deleted file mode 100644 index 27fc1e6255..0000000000 --- a/assets/map/elements/environment/player_spawner/player_spawner.ts +++ /dev/null @@ -1,52 +0,0 @@ -const initState: { currentSpawner: number } = { - currentSpawner: 0, -}; - -const state = Script.state(initState); - -export default { - preUpdate() { - const player_inputs = world.resource(PlayerInputs); - - const mapQuery = world.query(MapMeta)[0]; - if (!mapQuery) { - Script.clearEntityList("playerSpawners"); - return; - } - - const spawnedEntities = MapElement.getSpawnedEntities(); - if (spawnedEntities.length > 0) { - spawnedEntities.forEach((e) => - Script.addEntityToList("playerSpawners", e) - ); - } - - // Collect all the alive players on the map - const alive_players = world.query(PlayerIdx).map((x) => x.components[0][0]); - - // For every player - for (let i = 0; i < 4; i++) { - // Get the player input - const player = player_inputs.players[i]; - - const spawners = Script.getEntityList("playerSpawners"); - - // If the player is active, but not alive - if (player.active && !alive_players.includes(i)) { - // Get the next spawner - state.currentSpawner += 1; - state.currentSpawner %= spawners.length; - - const spawner = spawners[state.currentSpawner]; - - // Get the spawner transform - const [spawnerTransform] = world.query(Transform).get(spawner); - - // Spawn the player - const player = WorldTemp.spawn(); - world.insert(player, Value.create(PlayerIdx, [i])); - world.insert(player, spawnerTransform); - } - } - }, -}; diff --git a/assets/map/elements/environment/sproinger/jump.ogg b/assets/map/elements/environment/sproinger/jump.ogg new file mode 100644 index 0000000000..fdf1988baf Binary files /dev/null and b/assets/map/elements/environment/sproinger/jump.ogg differ diff --git a/assets/map/elements/environment/sproinger/sproinger.element.yaml b/assets/map/elements/environment/sproinger/sproinger.element.yaml index 65ea0d519e..476cf2c43c 100644 --- a/assets/map/elements/environment/sproinger/sproinger.element.yaml +++ b/assets/map/elements/environment/sproinger/sproinger.element.yaml @@ -1,4 +1,5 @@ name: Sproinger category: Gameplay builtin: !Sproinger - atlas: ./sproinger.atlas.yaml \ No newline at end of file + atlas: ./sproinger.atlas.yaml + sound: ./jump.ogg \ No newline at end of file diff --git a/assets/map/elements/environment/sproinger/sproinger.ts b/assets/map/elements/environment/sproinger/sproinger.ts deleted file mode 100644 index 10d48d3650..0000000000 --- a/assets/map/elements/environment/sproinger/sproinger.ts +++ /dev/null @@ -1,124 +0,0 @@ -// Define the sproinger state types -type SproingerState = { - sproinging: boolean; - frame: number; -}; - -// Add our constants -const FORCE = 25; - -export default { - preUpdateInGame() { - // Check for the existence of the map - const map = world.query(MapMeta)[0]; - // If there is no map - if (!map) { - // clear our sproinger list - Script.clearEntityList("sproingers"); - return; - } - - // Get the list of spawned entities - const spawnedEntities = MapElement.getSpawnedEntities(); - // If there are spawned entities, that means the map was loaded or reloaded. - if (spawnedEntities.length > 0) { - // So clear our sproinger list - Script.clearEntityList("sproingers"); - } - - // For every new sproinger entity - for (const entity of spawnedEntities) { - // Add this entity to our list of sproingers. - // - // Note: Because we cannot persist entity refs across frames, - // we must first convert the entity to a JSON representation. - Script.addEntityToList("sproingers", entity); - - // Add the sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 6, - repeat: false, - fps: 0, - atlas: { - id: Assets.getHandleId("./sproinger.atlas.yaml"), - }, - }) - ); - // And the physics body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 32, - y: 8, - }, - offset: { - y: -6, - }, - has_mass: false, - }) - ); - } - }, - - updateInGame() { - const bodies = world.query(KinematicBody); - const animatedSprites = world.query(AnimatedSprite); - - // Loop over all our sproingers - for (const entity of Script.getEntityList("sproingers")) { - // Get our sproinger sprite - const [sprite] = animatedSprites.get(entity); - - // Get the script-local state for the sproinger entity - const entState = Script.getEntityState(entity, { - frame: 0, - sproinging: false, - }); - - // If the sproinger is currently sproinging - if (entState.sproinging) { - // Play the sproinging animation - switch (entState.frame) { - case 0: - sprite.index = 2; - break; - case 4: - sprite.index = 3; - break; - case 8: - sprite.index = 4; - break; - case 12: - sprite.index = 5; - break; - case 20: - sprite.index = 0; - entState.sproinging = false; - entState.frame = 0; - break; - } - entState.frame += 1; - } - - // See if the spoinger has any collisions - for (const collidedEntity of CollisionWorld.actorCollisions(entity)) { - // Get the kinematic body of the collided entity - const components = bodies.get(collidedEntity); - if (!components) continue; - const [body] = components; - - if (!entState.sproinging) { - // Apply the sproing force to the body - body.velocity.y = FORCE; - - // Go into a sproinging state - entState.sproinging = true; - } - } - } - }, -}; diff --git a/assets/map/elements/item/blunderbass/blunderbass.element.yaml b/assets/map/elements/item/blunderbass/blunderbass.element.yaml index 8f6760fb95..a55bd88c21 100644 --- a/assets/map/elements/item/blunderbass/blunderbass.element.yaml +++ b/assets/map/elements/item/blunderbass/blunderbass.element.yaml @@ -1,4 +1,2 @@ name: Blunderbass category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/blunderbass/sproinger.ts b/assets/map/elements/item/blunderbass/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/blunderbass/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/cannon/cannon.element.yaml b/assets/map/elements/item/cannon/cannon.element.yaml index ee74a4a546..67ff6b53e0 100644 --- a/assets/map/elements/item/cannon/cannon.element.yaml +++ b/assets/map/elements/item/cannon/cannon.element.yaml @@ -1,4 +1,2 @@ name: Canon category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/cannon/sproinger.ts b/assets/map/elements/item/cannon/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/cannon/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/crate/crate.element.yaml b/assets/map/elements/item/crate/crate.element.yaml index 5db25a2c33..1f875fb200 100644 --- a/assets/map/elements/item/crate/crate.element.yaml +++ b/assets/map/elements/item/crate/crate.element.yaml @@ -1,4 +1,2 @@ name: Crate category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/crate/sproinger.ts b/assets/map/elements/item/crate/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/crate/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/grenade/explosion.ogg b/assets/map/elements/item/grenade/explosion.ogg new file mode 100755 index 0000000000..95bc9aeb74 Binary files /dev/null and b/assets/map/elements/item/grenade/explosion.ogg differ diff --git a/assets/map/elements/item/grenade/grenade.element.yaml b/assets/map/elements/item/grenade/grenade.element.yaml index a09fccc9a2..9bc6dddcbf 100644 --- a/assets/map/elements/item/grenade/grenade.element.yaml +++ b/assets/map/elements/item/grenade/grenade.element.yaml @@ -10,6 +10,7 @@ builtin: !Grenades explosion_lifetime: 1.0 explosion_frames: 12 explosion_fps: 8 + explosion_sound: ./explosion.ogg body_size: [18, 18] grab_offset: [-7, -6] diff --git a/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml b/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml index 9d92f99c02..1eb4dfe297 100644 --- a/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml +++ b/assets/map/elements/item/kick_bomb/kick_bomb.element.yaml @@ -1,8 +1,5 @@ name: Kick Bomb category: Weapons -scripts: - # - ./kick_bomb_spawner.ts - # - ./kick_bomb.ts preload_assets: - ./kick_bomb.atlas.yaml - - ./explosion.atlas.yaml \ No newline at end of file + - ./explosion.atlas.yaml diff --git a/assets/map/elements/item/kick_bomb/kick_bomb.ts b/assets/map/elements/item/kick_bomb/kick_bomb.ts deleted file mode 100644 index 4911b17ca9..0000000000 --- a/assets/map/elements/item/kick_bomb/kick_bomb.ts +++ /dev/null @@ -1,267 +0,0 @@ -const scriptPath = Script.getInfo().path; - -type LitBombState = { - frames: number; -}; - -const LIT_BOMBS = "kickBombsLit"; - -export default { - preUpdateInGame() { - // Hydrate newly spawned sword items - const names = world.query(EntityName); - const items = world.query(Item); - for (const { entity, components } of items) { - const [item] = components; - - // If this is one of our items without a name - if (item.script == scriptPath && !names.get(entity)) { - // Hydrate the entity - world.insert(entity, Value.create(EntityName, ["Item: Kick Bomb"])); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 5, - repeat: false, - fps: 0, - atlas: { - id: Assets.getHandleId("kick_bomb.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 26, - y: 26, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - }, - - updateInGame() { - const players = world.query( - AnimatedSprite, - Transform, - KinematicBody, - PlayerIdx, - GlobalTransform, - ComputedVisibility - ); - const parents = world.query(Parent); - const items = world.query( - Item, - Transform, - KinematicBody, - AnimatedSprite, - GlobalTransform - ); - const transforms = world.query( - Transform, - GlobalTransform, - Visibility, - ComputedVisibility - ); - const usedItems = world.query(ItemUsed); - const droppedItems = world.query(ItemDropped); - - // Update items that are being held - // - // This section will make the item follow the player around and match the player's facing - // direction. - for (const { entity: itemEnt, components } of items) { - const [item, itemTransform, body, sprite] = components; - if (item.script != scriptPath) continue; - - let parentComponents = parents.get(itemEnt); - // If this item isn't being held, skip the item - if (!parentComponents) continue; - - const [parent] = parentComponents; - const [playerSprite] = players.get(parent[0]); - - // Deactivate item collision - body.is_deactivated = true; - - // Set animation to default position if we are being held - sprite.index = 0; - - // Flip the sprite to match our player orientation - const flip = playerSprite.flip_x; - sprite.flip_x = flip; - const flipFactor = flip ? -1 : 1; - // Align the sprite with the player's position - itemTransform.translation = Value.create(Vec3, { - x: 13 * flipFactor, - y: 0, - }); - - // For every item that is being used - if (!!usedItems.get(itemEnt)) { - // Get the player info - const [parent] = parentComponents; - const playerEnt = parent[0]; - const [ - playerSprite, - transform, - _body, - _idx, - globalTransform, - computedVisibility, - ] = players.get(playerEnt); - const flip = playerSprite.flip_x; - const flipFactor = flip ? -1 : 1; - - // Despawn the item from the player's hand - Player.setInventory(playerEnt, null); - // WorldTemp.despawnRecursive(itemEnt); - - // Spawn a new, lit bomb to the map - const entity = WorldTemp.spawn(); - Script.addEntityToList(LIT_BOMBS, entity); - world.insert(entity, Value.create(EntityName, ["Kick Bomb ( Lit )"])); - world.insert(entity, transform); - world.insert(entity, globalTransform); - world.insert(entity, computedVisibility); - world.insert(entity, Value.create(Visibility)); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 3, - end: 5, - repeat: true, - fps: 8, - atlas: { - id: Assets.getHandleId("kick_bomb.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 26, - y: 26, - }, - velocity: { - x: 10 * flipFactor, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - - // Handle lit bombs - const litBombs = Script.getEntityList(LIT_BOMBS); - Script.clearEntityList(LIT_BOMBS); - for (const bombEntity of litBombs) { - // Get the bomb's state - const state = Script.getEntityState(bombEntity, { - frames: 0, - }); - const [transform, globalTransform, visibility, computedVisibility] = - transforms.get(bombEntity); - - if (state.frames >= 60) { - // Spawn damage region entity - const damageRegionEnt = WorldTemp.spawn(); - world.insert(damageRegionEnt, transform); - world.insert(damageRegionEnt, globalTransform); - world.insert(damageRegionEnt, visibility); - world.insert(damageRegionEnt, computedVisibility); - world.insert( - damageRegionEnt, - Value.create(DamageRegion, { - size: { - x: 26 * 3.5, - y: 26 * 3.5, - }, - }) - ); - world.insert( - damageRegionEnt, - Value.create(Lifetime, { - lifetime: (1 / 9) * 4, - }) - ); - // Spawn explosion sprite entity - const explosionSpriteEnt = WorldTemp.spawn(); - world.insert(explosionSpriteEnt, transform); - world.insert(explosionSpriteEnt, globalTransform); - world.insert(explosionSpriteEnt, visibility); - world.insert(explosionSpriteEnt, computedVisibility); - world.insert( - explosionSpriteEnt, - Value.create(AnimatedSprite, { - start: 0, - end: 11, - repeat: false, - fps: 9, - atlas: { - id: Assets.getHandleId("explosion.atlas.yaml"), - }, - }) - ); - world.insert( - explosionSpriteEnt, - Value.create(Lifetime, { - lifetime: (1 / 9) * 11, - }) - ); - - // Despawn the lit bomb - WorldTemp.despawnRecursive(bombEntity); - } else { - state.frames += 1; - Script.addEntityToList(LIT_BOMBS, bombEntity); - } - } - - // Update dropped items - for (const { - entity: itemEnt, - components: [item], - } of items) { - if (item.script != scriptPath) continue; - - const droppedItemComponents = droppedItems.get(itemEnt); - if (!!droppedItemComponents) { - const [droppedItem] = droppedItemComponents; - const [_item, itemTransform, body, sprite] = items.get(itemEnt); - const [_, playerTransform, playerBody] = players.get( - droppedItem.player - ); - let flip = sprite.flip_x; - let flipFactor = flip ? -1 : 1; - - // Re-activate physics body on the item - body.is_deactivated = false; - // Make sure item maintains player velocity - body.velocity = playerBody.velocity; - body.is_spawning = true; - - // Drop item at the middle of the player - itemTransform.translation.y = playerTransform.translation.y; - itemTransform.translation.x = - playerTransform.translation.x + 13 * flipFactor; - itemTransform.translation.z = playerTransform.translation.z; - } - } - }, -}; diff --git a/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts b/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts deleted file mode 100644 index 5a16d6fbc4..0000000000 --- a/assets/map/elements/item/kick_bomb/kick_bomb_spawner.ts +++ /dev/null @@ -1,25 +0,0 @@ -export default { - preUpdate() { - const spawnedEntities = MapElement.getSpawnedEntities(); - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the bomb item and copy the transform from the map element - const entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Item, { - script: Assets.getAbsolutePath("kick_bomb.ts"), - }) - ); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - } - }, -}; diff --git a/assets/map/elements/item/machine_gun/machine_gun.element.yaml b/assets/map/elements/item/machine_gun/machine_gun.element.yaml index e27ed529f1..8b9eb1005f 100644 --- a/assets/map/elements/item/machine_gun/machine_gun.element.yaml +++ b/assets/map/elements/item/machine_gun/machine_gun.element.yaml @@ -1,4 +1,2 @@ name: Machine Gun category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/machine_gun/sproinger.ts b/assets/map/elements/item/machine_gun/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/machine_gun/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/mines/mines.element.yaml b/assets/map/elements/item/mines/mines.element.yaml index 9ec2ea0d61..529141d8ee 100644 --- a/assets/map/elements/item/mines/mines.element.yaml +++ b/assets/map/elements/item/mines/mines.element.yaml @@ -1,4 +1,2 @@ name: Mines category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/mines/sproinger.ts b/assets/map/elements/item/mines/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/mines/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/musket/musket.element.yaml b/assets/map/elements/item/musket/musket.element.yaml index f0b0a09c39..06e1644f9d 100644 --- a/assets/map/elements/item/musket/musket.element.yaml +++ b/assets/map/elements/item/musket/musket.element.yaml @@ -1,4 +1,2 @@ name: Musket category: Weapons -scripts: - # - ./musket.ts diff --git a/assets/map/elements/item/musket/musket.ts b/assets/map/elements/item/musket/musket.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/musket/musket.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml b/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml index 58680c0180..c8d682c337 100644 --- a/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml +++ b/assets/map/elements/item/sniper_rifle/sniper_rifle.element.yaml @@ -1,4 +1,2 @@ name: Sniper Rifle category: Weapons -scripts: - # - ./sproinger.ts diff --git a/assets/map/elements/item/sniper_rifle/sproinger.ts b/assets/map/elements/item/sniper_rifle/sproinger.ts deleted file mode 100644 index 56004c9f9e..0000000000 --- a/assets/map/elements/item/sniper_rifle/sproinger.ts +++ /dev/null @@ -1 +0,0 @@ -export default {} \ No newline at end of file diff --git a/assets/map/elements/item/sword/sword.element.yaml b/assets/map/elements/item/sword/sword.element.yaml index a8c2c9e06a..cd5f0aed5a 100644 --- a/assets/map/elements/item/sword/sword.element.yaml +++ b/assets/map/elements/item/sword/sword.element.yaml @@ -2,4 +2,5 @@ name: Sword category: Weapons builtin: !Sword atlas: ./sword.atlas.yaml + sound: ./sword.ogg \ No newline at end of file diff --git a/assets/map/elements/item/sword/sword.ogg b/assets/map/elements/item/sword/sword.ogg new file mode 100644 index 0000000000..c9d20ad498 Binary files /dev/null and b/assets/map/elements/item/sword/sword.ogg differ diff --git a/assets/map/elements/item/sword/sword.ts b/assets/map/elements/item/sword/sword.ts deleted file mode 100644 index 22f82660ca..0000000000 --- a/assets/map/elements/item/sword/sword.ts +++ /dev/null @@ -1,262 +0,0 @@ -const scriptPath = Script.getInfo().path; - -type Idle = { status: "idle" }; -type Swinging = { status: "swinging"; frame: number }; -type Cooldown = { status: "cooldown"; frame: number }; -type ItemState = Idle | Swinging | Cooldown; -const itemStateInit: ItemState = { status: "idle" }; - -const COOLDOWN_FRAMES = 15; -const ATTACK_FPS = 10; - -export default { - preUpdateInGame() { - // Hydrate newly spawned sword items - const names = world.query(EntityName); - const items = world.query(Item); - for (const { entity, components } of items) { - const [item] = components; - - // If this is one of our items without a name - if (item.script == scriptPath && !names.get(entity)) { - // Hydrate the entity - world.insert(entity, Value.create(EntityName, ["Item: Sword"])); - - // Add the animated sprite - world.insert( - entity, - Value.create(AnimatedSprite, { - start: 0, - end: 0, - repeat: false, - fps: ATTACK_FPS, - atlas: { - id: Assets.getHandleId("sword.atlas.yaml"), - }, - }) - ); - // And the kinematic body - world.insert( - entity, - Value.create(KinematicBody, { - size: { - x: 64, - y: 16, - }, - offset: { - y: 38, - }, - gravity: 1, - has_friction: true, - has_mass: true, - }) - ); - } - } - }, - - updateInGame() { - const players = world.query( - AnimatedSprite, - Transform, - KinematicBody, - PlayerIdx - ); - const parents = world.query(Parent); - const items = world.query(Item, Transform, KinematicBody, AnimatedSprite); - const usedItems = world.query(ItemUsed); - const droppedItems = world.query(ItemDropped); - - // Helper to spawn a damage region - const spawnDamageRegion = ( - owner: Entity, - x: number, - y: number, - width: number, - height: number - ) => { - /// This is a hack to get a global transform because scripts can't construct it with - /// Value.create(). ( Fixed in Bevy 0.9 ) - const [_item, _transform, _kinematicBody, _animatedSprite] = - items[0].components; - - // Spawn damage region entity - let entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Transform, { - translation: { - x, - y, - }, - }) - ); - world.insert( - entity, - Value.create(DamageRegion, { - size: { - x: width, - y: height, - }, - }) - ); - world.insert(entity, Value.create(DamageRegionOwner, [owner])); - world.insert( - entity, - Value.create(Lifetime, { - lifetime: 1 / 60, - }) - ); - }; - - // Update items that are being held - // - // This section will make the item follow the player around and match the player's facing - // direction. - for (const { entity: itemEnt, components } of items) { - const [item, itemTransform, body, sprite] = components; - if (item.script != scriptPath) continue; - - const state = Script.getEntityState(itemEnt, itemStateInit); - - let parentComponents = parents.get(itemEnt); - // If this item isn't being held, skip the item - if (!parentComponents) continue; - - const [parent] = parentComponents; - const [playerSprite, playerTransform] = players.get(parent[0]); - - // Deactivate item collision - body.is_deactivated = true; - - // Set animation to default position if we aren't swinging - if (state.status != "swinging") { - sprite.start = 4; - sprite.end = 4; - sprite.index = 0; - sprite.repeat = false; - } - - // Flip the sprite to match our player orientation - const flip = playerSprite.flip_x; - sprite.flip_x = flip; - const flipFactor = flip ? -1 : 1; - // Align the sprite with the player's position - itemTransform.translation = Value.create(Vec3, { - x: 13 * (flip ? -1 : 1), - y: 21, - }); - - // If we're swinging the weapon - if (state.status == "swinging") { - // If we are at the end of the swing animation - if (sprite.index >= sprite.end - sprite.start - 1) { - // Go to cooldown frames - Script.setEntityState(itemEnt, { - status: "cooldown", - frame: 0, - }); - - // Set the current attack frame to the animation frame index - } else { - state.frame = sprite.index; - } - - // Trigger frame collisions for each sword animation position - switch (state.frame) { - case 0: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 20 * flipFactor, - playerTransform.translation.y + 20, - 30, - 70 - ); - break; - case 1: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 25 * flipFactor, - playerTransform.translation.y + 20, - 40, - 50 - ); - break; - case 2: - spawnDamageRegion( - parent[0], - playerTransform.translation.x + 20 * flipFactor, - playerTransform.translation.y, - 40, - 50 - ); - break; - } - - state.frame += 1; - - // If we are in cooldown frames - } else if (state.status == "cooldown") { - // If cooldown frames have finished - if (state.frame >= COOLDOWN_FRAMES) { - // Go back to idle state - Script.setEntityState(itemEnt, { status: "idle" }); - } else { - state.frame += 1; - } - } - - // If the item is being used - if (!!usedItems.get(itemEnt)) { - // Get the current item state - const state = Script.getEntityState(itemEnt, itemStateInit); - - if (state.status == "idle") { - const [_item, _itemTransform, _body, sprite] = items.get(itemEnt); - - // Start attacking animation - sprite.index = 0; - sprite.start = 8; - sprite.end = 12; - - // And move to an attacking state - Script.setEntityState(itemEnt, { - status: "swinging", - frame: 0, - }); - } - } - } - - // Update dropped items - for (const { - entity: itemEnt, - components: [item], - } of items) { - if (item.script != scriptPath) continue; - - const droppedItemComponents = droppedItems.get(itemEnt); - if (!!droppedItemComponents) { - const [droppedItem] = droppedItemComponents; - const [_item, itemTransform, body, sprite] = items.get(itemEnt); - const [_, playerTransform, playerBody] = players.get( - droppedItem.player - ); - - // Re-activate physics body on the item - body.is_deactivated = false; - // Put sword in rest position - sprite.start = 0; - sprite.end = 0; - // Make sure item maintains player velocity - body.velocity = playerBody.velocity; - body.is_spawning = true; - - // Drop item at the middle of the player - itemTransform.translation.y = playerTransform.translation.y - 30; - itemTransform.translation.x = playerTransform.translation.x; - itemTransform.translation.z = playerTransform.translation.z; - } - } - }, -}; diff --git a/assets/map/elements/item/sword/sword_spawner.ts b/assets/map/elements/item/sword/sword_spawner.ts deleted file mode 100644 index 77d916b47c..0000000000 --- a/assets/map/elements/item/sword/sword_spawner.ts +++ /dev/null @@ -1,25 +0,0 @@ -export default { - preUpdate() { - const spawnedEntities = MapElement.getSpawnedEntities(); - - // Handle newly spawned map entities - for (const spanwer_entity of spawnedEntities) { - const [transform, global_transform, computed_visibility] = world - .query(Transform, GlobalTransform, ComputedVisibility) - .get(spanwer_entity); - - // Spawn a new entity for the sword and copy the transform and visibility from the map element - const entity = WorldTemp.spawn(); - world.insert( - entity, - Value.create(Item, { - script: Assets.getAbsolutePath("./sword.ts"), - }) - ); - world.insert(entity, transform); - world.insert(entity, global_transform); - world.insert(entity, computed_visibility); - world.insert(entity, Value.create(Visibility)); - } - }, -}; diff --git a/assets/map/scripts/kill_out_of_bounds.ts b/assets/map/scripts/kill_out_of_bounds.ts index 4569b7c234..d54119988d 100644 --- a/assets/map/scripts/kill_out_of_bounds.ts +++ b/assets/map/scripts/kill_out_of_bounds.ts @@ -1,3 +1,8 @@ +/** + * TODO: Migrate to rust. + * + * This script isn't currently running. + */ const killZoneBorder = 500; export default { diff --git a/assets/player/skins/catty/catty.player.yaml b/assets/player/skins/catty/catty.player.yaml index a438acd14a..462cc2dad9 100644 --- a/assets/player/skins/catty/catty.player.yaml +++ b/assets/player/skins/catty/catty.player.yaml @@ -1,5 +1,15 @@ name: Catty +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: catty.png tile_size: [96, 80] diff --git a/assets/player/skins/fishy/fishy.player.yaml b/assets/player/skins/fishy/fishy.player.yaml index a0096e679c..f983b6f21b 100644 --- a/assets/player/skins/fishy/fishy.player.yaml +++ b/assets/player/skins/fishy/fishy.player.yaml @@ -1,5 +1,15 @@ name: Fishy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: fishy.png tile_size: [96, 80] diff --git a/assets/player/skins/lionfishy/lionfishy.player.yaml b/assets/player/skins/lionfishy/lionfishy.player.yaml index b2ca4919fd..c611bc45db 100644 --- a/assets/player/skins/lionfishy/lionfishy.player.yaml +++ b/assets/player/skins/lionfishy/lionfishy.player.yaml @@ -1,5 +1,15 @@ name: Lionfishy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: lionfishy.png tile_size: [96, 80] diff --git a/assets/player/skins/orcy/orcy.player.yaml b/assets/player/skins/orcy/orcy.player.yaml index bed21c9112..4c108ea8e4 100644 --- a/assets/player/skins/orcy/orcy.player.yaml +++ b/assets/player/skins/orcy/orcy.player.yaml @@ -1,5 +1,15 @@ name: Orcy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: orcy.png tile_size: [96, 80] diff --git a/assets/player/skins/pescy/pescy.player.yaml b/assets/player/skins/pescy/pescy.player.yaml index 12ec12d6cf..a6941b46a9 100644 --- a/assets/player/skins/pescy/pescy.player.yaml +++ b/assets/player/skins/pescy/pescy.player.yaml @@ -1,5 +1,15 @@ name: Pescy +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: pescy.png tile_size: [96, 80] diff --git a/assets/player/skins/sharky/sharky.player.yaml b/assets/player/skins/sharky/sharky.player.yaml index c1b8ebedae..6bb7d63d8f 100644 --- a/assets/player/skins/sharky/sharky.player.yaml +++ b/assets/player/skins/sharky/sharky.player.yaml @@ -1,5 +1,15 @@ name: Sharky +sounds: + jump: ../../sounds/jump.ogg + jump_volume: 0.05 + land: ../../sounds/land.ogg + land_volume: 0.05 + grab: ../../sounds/grab.ogg + grab_volume: 0.05 + drop: ../../sounds/drop.ogg + drop_volume: 0.05 + spritesheet: image: sharky.png tile_size: [96, 80] @@ -26,4 +36,3 @@ spritesheet: death_1: frames: [70, 76] repeat: false - diff --git a/assets/player/sounds/drop.ogg b/assets/player/sounds/drop.ogg new file mode 100755 index 0000000000..e058c9ea09 Binary files /dev/null and b/assets/player/sounds/drop.ogg differ diff --git a/assets/player/sounds/grab.ogg b/assets/player/sounds/grab.ogg new file mode 100644 index 0000000000..61d97eaf36 Binary files /dev/null and b/assets/player/sounds/grab.ogg differ diff --git a/assets/player/sounds/jump.ogg b/assets/player/sounds/jump.ogg new file mode 100644 index 0000000000..fdf1988baf Binary files /dev/null and b/assets/player/sounds/jump.ogg differ diff --git a/assets/player/sounds/land.ogg b/assets/player/sounds/land.ogg new file mode 100755 index 0000000000..4f36f5f669 Binary files /dev/null and b/assets/player/sounds/land.ogg differ diff --git a/assets/player/states/README.md b/assets/player/states/README.md deleted file mode 100644 index c016d744a4..0000000000 --- a/assets/player/states/README.md +++ /dev/null @@ -1,3 +0,0 @@ -# Player States - -These are the TypeScript implementations of the player states. For now they are unused as we migrated them to Rust for performance reasons. \ No newline at end of file diff --git a/assets/player/states/crouch.ts b/assets/player/states/crouch.ts deleted file mode 100644 index 3c5b27ab9d..0000000000 --- a/assets/player/states/crouch.ts +++ /dev/null @@ -1,49 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground || !(control.move_direction.y < -0.5)) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - // For every player - const playerComponents = world - .query(PlayerState, PlayerIdx, AnimationBankSprite, KinematicBody) - .map((x) => x.components); - for (const [ - playerState, - playerIdx, - animationBankSprite, - body, - ] of playerComponents) { - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "crouch"; - } - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - if (control.jump_just_pressed) { - body.fall_through = true; - } - } - }, -}; diff --git a/assets/player/states/dead.ts b/assets/player/states/dead.ts deleted file mode 100644 index 737269b19e..0000000000 --- a/assets/player/states/dead.ts +++ /dev/null @@ -1,42 +0,0 @@ -const scriptId = Script.getInfo().path; - -const DYING_PLAYERS = "dyingPlayers"; - -/** Responsible for transitioning players to the dead state whenever they are killed */ -export default { - playerStateTransition() { - const players = world.query(PlayerState, PlayerKilled); - - // Transition all players that have been killed to this state - for (const { entity } of players) { - if (!Script.entityListContains(DYING_PLAYERS, entity)) { - const [playerState] = players.get(entity); - playerState.id = Assets.getAbsolutePath("./dead.ts"); - Script.addEntityToList(DYING_PLAYERS, entity); - } - } - }, - handlePlayerState() { - const players = world.query(PlayerState, AnimationBankSprite); - - for (const { - entity, - components: [playerState, animationBankSprite], - } of players) { - // In this state - if (playerState.id != scriptId) continue; - - // Set animation when we enter the state - if (playerState.age == 0) { - animationBankSprite.current_animation = "death_1"; - } - - // Despawn player after 1.5 seconds ( 90 frames ) - if (playerState.age >= 90) { - Script.removeEntityFromList(DYING_PLAYERS, entity); - Player.despawn(entity); - Script.setEntityState(entity, undefined); - } - } - }, -}; diff --git a/assets/player/states/default.ts b/assets/player/states/default.ts deleted file mode 100644 index 694c80ca86..0000000000 --- a/assets/player/states/default.ts +++ /dev/null @@ -1,14 +0,0 @@ -/** Responsible for transitioning players in the default, meaningless state to "idle" */ -export default { - playerStateTransition() { - for (const [playerState] of world - .query(PlayerState) - .map((x) => x.components)) { - // Loop over players in the default state - if (playerState.id !== "") continue; - - // Transition to the idle state - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - }, -}; diff --git a/assets/player/states/idle.ts b/assets/player/states/idle.ts deleted file mode 100644 index 2c8d77b31a..0000000000 --- a/assets/player/states/idle.ts +++ /dev/null @@ -1,79 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./midair.ts"); - } else if (control.move_direction.y < -0.5) { - playerState.id = Assets.getAbsolutePath("./crouch.ts"); - } else if (control.move_direction.x != 0) { - playerState.id = Assets.getAbsolutePath("./walk.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - let items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "idle"; - } - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - // If we are grabbing - if (control.grab_just_pressed) { - // Get inventory - const currentInventory = Player.getInventory(playerEnt); - - if (!currentInventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - if (control.jump_just_pressed) { - body.velocity.y = 15; - } - body.velocity.x = 0; - } - }, -}; diff --git a/assets/player/states/midair.ts b/assets/player/states/midair.ts deleted file mode 100644 index 94a670dd2f..0000000000 --- a/assets/player/states/midair.ts +++ /dev/null @@ -1,80 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const playerComponents = world - .query(PlayerState, KinematicBody) - .map((x) => x.components); - - for (const [playerState, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - if (body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - const items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - if (playerState.id != scriptId) continue; - - // Set the current animation - if (body.velocity.y > 0) { - animationBankSprite.current_animation = "rise"; - } else { - animationBankSprite.current_animation = "fall"; - } - - const control = player_inputs.players[playerIdx[0]].control; - - // If we are grabbing - if (control.grab_just_pressed) { - const current_inventory = Player.getInventory(playerEnt); - if (!current_inventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - const [_item] = item; - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - // Add controls - body.velocity.x = control.move_direction.x * 5; - - // Fall through platforms when pressing down - if (control.move_direction.y < -0.5 && control.jump_pressed) { - body.fall_through = true; - } else { - body.fall_through = false; - } - - if (body.velocity.x > 0) { - animationBankSprite.flip_x = false; - } else if (body.velocity.x < 0) { - animationBankSprite.flip_x = true; - } - } - }, -}; diff --git a/assets/player/states/walk.ts b/assets/player/states/walk.ts deleted file mode 100644 index e17cb76752..0000000000 --- a/assets/player/states/walk.ts +++ /dev/null @@ -1,83 +0,0 @@ -const scriptId = Script.getInfo().path; - -export default { - playerStateTransition() { - const player_inputs = world.resource(PlayerInputs); - const playerComponents = world - .query(PlayerState, PlayerIdx, KinematicBody) - .map((x) => x.components); - - for (const [playerState, playerIdx, body] of playerComponents) { - if (playerState.id != scriptId) continue; - - const control = player_inputs.players[playerIdx[0]].control; - - if (!body.is_on_ground) { - playerState.id = Assets.getAbsolutePath("./midair.ts"); - } else if (body.is_on_ground && control.move_direction.y < -0.5) { - playerState.id = Assets.getAbsolutePath("./crouch.ts"); - } else if (control.move_direction.x == 0) { - playerState.id = Assets.getAbsolutePath("./idle.ts"); - } - } - }, - handlePlayerState() { - const player_inputs = world.resource(PlayerInputs); - - const items = world.query(Item); - - // For every player - for (const { entity: playerEnt, components } of world.query( - PlayerState, - PlayerIdx, - AnimationBankSprite, - KinematicBody - )) { - const [playerState, playerIdx, animationBankSprite, body] = components; - - // Add basic physics controls - const control = player_inputs.players[playerIdx[0]].control; - - // In this state - if (playerState.id != scriptId) continue; - - // Set the current animation - if (playerState.age == 0) { - animationBankSprite.current_animation = "walk"; - } - - // If we are grabbing - if (control.grab_just_pressed) { - const current_inventory = Player.getInventory(playerEnt); - if (!current_inventory) { - // For each actor colliding with the player - for (const collider of CollisionWorld.actorCollisions(playerEnt)) { - const item = items.get(collider); - if (!!item) { - Player.setInventory(playerEnt, collider); - break; - } - } - } else { - Player.setInventory(playerEnt, null); - } - } - - // Use item if we have one - if (control.shoot_just_pressed && Player.getInventory(playerEnt)) { - Player.useItem(playerEnt); - } - - // Add jump - if (control.jump_just_pressed) { - body.velocity.y = 15; - } - body.velocity.x = control.move_direction.x * 5; - if (control.move_direction.x > 0) { - animationBankSprite.flip_x = false; - } else if (control.move_direction.x < 0) { - animationBankSprite.flip_x = true; - } - } - }, -}; diff --git a/assets/ui/menu-background-zoom.ts b/assets/ui/menu-background-zoom.ts index 8ca513067a..62f3eb0e27 100644 --- a/assets/ui/menu-background-zoom.ts +++ b/assets/ui/menu-background-zoom.ts @@ -1,3 +1,7 @@ +/** + * TODO: Migrate to Rust + */ + type MenuBackground = unknown; const MenuBackground: BevyType = { typeName: "jumpy::ui::main_menu::MainMenuBackground", diff --git a/src.bkup/README.md b/src.bkup/README.md deleted file mode 100644 index ecef0ff3de..0000000000 --- a/src.bkup/README.md +++ /dev/null @@ -1 +0,0 @@ -These are modules with code we might want later, but that aren't used in the game right now. \ No newline at end of file diff --git a/src.bkup/networking/client/player_input.rs b/src.bkup/networking/client/player_input.rs deleted file mode 100644 index 9773278f3b..0000000000 --- a/src.bkup/networking/client/player_input.rs +++ /dev/null @@ -1,50 +0,0 @@ -use crate::{ - networking::proto::{ - player_input::{PlayerInputFromClient, PlayerInputFromServer}, - ClientMatchInfo, - }, - player::input::PlayerInputs, - prelude::*, -}; - -use super::NetClient; - -pub struct ClientPlayerInputPlugin; - -impl Plugin for ClientPlayerInputPlugin { - fn build(&self, app: &mut App) { - app.add_system_to_stage( - CoreStage::First, - recv_player_input_from_server.run_if_resource_exists::(), - ); - app.add_system_to_stage( - CoreStage::Last, - send_player_input_to_server - .run_if_resource_exists::() - .run_if_resource_exists::(), - ); - } -} - -fn recv_player_input_from_server( - mut client: ResMut, - mut player_inputs: ResMut, -) { - // FIXME: Unordered packets not handled correctly. We need a network tick. - while let Some(message) = client.recv_unreliable::() { - let player_input = &mut player_inputs.players[message.player_idx as usize]; - - player_input.control = message.control; - } -} - -fn send_player_input_to_server( - client: Res, - player_inputs: Res, - match_info: Res, -) { - let control = &player_inputs.players[match_info.player_idx].control; - client.send_unreliable(&PlayerInputFromClient { - control: control.clone(), - }); -} diff --git a/src.bkup/networking/commands.rs b/src.bkup/networking/commands.rs deleted file mode 100644 index 9a7d84bc52..0000000000 --- a/src.bkup/networking/commands.rs +++ /dev/null @@ -1,411 +0,0 @@ -#![allow(dead_code)] // TODO: Remove this when we use more stuff - -use std::marker::PhantomData; - -use bevy::{ - ecs::{ - entity::Entities, - system::{Command, EntityCommands, Resource, SystemParam}, - }, - reflect::TypeRegistryArc, -}; -use serde::{de::DeserializeSeed, Deserialize, Serialize}; - -use crate::{config::ENGINE_CONFIG, prelude::*, utils::ResetController}; - -use super::{ - client::NetClient, - serialization::{ - de::CompactReflectDeserializer, deserializer_from_bytes, get_type_name_cache, - ser::CompactReflectSerializer, serialize_to_bytes, TypeNameCache, - }, - server::NetServer, - NetId, NetIdMap, -}; - -pub struct NetCommandsPlugin; - -impl Plugin for NetCommandsPlugin { - fn build(&self, app: &mut App) { - app.init_resource::().add_system( - client_handle_net_commands - .run_if_resource_exists::() - .run_if_resource_exists::(), - ); - - if ENGINE_CONFIG.server_mode { - app.world.resource_scope(|world, server: Mut| { - let type_registry = world.resource::(); - let type_name_cache = get_type_name_cache(type_registry); - - server.broadcast_reliable(&type_name_cache); - - world.insert_resource(type_name_cache); - }); - } else { - app.add_system( - update_type_name_cache_from_server.run_if_resource_exists::(), - ); - } - } -} - -fn update_type_name_cache_from_server(mut client: ResMut, mut commands: Commands) { - while let Some(type_name_cache) = client.recv_reliable::() { - commands.insert_resource(type_name_cache); - } -} - -#[derive(Serialize, Deserialize, Clone)] -pub enum CommandMessage { - Spawn { - net_id: NetId, - }, - Insert { - net_id: NetId, - component_bytes: Vec, - type_name: String, - }, - InsertResource { - resource_bytes: Vec, - type_name: String, - }, - Despawn { - recursive: bool, - net_id: NetId, - }, - NextState(State), - /// This corresponds to the action implemented by the [`jumpy::utils::ResetController`]. - /// - /// Technically it's not a "Command", but it's similar enough that we put it in here. - ResetWorld, -} - -impl std::fmt::Debug for CommandMessage { - fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { - match self { - Self::Spawn { net_id } => f.debug_struct("Spawn").field("net_id", net_id).finish(), - Self::Insert { - net_id, - component_bytes: _, - type_name, - } => f - .debug_struct("Insert") - .field("net_id", net_id) - .field("component_bytes", &"...") - .field("type_name", type_name) - .finish(), - Self::InsertResource { - resource_bytes: _, - type_name, - } => f - .debug_struct("InsertResource") - .field("resource_bytes", &"...") - .field("type_name", type_name) - .finish(), - Self::Despawn { recursive, net_id } => f - .debug_struct("Despawn") - .field("recursive", recursive) - .field("net_id", net_id) - .finish(), - Self::NextState(arg0) => f.debug_tuple("NextState").field(arg0).finish(), - Self::ResetWorld => write!(f, "ResetWorld"), - } - } -} - -#[derive(Debug, Clone, Copy, Deserialize, Serialize)] -pub enum State { - GameState(GameState), - InGameState(InGameState), -} - -impl From for State { - fn from(s: GameState) -> Self { - Self::GameState(s) - } -} -impl From for State { - fn from(s: InGameState) -> Self { - Self::InGameState(s) - } -} - -pub fn client_handle_net_commands( - entities: &Entities, - mut commands: Commands, - type_registry: Res, - mut client: Res, - mut net_ids: ResMut, - type_names: Res, - mut reset_controller: ResetController, -) { - while let Some(message) = client.recv_reliable::() { - trace!(command=?message, "Received CommandMessage from server"); - - match message { - CommandMessage::Spawn { net_id } => { - let entity = commands.spawn().insert(net_id).id(); - info!("Spawning entity"); - net_ids.insert(entity, net_id); - } - CommandMessage::Insert { - net_id, - component_bytes, - type_name, - } => { - let entity = net_ids.get_entity(net_id).expect("Entity not spawned"); - let type_registry = type_registry.read(); - let type_registration = type_registry - .get_with_name(&type_name) - .expect("Not registered in TypeRegistry"); - - let reflect_component = type_registration - .data::() - .expect("Doesn't have ReflectComponent") - .clone(); - let reflect_deserializer = - CompactReflectDeserializer::new(&type_registry, &type_names.0); - let component_data = reflect_deserializer - .deserialize(&mut deserializer_from_bytes(&component_bytes)) - .expect("Deserialize net component"); - - commands.add(InsertReflectComponent { - entity, - component_data, - reflect_component, - }); - } - CommandMessage::InsertResource { - resource_bytes, - type_name, - } => { - let type_registry = type_registry.read(); - let type_registration = type_registry - .get_with_name(&type_name) - .expect("Not registered in TypeRegistry"); - let reflect_resource = type_registration - .data::() - .expect("Doesn't have ReflectResource") - .clone(); - let reflect_deserializer = - CompactReflectDeserializer::new(&type_registry, &type_names.0); - let resource_data = reflect_deserializer - .deserialize(&mut deserializer_from_bytes(&resource_bytes)) - .expect("Deserialize component"); - - commands.add(InsertReflectResource { - reflect_resource, - resource_data, - }); - } - CommandMessage::NextState(s) => match s { - State::GameState(s) => commands.insert_resource(NextState(s)), - State::InGameState(s) => commands.insert_resource(NextState(s)), - }, - CommandMessage::Despawn { recursive, net_id } => { - if let Some(entity) = net_ids.remove_net_id(net_id) { - if entities.contains(entity) { - let mut cmds = commands.entity(entity); - if recursive { - cmds.despawn_recursive() - } else { - cmds.despawn() - } - } - } - } - CommandMessage::ResetWorld => { - reset_controller.reset_world(); - } - } - } -} - -struct InsertReflectComponent { - entity: Entity, - reflect_component: ReflectComponent, - component_data: Box, -} -impl Command for InsertReflectComponent { - fn write(self, world: &mut World) { - self.reflect_component.apply_or_insert( - world, - self.entity, - self.component_data.as_reflect(), - ); - } -} - -struct InsertReflectResource { - reflect_resource: ReflectResource, - resource_data: Box, -} -impl Command for InsertReflectResource { - fn write(self, world: &mut World) { - self.reflect_resource - .apply_or_insert(world, self.resource_data.as_reflect()); - } -} - -/// Similar to [`Commands`], but with network synchronization of the executed commands. -#[derive(SystemParam)] -pub struct NetCommands<'w, 's> { - commands: Commands<'w, 's>, - res: NetResources<'w, 's>, -} - -#[derive(SystemParam)] -pub struct NetResources<'w, 's> { - type_registry: Res<'w, TypeRegistryArc>, - net_ids: ResMut<'w, NetIdMap>, - server: Option>, - type_names: Option>, - #[system_param(ignore)] - _phantom: PhantomData<&'s ()>, -} - -impl<'w, 's> NetCommands<'w, 's> { - pub fn spawn<'a>(&'a mut self) -> NetEntityCommands<'w, 's, 'a> { - let mut entity_cmds = self.commands.spawn(); - - if let Some(server) = &mut self.res.server { - // Allocate a network identifier for the new entity - let net_id = NetId::new(); - // Add it to the queued network IDs - self.res.net_ids.insert(entity_cmds.id(), net_id); - - // Inser the network ID as a component on the entity - entity_cmds.insert(net_id); - - // Notify clients/server that an entity has been spawned - server.broadcast_reliable(&CommandMessage::Spawn { net_id }); - } - - NetEntityCommands { - entity_cmds, - res: &mut self.res, - } - } - - pub fn entity<'a>(&'a mut self, entity: Entity) -> NetEntityCommands<'w, 's, 'a> { - let entity_cmds = self.commands.entity(entity); - NetEntityCommands { - entity_cmds, - res: &mut self.res, - } - } - - pub fn next_state(&mut self, state: impl Into) -> &mut Self { - let state = state.into(); - - if let Some(server) = &mut self.res.server { - server.broadcast_reliable(&CommandMessage::NextState(state)); - } - - match state { - State::GameState(s) => self.commands.insert_resource(NextState(s)), - State::InGameState(s) => self.commands.insert_resource(NextState(s)), - } - - self - } - - pub fn insert_resource(&mut self, resource: impl Resource + Reflect) -> &mut Self { - if let Some(server) = &mut self.res.server { - // Serialize the component - let (resource_bytes, type_name) = { - let type_registry = self.res.type_registry.read(); - let type_registration = type_registry - .get(resource.type_id()) - .expect("Not registered in TypeRegistry"); - let serializer = CompactReflectSerializer::new( - resource.as_reflect(), - &type_registry, - &self.res.type_names.as_ref().unwrap().0, - ); - - let message = serialize_to_bytes(&serializer).expect("Serialize net message"); - - (message, type_registration.type_name()) - }; - - // Send the clients/server the inserted component - server.broadcast_reliable(&CommandMessage::InsertResource { - resource_bytes, - type_name: type_name.into(), - }); - } - - self.commands.insert_resource(resource); - - self - } -} - -pub struct NetEntityCommands<'w, 's, 'a> { - entity_cmds: EntityCommands<'w, 's, 'a>, - res: &'a mut NetResources<'w, 's>, -} - -impl<'w, 's, 'a> NetEntityCommands<'w, 's, 'a> { - pub fn id(&self) -> Entity { - self.entity_cmds.id() - } - pub fn insert(&mut self, c: C) -> &mut Self { - if let Some(server) = &mut self.res.server { - let entity = self.entity_cmds.id(); - - // Get the network ID - let net_id = self - .res - .net_ids - .get_net_id(entity) - .expect("Entity has no NetId"); - - // Serialize the component - let (component_bytes, type_name) = { - let type_registry = self.res.type_registry.read(); - let type_registration = type_registry.get(c.type_id()).unwrap_or_else(|| { - panic!( - "{} not registered in TypeRegistry", - std::any::type_name::() - ) - }); - let serializable = CompactReflectSerializer::new( - c.as_reflect(), - &type_registry, - &self.res.type_names.as_ref().unwrap().0, - ); - - let message = serialize_to_bytes(&serializable).expect("Serialize net message"); - - (message, type_registration.type_name()) - }; - - // Send the clients/server the inserted component - server.broadcast_reliable(&CommandMessage::Insert { - net_id, - component_bytes, - type_name: type_name.into(), - }); - } - - self.entity_cmds.insert(c); - - self - } - - pub fn despawn_recursive(self) { - if let Some(server) = &mut self.res.server { - if let Some(net_id) = self.res.net_ids.remove_entity(self.entity_cmds.id()) { - server.broadcast_reliable(&CommandMessage::Despawn { - recursive: true, - net_id, - }); - } - } - - self.entity_cmds.despawn_recursive(); - } -} diff --git a/src.bkup/networking/frame_sync.rs b/src.bkup/networking/frame_sync.rs deleted file mode 100644 index f7de0bacbc..0000000000 --- a/src.bkup/networking/frame_sync.rs +++ /dev/null @@ -1,332 +0,0 @@ -use bevy::{ - ecs::component::ComponentId, - reflect::{ReflectFromPtr, TypeRegistryArc, TypeRegistryInternal}, -}; -use bevy_ecs_dynamic::dynamic_query::{DynamicQuery, FetchKind, FetchResult}; -use serde::de::DeserializeSeed; - -use crate::prelude::*; - -use super::{ - client::NetClient, - serialization::{ - de::CompactReflectDeserializer, deserializer_from_bytes, ser::CompactReflectSerializer, - serialize_to_bytes, TypeNameCache, - }, - server::NetServer, - NetId, NetIdMap, -}; - -mod dynamic_query_info; -use self::dynamic_query_info::{DynamicQueryInfo, DynamicQueryInfoResources}; - -pub struct NetFrameSyncPlugin; - -impl Plugin for NetFrameSyncPlugin { - fn build(&self, app: &mut App) { - app.init_resource::() - .add_system_to_stage( - FixedUpdateStage::First, - client_get_sync_data.exclusive_system().at_start(), - ) - .add_system_to_stage( - FixedUpdateStage::First, - server_send_sync_data.exclusive_system().at_end(), - ); - } -} - -#[derive(Default)] -pub struct NetworkSyncConfig { - pub queries: Vec, -} - -pub struct NetworkSyncQuery { - pub query: DynamicQuery, - pub prune: bool, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct FrameSyncMessage { - pub queries: Vec, -} - -type Bytes = Vec; -type ComponentsBytes = Vec; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct FrameSyncQuery { - query_info: DynamicQueryInfo, - items: Vec, - prune: bool, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -struct FrameSyncQueryItem { - net_id: NetId, - components: ComponentsBytes, -} - -fn client_get_sync_data(world: &mut World) { - if !world.contains_resource::() { - return; - } - if !world.contains_resource::() { - return; - } - - world.resource_scope(|world, mut client: Mut| { - world.resource_scope(|world, net_ids: Mut| { - world.resource_scope(|world, type_registry: Mut| { - world.resource_scope(|world, type_names: Mut| { - let type_registry = type_registry.read(); - impl_client_get_sync_data( - world, - &mut client, - &net_ids, - &*type_registry, - &type_names, - ) - }); - }); - }); - }); -} - -fn impl_client_get_sync_data( - world: &mut World, - client: &mut NetClient, - net_ids: &NetIdMap, - type_registry: &TypeRegistryInternal, - type_names: &TypeNameCache, -) { - let mut message = None; - // We only care about the last message, so loop until we stop getting messages and store the - // latest one. - // - // FIXME: We currently send unordered packets, but assume that the latest one received is indeed the - // latest, when it could be older than a previously received packet. We need to keep a network tick - // so that we can tell which packet is the newest one we've seen. - while let Some(m) = client.recv_unreliable::() { - message = Some(m); - } - - // If we have a frame update - if let Some(message) = message { - for net_query in message.queries { - let mut query = net_query - .query_info - .with_all_fetches_mutable() - .get_query(DynamicQueryInfoResources { - world, - type_names, - type_registry, - }) - .expect("Invalid query"); - let reflect_tools = get_reflect_from_ptr(world, type_registry, &query); - - // Collect entities matching the query - let entities = query.iter_mut(world).map(|x| x.entity).collect::>(); - - // Collect entities that have a net ID - let mut net_entities = Vec::with_capacity(entities.len()); - for entity in entities { - if let Some(net_id) = net_ids.get_net_id(entity) { - net_entities.push((entity, net_id)); - - // Delete non-networked entities matching the query - } else if net_query.prune { - despawn_with_children_recursive(world, entity); - } - } - - // Sort entities by net ID - net_entities.sort_unstable_by_key(|x| x.1); - - let mut net_items_iter = net_query.items.into_iter(); - 'entities: for (entity, net_id) in net_entities { - // Get the components bytes for the matching networked entity - let components_bytes = loop { - if let Some(item) = net_items_iter.next() { - if item.net_id == net_id { - break item.components; - } - } else { - break 'entities; - } - }; - - // Collect the pointers for the components of the entity - let components_target_pointers = query - .get_mut(world, entity) - .expect("Query entity") - .into_iter() - .map(|x| { - if let FetchResult::RefMut { value, .. } = x { - value - } else { - unreachable!("All fetches should have been mutable") - } - }); - - // Loop through the components and update them from the data from the network - for ((target_pointer, component_bytes), reflect_from_ptr) in - components_target_pointers - .zip(components_bytes) - .zip(&reflect_tools) - { - let target_reflect = - unsafe { reflect_from_ptr.as_reflect_ptr_mut(target_pointer) }; - - let deserializer = - CompactReflectDeserializer::new(type_registry, &type_names.0); - - let component_data = deserializer - .deserialize(&mut deserializer_from_bytes(&component_bytes)) - .expect("Deserialize net component"); - - target_reflect.apply(component_data.as_ref()); - } - } - } - } -} - -fn server_send_sync_data(world: &mut World) { - if !world.contains_resource::() { - return; - } - if !world.contains_resource::() { - return; - } - - world.resource_scope(|world, mut server: Mut| { - world.resource_scope(|world, mut queries: Mut| { - world.resource_scope(|world, net_ids: Mut| { - world.resource_scope(|world, type_registry: Mut| { - world.resource_scope(|world, type_names: Mut| { - let type_registry = type_registry.read(); - impl_server_send_sync_data( - world, - &mut server, - &mut queries, - &net_ids, - &*type_registry, - &type_names, - ); - }); - }); - }); - }); - }); -} - -fn impl_server_send_sync_data( - world: &mut World, - server: &mut NetServer, - network_sync: &mut NetworkSyncConfig, - net_ids: &NetIdMap, - type_registry: &TypeRegistryInternal, - type_names: &TypeNameCache, -) { - let mut frame_sync_queries = Vec::with_capacity(network_sync.queries.len()); - - // Iterate over queries that need to be synced - for net_query in network_sync.queries.iter_mut() { - let query = &mut net_query.query; - let query_info = DynamicQueryInfo::from_query( - query, - DynamicQueryInfoResources { - world, - type_names, - type_registry, - }, - ); - - // Get the ReflectFromPtr and ReflectSerialize for each component type in the query - let reflect_tools = get_reflect_from_ptr(world, type_registry, query); - - // Loop over all entities matching the query - let mut serialized_items = Vec::new(); - for item in query.iter_mut(world) { - let Some(net_id) = net_ids.get_net_id(item.entity) else { - warn!("Skipping sync of entity without known NetId"); - continue; - }; - - let mut components_bytes = Vec::with_capacity(item.items.len()); - for (fetch_result, reflect_from_ptr) in item.items.into_iter().zip(reflect_tools.iter()) - { - let ptr = if let FetchResult::Ref(ptr) = fetch_result { - ptr - } else { - panic!("Only read-only query supported for network sync"); - }; - - let reflect = unsafe { reflect_from_ptr.as_reflect_ptr(ptr) }; - let serializable = - CompactReflectSerializer::new(reflect, type_registry, &type_names.0); - let bytes = serialize_to_bytes(&serializable).expect("Serialize component"); - components_bytes.push(bytes); - } - serialized_items.push(FrameSyncQueryItem { - net_id, - components: components_bytes, - }); - } - - // Sort items by net_id - serialized_items.sort_unstable_by_key(|x| x.net_id); - - frame_sync_queries.push(FrameSyncQuery { - query_info, - items: serialized_items, - prune: net_query.prune, - }); - } - - let message = FrameSyncMessage { - queries: frame_sync_queries, - }; - - server.broadcast_unreliable(&message); -} - -fn get_reflect_from_ptr<'a, 'b>( - world: &'b World, - type_registry: &'a TypeRegistryInternal, - query: &'b DynamicQuery, -) -> Vec<&'a ReflectFromPtr> { - query - .fetches() - .iter() - .map(|fetch_kind| fetch_kind.component_id()) - .map(|component_id| { - world - .components() - .get_info(component_id) - .unwrap() - .type_id() - .unwrap() - }) - .map(|type_id| { - let type_registration = type_registry.get(type_id).expect("Type not registered"); - let reflect_from_ptr = type_registration - .data::() - .expect("Missing ReflectFromPtr"); - reflect_from_ptr - }) - .collect::>() -} - -trait FetchKindExt { - fn component_id(&self) -> ComponentId; -} - -impl FetchKindExt for FetchKind { - fn component_id(&self) -> ComponentId { - match self { - FetchKind::Ref(id) | FetchKind::RefMut(id) => *id, - } - } -} diff --git a/src.bkup/networking/frame_sync/dynamic_query_info.rs b/src.bkup/networking/frame_sync/dynamic_query_info.rs deleted file mode 100644 index adbfae3d9f..0000000000 --- a/src.bkup/networking/frame_sync/dynamic_query_info.rs +++ /dev/null @@ -1,170 +0,0 @@ -use bevy::{ecs::component::ComponentId, prelude::World, reflect::TypeRegistryInternal}; -use bevy_ecs_dynamic::dynamic_query::{DynamicQuery, FetchKind, FilterKind, QueryError}; - -use crate::{networking::serialization::TypeNameCache, prelude::*}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct DynamicQueryInfo { - fetches: Vec, - filters: Vec, -} - -/// References to the types needed to convert and construct [`DynamicQueryInfo`]. -#[derive(Copy, Clone)] -pub struct DynamicQueryInfoResources<'a> { - pub world: &'a World, - pub type_names: &'a TypeNameCache, - pub type_registry: &'a TypeRegistryInternal, -} - -impl DynamicQueryInfo { - pub fn from_query(query: &DynamicQuery, info: DynamicQueryInfoResources) -> Self { - let fetches = query - .fetches() - .iter() - .cloned() - .map(|x| FetchKindInfo::from_fetch_kind(x, info)) - .collect(); - let filters = query - .filters() - .iter() - .cloned() - .map(|x| FilterKindInfo::from_filter_kind(x, info)) - .collect(); - Self { fetches, filters } - } - - pub fn with_all_fetches_mutable(mut self) -> Self { - for fetch in &mut self.fetches { - *fetch = FetchKindInfo::RefMut(match fetch { - FetchKindInfo::Ref(id) | FetchKindInfo::RefMut(id) => *id, - }); - } - self - } - - pub fn get_query( - self: DynamicQueryInfo, - info: DynamicQueryInfoResources, - ) -> Result { - let fetches = self - .fetches - .into_iter() - .map(|x| x.get_fetch_kind(info)) - .collect(); - let filters = self - .filters - .into_iter() - .map(|x| x.get_filter_kind(info)) - .collect(); - DynamicQuery::new(info.world, fetches, filters) - } -} - -/// The index into the type name cache for this component -#[derive(Copy, Clone, Debug, Serialize, Deserialize)] -struct ComponentTypeNameIdx(pub u32); - -impl ComponentTypeNameIdx { - fn get_component_id(&self, info: DynamicQueryInfoResources) -> ComponentId { - let type_registry = info.type_registry; - - let type_name = info - .type_names - .0 - .get_str(self.0) - .expect("Missing type name in cache"); - let type_id = type_registry - .get_with_name(type_name) - .expect("Type not registered") - .type_id(); - - // FIXME(scripting): This can't support custom components created by scripts, because we - // assume the component ID can be directly tied to the type ID that we are syncing. - // We need to fix that and find a way to map component Ids on the server to component ids on the client - info.world - .components() - .get_id(type_id) - .expect("Component not found") - } - - fn from_component_id(id: ComponentId, info: DynamicQueryInfoResources) -> Self { - let world = info.world; - let type_names = info.type_names; - let type_registry = info.type_registry; - - let type_id = world - .components() - .get_info(id) - .expect("Component ID not found") - .type_id() - .expect("Component without Type ID"); - let type_name = type_registry - .get(type_id) - .expect("Type not registered") - .type_name(); - - Self( - type_names - .0 - .get_idx(type_name) - .expect("Missing type name in cache"), - ) - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -enum FetchKindInfo { - Ref(ComponentTypeNameIdx), - RefMut(ComponentTypeNameIdx), -} - -impl FetchKindInfo { - fn get_fetch_kind(&self, info: DynamicQueryInfoResources) -> FetchKind { - match self { - FetchKindInfo::Ref(id) => FetchKind::Ref(id.get_component_id(info)), - FetchKindInfo::RefMut(id) => FetchKind::RefMut(id.get_component_id(info)), - } - } - - fn from_fetch_kind(f: FetchKind, info: DynamicQueryInfoResources) -> Self { - match f { - FetchKind::Ref(id) => Self::Ref(ComponentTypeNameIdx::from_component_id(id, info)), - FetchKind::RefMut(id) => { - Self::RefMut(ComponentTypeNameIdx::from_component_id(id, info)) - } - } - } -} - -#[derive(Clone, Debug, Serialize, Deserialize)] -enum FilterKindInfo { - With(ComponentTypeNameIdx), - Without(ComponentTypeNameIdx), - Changed(ComponentTypeNameIdx), - Added(ComponentTypeNameIdx), -} - -impl FilterKindInfo { - fn get_filter_kind(&self, info: DynamicQueryInfoResources) -> FilterKind { - match self { - FilterKindInfo::With(id) => FilterKind::With(id.get_component_id(info)), - FilterKindInfo::Without(id) => FilterKind::Without(id.get_component_id(info)), - FilterKindInfo::Changed(id) => FilterKind::Changed(id.get_component_id(info)), - FilterKindInfo::Added(id) => FilterKind::Added(id.get_component_id(info)), - } - } - - fn from_filter_kind(f: FilterKind, info: DynamicQueryInfoResources) -> Self { - match f { - FilterKind::With(id) => Self::With(ComponentTypeNameIdx::from_component_id(id, info)), - FilterKind::Without(id) => { - Self::Without(ComponentTypeNameIdx::from_component_id(id, info)) - } - FilterKind::Changed(id) => { - Self::Changed(ComponentTypeNameIdx::from_component_id(id, info)) - } - FilterKind::Added(id) => Self::Added(ComponentTypeNameIdx::from_component_id(id, info)), - } - } -} diff --git a/src.bkup/networking/proto/player_input.rs b/src.bkup/networking/proto/player_input.rs deleted file mode 100644 index fbfd2ee778..0000000000 --- a/src.bkup/networking/proto/player_input.rs +++ /dev/null @@ -1,12 +0,0 @@ -use crate::{player::input::PlayerControl, prelude::*}; - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PlayerInputFromClient { - pub control: PlayerControl, -} - -#[derive(Serialize, Deserialize, Clone, Debug)] -pub struct PlayerInputFromServer { - pub player_idx: u32, - pub control: PlayerControl, -} diff --git a/src.bkup/networking/serialization.rs b/src.bkup/networking/serialization.rs deleted file mode 100644 index 06783bd7ec..0000000000 --- a/src.bkup/networking/serialization.rs +++ /dev/null @@ -1,74 +0,0 @@ -use crate::prelude::*; - -use bevy::{reflect::TypeRegistry, utils::HashMap}; - -pub mod de; -pub mod ser; - -pub struct SerializationPlugin; - -impl Plugin for SerializationPlugin { - fn build(&self, app: &mut App) { - // This type isn't registered - app.register_type::(); - } -} - -pub fn serialize_to_bytes(value: &T) -> anyhow::Result> -where - T: Serialize + ?Sized, -{ - Ok(postcard::to_allocvec(value)?) -} - -pub fn deserialize_from_bytes<'a, T>(bytes: &'a [u8]) -> anyhow::Result -where - T: Deserialize<'a>, -{ - Ok(postcard::from_bytes(bytes)?) -} - -pub fn deserializer_from_bytes( - bytes: &[u8], -) -> postcard::Deserializer { - postcard::Deserializer::from_bytes(bytes) -} - -#[derive(Default, Serialize, Deserialize)] -pub struct TypeNameCache(pub StringCache); - -/// String cache that can be used to map strings to indices in order to save space. -#[derive(Debug, Clone, Reflect, Default, Serialize, Deserialize)] -#[reflect(Default)] -pub struct StringCache { - strings: Vec, - indexes: HashMap, -} - -impl StringCache { - pub fn insert(&mut self, s: &str) { - let idx = self.strings.len(); - self.strings.push(s.into()); - self.indexes - .insert(s.into(), idx.try_into().expect("Too many strings in cache")); - } - - pub fn get_idx(&self, str: &str) -> Option { - self.indexes.get(str).copied() - } - - pub fn get_str(&self, idx: u32) -> Option<&str> { - self.strings.get(idx as usize).map(|x| x.as_str()) - } -} - -pub fn get_type_name_cache(type_registry: &TypeRegistry) -> TypeNameCache { - let mut cache = StringCache::default(); - - let type_registry = type_registry.read(); - for registration in type_registry.iter() { - cache.insert(registration.type_name()); - } - - TypeNameCache(cache) -} diff --git a/src.bkup/networking/serialization/de.rs b/src.bkup/networking/serialization/de.rs deleted file mode 100644 index caac9b0b72..0000000000 --- a/src.bkup/networking/serialization/de.rs +++ /dev/null @@ -1,441 +0,0 @@ -use std::any::TypeId; - -use bevy::reflect::{ - ArrayInfo, DynamicList, DynamicMap, DynamicStruct, DynamicTuple, DynamicTupleStruct, ListInfo, - Map, MapInfo, StructInfo, TupleInfo, TupleStructInfo, TypeInfo, TypeRegistration, - TypeRegistryInternal, -}; -use serde::de::{DeserializeSeed, Error, Visitor}; - -use super::StringCache; -use crate::prelude::*; - -macro_rules! custom_err { - ($($arg:expr),* $(,)?) => { - Error::custom(format_args!($($arg),*)) - }; -} - -pub struct CompactReflectDeserializer<'a>(DeserializerInner<'a>); - -impl<'a> CompactReflectDeserializer<'a> { - pub fn new(registry: &'a TypeRegistryInternal, type_names: &'a StringCache) -> Self { - Self(DeserializerInner { - registry, - type_names, - }) - } -} - -#[derive(Clone, Copy)] -struct DeserializerInner<'a> { - registry: &'a TypeRegistryInternal, - type_names: &'a StringCache, -} - -impl<'a> DeserializerInner<'a> { - fn get_registration_from_idx(&self, type_idx: u32) -> Result<&TypeRegistration, E> { - let type_name = self - .type_names - .get_str(type_idx) - .ok_or_else(|| custom_err!("Type name not in name cache"))?; - - self.registry - .get_with_name(type_name) - .ok_or_else(|| custom_err!("Type not in type registry")) - } - - fn get_registration_from_type_id( - &self, - type_id: TypeId, - type_name: &str, - ) -> Result<&TypeRegistration, E> { - self.registry - .get(type_id) - .ok_or_else(|| custom_err!("Type not in type registry: {}", type_name)) - } -} - -impl<'a, 'de> DeserializeSeed<'de> for CompactReflectDeserializer<'a> { - type Value = Box; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - deserializer.deserialize_tuple(2, OuterTypeVisitor(self.0)) - } -} - -struct OuterTypeVisitor<'a>(DeserializerInner<'a>); - -impl<'a, 'de> Visitor<'de> for OuterTypeVisitor<'a> { - type Value = Box; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple like (type_idx_in_str_cache, type_data)") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - let type_idx = seq - .next_element::()? - .ok_or_else(|| custom_err!("Missing type idx in top-level type"))?; - let registration = self.0.get_registration_from_idx(type_idx)?; - - let reflect = seq - .next_element_seed(ReflectValueDeserializer { - inner: self.0, - registration, - })? - .ok_or_else(|| custom_err!("Missing type idx in top-level type"))?; - - Ok(reflect) - } -} - -#[derive(Copy, Clone)] -struct ReflectValueDeserializer<'a> { - inner: DeserializerInner<'a>, - registration: &'a TypeRegistration, -} - -impl<'a, 'de> DeserializeSeed<'de> for ReflectValueDeserializer<'a> { - type Value = Box; - - fn deserialize(self, deserializer: D) -> Result - where - D: serde::Deserializer<'de>, - { - // Handle both Value case and types that have a custom `ReflectDeserialize` - if let Some(deserialize_reflect) = self.registration.data::() { - let value = deserialize_reflect.deserialize(deserializer)?; - return Ok(value); - } - - match self.registration.type_info() { - TypeInfo::Struct(info) => { - let len = info.field_len(); - let mut dynamic_struct = deserializer.deserialize_tuple( - len, - StructVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_struct.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_struct)) - } - TypeInfo::TupleStruct(info) => { - let len = info.field_len(); - let mut dynamic_tuple_struct = deserializer.deserialize_tuple( - len, - TupleStructVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_tuple_struct.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_tuple_struct)) - } - TypeInfo::Tuple(info) => { - let len = info.field_len(); - let mut dynamic_tuple = deserializer.deserialize_tuple( - len, - TupleVisitor { - inner: self.inner, - info, - }, - )?; - dynamic_tuple.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_tuple)) - } - TypeInfo::List(info) => { - let mut dynamic_list = deserializer.deserialize_seq(ListVisitor { - inner: self.inner, - info, - })?; - dynamic_list.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_list)) - } - TypeInfo::Array(info) => { - let mut dynamic_list = deserializer.deserialize_seq(ArrayVisitor { - inner: self.inner, - info, - })?; - dynamic_list.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_list)) - } - TypeInfo::Map(info) => { - let mut dynamic_map = deserializer.deserialize_map(MapVisitor { - inner: self.inner, - info, - })?; - dynamic_map.set_name(info.type_name().into()); - - Ok(Box::new(dynamic_map)) - } - TypeInfo::Value(_) => { - // This case should already be handled - Err(custom_err!( - "the TypeRegistration for {} doesn't have ReflectDeserialize", - self.registration.type_name() - )) - } - TypeInfo::Dynamic(_) => { - // We could potentially allow this but we'd have no idea what the actual types of the - // fields are and would rely on the deserializer to determine them (e.g. `i32` vs `i64`) - Err(custom_err!( - "cannot deserialize arbitrary dynamic type yet: {}", - self.registration.type_name() - )) - } - } - } -} - -struct StructVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a StructInfo, -} - -impl<'a, 'de> Visitor<'de> for StructVisitor<'a> { - type Value = DynamicStruct; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with struct fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting struct {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicStruct::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - let name = self.info.field_at(index).unwrap().name(); - trace!("Visiting field {}", name); - output.insert_boxed(name, value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct TupleStructVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a TupleStructInfo, -} - -impl<'a, 'de> Visitor<'de> for TupleStructVisitor<'a> { - type Value = DynamicTupleStruct; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple struct fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting tuple struct {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicTupleStruct::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - output.insert_boxed(value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct TupleVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a TupleInfo, -} - -impl<'a, 'de> Visitor<'de> for TupleVisitor<'a> { - type Value = DynamicTuple; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting tuple {}", self.info.type_name()); - let mut index = 0usize; - let mut output = DynamicTuple::default(); - - while let Some(value) = seq.next_element_seed({ - let field = self.info.field_at(index).unwrap(); - let type_id = field.type_id(); - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, field.type_name())?, - } - })? { - output.insert_boxed(value); - index += 1; - if index >= self.info.field_len() { - break; - } - } - - Ok(output) - } -} - -struct ListVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a ListInfo, -} - -impl<'a, 'de> Visitor<'de> for ListVisitor<'a> { - type Value = DynamicList; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple list fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting list {}", self.info.type_name()); - let mut output = DynamicList::default(); - - let type_id = self.info.item_type_id(); - - while let Some(value) = seq.next_element_seed({ - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, self.info.item_type_name())?, - } - })? { - output.push_box(value); - } - - Ok(output) - } -} - -struct ArrayVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a ArrayInfo, -} - -impl<'a, 'de> Visitor<'de> for ArrayVisitor<'a> { - type Value = DynamicList; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("Tuple with tuple list fields") - } - - fn visit_seq(self, mut seq: A) -> Result - where - A: serde::de::SeqAccess<'de>, - { - trace!("Visiting array {}", self.info.type_name()); - let mut output = DynamicList::default(); - - let type_id = self.info.item_type_id(); - - while let Some(value) = seq.next_element_seed({ - ReflectValueDeserializer { - inner: self.inner, - registration: self - .inner - .get_registration_from_type_id(type_id, self.info.item_type_name())?, - } - })? { - output.push_box(value); - } - - Ok(output) - } -} - -struct MapVisitor<'a> { - inner: DeserializerInner<'a>, - info: &'a MapInfo, -} - -impl<'a, 'de> Visitor<'de> for MapVisitor<'a> { - type Value = DynamicMap; - - fn expecting(&self, formatter: &mut std::fmt::Formatter) -> std::fmt::Result { - formatter.write_str("map") - } - - fn visit_map(self, mut map: A) -> Result - where - A: serde::de::MapAccess<'de>, - { - trace!("Visiting map {}", self.info.type_name()); - let mut output = DynamicMap::default(); - - let key_registration = self - .inner - .get_registration_from_type_id(self.info.key_type_id(), self.info.key_type_name())?; - let value_registration = self.inner.get_registration_from_type_id( - self.info.value_type_id(), - self.info.value_type_name(), - )?; - - while let Some(key) = map.next_key_seed(ReflectValueDeserializer { - inner: self.inner, - registration: key_registration, - })? { - let value = map.next_value_seed(ReflectValueDeserializer { - registration: value_registration, - inner: self.inner, - })?; - output.insert_boxed(key, value); - } - - Ok(output) - } -} diff --git a/src.bkup/networking/serialization/ser.rs b/src.bkup/networking/serialization/ser.rs deleted file mode 100644 index 0dbab2f0c9..0000000000 --- a/src.bkup/networking/serialization/ser.rs +++ /dev/null @@ -1,169 +0,0 @@ -use bevy::reflect::{serde::Serializable, ReflectRef, TypeRegistryInternal}; -use serde::ser::{Error, SerializeMap, SerializeSeq, SerializeTuple}; - -use super::StringCache; -use crate::prelude::*; - -pub struct CompactReflectSerializer<'a>(SerializerInner<'a>); - -#[derive(Clone, Copy)] -struct SerializerInner<'a> { - value: &'a dyn Reflect, - registry: &'a TypeRegistryInternal, - type_names: &'a StringCache, -} - -impl<'a> SerializerInner<'a> { - fn serializable(&self) -> Result { - let reflect_serialize = self - .registry - .get_type_data::(self.value.type_id()) - .ok_or_else(|| { - serde::ser::Error::custom(format_args!( - "Type '{}' did not register ReflectSerialize", - self.value.type_name() - )) - })?; - Ok(reflect_serialize.get_serializable(self.value)) - } - - fn for_value<'b>(&self, value: &'a dyn Reflect) -> SerializerInner<'b> - where - 'a: 'b, - { - let mut s = *self; - s.value = value; - s - } -} - -impl<'a> CompactReflectSerializer<'a> { - pub fn new( - value: &'a dyn Reflect, - registry: &'a TypeRegistryInternal, - type_name_cache: &'a StringCache, - ) -> Self { - CompactReflectSerializer(SerializerInner { - value, - registry, - type_names: type_name_cache, - }) - } - - fn value_serializer(&self) -> ValueSerializer { - ValueSerializer(self.0) - } -} - -impl<'a> Serialize for CompactReflectSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let mut tup = serializer.serialize_tuple(2)?; - - let type_name = self.0.value.type_name(); - let type_idx = self.0.type_names.get_idx(type_name).ok_or_else(|| { - Error::custom(format_args!("Type name not in string cache: {}", type_name)) - })?; - tup.serialize_element(&type_idx)?; - tup.serialize_element(&self.value_serializer())?; - - tup.end() - } -} - -struct ValueSerializer<'a>(SerializerInner<'a>); - -impl<'a> Serialize for ValueSerializer<'a> { - fn serialize(&self, serializer: S) -> Result - where - S: serde::Serializer, - { - let serializable = self.0.serializable::(); - if let Ok(serializable) = serializable { - return serializable.borrow().serialize(serializer); - } - - trace!("Serializing {}", self.0.value.type_name()); - - match self.0.value.reflect_ref() { - ReflectRef::Struct(s) => { - let len = s.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for (i, field) in s.iter_fields().enumerate() { - trace!("Serializing field named `{:?}`", s.name_at(i).unwrap()); - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::TupleStruct(s) => { - let len = s.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for field in s.iter_fields() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::Tuple(t) => { - let len = t.field_len(); - let mut tup = serializer.serialize_tuple(len)?; - for field in t.iter_fields() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - tup.serialize_element(&field_serializer)?; - } - tup.end() - } - ReflectRef::List(l) => { - let len = l.len(); - let mut seq = serializer.serialize_seq(Some(len))?; - for field in l.iter() { - let field_serializer = ValueSerializer(SerializerInner { - value: field, - ..self.0 - }); - - seq.serialize_element(&field_serializer)?; - } - seq.end() - } - ReflectRef::Array(a) => { - let len = a.len(); - let mut seq = serializer.serialize_seq(Some(len))?; - for field in a.iter() { - let field_serializer = ValueSerializer(self.0.for_value(field)); - - seq.serialize_element(&field_serializer)?; - } - seq.end() - } - ReflectRef::Map(m) => { - let len = m.len(); - let mut map = serializer.serialize_map(Some(len))?; - for (key, value) in m.iter() { - map.serialize_entry( - &ValueSerializer(self.0.for_value(key)), - &ValueSerializer(self.0.for_value(value)), - )?; - } - - map.end() - } - ReflectRef::Value(_) => Err(serializable.err().unwrap()), - } - } -} diff --git a/src.bkup/networking/server/player_input.rs b/src.bkup/networking/server/player_input.rs deleted file mode 100644 index 86042c7353..0000000000 --- a/src.bkup/networking/server/player_input.rs +++ /dev/null @@ -1,35 +0,0 @@ -use crate::{ - networking::proto::player_input::{PlayerInputFromClient, PlayerInputFromServer}, - player::input::PlayerInputs, - prelude::*, -}; - -use super::NetServer; - -pub struct ServerPlayerInputPlugin; - -impl Plugin for ServerPlayerInputPlugin { - fn build(&self, app: &mut App) { - app.add_system_to_stage(CoreStage::First, recv_player_input); - } -} - -fn recv_player_input(mut server: ResMut, mut player_inputs: ResMut) { - // FIXME: We are not ordering packets, so we may apply a stale user input, which is not good. We - // need to track a network tick to know what the latest input really is. - while let Some(incomming) = server.recv_unreliable::() { - let input = &mut player_inputs.players[incomming.client_idx]; - - input.control = incomming.message.control.clone(); - - // FIXME: We may receive multiple updates for each user, so we may send multiple updates to - // the client, but we don't want to do that, we should just send one update per changed client. - server.send_unreliable_to( - &PlayerInputFromServer { - player_idx: incomming.client_idx.try_into().unwrap(), - control: incomming.message.control, - }, - super::MessageTarget::AllExcept(incomming.client_idx), - ) - } -} diff --git a/src.bkup/scripting/ops/net_commands.rs b/src.bkup/scripting/ops/net_commands.rs deleted file mode 100644 index c4c2a76f2c..0000000000 --- a/src.bkup/scripting/ops/net_commands.rs +++ /dev/null @@ -1,161 +0,0 @@ -use anyhow::{format_err, Context}; -use bevy::ecs::system::SystemState; -use bevy::prelude::{default, ReflectComponent}; -use bevy::reflect::TypeRegistryArc; - -use bevy_mod_js_scripting::{serde_json, JsRuntimeOp, JsValueRef, JsValueRefs, OpContext}; - -use crate::networking::serialization::TypeNameCache; -use crate::networking::server::NetServer; -use crate::{ - networking::{ - commands::CommandMessage, - serialization::{ser::CompactReflectSerializer, serialize_to_bytes}, - NetIdMap, - }, - prelude::*, -}; - -pub struct NetCommandsSpawn; -impl JsRuntimeOp for NetCommandsSpawn { - fn js(&self) -> Option<&'static str> { - Some( - r#" - if (!globalThis.NetCommands) { - globalThis.NetCommands = {} - } - - globalThis.NetCommands.spawn = () => { - return Value.wrapValueRef( - bevyModJsScriptingOpSync("jumpy_net_commands_spawn") - ); - } - "#, - ) - } - - fn run( - &self, - context: OpContext<'_>, - world: &mut bevy::prelude::World, - args: serde_json::Value, - ) -> anyhow::Result { - // Expect empty arguments - let _: [(); 0] = serde_json::from_value(args).context("parse args")?; - - let value_refs = context - .op_state - .entry::() - .or_insert_with(default); - - let mut net_commands_state = SystemState::::new(world); - let entity = { - let mut net_commands = net_commands_state.get_mut(world); - net_commands.spawn().id() - }; - - net_commands_state.apply(world); - - let value_ref = JsValueRef::new_free(Box::new(entity), value_refs); - - Ok(serde_json::to_value(value_ref)?) - } -} - -pub struct NetCommandsInsert; -impl JsRuntimeOp for NetCommandsInsert { - fn js(&self) -> Option<&'static str> { - Some( - r#" - if (!globalThis.NetCommands) { - globalThis.NetCommands = {} - } - - globalThis.NetCommands.insert = (entity, component) => { - bevyModJsScriptingOpSync( - "jumpy_net_commands_insert", - Value.unwrapValueRef(entity), - Value.unwrapValueRef(component) - ); - } - "#, - ) - } - - fn run( - &self, - context: OpContext<'_>, - world: &mut bevy::prelude::World, - args: serde_json::Value, - ) -> anyhow::Result { - // Parse args - let (entity_value_ref, component_value_ref): (JsValueRef, JsValueRef) = - serde_json::from_value(args).context("parse args")?; - - let mut server = world.remove_resource::(); - - let value_refs = context - .op_state - .entry::() - .or_insert_with(default); - - // Get entity and make sure the entity exists - let entity = entity_value_ref.get_entity(world, value_refs)?; - world - .get_entity(entity) - .ok_or_else(|| format_err!("Entity does not exist"))?; - - let component_value_ref = value_refs - .get(component_value_ref.key) - .ok_or_else(|| format_err!("Value ref doesn't exist"))? - .clone(); - - // Load the type registry - let type_registry = world.resource::(); - let type_names = world.resource::(); - let net_ids = world.resource::(); - let type_registry = type_registry.read(); - - // Clone the reflect value of the component - let reflect_value_ref = component_value_ref.get(world)?; - let type_id = reflect_value_ref.type_id(); - let reflect_value = reflect_value_ref.clone_value(); - - // Get the ReflectComponent - let type_registration = type_registry.get(type_id).expect("Type not registered"); - let reflect_component = type_registration - .data::() - .ok_or_else(|| format_err!("ReflectComponent not found for component value ref"))? - .clone(); - - if let Some(server) = &mut server { - let net_id = net_ids.get_net_id(entity).expect("Entity has no NetId"); - let serializable = CompactReflectSerializer::new( - reflect_value_ref.as_reflect(), - &type_registry, - &type_names.0, - ); - let component_bytes = serialize_to_bytes(&serializable).expect("Serialize component"); - - // Send component insertion message over the network - let type_name = type_registration.type_name(); - server.broadcast_reliable(&CommandMessage::Insert { - net_id, - component_bytes, - type_name: type_name.into(), - }); - } - - // Drop our immutable borrow of the world - drop(type_registry); - drop(reflect_value_ref); - - reflect_component.apply_or_insert(world, entity, reflect_value.as_reflect()); - - if let Some(server) = server { - world.insert_resource(server); - } - - Ok(serde_json::Value::Null) - } -} diff --git a/src/assets.rs b/src/assets.rs index 145070ace9..eb8e290580 100644 --- a/src/assets.rs +++ b/src/assets.rs @@ -8,7 +8,6 @@ use bevy::{ reflect::TypeUuid, }; use bevy_egui::egui; -use bevy_mod_js_scripting::{serde_json, JsScript}; use normalize_path::NormalizePath; use crate::{ @@ -26,7 +25,8 @@ pub struct AssetPlugin; impl Plugin for AssetPlugin { fn build(&self, app: &mut App) { - app.register_type::>() + app + // .register_type::>() .register_type::>() .add_jumpy_asset::() .add_asset_loader(GameMetaLoader) @@ -208,14 +208,14 @@ impl AssetLoader for GameMetaLoader { ); } - // Load the script handles - for script_relative_path in &meta.scripts { - let (script_path, script_handle) = - get_relative_asset(load_context, self_path, script_relative_path); - dependencies.push(script_path.clone()); - meta.script_handles - .push(AssetHandle::new(script_path, script_handle.typed())); - } + // // Load the script handles + // for script_relative_path in &meta.scripts { + // let (script_path, script_handle) = + // get_relative_asset(load_context, self_path, script_relative_path); + // dependencies.push(script_path.clone()); + // meta.script_handles + // .push(AssetHandle::new(script_path, script_handle.typed())); + // } load_context.set_default_asset(LoadedAsset::new(meta).with_dependencies(dependencies)); @@ -238,6 +238,7 @@ impl AssetLoader for PlayerMetaLoader { ) -> bevy::utils::BoxedFuture<'a, Result<(), anyhow::Error>> { Box::pin(async move { let self_path = load_context.path(); + let mut dependencies = Vec::new(); let mut meta: PlayerMeta = if self_path.extension() == Some(OsStr::new("json")) { serde_json::from_slice(bytes)? } else { @@ -248,6 +249,17 @@ impl AssetLoader for PlayerMetaLoader { let (atlas_path, atlas_handle) = get_relative_asset(load_context, load_context.path(), &meta.spritesheet.image); + for (sound, sound_handle) in [ + (&meta.sounds.jump, &mut meta.sounds.jump_handle), + (&meta.sounds.land, &mut meta.sounds.land_handle), + (&meta.sounds.grab, &mut meta.sounds.grab_handle), + (&meta.sounds.drop, &mut meta.sounds.drop_handle), + ] { + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); + } + let atlas_handle = load_context.set_labeled_asset( "atlas", LoadedAsset::new(TextureAtlas::from_grid( @@ -260,7 +272,7 @@ impl AssetLoader for PlayerMetaLoader { ); meta.spritesheet.atlas_handle = AssetHandle::new(atlas_path, atlas_handle); - load_context.set_default_asset(LoadedAsset::new(meta)); + load_context.set_default_asset(LoadedAsset::new(meta).with_dependencies(dependencies)); Ok(()) }) @@ -354,41 +366,63 @@ impl AssetLoader for MapElementMetaLoader { let mut dependencies = Vec::new(); - // Load the element script - for script in &meta.scripts { - let (script_path, script_handle) = - get_relative_asset(load_context, self_path, script); - meta.script_handles - .push(AssetHandle::new(script_path.clone(), script_handle.typed())); - dependencies.push(script_path); - } + // // Load the element script + // for script in &meta.scripts { + // let (script_path, script_handle) = + // get_relative_asset(load_context, self_path, script); + // meta.script_handles + // .push(AssetHandle::new(script_path.clone(), script_handle.typed())); + // dependencies.push(script_path); + // } // Load assets for built-in types match &mut meta.builtin { BuiltinElementKind::None => (), BuiltinElementKind::PlayerSpawner => (), - BuiltinElementKind::Sproinger { + BuiltinElementKind::AnimatedDecoration { atlas, atlas_handle, + .. + } => { + let (path, handle) = get_relative_asset(load_context, self_path, atlas); + *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); + dependencies.push(path); } - | BuiltinElementKind::AnimatedDecoration { + BuiltinElementKind::Sword { atlas, atlas_handle, - .. + sound, + sound_handle, + } => { + let (path, handle) = get_relative_asset(load_context, self_path, atlas); + *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); + dependencies.push(path); + + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); } - | BuiltinElementKind::Sword { + BuiltinElementKind::Sproinger { atlas, atlas_handle, + sound, + sound_handle, } => { let (path, handle) = get_relative_asset(load_context, self_path, atlas); *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); + + let (path, handle) = get_relative_asset(load_context, self_path, sound); + dependencies.push(path); + *sound_handle = handle.typed(); } BuiltinElementKind::Grenades { atlas, atlas_handle, explosion_atlas, explosion_atlas_handle, + explosion_sound, + explosion_sound_handle, .. } => { for (atlas, atlas_handle) in [ @@ -399,6 +433,10 @@ impl AssetLoader for MapElementMetaLoader { *atlas_handle = AssetHandle::new(path.clone(), handle.typed()); dependencies.push(path); } + let (sound_path, sound_handle) = + get_relative_asset(load_context, self_path, explosion_sound); + dependencies.push(sound_path); + *explosion_sound_handle = sound_handle.typed(); } } diff --git a/src/audio.rs b/src/audio.rs index a5b7980f18..39f384e217 100644 --- a/src/audio.rs +++ b/src/audio.rs @@ -15,11 +15,14 @@ impl Plugin for AudioPlugin { .init_resource::() .init_resource::() .add_audio_channel::() + .add_audio_channel::() + .add_startup_system(setup_audio_defaults) .add_system(music_system.run_if_resource_exists::()); } } pub struct MusicChannel; +pub struct EffectsChannel; #[derive(Clone, Debug, Default)] pub struct CurrentMusic { @@ -30,6 +33,14 @@ pub struct CurrentMusic { #[derive(Deref, DerefMut, Clone, Debug, Default)] pub struct ShuffledPlaylist(pub Vec>); +fn setup_audio_defaults( + music: Res>, + effects: Res>, +) { + music.set_volume(0.12); + effects.set_volume(0.1); +} + /// Loops through all the game music as the game is on. fn music_system( game: Res, diff --git a/src/loading.rs b/src/loading.rs index b1da6724df..630cf9b42d 100644 --- a/src/loading.rs +++ b/src/loading.rs @@ -2,7 +2,6 @@ use bevy::{ecs::system::SystemParam, render::camera::ScalingMode}; use bevy_egui::{egui, EguiContext}; use bevy_fluent::Locale; use bevy_has_load_progress::{HasLoadProgress, LoadingResources}; -use bevy_mod_js_scripting::ActiveScripts; use leafwing_input_manager::{ axislike::{AxisType, SingleAxis}, prelude::InputMap, @@ -99,7 +98,7 @@ pub struct GameLoader<'w, 's> { game_assets: ResMut<'w, Assets>, egui_ctx: Option>, events: EventReader<'w, 's, AssetEvent>, - active_scripts: ResMut<'w, ActiveScripts>, + // active_scripts: ResMut<'w, ActiveScripts>, storage: ResMut<'w, Storage>, player_assets: ResMut<'w, Assets>, texture_atlas_assets: Res<'w, Assets>, @@ -126,7 +125,7 @@ impl<'w, 's> GameLoader<'w, 's> { game_handle, mut game_assets, mut egui_ctx, - mut active_scripts, + // mut active_scripts, mut clear_color, mut storage, mut player_assets, @@ -142,10 +141,10 @@ impl<'w, 's> GameLoader<'w, 's> { // event, we need to skip the next update event. *skip_next_asset_update_event = true; - // Clear the active scripts - active_scripts.clear(); + // // Clear the active scripts + // active_scripts.clear(); - // One-time initialization + // One-time initialization } else { if let Some(ctx) = egui_ctx.as_mut() { // Initialize empty fonts for all game fonts. @@ -238,10 +237,10 @@ impl<'w, 's> GameLoader<'w, 's> { } } - // Set the active scripts - for script_handle in &game.script_handles { - active_scripts.insert(script_handle.inner.clone_weak()); - } + // // Set the active scripts + // for script_handle in &game.script_handles { + // active_scripts.insert(script_handle.inner.clone_weak()); + // } // Insert the game resource commands.insert_resource(game.clone()); diff --git a/src/main.rs b/src/main.rs index a8d75a1275..da2d2bbbb1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -47,7 +47,7 @@ pub mod prelude; pub mod random; pub mod run_criteria; pub mod schedule; -pub mod scripting; +// pub mod scripting; pub mod session; pub mod ui; pub mod utils; @@ -74,7 +74,6 @@ use crate::{ player::PlayerPlugin, prelude::*, random::RandomPlugin, - scripting::ScriptingPlugin, session::SessionPlugin, ui::UiPlugin, utils::{is_in_game_run_criteria, UtilsPlugin}, @@ -232,7 +231,7 @@ pub fn main() { .add_plugin(WorkaroundsPlugin) .add_plugin(DebugPlugin) .add_plugin(RandomPlugin) - .add_plugin(ScriptingPlugin) + // .add_plugin(ScriptingPlugin) .add_plugin(NetworkingPlugin) .add_plugin(SessionPlugin); diff --git a/src/map.rs b/src/map.rs index 1f3cd288ee..a1dbf4c5d8 100644 --- a/src/map.rs +++ b/src/map.rs @@ -1,6 +1,6 @@ -use bevy::{render::view::RenderLayers, utils::HashSet}; +use bevy::render::view::RenderLayers; use bevy_ecs_tilemap::prelude::*; -use bevy_mod_js_scripting::{ActiveScripts, JsScript}; +// use bevy_mod_js_scripting::{ActiveScripts, JsScript}; use bevy_parallax::ParallaxResource; use bevy_prototype_lyon::{prelude::*, shapes::Rectangle}; @@ -21,7 +21,7 @@ pub struct MapPlugin; impl Plugin for MapPlugin { fn build(&self, app: &mut App) { app.add_plugin(TilemapPlugin) - .init_resource::() + // .init_resource::() .add_system(hydrate_maps) .extend_rollback_plugin(|plugin| { plugin @@ -38,9 +38,9 @@ impl Plugin for MapPlugin { #[reflect(Component, Default)] pub struct MapElementHydrated; -/// Contains the scripts that have been added for the currently loaded map -#[derive(Deref, DerefMut, Default)] -pub struct MapScripts(pub HashSet>); +// /// Contains the scripts that have been added for the currently loaded map +// #[derive(Deref, DerefMut, Default)] +// pub struct MapScripts(pub HashSet>); /// Marker component for the map grid #[derive(Component)] @@ -54,8 +54,8 @@ pub fn hydrate_maps( asset_server: Res, mut texture_atlas_assets: ResMut>, element_assets: ResMut>, - mut active_scripts: ResMut, - mut map_scripts: ResMut, + // mut active_scripts: ResMut, + // mut map_scripts: ResMut, mut rids: ResMut, unspawned_maps: Query<(Entity, &AssetHandle), Without>, ) { @@ -101,10 +101,10 @@ pub fn hydrate_maps( .id(); map_children.push(grid_entity); - // Clear any previously loaded map scripts - for script in map_scripts.drain() { - active_scripts.remove(&script); - } + // // Clear any previously loaded map scripts + // for script in map_scripts.drain() { + // active_scripts.remove(&script); + // } let mut current_map_element_idx = 0; @@ -195,10 +195,10 @@ pub fn hydrate_maps( for element in &element_layer.elements { let element_meta = element_assets.get(&element.element_handle).unwrap().clone(); - for script_handle in &element_meta.script_handles { - active_scripts.insert(script_handle.inner.clone_weak()); - map_scripts.insert(script_handle.inner.clone_weak()); - } + // for script_handle in &element_meta.script_handles { + // active_scripts.insert(script_handle.inner.clone_weak()); + // map_scripts.insert(script_handle.inner.clone_weak()); + // } let element_name = &element_meta.name; diff --git a/src/map/elements/grenade.rs b/src/map/elements/grenade.rs index 44e2bc3207..b6ed714fd3 100644 --- a/src/map/elements/grenade.rs +++ b/src/map/elements/grenade.rs @@ -92,7 +92,7 @@ fn pre_update_in_game( repeat: false, ..default() }) - .insert(map_element_handle.clone()) + .insert(map_element_handle.clone_weak()) .insert_bundle(VisibilityBundle::default()) .insert_bundle(TransformBundle { local: *transform, @@ -194,7 +194,7 @@ fn update_idle_grenades( atlas: atlas_handle.inner.clone(), ..default() }) - .insert(meta_handle.clone()) + .insert(meta_handle.clone_weak()) .insert(body.clone()) .insert(LitGrenade { spawner: grenade.spawner, @@ -211,7 +211,7 @@ fn update_idle_grenades( // If the item is dropped if let Some(dropped) = dropped { commands.entity(item_ent).remove::(); - let (.., player_transform, player_body) = + let (player_sprite, player_transform, player_body) = players.get(dropped.player).expect("Parent is not a player"); // Re-activate physics @@ -223,8 +223,15 @@ fn update_idle_grenades( body.velocity = player_body.velocity; body.is_spawning = true; + let horizontal_flip_factor = if player_sprite.flip_x { + Vec2::new(-1.0, 1.0) + } else { + Vec2::ONE + }; + // Drop item at player position - transform.translation = player_transform.translation + grab_offset.extend(0.0); + transform.translation = + player_transform.translation + (*grab_offset * horizontal_flip_factor).extend(0.0); } } } @@ -243,6 +250,8 @@ fn update_lit_grenades( >, mut ridp: ResMut, element_assets: ResMut>, + player_inputs: Res, + effects: Res>, ) { let mut items = grenades.iter_mut().collect::>(); items.sort_by_key(|x| x.0.id()); @@ -256,6 +265,7 @@ fn update_lit_grenades( explosion_lifetime, explosion_fps, explosion_frames, + explosion_sound_handle, .. } = &meta.builtin else { unreachable!(); @@ -264,6 +274,10 @@ fn update_lit_grenades( grenade.age += 1.0 / crate::FPS as f32; if grenade.age >= *fuse_time { + if player_inputs.is_confirmed { + effects.play(explosion_sound_handle.clone_weak()); + } + // Despawn the grenade commands.entity(item_ent).despawn(); // Cause the item to re-spawn by re-triggering spawner hydration diff --git a/src/map/elements/sproinger.rs b/src/map/elements/sproinger.rs index aa52ac4e86..3fa1e6fd06 100644 --- a/src/map/elements/sproinger.rs +++ b/src/map/elements/sproinger.rs @@ -1,5 +1,3 @@ -use crate::metadata::BuiltinElementKind; - use super::*; const FORCE: f32 = 30.0; @@ -58,14 +56,33 @@ fn pre_update_in_game( } fn update_in_game( - mut sproingers: Query<(Entity, &mut Sproinger, &mut AnimatedSprite)>, + mut sproingers: Query<( + Entity, + &mut Sproinger, + &Handle, + &mut AnimatedSprite, + )>, mut bodies: Query<&mut KinematicBody>, collision_world: CollisionWorld, + element_assets: ResMut>, + player_inputs: Res, + sound_effects: Res>, ) { - for (sproinger_ent, mut sproinger, mut sprite) in &mut sproingers { + for (sproinger_ent, mut sproinger, meta_handle, mut sprite) in &mut sproingers { + let meta = element_assets.get(meta_handle).unwrap(); + let BuiltinElementKind::Sproinger { sound_handle, .. } = &meta.builtin else { + continue; + }; + if sproinger.sproinging { match sproinger.frame { - 1 => sprite.index = 2, + 1 => { + // Only play the sound effect if this is a frame that will not be rolled back + if player_inputs.is_confirmed { + sound_effects.play(sound_handle.clone_weak()); + } + sprite.index = 2 + } 4 => sprite.index = 3, 8 => sprite.index = 4, 12 => sprite.index = 5, diff --git a/src/map/elements/sword.rs b/src/map/elements/sword.rs index 60466a0e25..a94d16a159 100644 --- a/src/map/elements/sword.rs +++ b/src/map/elements/sword.rs @@ -90,6 +90,7 @@ fn update_in_game( &mut SwordState, &mut AnimatedSprite, &mut KinematicBody, + &Handle, Option<&Parent>, Option<&ItemUsed>, Option<&ItemDropped>, @@ -97,6 +98,9 @@ fn update_in_game( Without, >, mut ridp: ResMut, + player_inputs: Res, + effects: Res>, + element_assets: Res>, ) { // Helper to spawn damage regions let mut spawn_damage_region = @@ -117,11 +121,17 @@ fn update_in_game( mut state, mut sprite, mut body, + meta_handle, parent, item_used, item_dropped, ) in &mut swords { + let meta = element_assets.get(meta_handle).unwrap(); + let BuiltinElementKind::Sword { sound_handle, .. } = &meta.builtin else { + unreachable!(); + }; + // For all tiems that are being held if let Some(parent) = parent { let (player_sprite, player_transform, ..) = @@ -217,6 +227,9 @@ fn update_in_game( sprite.start = 8; sprite.end = 12; *state = SwordState::Swinging { frame: 0 }; + if player_inputs.is_confirmed { + effects.play(sound_handle.clone_weak()); + } } } diff --git a/src/metadata.rs b/src/metadata.rs index e900eb3b27..0443750382 100644 --- a/src/metadata.rs +++ b/src/metadata.rs @@ -5,7 +5,6 @@ use crate::prelude::*; use bevy::{reflect::TypeUuid, utils::HashMap}; use bevy_has_load_progress::HasLoadProgress; use bevy_kira_audio::AudioSource; -use bevy_mod_js_scripting::JsScript; mod localization; mod map; @@ -51,12 +50,11 @@ pub struct GameMeta { pub playlist: Vec, #[serde(skip)] pub playlist_handles: Vec>, - - /// Scripts that run on both the server and the client - #[serde(default)] - pub scripts: Vec, - #[serde(skip)] - pub script_handles: Vec>, + // /// Scripts that run on both the server and the client + // #[serde(default)] + // pub scripts: Vec, + // #[serde(skip)] + // pub script_handles: Vec>, } #[derive(HasLoadProgress, Deserialize, Clone, Debug)] diff --git a/src/metadata/map.rs b/src/metadata/map.rs index de7a59787c..0dc4d741ce 100644 --- a/src/metadata/map.rs +++ b/src/metadata/map.rs @@ -173,8 +173,8 @@ impl From for ParallaxLayerData { pub struct MapElementMeta { pub name: String, pub category: String, - #[serde(default)] - pub scripts: Vec, + // #[serde(default)] + // pub scripts: Vec, #[serde(default)] #[has_load_progress(none)] pub builtin: BuiltinElementKind, @@ -183,8 +183,8 @@ pub struct MapElementMeta { #[serde(default = "editor_size_default")] pub editor_size: Vec2, - #[serde(skip)] - pub script_handles: Vec>, + // #[serde(skip)] + // pub script_handles: Vec>, /// Assets that should be pre-loaded by the game before starting #[serde(default)] pub preload_assets: Vec, @@ -218,6 +218,9 @@ pub enum BuiltinElementKind { explosion_lifetime: f32, explosion_frames: usize, explosion_fps: f32, + explosion_sound: String, + #[serde(skip)] + explosion_sound_handle: Handle, /// The time in seconds before a grenade explodes fuse_time: f32, #[serde(default)] @@ -244,11 +247,17 @@ pub enum BuiltinElementKind { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, + sound: String, + #[serde(skip)] + sound_handle: Handle, }, /// This is a sword Sword { atlas: String, #[serde(skip)] atlas_handle: AssetHandle, + sound: String, + #[serde(skip)] + sound_handle: Handle, }, } diff --git a/src/metadata/player.rs b/src/metadata/player.rs index 327386c02a..8baf54e177 100644 --- a/src/metadata/player.rs +++ b/src/metadata/player.rs @@ -21,6 +21,7 @@ impl Plugin for PlayerMetadataPlugin { pub struct PlayerMeta { pub name: String, pub spritesheet: PlayerSpritesheetMeta, + pub sounds: PlayerSounds, } #[derive(Reflect, Deserialize, Clone, Debug, Default)] @@ -39,6 +40,30 @@ pub struct PlayerSpritesheetMeta { pub animations: HashMap, } +#[derive(Reflect, Deserialize, Clone, Debug, Default)] +#[serde(deny_unknown_fields)] +pub struct PlayerSounds { + pub land: String, + pub land_volume: f32, + #[serde(skip)] + pub land_handle: Handle, + + pub jump: String, + pub jump_volume: f32, + #[serde(skip)] + pub jump_handle: Handle, + + pub grab: String, + pub grab_volume: f32, + #[serde(skip)] + pub grab_handle: Handle, + + pub drop: String, + pub drop_volume: f32, + #[serde(skip)] + pub drop_handle: Handle, +} + impl PlayerSpritesheetMeta { pub fn get_animation_bank_and_sprite(&self) -> (AnimationBank, AnimationBankSprite) { let animations = self diff --git a/src/player.rs b/src/player.rs index b6468178f9..c856adce5c 100644 --- a/src/player.rs +++ b/src/player.rs @@ -327,6 +327,7 @@ fn hydrate_players( entity_commands .insert(Name::new(format!("Player {}", player_idx.0))) + .insert(input.selected_player.inner.clone_weak()) .insert(PlayerState::default()) .insert(animation_bank) .insert(animation_bank_sprite) diff --git a/src/player/input.rs b/src/player/input.rs index 9effcbeb62..a9dc6d8853 100644 --- a/src/player/input.rs +++ b/src/player/input.rs @@ -99,12 +99,16 @@ pub enum PlayerAction { #[derive(Reflect, Clone, Debug, Component)] #[reflect(Default, Resource)] pub struct PlayerInputs { + /// This will be `true` if _all_ of the inputs for all players for this frame have been + /// confirmed and will not be rolled back. + pub is_confirmed: bool, pub players: Vec, } impl Default for PlayerInputs { fn default() -> Self { Self { + is_confirmed: false, players: vec![default(); MAX_PLAYERS], // has_updated: false, } @@ -218,6 +222,11 @@ fn update_user_input( inputs: Res>, mut player_inputs: ResMut, ) { + player_inputs.is_confirmed = inputs + .iter() + .map(|x| x.1) + .all(|x| x == InputStatus::Confirmed); + for (player_idx, (input, _)) in inputs.iter().enumerate() { let PlayerInput { control, diff --git a/src/player/state/states.rs b/src/player/state/states.rs index 7cbdf76e7d..27e6842155 100644 --- a/src/player/state/states.rs +++ b/src/player/state/states.rs @@ -3,6 +3,7 @@ use crate::prelude::*; use crate::{ animation::AnimationBankSprite, item::Item, + metadata::PlayerMeta, physics::collisions::CollisionWorld, physics::KinematicBody, player::{ diff --git a/src/player/state/states/idle.rs b/src/player/state/states/idle.rs index 3a27674e40..51d8cf408d 100644 --- a/src/player/state/states/idle.rs +++ b/src/player/state/states/idle.rs @@ -31,12 +31,17 @@ pub fn handle_player_state( Entity, &PlayerState, &PlayerIdx, + &Handle, &mut AnimationBankSprite, &mut KinematicBody, )>, collision_world: CollisionWorld, + player_assets: Res>, + effects: Res>, ) { - for (player_ent, player_state, player_idx, mut sprite, mut body) in &mut players { + for (player_ent, player_state, player_idx, meta_handle, mut sprite, mut body) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } @@ -78,12 +83,26 @@ pub fn handle_player_state( // Grab the first item we are touching if let Some((item, _)) = colliders.get(0) { commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item))); + + // Play grab sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.grab_handle.clone_weak()) + .with_volume(meta.sounds.grab_volume as _); + } } // If we are already carrying an item } else { // Drop it commands.add(PlayerSetInventoryCommand::new(player_ent, None)); + + // Play drop sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.drop_handle.clone_weak()) + .with_volume(meta.sounds.drop_volume as _); + } } } @@ -94,6 +113,15 @@ pub fn handle_player_state( // If we are jumping if control.jump_just_pressed { + // Play jump sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.jump_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.jump_volume as _); + } + // Move up body.velocity.y = JUMP_SPEED; } diff --git a/src/player/state/states/midair.rs b/src/player/state/states/midair.rs index 1cb1f9ced9..3820a54c7f 100644 --- a/src/player/state/states/midair.rs +++ b/src/player/state/states/midair.rs @@ -4,13 +4,28 @@ pub const ID: &str = "core:midair"; pub const AIR_MOVE_SPEED: f32 = 7.0; -pub fn player_state_transition(mut players: Query<(&mut PlayerState, &KinematicBody)>) { - for (mut player_state, body) in &mut players { +pub fn player_state_transition( + mut players: Query<(&mut PlayerState, &KinematicBody, &Handle)>, + player_inputs: Res, + effects: Res>, + player_assets: Res>, +) { + for (mut player_state, body, meta_handle) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } if body.is_on_ground { + // Play land sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.land_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.land_volume as _); + } player_state.id = idle::ID.into(); } } diff --git a/src/player/state/states/walk.rs b/src/player/state/states/walk.rs index 5e71a5c1b6..8a07566f54 100644 --- a/src/player/state/states/walk.rs +++ b/src/player/state/states/walk.rs @@ -32,12 +32,17 @@ pub fn handle_player_state( Entity, &PlayerState, &PlayerIdx, + &Handle, &mut AnimationBankSprite, &mut KinematicBody, )>, collision_world: CollisionWorld, + effects: Res>, + player_assets: Res>, ) { - for (player_ent, player_state, player_idx, mut sprite, mut body) in &mut players { + for (player_ent, player_state, player_idx, meta_handle, mut sprite, mut body) in &mut players { + let meta = player_assets.get(meta_handle).unwrap(); + if player_state.id != ID { continue; } @@ -79,12 +84,26 @@ pub fn handle_player_state( // Grab the first item we are touching if let Some((item, _)) = colliders.get(0) { commands.add(PlayerSetInventoryCommand::new(player_ent, Some(*item))); + + // Play grab sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.grab_handle.clone_weak()) + .with_volume(meta.sounds.grab_volume as _); + } } // If we are already carrying an item } else { // Drop it commands.add(PlayerSetInventoryCommand::new(player_ent, None)); + + // Play drop sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.drop_handle.clone_weak()) + .with_volume(meta.sounds.drop_volume as _); + } } } @@ -95,6 +114,15 @@ pub fn handle_player_state( // If we are jumping if control.jump_just_pressed { + // Play jump sound + if player_inputs.is_confirmed { + effects + .play(meta.sounds.jump_handle.clone_weak()) + // TODO: This volume should be relative to the current channel volume, not + // hard-coded, so that when the user changes the sound effect volume it's relative. + .with_volume(meta.sounds.jump_volume as _); + } + // Move up body.velocity.y = JUMP_SPEED; } diff --git a/src/prelude.rs b/src/prelude.rs index 9448a141bf..d24375c0c7 100644 --- a/src/prelude.rs +++ b/src/prelude.rs @@ -1,9 +1,13 @@ pub use crate::{ - assets::AssetHandle, schedule::RollbackScheduleAppExt, utils::event::FixedUpdateEventAppExt, + assets::AssetHandle, + audio::{EffectsChannel, MusicChannel}, + schedule::RollbackScheduleAppExt, + utils::event::FixedUpdateEventAppExt, GameState, InGameState, RollbackStage, }; pub use bevy::prelude::*; pub use bevy_ggrs::{Rollback, RollbackIdProvider}; +pub use bevy_kira_audio::prelude::*; pub use iyes_loopless::prelude::*; pub use leafwing_input_manager::prelude::*; pub use serde::{Deserialize, Serialize}; diff --git a/src/ui/main_menu.rs b/src/ui/main_menu.rs index 498f6b0bf2..a333648e2b 100644 --- a/src/ui/main_menu.rs +++ b/src/ui/main_menu.rs @@ -75,7 +75,7 @@ pub fn setup_main_menu( } // Spawn menu background - let bg_handle = game.main_menu.background_image.image_handle.clone(); + let bg_handle = game.main_menu.background_image.image_handle.clone_weak(); let img_size = game.main_menu.background_image.image_size; let ratio = img_size.x / img_size.y; let height = game.camera_height as f32;