From f56e1d84b5985087df5f896bbd3cc159a26e6221 Mon Sep 17 00:00:00 2001 From: Christof Petig Date: Sat, 10 Feb 2024 09:35:04 +0000 Subject: [PATCH] Use wasmtime to execute wasm components as veloren plugins --- CHANGELOG.md | 1 + Cargo.lock | 1623 +++++++++++---------- Cargo.toml | 4 +- common/state/Cargo.toml | 10 +- common/state/src/plugin/errors.rs | 28 +- common/state/src/plugin/exports.rs | 139 -- common/state/src/plugin/memory_manager.rs | 149 +- common/state/src/plugin/mod.rs | 154 +- common/state/src/plugin/module.rs | 574 ++++---- common/state/src/plugin/wasm_env.rs | 119 -- common/state/src/state.rs | 6 +- network/Cargo.toml | 2 +- network/protocol/Cargo.toml | 2 +- plugin/api/Cargo.toml | 9 - plugin/api/src/errors.rs | 71 - plugin/api/src/lib.rs | 228 --- plugin/derive/Cargo.toml | 15 - plugin/derive/src/lib.rs | 76 - plugin/examples/hello/Cargo.lock | 25 + plugin/examples/hello/Cargo.toml | 22 + plugin/examples/hello/src/lib.rs | 54 + plugin/rt/Cargo.toml | 18 - plugin/rt/examples/hello.rs | 46 - plugin/rt/src/lib.rs | 106 -- plugin/rt/src/retrieve.rs | 35 - plugin/wit/veloren.wit | 56 + server/Cargo.toml | 2 - server/src/events/mounting.rs | 3 +- server/src/lib.rs | 85 +- server/src/sys/msg/register.rs | 3 +- 30 files changed, 1458 insertions(+), 2207 deletions(-) delete mode 100644 common/state/src/plugin/exports.rs delete mode 100644 common/state/src/plugin/wasm_env.rs delete mode 100644 plugin/api/Cargo.toml delete mode 100644 plugin/api/src/errors.rs delete mode 100644 plugin/api/src/lib.rs delete mode 100644 plugin/derive/Cargo.toml delete mode 100644 plugin/derive/src/lib.rs create mode 100644 plugin/examples/hello/Cargo.lock create mode 100644 plugin/examples/hello/Cargo.toml create mode 100644 plugin/examples/hello/src/lib.rs delete mode 100644 plugin/rt/Cargo.toml delete mode 100644 plugin/rt/examples/hello.rs delete mode 100644 plugin/rt/src/lib.rs delete mode 100644 plugin/rt/src/retrieve.rs create mode 100644 plugin/wit/veloren.wit diff --git a/CHANGELOG.md b/CHANGELOG.md index b05a62def2..730672dbeb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -84,6 +84,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 - Camera no longer jumps on first mouse event after cursor grab is released on macos - Updated wgpu. Now supports OpenGL. Dx11 no longer supported. - Changes center_cursor to be reset_cursor_position so the cursor is effectively grabbed +- Plugin interface based on WASI 0.2 WIT, wasmtime executes these components ### Removed - Medium and large potions from all loot tables diff --git a/Cargo.lock b/Cargo.lock index 93260f1f49..1c480ec7a9 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -24,7 +24,7 @@ version = "0.21.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a30b2e23b9e17a9f90641c7ab1549cd9b44f296d3ccbf309d2863cfe398a0cb" dependencies = [ - "gimli 0.28.1", + "gimli", ] [[package]] @@ -106,6 +106,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "ambient-authority" +version = "0.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e9d4ee0d472d1cd2e28c97dfa124b3d8d992e10eb0a035f33f5d12e3a177ba3b" + [[package]] name = "android-activity" version = "0.4.3" @@ -250,6 +256,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "arbitrary" +version = "1.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7d5a26814d8dcb93b0e5a0ff3c6d80a8843bafb21b39e8e18a6f05471870e110" + [[package]] name = "arr_macro" version = "0.2.1" @@ -474,12 +486,6 @@ dependencies = [ "rustc-demangle", ] -[[package]] -name = "base-x" -version = "0.2.11" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4cbbc9d0964165b47557570cce6c952866c2678457aca742aafc9fb771d30270" - [[package]] name = "base64" version = "0.21.7" @@ -608,28 +614,6 @@ version = "3.14.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f30e7476521f6f8af1a1c4c0b8cc94f0bee37d91763d0ca2665f299b6cd8aec" -[[package]] -name = "bytecheck" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "23cdc57ce23ac53c931e88a43d06d070a6fd142f2617be5855eb75efc9beb1c2" -dependencies = [ - "bytecheck_derive", - "ptr_meta", - "simdutf8", -] - -[[package]] -name = "bytecheck_derive" -version = "0.6.12" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3db406d29fbcd95542e92559bed4d8ad92636d1ca8b3b72ede10b4bcc010e659" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "bytemuck" version = "1.14.1" @@ -682,6 +666,83 @@ version = "2.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4bdcae87153686017415ce77e48c53e6818a0a058f0e21b56640d1e944967ef8" +[[package]] +name = "cap-fs-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "88e341d15ac1029aadce600be764a1a1edafe40e03cde23285bc1d261b3a4866" +dependencies = [ + "cap-primitives", + "cap-std", + "io-lifetimes", + "windows-sys 0.52.0", +] + +[[package]] +name = "cap-net-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "434168fe6533055f0f4204039abe3ff6d7db338ef46872a5fa39e9d5ad5ab7a9" +dependencies = [ + "cap-primitives", + "cap-std", + "rustix", + "smallvec", +] + +[[package]] +name = "cap-primitives" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe16767ed8eee6d3f1f00d6a7576b81c226ab917eb54b96e5f77a5216ef67abb" +dependencies = [ + "ambient-authority", + "fs-set-times", + "io-extras", + "io-lifetimes", + "ipnet", + "maybe-owned", + "rustix", + "windows-sys 0.52.0", + "winx", +] + +[[package]] +name = "cap-rand" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20e5695565f0cd7106bc3c7170323597540e772bb73e0be2cd2c662a0f8fa4ca" +dependencies = [ + "ambient-authority", + "rand 0.8.5", +] + +[[package]] +name = "cap-std" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "593db20e4c51f62d3284bae7ee718849c3214f93a3b94ea1899ad85ba119d330" +dependencies = [ + "cap-primitives", + "io-extras", + "io-lifetimes", + "rustix", +] + +[[package]] +name = "cap-time-ext" +version = "2.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "03261630f291f425430a36f38c847828265bc928f517cdd2004c56f4b02f002b" +dependencies = [ + "ambient-authority", + "cap-primitives", + "iana-time-zone", + "once_cell", + "rustix", + "winx", +] + [[package]] name = "cassowary" version = "0.3.0" @@ -869,7 +930,7 @@ version = "4.4.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cf9804afaaf59a91e75b022a30fb7229a7901f60c755489cc61c9b423b836442" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2 1.0.78", "quote 1.0.35", "syn 2.0.48", @@ -1070,12 +1131,6 @@ name = "conrod_winit" version = "0.63.0" source = "git+https://gitlab.com/veloren/conrod.git?branch=copypasta_0.7#59fddc617696e68d28a75c2137a08c2572efb986" -[[package]] -name = "const_fn" -version = "0.4.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fbdcdcb6d86f71c5e97409ad45898af11cbc995b4ee8112d59095a28d376c935" - [[package]] name = "constant_time_eq" version = "0.3.0" @@ -1155,19 +1210,6 @@ dependencies = [ "bindgen", ] -[[package]] -name = "corosensei" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "80128832c58ea9cbd041d2a759ec449224487b2c1e400453d99d244eead87a8e" -dependencies = [ - "autocfg", - "cfg-if 1.0.0", - "libc", - "scopeguard", - "windows-sys 0.33.0", -] - [[package]] name = "cpal" version = "0.13.5" @@ -1187,12 +1229,21 @@ dependencies = [ "nix 0.23.2", "oboe", "parking_lot 0.11.2", - "stdweb 0.1.3", + "stdweb", "thiserror", "web-sys", "winapi", ] +[[package]] +name = "cpp_demangle" +version = "0.3.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "eeaa953eaad386a53111e47172c2fedba671e5684c8dd601a5f474f4f118710f" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "cpufeatures" version = "0.2.12" @@ -1204,28 +1255,28 @@ dependencies = [ [[package]] name = "cranelift-bforest" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "2a2ab4512dfd3a6f4be184403a195f76e81a8a9f9e6c898e19d2dc3ce20e0115" +checksum = "d819feeda4c420a18f1e28236ca0ce1177b22bf7c8a44ddee92dfe40de15bcf0" dependencies = [ "cranelift-entity", ] [[package]] name = "cranelift-codegen" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "98b022ed2a5913a38839dfbafe6cf135342661293b08049843362df4301261dc" +checksum = "e9b8d03d5bdbca7e5f72b0e0a0f69933ed1f09e24be6c075aa6fe3f802b0cc0c" dependencies = [ - "arrayvec", "bumpalo", "cranelift-bforest", "cranelift-codegen-meta", "cranelift-codegen-shared", - "cranelift-egraph", + "cranelift-control", "cranelift-entity", "cranelift-isle", - "gimli 0.26.2", + "gimli", + "hashbrown 0.14.3", "log", "regalloc2", "smallvec", @@ -1234,44 +1285,43 @@ dependencies = [ [[package]] name = "cranelift-codegen-meta" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "639307b45434ad112a98f8300c0f0ab085cbefcd767efcdef9ef19d4c0756e74" +checksum = "a3fd3664e38e51649b17dc30cfdd561273fe2f590dcd013fb75d9eabc6272dfb" dependencies = [ "cranelift-codegen-shared", ] [[package]] name = "cranelift-codegen-shared" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "278e52e29c53fcf32431ef08406c295699a70306d05a0715c5b1bf50e33a9ab7" +checksum = "4b031ec5e605828975952622b5a77d49126f20ffe88d33719a0af66b23a0fc36" [[package]] -name = "cranelift-egraph" -version = "0.91.1" +name = "cranelift-control" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "624b54323b06e675293939311943ba82d323bb340468ce1889be5da7932c8d73" +checksum = "fada054d017cf2ed8f7ed2336e0517fc1b19e6825be1790de9eb00c94788362b" dependencies = [ - "cranelift-entity", - "fxhash", - "hashbrown 0.12.3", - "indexmap 1.9.3", - "log", - "smallvec", + "arbitrary", ] [[package]] name = "cranelift-entity" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9a59bcbca89c3f1b70b93ab3cbba5e5e0cbf3e63dadb23c7525cb142e21a9d4c" +checksum = "177b6f94ae8de6348eb45bf977c79ab9e3c40fc3ac8cb7ed8109560ea39bee7d" +dependencies = [ + "serde", + "serde_derive", +] [[package]] name = "cranelift-frontend" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0d70abacb8cfef3dc8ff7e8836e9c1d70f7967dfdac824a4cd5e30223415aca6" +checksum = "ebebd23a69a23e3ddea78e98ff3a2de222e88c8e045d81ef4a72f042e0d79dbd" dependencies = [ "cranelift-codegen", "log", @@ -1281,9 +1331,36 @@ dependencies = [ [[package]] name = "cranelift-isle" -version = "0.91.1" +version = "0.104.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "393bc73c451830ff8dbb3a07f61843d6cb41a084f9996319917c0b291ed785bb" +checksum = "1571bfc14df8966d12c6121b5325026591a4b4009e22fea0fe3765ab7cd33b96" + +[[package]] +name = "cranelift-native" +version = "0.104.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "35a69c37e0c10b46fe5527f2397ac821046efbf5f7ec112c8b84df25712f465b" +dependencies = [ + "cranelift-codegen", + "libc", + "target-lexicon", +] + +[[package]] +name = "cranelift-wasm" +version = "0.104.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3fef8bbceb8cb56d3f1778b0418d75c5cf12ec571a35fc01eb41abb0227a25" +dependencies = [ + "cranelift-codegen", + "cranelift-entity", + "cranelift-frontend", + "itertools 0.10.5", + "log", + "smallvec", + "wasmparser 0.118.1", + "wasmtime-types", +] [[package]] name = "crc32fast" @@ -1574,25 +1651,21 @@ dependencies = [ "syn 2.0.48", ] -[[package]] -name = "dashmap" -version = "5.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "978747c1d849a7d2ee5e8adc0159961c48fb7e5db2f06af6723b80123bb53856" -dependencies = [ - "cfg-if 1.0.0", - "hashbrown 0.14.3", - "lock_api", - "once_cell", - "parking_lot_core 0.9.9", -] - [[package]] name = "data-encoding" version = "2.5.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7e962a19be5cfc3f3bf6dd8f61eb50107f356ad6270fbb3ed41476571db78be5" +[[package]] +name = "debugid" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bef552e6f588e446098f6ba40d89ac146c8c7b64aade83c051ee00bb5d2bc18d" +dependencies = [ + "uuid", +] + [[package]] name = "deflate" version = "1.0.0" @@ -1611,17 +1684,6 @@ dependencies = [ "powerfmt", ] -[[package]] -name = "derivative" -version = "2.2.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fcc3dd5e9e9c0b295d6e1e4d811fb6f157d5ffd784b8d202fc62eac8035a770b" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "deunicode" version = "1.4.2" @@ -1648,13 +1710,22 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs" +version = "4.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ca3aa72a6f96ea37bbc5aa912f6788242832f75369bdfdadcb0e38423f100059" +dependencies = [ + "dirs-sys 0.3.7", +] + [[package]] name = "dirs" version = "5.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "44c45a9d03d6676652bcb5e724c7e988de1acad23a711b5217ab9cbecbec2225" dependencies = [ - "dirs-sys", + "dirs-sys 0.4.1", ] [[package]] @@ -1667,6 +1738,17 @@ dependencies = [ "dirs-sys-next", ] +[[package]] +name = "dirs-sys" +version = "0.3.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1b1d1d91c932ef41c0f2663aa8b0ca0342d444d842c06914aa0a7e352d0bada6" +dependencies = [ + "libc", + "redox_users", + "winapi", +] + [[package]] name = "dirs-sys" version = "0.4.1" @@ -1690,12 +1772,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "discard" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "212d0f5754cb6769937f4501cc0e67f4f4483c8d2c3e1e922ee9edbe4ab4c7c0" - [[package]] name = "discord-sdk" version = "0.3.5" @@ -1714,7 +1790,7 @@ dependencies = [ "serde_json", "serde_repr", "thiserror", - "time 0.3.34", + "time", "tokio", "tracing", "url", @@ -1841,6 +1917,15 @@ dependencies = [ "bytemuck", ] +[[package]] +name = "encoding_rs" +version = "0.8.33" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7268b386296a025e474d5140678f75d6de9493ae55a5d709eeb9dd08149945e1" +dependencies = [ + "cfg-if 1.0.0", +] + [[package]] name = "endian-type" version = "0.1.2" @@ -1853,32 +1938,12 @@ version = "0.6.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5ffccbb6966c05b32ef8fbac435df276c4ae4d3dc55a8cd0eb9745e6c12f546a" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2 1.0.78", "quote 1.0.35", "syn 2.0.48", ] -[[package]] -name = "enum-iterator" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" -dependencies = [ - "enum-iterator-derive", -] - -[[package]] -name = "enum-iterator-derive" -version = "0.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "enum-map" version = "2.7.3" @@ -2013,6 +2078,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4443176a9f2c162692bd3d352d745ef9413eec5782a80d8fd6f8a1ac692a07f7" +[[package]] +name = "fallible-iterator" +version = "0.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2acce4a10f12dc2fb14a218589d4f1f62ef011b2d0cc4b3cb1bba8e94da14649" + [[package]] name = "fallible-streaming-iterator" version = "0.1.9" @@ -2224,6 +2295,17 @@ dependencies = [ "percent-encoding", ] +[[package]] +name = "fs-set-times" +version = "0.20.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "033b337d725b97690d86893f9de22b67b80dcc4e9ad815f348254c38119db8fb" +dependencies = [ + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", +] + [[package]] name = "fsevent-sys" version = "4.1.0" @@ -2338,6 +2420,19 @@ dependencies = [ "byteorder", ] +[[package]] +name = "fxprof-processed-profile" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "27d12c0aed7f1e24276a241aadc4cb8ea9f83000f34bc062b7cc2d51e3b0fabd" +dependencies = [ + "bitflags 2.4.2", + "debugid", + "fxhash", + "serde", + "serde_json", +] + [[package]] name = "generator" version = "0.7.5" @@ -2441,22 +2536,16 @@ dependencies = [ "windows 0.52.0", ] -[[package]] -name = "gimli" -version = "0.26.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "22030e2c5a68ec659fde1e949a745124b48e6fa8b045b7ed5bd1fe4ccc5c4e5d" -dependencies = [ - "fallible-iterator", - "indexmap 1.9.3", - "stable_deref_trait", -] - [[package]] name = "gimli" version = "0.28.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4271d37baee1b8c7e4b708028c57d816cf9d2434acb33a549475f78c181f6253" +dependencies = [ + "fallible-iterator 0.3.0", + "indexmap 2.2.2", + "stable_deref_trait", +] [[package]] name = "gl_generator" @@ -2658,9 +2747,6 @@ name = "hashbrown" version = "0.12.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8a9ee70c43aaf417c914396645a0fa852624801b24ebb7ae78fe8272889ac888" -dependencies = [ - "ahash 0.7.7", -] [[package]] name = "hashbrown" @@ -2720,15 +2806,6 @@ dependencies = [ "stable_deref_trait", ] -[[package]] -name = "heck" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6d621efb26863f0e9924c6ac577e8275e5e6b77455db64ffa6c65c904e9e132c" -dependencies = [ - "unicode-segmentation", -] - [[package]] name = "heck" version = "0.4.1" @@ -3138,6 +3215,16 @@ dependencies = [ "unic-langid", ] +[[package]] +name = "io-extras" +version = "0.18.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c301e73fb90e8a29e600a9f402d095765f74310d582916a952f618836a1bd1ed" +dependencies = [ + "io-lifetimes", + "windows-sys 0.52.0", +] + [[package]] name = "io-kit-sys" version = "0.4.0" @@ -3148,6 +3235,12 @@ dependencies = [ "mach2", ] +[[package]] +name = "io-lifetimes" +version = "2.0.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5a611371471e98973dbcab4e0ec66c31a10bc356eeb4d54a0e05eac8158fe38c" + [[package]] name = "ipconfig" version = "0.3.2" @@ -3201,6 +3294,26 @@ version = "1.0.10" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b1a46d1a171d865aa5f83f92695765caa047a9b4cbae2cbf37dbd613a793fd4c" +[[package]] +name = "ittapi" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6b996fe614c41395cdaedf3cf408a9534851090959d90d54a535f675550b64b1" +dependencies = [ + "anyhow", + "ittapi-sys", + "log", +] + +[[package]] +name = "ittapi-sys" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "52f5385394064fa2c886205dba02598013ce83d3e92d33dbdc0c52fe0e7bf4fc" +dependencies = [ + "cc", +] + [[package]] name = "jni" version = "0.19.0" @@ -3581,6 +3694,12 @@ version = "0.7.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "0e7465ac9959cc2b1404e8e2367b43684a6d13790fe23056cc8c6c5a6b7bcb94" +[[package]] +name = "maybe-owned" +version = "0.3.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4facc753ae494aeb6e3c22f839b158aebd4f9270f55cd3c79906c45476c47ab4" + [[package]] name = "maybe-uninit" version = "2.0.0" @@ -3593,6 +3712,15 @@ version = "2.7.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "523dc4f511e55ab87b694dc30d0f820d60906ef06413f93d4d7a1385599cc149" +[[package]] +name = "memfd" +version = "0.6.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b2cffa4ad52c6f791f4f8b15f0c05f9824b2ced1160e88cc393d64fff9a8ac64" +dependencies = [ + "rustix", +] + [[package]] name = "memmap2" version = "0.5.10" @@ -3631,9 +3759,9 @@ dependencies = [ [[package]] name = "memoffset" -version = "0.8.0" +version = "0.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d61c719bcfbcf5d62b3a09efa6088de8c54bc0bfcd3ea7ae39fcc186108b8de1" +checksum = "5a634b1c61a95585bd15607c6ab0c4e5b226e695ff2800ba0cdccddf208c406c" dependencies = [ "autocfg", ] @@ -3722,12 +3850,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "more-asserts" -version = "0.2.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7843ec2de400bcbc6a6328c958dc38e5359da6e93e72e37bc5246bf1ae776389" - [[package]] name = "mumble-link" version = "0.2.0" @@ -4278,6 +4400,9 @@ version = "0.32.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a6a622008b6e321afc04970976f62ee297fdbaa6f95318ca343e3eebb9648441" dependencies = [ + "crc32fast", + "hashbrown 0.14.3", + "indexmap 2.2.2", "memchr", ] @@ -4666,30 +4791,6 @@ dependencies = [ "toml_edit 0.19.15", ] -[[package]] -name = "proc-macro-error" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "da25490ff9892aab3fcf7c36f08cfb902dd3e71ca0f9f9517bea02a73a5ce38c" -dependencies = [ - "proc-macro-error-attr", - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", - "version_check", -] - -[[package]] -name = "proc-macro-error-attr" -version = "1.0.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1be40180e52ecc98ad80b184934baf3d0d29f979574e439af5a55274b35f869" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "version_check", -] - [[package]] name = "proc-macro-hack" version = "0.5.20+deprecated" @@ -4775,37 +4876,6 @@ dependencies = [ "cc", ] -[[package]] -name = "ptr_meta" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "0738ccf7ea06b608c10564b31debd4f5bc5e197fc8bfe088f68ae5ce81e7a4f1" -dependencies = [ - "ptr_meta_derive", -] - -[[package]] -name = "ptr_meta_derive" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "16b845dbfca988fa33db069c0e230574d15a3088f147a87b64c7589eb662c9ac" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - -[[package]] -name = "pulldown-cmark" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ffade02495f22453cd593159ea2f59827aae7f53fa8323f756799b670881dcf8" -dependencies = [ - "bitflags 1.3.2", - "memchr", - "unicase", -] - [[package]] name = "quick-error" version = "1.2.3" @@ -5052,7 +5122,7 @@ checksum = "52c4f3084aa3bc7dfbba4eff4fab2a54db4324965d8872ab933565e6fbd83bc6" dependencies = [ "pem", "ring 0.16.20", - "time 0.3.34", + "time", "yasna", ] @@ -5118,7 +5188,7 @@ dependencies = [ "serde", "siphasher 1.0.0", "thiserror", - "time 0.3.34", + "time", "toml 0.8.10", "url", "walkdir", @@ -5139,12 +5209,13 @@ dependencies = [ [[package]] name = "regalloc2" -version = "0.5.1" +version = "0.9.3" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "300d4fbfb40c1c66a78ba3ddd41c1110247cf52f97b87d0f2fc9209bd49b030c" +checksum = "ad156d539c879b7a24a363a2016d77961786e71f48f2e2fc8302a92abd2429a6" dependencies = [ - "fxhash", + "hashbrown 0.13.2", "log", + "rustc-hash", "slice-group-by", "smallvec", ] @@ -5193,27 +5264,6 @@ version = "0.8.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "c08c74e62047bb2de4ff487b251e4a92e24f48745648451635cec7d591162d9f" -[[package]] -name = "region" -version = "3.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "76e189c2369884dce920945e2ddf79b3dff49e071a167dd1817fa9c4c00d512e" -dependencies = [ - "bitflags 1.3.2", - "libc", - "mach", - "winapi", -] - -[[package]] -name = "rend" -version = "0.4.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "71fe3824f5629716b1589be05dacd749f6aa084c87e00e016714a8cdfccc997c" -dependencies = [ - "bytecheck", -] - [[package]] name = "renderdoc-sys" version = "1.0.0" @@ -5259,36 +5309,6 @@ dependencies = [ "windows-sys 0.48.0", ] -[[package]] -name = "rkyv" -version = "0.7.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5cba464629b3394fc4dbc6f940ff8f5b4ff5c7aef40f29166fd4ad12acbc99c0" -dependencies = [ - "bitvec", - "bytecheck", - "bytes", - "hashbrown 0.12.3", - "indexmap 1.9.3", - "ptr_meta", - "rend", - "rkyv_derive", - "seahash", - "tinyvec", - "uuid", -] - -[[package]] -name = "rkyv_derive" -version = "0.7.44" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a7dddfff8de25e6f62b9d64e6e432bf1c6736c57d20323e15ee10435fbda7c65" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "rmp" version = "0.8.12" @@ -5366,7 +5386,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "01e213bc3ecb39ac32e81e51ebe31fd888a940515173e3a18a35f8c6e896422a" dependencies = [ "bitflags 1.3.2", - "fallible-iterator", + "fallible-iterator 0.2.0", "fallible-streaming-iterator", "hashlink", "libsqlite3-sys", @@ -5422,8 +5442,10 @@ checksum = "6ea3e1a662af26cd7a3ba09c0297a31af215563ecf42817c98df621387f4e949" dependencies = [ "bitflags 2.4.2", "errno", + "itoa", "libc", "linux-raw-sys", + "once_cell", "windows-sys 0.52.0", ] @@ -5616,12 +5638,6 @@ dependencies = [ "version-compare", ] -[[package]] -name = "seahash" -version = "4.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1c107b6f4780854c8b126e228ea8869f4d7b71260f962fefb57b996b8959ba6b" - [[package]] name = "security-framework" version = "2.9.2" @@ -5690,17 +5706,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_derive" version = "1.0.196" @@ -5765,21 +5770,6 @@ dependencies = [ "serde", ] -[[package]] -name = "sha1" -version = "0.6.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c1da05c97445caa12d05e848c4a4fcbbea29e748ac28f7e80e9b010392063770" -dependencies = [ - "sha1_smol", -] - -[[package]] -name = "sha1_smol" -version = "1.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ae1a47186c03a32177042e55dbc5fd5aee900b8e0069a8d70fba96a9375cd012" - [[package]] name = "sha2" version = "0.10.8" @@ -5825,13 +5815,22 @@ version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "24188a676b6ae68c3b2cb3a01be17fbf7240ce009799bb56d5b1409051e78fde" +[[package]] +name = "shellexpand" +version = "2.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7ccc8076840c4da029af4f87e4e8daeb0fca6b87bbb02e10cb60b791450e11e4" +dependencies = [ + "dirs 4.0.0", +] + [[package]] name = "shellexpand" version = "3.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "da03fa3b94cc19e3ebfc88c4229c49d8f08cdbd1228870a45f0ffdf84988e14b" dependencies = [ - "dirs", + "dirs 5.0.1", ] [[package]] @@ -5906,12 +5905,6 @@ version = "0.3.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d66dc143e6b11c1eddc06d5c423cfc97062865baf299914ab64caa38182078fe" -[[package]] -name = "simdutf8" -version = "0.1.4" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f27f6278552951f1f2b8cf9da965d10969b2efdea95a6ec47987ab46edfe263a" - [[package]] name = "siphasher" version = "0.3.11" @@ -6058,6 +6051,12 @@ dependencies = [ "num-traits", ] +[[package]] +name = "sptr" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3b9b39299b249ad65f3b7e96443bad61c02ca5cd3589f46cb6d610a0fd6c0d6a" + [[package]] name = "stability" version = "0.1.1" @@ -6087,15 +6086,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "standback" -version = "0.2.17" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e113fb6f3de07a243d434a56ec6f186dfd51cb08448239fe7bcae73f87ff28ff" -dependencies = [ - "version_check", -] - [[package]] name = "static_assertions" version = "1.1.0" @@ -6117,55 +6107,6 @@ version = "0.1.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef5430c8e36b713e13b48a9f709cc21e046723fe44ce34587b73a830203b533e" -[[package]] -name = "stdweb" -version = "0.4.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d022496b16281348b52d0e30ae99e01a73d737b2f45d38fed4edf79f9325a1d5" -dependencies = [ - "discard", - "rustc_version 0.2.3", - "stdweb-derive", - "stdweb-internal-macros", - "stdweb-internal-runtime", - "wasm-bindgen", -] - -[[package]] -name = "stdweb-derive" -version = "0.5.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c87a60a40fccc84bef0652345bbbbbe20a605bf5d0ce81719fc476f5c03b50ef" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "serde", - "serde_derive", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-macros" -version = "0.2.9" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "58fa5ff6ad0d98d1ffa8cb115892b6e69d67799f6763e162a1c9db421dc22e11" -dependencies = [ - "base-x", - "proc-macro2 1.0.78", - "quote 1.0.35", - "serde", - "serde_derive", - "serde_json", - "sha1", - "syn 1.0.109", -] - -[[package]] -name = "stdweb-internal-runtime" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "213701ba3370744dcd1a12960caa4843b3d68b4d1c0a5d575e0d65b2ee9d16c0" - [[package]] name = "str-buf" version = "1.0.6" @@ -6208,7 +6149,7 @@ version = "0.24.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1e385be0d24f186b4ce2f9982191e7101bb737312ad61c1f2f984f34bcf85d59" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2 1.0.78", "quote 1.0.35", "rustversion", @@ -6221,7 +6162,7 @@ version = "0.26.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7a3417fc93d76740d974a01654a09777cb500428cc874ca9f45edfe0c4d4cd18" dependencies = [ - "heck 0.4.1", + "heck", "proc-macro2 1.0.78", "quote 1.0.35", "rustversion", @@ -6288,6 +6229,22 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2047c6ded9c721764247e62cd3b03c09ffc529b2ba5b10ec482ae507a4a70160" +[[package]] +name = "system-interface" +version = "0.26.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0682e006dd35771e392a6623ac180999a9a854b1d4a6c12fb2e804941c2b1f58" +dependencies = [ + "bitflags 2.4.2", + "cap-fs-ext", + "cap-std", + "fd-lock", + "io-lifetimes", + "rustix", + "windows-sys 0.52.0", + "winx", +] + [[package]] name = "tap" version = "1.0.1" @@ -6362,21 +6319,6 @@ dependencies = [ "once_cell", ] -[[package]] -name = "time" -version = "0.2.27" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4752a97f8eebd6854ff91f1c1824cd6160626ac4bd44287f7f4ea2035a02a242" -dependencies = [ - "const_fn", - "libc", - "standback", - "stdweb 0.4.20", - "time-macros 0.1.1", - "version_check", - "winapi", -] - [[package]] name = "time" version = "0.3.34" @@ -6389,7 +6331,7 @@ dependencies = [ "powerfmt", "serde", "time-core", - "time-macros 0.2.17", + "time-macros", ] [[package]] @@ -6398,16 +6340,6 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ef927ca75afb808a4d64dd374f00a2adf8d0fcff8e7b184af886c3c87ec4a3f3" -[[package]] -name = "time-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "957e9c6e26f12cb6d0dd7fc776bb67a706312e7299aed74c8dd5b17ebb27e2f1" -dependencies = [ - "proc-macro-hack", - "time-macros-impl", -] - [[package]] name = "time-macros" version = "0.2.17" @@ -6418,19 +6350,6 @@ dependencies = [ "time-core", ] -[[package]] -name = "time-macros-impl" -version = "0.1.2" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fd3c141a1b43194f3f56a1411225df8646c55781d5f26db825b3d98507eb482f" -dependencies = [ - "proc-macro-hack", - "proc-macro2 1.0.78", - "quote 1.0.35", - "standback", - "syn 1.0.109", -] - [[package]] name = "timer-queue" version = "0.1.0" @@ -6665,7 +6584,7 @@ checksum = "3566e8ce28cc0a3fe42519fc80e6b4c943cc4c8cef275620eb8dac2d3d4e06cf" dependencies = [ "crossbeam-channel", "thiserror", - "time 0.3.34", + "time", "tracing-subscriber", ] @@ -6714,7 +6633,7 @@ dependencies = [ "sharded-slab", "smallvec", "thread_local", - "time 0.3.34", + "time", "tracing", "tracing-core", "tracing-log", @@ -6832,15 +6751,6 @@ dependencies = [ "tinystr", ] -[[package]] -name = "unicase" -version = "2.7.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f7d2d4dafb69621809a81864c9c1b864479e1235c0dd4e199924b9742439ed89" -dependencies = [ - "version_check", -] - [[package]] name = "unicode-bidi" version = "0.3.15" @@ -7155,7 +7065,10 @@ dependencies = [ name = "veloren-common-state" version = "0.10.0" dependencies = [ + "async-trait", "bincode", + "bytes", + "futures", "hashbrown 0.13.2", "num_cpus", "rayon", @@ -7172,9 +7085,8 @@ dependencies = [ "veloren-common-base", "veloren-common-ecs", "veloren-common-net", - "veloren-plugin-api", - "wasmer", - "wasmer-wasix-types", + "wasmtime", + "wasmtime-wasi", ] [[package]] @@ -7217,7 +7129,7 @@ dependencies = [ "rcgen", "rustls", "serde", - "shellexpand", + "shellexpand 3.1.0", "socket2", "tokio", "tokio-stream", @@ -7242,33 +7154,6 @@ dependencies = [ "tracing", ] -[[package]] -name = "veloren-plugin-api" -version = "0.1.0" -dependencies = [ - "serde", - "veloren-common", -] - -[[package]] -name = "veloren-plugin-derive" -version = "0.1.0" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 2.0.48", -] - -[[package]] -name = "veloren-plugin-rt" -version = "0.1.0" -dependencies = [ - "bincode", - "serde", - "veloren-plugin-api", - "veloren-plugin-derive", -] - [[package]] name = "veloren-rtsim" version = "0.10.0" @@ -7337,7 +7222,6 @@ dependencies = [ "veloren-common-state", "veloren-common-systems", "veloren-network", - "veloren-plugin-api", "veloren-rtsim", "veloren-server-agent", "veloren-world", @@ -7512,7 +7396,7 @@ dependencies = [ "deflate", "enum-map", "enumset", - "fallible-iterator", + "fallible-iterator 0.2.0", "flate2", "fxhash", "hashbrown 0.13.2", @@ -7559,72 +7443,6 @@ version = "0.9.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "49874b5167b65d7193b8aba1567f5c7d93d001cafc34600cee003eda787e483f" -[[package]] -name = "wai-bindgen-gen-core" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "1aa3dc41b510811122b3088197234c27e08fcad63ef936306dd8e11e2803876c" -dependencies = [ - "anyhow", - "wai-parser", -] - -[[package]] -name = "wai-bindgen-gen-rust" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "19bc05e8380515c4337c40ef03b2ff233e391315b178a320de8640703d522efe" -dependencies = [ - "heck 0.3.3", - "wai-bindgen-gen-core", -] - -[[package]] -name = "wai-bindgen-gen-rust-wasm" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d6f35ce5e74086fac87f3a7bd50f643f00fe3559adb75c88521ecaa01c8a6199" -dependencies = [ - "heck 0.3.3", - "wai-bindgen-gen-core", - "wai-bindgen-gen-rust", -] - -[[package]] -name = "wai-bindgen-rust" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4e5601c6f448c063e83a5e931b8fefcdf7e01ada424ad42372c948d2e3d67741" -dependencies = [ - "bitflags 1.3.2", - "wai-bindgen-rust-impl", -] - -[[package]] -name = "wai-bindgen-rust-impl" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "bdeeb5c1170246de8425a3e123e7ef260dc05ba2b522a1d369fe2315376efea4" -dependencies = [ - "proc-macro2 1.0.78", - "syn 1.0.109", - "wai-bindgen-gen-core", - "wai-bindgen-gen-rust-wasm", -] - -[[package]] -name = "wai-parser" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "9bd0acb6d70885ea0c343749019ba74f015f64a9d30542e66db69b49b7e28186" -dependencies = [ - "anyhow", - "id-arena", - "pulldown-cmark", - "unicode-normalization", - "unicode-xid 0.2.4", -] - [[package]] name = "walkdir" version = "2.4.0" @@ -7656,6 +7474,49 @@ version = "0.11.0+wasi-snapshot-preview1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9c8d87e72b64a3b4db28d11ce29237c246188f4f51057d65a7eab63b7987e423" +[[package]] +name = "wasi-cap-std-sync" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "db014d2ced91f17d1f1a8f2b76d6ea8d731bc1dbc8c2bbaec689d6a242568e5d" +dependencies = [ + "anyhow", + "async-trait", + "cap-fs-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "io-extras", + "io-lifetimes", + "once_cell", + "rustix", + "system-interface", + "tracing", + "wasi-common", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasi-common" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "449d17849e3c83a931374442fe2deee4d6bd1ebf469719ef44192e9e82e19c89" +dependencies = [ + "anyhow", + "bitflags 2.4.2", + "cap-rand", + "cap-std", + "io-extras", + "log", + "rustix", + "thiserror", + "tracing", + "wasmtime", + "wiggle", + "windows-sys 0.52.0", +] + [[package]] name = "wasm-bindgen" version = "0.2.90" @@ -7681,29 +7542,6 @@ dependencies = [ "wasm-bindgen-shared", ] -[[package]] -name = "wasm-bindgen-downcast" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "5dac026d43bcca6e7ce1c0956ba68f59edf6403e8e930a5d891be72c31a44340" -dependencies = [ - "js-sys", - "once_cell", - "wasm-bindgen", - "wasm-bindgen-downcast-macros", -] - -[[package]] -name = "wasm-bindgen-downcast-macros" -version = "0.1.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c5020cfa87c7cecefef118055d44e3c1fc122c7ec25701d528ee458a0b45f38f" -dependencies = [ - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - [[package]] name = "wasm-bindgen-futures" version = "0.4.40" @@ -7745,6 +7583,15 @@ version = "0.2.90" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4d91413b1c31d7539ba5ef2451af3f0b833a005eb27a631cec32bc0635a8602b" +[[package]] +name = "wasm-encoder" +version = "0.38.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0ad2b51884de9c7f4fe2fd1043fccb8dcad4b1e29558146ee57a144d15779f3f" +dependencies = [ + "leb128", +] + [[package]] name = "wasm-encoder" version = "0.41.0" @@ -7755,160 +7602,385 @@ dependencies = [ ] [[package]] -name = "wasmer" -version = "4.0.0" +name = "wasmparser" +version = "0.118.1" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ea790bcdfb4e6e9d1e5ddf75b4699aac62b078fcc9f27f44e1748165ceea67bf" +checksum = "95ee9723b928e735d53000dec9eae7b07a60e490c85ab54abb66659fc61bfcd9" dependencies = [ - "bytes", - "cfg-if 1.0.0", - "derivative", - "indexmap 1.9.3", - "js-sys", - "more-asserts", - "rustc-demangle", - "serde", - "serde-wasm-bindgen", - "target-lexicon", - "thiserror", - "wasm-bindgen", - "wasm-bindgen-downcast", - "wasmer-compiler", - "wasmer-compiler-cranelift", - "wasmer-derive", - "wasmer-types", - "wasmer-vm", - "wat", - "winapi", -] - -[[package]] -name = "wasmer-compiler" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f093937725e242e5529fed27e08ff836c011a9ecc22e6819fb818c2ac6ff5f88" -dependencies = [ - "backtrace", - "cfg-if 1.0.0", - "enum-iterator", - "enumset", - "lazy_static", - "leb128", - "memmap2 0.5.10", - "more-asserts", - "region", - "smallvec", - "thiserror", - "wasmer-types", - "wasmer-vm", - "wasmparser", - "winapi", -] - -[[package]] -name = "wasmer-compiler-cranelift" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3b27b1670d27158789ebe14e4da3902c72132174884a1c6a3533ce4fd9dd83db" -dependencies = [ - "cranelift-codegen", - "cranelift-entity", - "cranelift-frontend", - "gimli 0.26.2", - "more-asserts", - "rayon", - "smallvec", - "target-lexicon", - "tracing", - "wasmer-compiler", - "wasmer-types", -] - -[[package]] -name = "wasmer-derive" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "13ae8286cba2acb10065a4dac129c7c7f7bcd24acd6538555d96616eea16bc27" -dependencies = [ - "proc-macro-error", - "proc-macro2 1.0.78", - "quote 1.0.35", - "syn 1.0.109", -] - -[[package]] -name = "wasmer-types" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "918d2f0bb5eaa95a80c06be33f21dee92f40f12cd0982da34490d121a99d244b" -dependencies = [ - "bytecheck", - "enum-iterator", - "enumset", - "indexmap 1.9.3", - "more-asserts", - "rkyv", - "target-lexicon", - "thiserror", -] - -[[package]] -name = "wasmer-vm" -version = "4.0.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a1e000c2cbd4f9805427af5f3b3446574caf89ab3a1e66c2f3579fbde22b072b" -dependencies = [ - "backtrace", - "cc", - "cfg-if 1.0.0", - "corosensei", - "dashmap", - "derivative", - "enum-iterator", - "fnv", - "indexmap 1.9.3", - "lazy_static", - "libc", - "mach", - "memoffset 0.8.0", - "more-asserts", - "region", - "scopeguard", - "thiserror", - "wasmer-types", - "winapi", -] - -[[package]] -name = "wasmer-wasix-types" -version = "0.9.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7a4a519e8f0b878bb4cd2b1bc733235aa6c331b7b4857dd6e0ac3c9a36d942ae" -dependencies = [ - "anyhow", - "bitflags 1.3.2", - "byteorder", - "cfg-if 1.0.0", - "num_enum 0.5.11", - "time 0.2.27", - "wai-bindgen-gen-core", - "wai-bindgen-gen-rust", - "wai-bindgen-gen-rust-wasm", - "wai-bindgen-rust", - "wai-parser", - "wasmer", - "wasmer-derive", - "wasmer-types", + "indexmap 2.2.2", + "semver 1.0.21", ] [[package]] name = "wasmparser" -version = "0.95.0" +version = "0.121.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f2ea896273ea99b15132414be1da01ab0d8836415083298ecaffbe308eaac87a" +checksum = "953cf6a7606ab31382cb1caa5ae403e77ba70c7f8e12eeda167e7040d42bfda8" dependencies = [ - "indexmap 1.9.3", + "bitflags 2.4.2", + "indexmap 2.2.2", + "semver 1.0.21", +] + +[[package]] +name = "wasmprinter" +version = "0.2.78" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "05e32c13c59fdc64d3f6998a1d52eb1d362b6904a88b754190ccb85661ad577a" +dependencies = [ + "anyhow", + "wasmparser 0.121.0", +] + +[[package]] +name = "wasmtime" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "910fabce77e660f0e0e41cfd5f69fc8bf020a025f059718846e918db7177f469" +dependencies = [ + "anyhow", + "async-trait", + "bincode", + "bumpalo", + "cfg-if 1.0.0", + "encoding_rs", + "fxprof-processed-profile", + "indexmap 2.2.2", + "libc", + "log", + "object", + "once_cell", + "paste", + "rayon", + "serde", + "serde_derive", + "serde_json", + "target-lexicon", + "wasm-encoder 0.38.1", + "wasmparser 0.118.1", + "wasmtime-cache", + "wasmtime-component-macro", + "wasmtime-component-util", + "wasmtime-cranelift", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit", + "wasmtime-runtime", + "wasmtime-winch", + "wat", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-asm-macros" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "37288142e9b4a61655a3bcbdc7316c2e4bb9e776b10ce3dd758f8186b4469572" +dependencies = [ + "cfg-if 1.0.0", +] + +[[package]] +name = "wasmtime-cache" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "45cbd74a636f09d2108f9405c79857f061e19323e4abeed22e837cfe7b08a22b" +dependencies = [ + "anyhow", + "base64", + "bincode", + "directories-next", + "log", + "rustix", + "serde", + "serde_derive", + "sha2", + "toml 0.5.11", + "windows-sys 0.52.0", + "zstd", +] + +[[package]] +name = "wasmtime-component-macro" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad63de18eb42e586386b6091f787c82707cbd5ac5e9343216dba1976190cd03a" +dependencies = [ + "anyhow", + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", + "wasmtime-component-util", + "wasmtime-wit-bindgen", + "wit-parser", +] + +[[package]] +name = "wasmtime-component-util" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7e0a160c0c44369aa4bee6d311a8e4366943bab1651040cc8b0fcec2c9eb8906" + +[[package]] +name = "wasmtime-cranelift" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3734cc01b7cd37bc62fdbcd9529ca9547440052d4b3886cfdec3b8081a5d3647" +dependencies = [ + "anyhow", + "cfg-if 1.0.0", + "cranelift-codegen", + "cranelift-control", + "cranelift-entity", + "cranelift-frontend", + "cranelift-native", + "cranelift-wasm", + "gimli", + "log", + "object", + "target-lexicon", + "thiserror", + "wasmparser 0.118.1", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-cranelift-shared" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0eb33cd30c47844aa228d4d0030587e65c1108343f311fe9f7248b5bd9cb65c" +dependencies = [ + "anyhow", + "cranelift-codegen", + "cranelift-control", + "cranelift-native", + "gimli", + "object", + "target-lexicon", + "wasmtime-environ", +] + +[[package]] +name = "wasmtime-environ" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9a3a056b041fdea604f0972e2fae97958e7748d629a55180228348baefdfc217" +dependencies = [ + "anyhow", + "cranelift-entity", + "gimli", + "indexmap 2.2.2", + "log", + "object", + "serde", + "serde_derive", + "target-lexicon", + "thiserror", + "wasm-encoder 0.38.1", + "wasmparser 0.118.1", + "wasmprinter", + "wasmtime-component-util", + "wasmtime-types", +] + +[[package]] +name = "wasmtime-fiber" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "43987d0977c07f15c3608c2f255870c127ffd19e35eeedb1ac1dccedf9932a42" +dependencies = [ + "anyhow", + "cc", + "cfg-if 1.0.0", + "rustix", + "wasmtime-asm-macros", + "wasmtime-versioned-export-macros", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-jit" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9b3e48395ac672b386ed588d97a9612aa13a345008f26466f0dfb2a91628aa9f" +dependencies = [ + "addr2line", + "anyhow", + "bincode", + "cfg-if 1.0.0", + "cpp_demangle", + "gimli", + "ittapi", + "log", + "object", + "rustc-demangle", + "rustix", + "serde", + "serde_derive", + "target-lexicon", + "wasmtime-environ", + "wasmtime-jit-debug", + "wasmtime-jit-icache-coherence", + "wasmtime-runtime", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-jit-debug" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "dd21fd0f5ca68681d3d5b636eea00f182d0f9d764144469e9257fd7e3f55ae0e" +dependencies = [ + "object", + "once_cell", + "rustix", + "wasmtime-versioned-export-macros", +] + +[[package]] +name = "wasmtime-jit-icache-coherence" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "bdc26415bb89e9ccd3bdc498fef63aabf665c4c0dd710c107691deb9694955da" +dependencies = [ + "cfg-if 1.0.0", + "libc", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-runtime" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0abddaf17912aabaf39be0802d5eba9a002e956e902d1ebd438a2fe1c88769a2" +dependencies = [ + "anyhow", + "cc", + "cfg-if 1.0.0", + "encoding_rs", + "indexmap 2.2.2", + "libc", + "log", + "mach", + "memfd", + "memoffset 0.9.0", + "paste", + "psm", + "rustix", + "sptr", + "wasm-encoder 0.38.1", + "wasmtime-asm-macros", + "wasmtime-environ", + "wasmtime-fiber", + "wasmtime-jit-debug", + "wasmtime-versioned-export-macros", + "wasmtime-wmemcheck", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-types" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b35a95cdc1433729085beab42c0a5c742b431f25b17c40d7718e46df63d5ffc7" +dependencies = [ + "cranelift-entity", + "serde", + "serde_derive", + "thiserror", + "wasmparser 0.118.1", +] + +[[package]] +name = "wasmtime-versioned-export-macros" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fad322733fe67e45743784d8b1df452bcb54f581572a4f1a646a4332deecbcc2" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", +] + +[[package]] +name = "wasmtime-wasi" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "902cc299b73655c36679b77efdfce4bb5971992f1a4a8a436dd3809a6848ff0e" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 2.4.2", + "bytes", + "cap-fs-ext", + "cap-net-ext", + "cap-rand", + "cap-std", + "cap-time-ext", + "fs-set-times", + "futures", + "io-extras", + "io-lifetimes", + "libc", + "log", + "once_cell", + "rustix", + "system-interface", + "thiserror", + "tokio", + "tracing", "url", + "wasi-cap-std-sync", + "wasi-common", + "wasmtime", + "wiggle", + "windows-sys 0.52.0", +] + +[[package]] +name = "wasmtime-winch" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e63aeca929f84560eec52c5af43bf5d623b92683b0195d9fb06da8ed860e092" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "object", + "target-lexicon", + "wasmparser 0.118.1", + "wasmtime-cranelift-shared", + "wasmtime-environ", + "winch-codegen", +] + +[[package]] +name = "wasmtime-wit-bindgen" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "41e5675998fdc74495afdd90ad2bd221206a258075b23048af0535a969b07893" +dependencies = [ + "anyhow", + "heck", + "indexmap 2.2.2", + "wit-parser", +] + +[[package]] +name = "wasmtime-wmemcheck" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b20a19e10d8cb50b45412fb21192982b7ce85c0122dc33bb71f1813e25dc6e52" + +[[package]] +name = "wast" +version = "35.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2ef140f1b49946586078353a453a1d28ba90adfc54dde75710bc1931de204d68" +dependencies = [ + "leb128", ] [[package]] @@ -7921,7 +7993,7 @@ dependencies = [ "leb128", "memchr", "unicode-width", - "wasm-encoder", + "wasm-encoder 0.41.0", ] [[package]] @@ -7930,7 +8002,7 @@ version = "1.0.85" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "afd7357b6cc46d46a2509c43dcb1dd4131dafbf4e75562d87017b5a05ffad2d6" dependencies = [ - "wast", + "wast 70.0.2", ] [[package]] @@ -8165,6 +8237,48 @@ version = "1.0.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" +[[package]] +name = "wiggle" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "737728db69a7657a5f6a7bac445c02d8564d603d62c46c95edf928554e67d072" +dependencies = [ + "anyhow", + "async-trait", + "bitflags 2.4.2", + "thiserror", + "tracing", + "wasmtime", + "wiggle-macro", +] + +[[package]] +name = "wiggle-generate" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2460c7163b79ffefd9a564eaeab0a5b0e84bb91afdfeeb84d36f304ddbe08982" +dependencies = [ + "anyhow", + "heck", + "proc-macro2 1.0.78", + "quote 1.0.35", + "shellexpand 2.1.2", + "syn 2.0.48", + "witx", +] + +[[package]] +name = "wiggle-macro" +version = "17.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fa8d8412375ba8325d61fbae56dead51dabfaec85d620ce36427922fb9cece83" +dependencies = [ + "proc-macro2 1.0.78", + "quote 1.0.35", + "syn 2.0.48", + "wiggle-generate", +] + [[package]] name = "winapi" version = "0.3.9" @@ -8205,6 +8319,22 @@ version = "0.4.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" +[[package]] +name = "winch-codegen" +version = "0.15.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9d2b346bad5397b219b4ff0a8fa7230936061ff07c61f05d589d8d81e06fb7b2" +dependencies = [ + "anyhow", + "cranelift-codegen", + "gimli", + "regalloc2", + "smallvec", + "target-lexicon", + "wasmparser 0.118.1", + "wasmtime-environ", +] + [[package]] name = "window_clipboard" version = "0.3.0" @@ -8266,19 +8396,6 @@ dependencies = [ "windows-targets 0.52.0", ] -[[package]] -name = "windows-sys" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "43dbb096663629518eb1dfa72d80243ca5a6aca764cae62a2df70af760a9be75" -dependencies = [ - "windows_aarch64_msvc 0.33.0", - "windows_i686_gnu 0.33.0", - "windows_i686_msvc 0.33.0", - "windows_x86_64_gnu 0.33.0", - "windows_x86_64_msvc 0.33.0", -] - [[package]] name = "windows-sys" version = "0.45.0" @@ -8369,12 +8486,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "cb7764e35d4db8a7921e09562a0304bf2f93e0a51bfccee0bd0bb0b666b015ea" -[[package]] -name = "windows_aarch64_msvc" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cd761fd3eb9ab8cc1ed81e56e567f02dd82c4c837e48ac3b2181b9ffc5060807" - [[package]] name = "windows_aarch64_msvc" version = "0.42.2" @@ -8393,12 +8504,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bbaa0368d4f1d2aaefc55b6fcfee13f41544ddf36801e793edbbfd7d7df075ef" -[[package]] -name = "windows_i686_gnu" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "cab0cf703a96bab2dc0c02c0fa748491294bf9b7feb27e1f4f96340f208ada0e" - [[package]] name = "windows_i686_gnu" version = "0.42.2" @@ -8417,12 +8522,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a28637cb1fa3560a16915793afb20081aba2c92ee8af57b4d5f28e4b3e7df313" -[[package]] -name = "windows_i686_msvc" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cfdbe89cc9ad7ce618ba34abc34bbb6c36d99e96cae2245b7943cd75ee773d0" - [[package]] name = "windows_i686_msvc" version = "0.42.2" @@ -8441,12 +8540,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ffe5e8e31046ce6230cc7215707b816e339ff4d4d67c65dffa206fd0f7aa7b9a" -[[package]] -name = "windows_x86_64_gnu" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b4dd9b0c0e9ece7bb22e84d70d01b71c6d6248b81a3c60d11869451b4cb24784" - [[package]] name = "windows_x86_64_gnu" version = "0.42.2" @@ -8483,12 +8576,6 @@ version = "0.52.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1a657e1e9d3f514745a572a6846d3c7aa7dbe1658c056ed9c3344c4109a6949e" -[[package]] -name = "windows_x86_64_msvc" -version = "0.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "ff1e4aa646495048ec7f3ffddc411e1d829c026a2ec62b39da15c1055e406eaa" - [[package]] name = "windows_x86_64_msvc" version = "0.42.2" @@ -8581,6 +8668,45 @@ dependencies = [ "toml 0.5.11", ] +[[package]] +name = "winx" +version = "0.36.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f9643b83820c0cd246ecabe5fa454dd04ba4fa67996369466d0747472d337346" +dependencies = [ + "bitflags 2.4.2", + "windows-sys 0.52.0", +] + +[[package]] +name = "wit-parser" +version = "0.13.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "df4913a2219096373fd6512adead1fb77ecdaa59d7fc517972a7d30b12f625be" +dependencies = [ + "anyhow", + "id-arena", + "indexmap 2.2.2", + "log", + "semver 1.0.21", + "serde", + "serde_derive", + "serde_json", + "unicode-xid 0.2.4", +] + +[[package]] +name = "witx" +version = "0.9.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e366f27a5cabcddb2706a78296a40b8fcc451e1a6aba2fc1d94b4a01bdaaef4b" +dependencies = [ + "anyhow", + "log", + "thiserror", + "wast 35.0.2", +] + [[package]] name = "wyz" version = "0.5.1" @@ -8719,7 +8845,7 @@ version = "0.5.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e17bb3549cc1321ae1296b9cdc2698e2b6cb1992adfa19a8c72e5b7a738f44cd" dependencies = [ - "time 0.3.34", + "time", ] [[package]] @@ -8741,3 +8867,32 @@ dependencies = [ "quote 1.0.35", "syn 2.0.48", ] + +[[package]] +name = "zstd" +version = "0.11.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "20cc960326ece64f010d2d2107537f26dc589a6573a316bd5b1dba685fa5fde4" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "5.0.2+zstd.1.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1d2a5585e04f9eea4b2a3d1eca508c4dee9592a89ef6f450c11719da0726f4db" +dependencies = [ + "libc", + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.9+zstd.1.5.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9e16efa8a874a0481a574084d34cc26fdb3b99627480f785888deb6386506656" +dependencies = [ + "cc", + "pkg-config", +] diff --git a/Cargo.toml b/Cargo.toml index ad33f01eb4..c8b1ff29fb 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -15,9 +15,6 @@ members = [ "common/frontend", "client", "client/i18n", - "plugin/api", - "plugin/derive", - "plugin/rt", "rtsim", "server", "server/agent", @@ -156,6 +153,7 @@ image = { version = "0.24", default-features = false, features = ["png"] } rayon = { version = "1.5" } clap = { version = "4.2", features = ["derive"]} +async-trait = "0.1.42" [patch.crates-io] vek = { git = "https://github.com/yoanlcq/vek.git", rev = "84d5cb65841d46599a986c5477341bea4456be26" } diff --git a/common/state/Cargo.toml b/common/state/Cargo.toml index faa4b6e95b..8abae2cafa 100644 --- a/common/state/Cargo.toml +++ b/common/state/Cargo.toml @@ -6,7 +6,7 @@ version = "0.10.0" [features] simd = ["vek/platform_intrinsics"] -plugins = ["common-assets/plugins", "toml", "tar", "wasmer", "wasmer-wasix-types", "bincode", "plugin-api", "serde"] +plugins = ["common-assets/plugins", "toml", "wasmtime", "tar", "bincode", "serde"] default = ["simd"] @@ -33,11 +33,13 @@ scopeguard = "1.1.0" serde = { workspace = true, optional = true } toml = { version = "0.8", optional = true } tar = { version = "0.4.37", optional = true } -wasmer = { version = "4.0.0", optional = true, default-features = false, features = ["sys", "wat", "cranelift"] } bincode = { workspace = true, optional = true } -plugin-api = { package = "veloren-plugin-api", path = "../../plugin/api", optional = true } timer-queue = "0.1.0" -wasmer-wasix-types = { version = "0.9.0", optional = true, default-features = false } +wasmtime = { version = "17.0.0", optional = true , features = ["component-model", "async"] } +wasmtime-wasi = "17.0.0" +async-trait = { workspace = true } +bytes = "^1" +futures = "0.3.30" # Tweak running code #inline_tweak = { version = "1.0.8", features = ["release_tweak"] } diff --git a/common/state/src/plugin/errors.rs b/common/state/src/plugin/errors.rs index 40154eb922..abea6a0d3f 100644 --- a/common/state/src/plugin/errors.rs +++ b/common/state/src/plugin/errors.rs @@ -1,5 +1,4 @@ use bincode::ErrorKind; -use wasmer::{CompileError, ExportError, InstantiationError, RuntimeError}; #[derive(Debug)] pub enum PluginError { @@ -14,20 +13,21 @@ pub enum PluginError { #[derive(Debug)] pub enum PluginModuleError { - InstantiationError(Box), - InvalidPointer, - MemoryAllocation(MemoryAllocationError), - MemoryUninit(ExportError), - FindFunction(ExportError), - RunFunction(RuntimeError), - InvalidArgumentType(), - Encoding(Box), - CompileError(CompileError), + Wasmtime(wasmtime::Error), } #[derive(Debug)] -pub enum MemoryAllocationError { - InvalidReturnType, - AllocatorNotFound(ExportError), - CantAllocate(RuntimeError), +pub enum EcsAccessError { + EcsPointerNotAvailable, + EcsComponentNotFound(common::uid::Uid, String), + EcsResourceNotFound(String), + EcsEntityNotFound(common::uid::Uid), } + +impl std::fmt::Display for EcsAccessError { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + std::fmt::Debug::fmt(self, f) + } +} + +impl std::error::Error for EcsAccessError {} diff --git a/common/state/src/plugin/exports.rs b/common/state/src/plugin/exports.rs deleted file mode 100644 index 7ff9a1d9cc..0000000000 --- a/common/state/src/plugin/exports.rs +++ /dev/null @@ -1,139 +0,0 @@ -use crate::plugin::wasm_env::{HostFunctionEnvironment, HostFunctionException}; -use wasmer::{AsStoreMut, AsStoreRef, FunctionEnvMut, Memory32, Memory64, MemorySize, WasmPtr}; -// there is no WASI defined for wasm64, yet, so always use 32bit pointers -type MemoryModel = wasmer::Memory32; - -trait PtrConversion { - fn convert(self) -> WasmPtr - where - Self: Sized; -} - -impl PtrConversion for WasmPtr { - fn convert(self) -> WasmPtr - where - Self: Sized, - { - WasmPtr::new(self.offset().into()) - } -} - -fn print_impl( - env: &HostFunctionEnvironment, - store: &wasmer::StoreRef<'_>, - ptr: WasmPtr, - len: ::Offset, -) -> Result<(), wasmer_wasix_types::wasi::Errno> { - env.read_bytes(store, ptr.convert(), len.into()) - .map_err(|error| { - tracing::error!( - "Logging message from plugin {} failed with {:?}!", - env.name(), - error - ); - wasmer_wasix_types::wasi::Errno::Memviolation - }) - .and_then(|bytes| { - std::str::from_utf8(bytes.as_slice()) - .map_err(|error| { - tracing::error!( - "Logging message from plugin {} failed with {}!", - env.name(), - error - ); - wasmer_wasix_types::wasi::Errno::Inval - }) - .map(|msg| tracing::info!("[{}]: {}", env.name(), msg)) - }) -} - -#[derive(Clone, Copy)] -#[repr(C)] -pub(crate) struct CioVec { - buf: WasmPtr, - buf_len: ::Offset, -} - -// CioVec has no padding bytes, thus no action is necessary -unsafe impl wasmer::ValueType for CioVec { - fn zero_padding_bytes(&self, _bytes: &mut [std::mem::MaybeUninit]) { - const _: () = assert!( - core::mem::size_of::() - == core::mem::size_of::>() - + core::mem::size_of::<::Offset>() - ); - } -} - -// fd_write(fd: fd, iovs: ciovec_array) -> Result -pub(crate) fn wasi_fd_write( - mut env: FunctionEnvMut, - fd: i32, - iov_addr: WasmPtr, - iov_len: ::Offset, - out_result: WasmPtr<::Offset, MemoryModel>, -) -> i32 { - use wasmer_wasix_types::wasi::Errno; - if fd != 1 && fd != 2 { - Errno::Badf as i32 - } else { - let memory = env.data().memory().clone(); - let mut written: u32 = 0; - for i in 0..iov_len { - let store = env.as_store_ref(); - let Ok(cio) = iov_addr - .add_offset(i) - .and_then(|p| p.read(&memory.view(&store))) - else { - return Errno::Memviolation as i32; - }; - if let Err(e) = print_impl(env.data(), &store, cio.buf, cio.buf_len) { - return e as i32; - } - written += cio.buf_len; - } - let store = env.as_store_mut(); - let mem = memory.view(&store); - out_result - .write(&mem, written) - .map_or(Errno::Memviolation as i32, |()| Errno::Success as i32) - } -} - -// environ_get(environ: Pointer>, environ_buf: Pointer) -> -// Result<(), errno> -pub(crate) fn wasi_env_get( - _env: FunctionEnvMut, - _environ: WasmPtr, MemoryModel>, - _environ_buf: WasmPtr, -) -> i32 { - // as the environment is always empty (0 bytes, 0 entries) this function will - // just unconditionally return Success. - wasmer_wasix_types::wasi::Errno::Success as i32 -} - -// environ_sizes_get() -> Result<(size, size), errno> -pub(crate) fn wasi_env_sizes_get( - mut env: FunctionEnvMut, - numptr: WasmPtr, - bytesptr: WasmPtr, -) -> i32 { - use wasmer_wasix_types::wasi::Errno; - let memory = env.data().memory().clone(); - let store = env.as_store_mut(); - let mem = memory.view(&store); - const NUMBER_OF_ENVIRONMENT_ENTRIES: u32 = 0; - const NUMBER_OF_ENVIRONMENT_BYTES: u32 = 0; - numptr - .write(&mem, NUMBER_OF_ENVIRONMENT_ENTRIES) - .and_then(|()| bytesptr.write(&mem, NUMBER_OF_ENVIRONMENT_BYTES)) - .map_or(Errno::Memviolation, |()| Errno::Success) as i32 -} - -// proc_exit(rval: exitcode) -pub(crate) fn wasi_proc_exit( - _env: FunctionEnvMut, - exitcode: i32, -) -> Result<(), HostFunctionException> { - Err(HostFunctionException::ProcessExit(exitcode)) -} diff --git a/common/state/src/plugin/memory_manager.rs b/common/state/src/plugin/memory_manager.rs index 6abf885980..bd529e584e 100644 --- a/common/state/src/plugin/memory_manager.rs +++ b/common/state/src/plugin/memory_manager.rs @@ -1,23 +1,11 @@ -use std::{ - mem::MaybeUninit, - sync::atomic::{AtomicPtr, Ordering}, -}; - -use serde::{Deserialize, Serialize}; -use specs::{ - storage::GenericReadStorage, Component, Entities, Entity, Read, ReadStorage, WriteStorage, -}; -use wasmer::{Memory, StoreMut, StoreRef, TypedFunction, WasmPtr}; - use common::{ comp::{Health, Player}, uid::{IdMaps, Uid}, }; - -use super::{ - errors::{MemoryAllocationError, PluginModuleError}, - MemoryModel, +use specs::{ + storage::GenericReadStorage, Component, Entities, Entity, Read, ReadStorage, WriteStorage, }; +use std::sync::atomic::{AtomicPtr, Ordering}; pub struct EcsWorld<'a, 'b> { pub entities: &'b Entities<'a>, @@ -105,134 +93,3 @@ impl EcsAccessManager { self.ecs_pointer.load(Ordering::Relaxed).as_ref() } } - -/// This function check if the buffer is wide enough if not it realloc the -/// buffer calling the `wasm_prepare_buffer` function Note: There is -/// probably optimizations that can be done using less restrictive -/// ordering -fn get_pointer( - store: &mut StoreMut, - object_length: ::Offset, - allocator: &TypedFunction< - ::Offset, - WasmPtr, - >, -) -> Result, MemoryAllocationError> { - allocator - .call(store, object_length) - .map_err(MemoryAllocationError::CantAllocate) -} - -/// This functions wraps the serialization process -fn serialize_data(object: &T) -> Result, PluginModuleError> { - bincode::serialize(object).map_err(PluginModuleError::Encoding) -} - -/// This function writes an object to the wasm memory using the allocator if -/// necessary using length padding. -/// -/// With length padding the first bytes written are the length of the the -/// following slice (The object serialized). -pub(crate) fn write_serialized_with_length( - store: &mut StoreMut, - memory: &Memory, - allocator: &TypedFunction< - ::Offset, - WasmPtr, - >, - object: &T, -) -> Result, PluginModuleError> { - write_length_and_bytes(store, memory, allocator, &serialize_data(object)?) -} - -/// This function writes an raw bytes to WASM memory returning a pointer and -/// a length. Will realloc the buffer is not wide enough. -/// -/// As this function is often called after prepending a length to an existing -/// object it accepts two slices and concatenates them to cut down copying in -/// the caller. -pub(crate) fn write_bytes( - store: &mut StoreMut, - memory: &Memory, - allocator: &TypedFunction< - ::Offset, - WasmPtr, - >, - bytes: (&[u8], &[u8]), -) -> Result< - ( - WasmPtr, - ::Offset, - ), - PluginModuleError, -> { - let len = (bytes.0.len() + bytes.1.len()) as ::Offset; - let ptr = get_pointer(store, len, allocator).map_err(PluginModuleError::MemoryAllocation)?; - ptr.slice( - &memory.view(store), - len as ::Offset, - ) - .and_then(|s| { - s.subslice(0..bytes.0.len() as u64).write_slice(bytes.0)?; - s.subslice(bytes.0.len() as u64..len).write_slice(bytes.1) - }) - .map_err(|_| PluginModuleError::InvalidPointer)?; - Ok((ptr, len)) -} - -/// This function writes bytes to the wasm memory using the allocator if -/// necessary using length padding. -/// -/// With length padding the first bytes written are the length of the the -/// following slice. -pub(crate) fn write_length_and_bytes( - store: &mut StoreMut, - memory: &Memory, - allocator: &TypedFunction< - ::Offset, - WasmPtr, - >, - bytes: &[u8], -) -> Result, PluginModuleError> { - let len = bytes.len() as ::Offset; - write_bytes(store, memory, allocator, (&len.to_le_bytes(), bytes)).map(|val| val.0) -} - -/// This function reads data from memory at a position with the array length and -/// converts it to an object using bincode -pub(crate) fn read_serialized<'a, T: for<'b> Deserialize<'b>>( - memory: &'a Memory, - store: &StoreRef, - ptr: WasmPtr, - len: ::Offset, -) -> Result { - bincode::deserialize( - &read_bytes(memory, store, ptr, len).map_err(|_| bincode::ErrorKind::SizeLimit)?, - ) -} - -/// This function reads raw bytes from memory at a position with the array -/// length -pub(crate) fn read_bytes( - memory: &Memory, - store: &StoreRef, - ptr: WasmPtr, - len: ::Offset, -) -> Result, PluginModuleError> { - ptr.slice(&memory.view(store), len) - .and_then(|s| s.read_to_vec()) - .map_err(|_| PluginModuleError::InvalidPointer) -} - -/// This function reads a constant amount of raw bytes from memory -pub(crate) fn read_exact_bytes( - memory: &Memory, - store: &StoreRef, - ptr: WasmPtr, -) -> Result<[u8; N], PluginModuleError> { - let mut result = MaybeUninit::uninit_array(); - ptr.slice(&memory.view(store), N.try_into().unwrap()) - .and_then(|s| s.read_slice_uninit(&mut result)) - .map_err(|_| PluginModuleError::InvalidPointer)?; - unsafe { Ok(MaybeUninit::array_assume_init(result)) } -} diff --git a/common/state/src/plugin/mod.rs b/common/state/src/plugin/mod.rs index ae25d31d60..c5bec966d3 100644 --- a/common/state/src/plugin/mod.rs +++ b/common/state/src/plugin/mod.rs @@ -1,11 +1,9 @@ pub mod errors; -pub mod exports; pub mod memory_manager; pub mod module; -pub mod wasm_env; use bincode::ErrorKind; -use common::assets::ASSETS_PATH; +use common::{assets::ASSETS_PATH, uid::Uid}; use serde::{Deserialize, Serialize}; use std::{ collections::{HashMap, HashSet}, @@ -14,21 +12,13 @@ use std::{ path::{Path, PathBuf}, }; use tracing::{error, info}; -use wasmer::Memory64; - -use plugin_api::Event; use self::{ - errors::PluginError, + errors::{PluginError, PluginModuleError}, memory_manager::EcsWorld, - module::{PluginModule, PreparedEventQuery}, - wasm_env::HostFunctionException, + module::PluginModule, }; -use rayon::prelude::*; - -pub type MemoryModel = Memory64; - #[derive(Clone, Debug, Serialize, Deserialize)] pub struct PluginData { name: String, @@ -90,53 +80,36 @@ impl Plugin { }) } - pub fn execute_prepared( + pub fn load_event( &mut self, ecs: &EcsWorld, - event: &PreparedEventQuery, - ) -> Result, PluginError> - where - T: Event, - { + mode: common::resources::GameMode, + ) -> Result<(), PluginModuleError> { self.modules .iter_mut() - .flat_map(|module| { - module.try_execute(ecs, event).map(|x| { - x.map_err(|e| { - if let errors::PluginModuleError::RunFunction(runtime_err) = &e { - if let Some(host_except) = - runtime_err.downcast_ref::() - { - match host_except { - HostFunctionException::ProcessExit(code) => { - module.exit_code = Some(*code); - tracing::warn!( - "Module {} binary {} exited with {}", - self.data.name, - module.name(), - *code - ); - return PluginError::ProcessExit; - }, - } - } - } - PluginError::PluginModuleError( - self.data.name.to_owned(), - event.get_function_name().to_owned(), - e, - ) - }) - }) - }) - .collect::, _>>() - .map_err(|e| { - if matches!(e, PluginError::ProcessExit) { - // remove the executable from the module which called process exit - self.modules.retain(|m| m.exit_code.is_none()) - } - e - }) + .try_for_each(|module| module.load_event(ecs, mode)) + } + + pub fn command_event( + &mut self, + ecs: &EcsWorld, + name: &str, + args: &[String], + player: common::uid::Uid, + ) -> Result, CommandResults> { + let mut result = Err(CommandResults::UnknownCommand); + self.modules.iter_mut().for_each(|module| { + match module.command_event(ecs, name, args, player) { + Ok(res) => result = Ok(res), + Err(CommandResults::UnknownCommand) => (), + Err(err) => { + if result.is_err() { + result = Err(err) + } + }, + } + }); + result } } @@ -153,35 +126,6 @@ impl PluginMgr { Self::from_dir(assets_path) } - pub fn execute_prepared( - &mut self, - ecs: &EcsWorld, - event: &PreparedEventQuery, - ) -> Result, PluginError> - where - T: Event, - { - Ok(self - .plugins - .par_iter_mut() - .map(|plugin| plugin.execute_prepared(ecs, event)) - .collect::, _>>()? - .into_iter() - .flatten() - .collect()) - } - - pub fn execute_event( - &mut self, - ecs: &EcsWorld, - event: &T, - ) -> Result, PluginError> - where - T: Event, - { - self.execute_prepared(ecs, &PreparedEventQuery::new(event)?) - } - pub fn from_dir>(path: P) -> Result { let plugins = fs::read_dir(path) .map_err(PluginError::Io)? @@ -224,4 +168,44 @@ impl PluginMgr { Ok(Self { plugins }) } + + pub fn load_event( + &mut self, + ecs: &EcsWorld, + mode: common::resources::GameMode, + ) -> Result<(), PluginModuleError> { + self.plugins + .iter_mut() + .try_for_each(|plugin| plugin.load_event(ecs, mode)) + } + + pub fn command_event( + &mut self, + ecs: &EcsWorld, + name: &str, + args: &[String], + player: Uid, + ) -> Result, CommandResults> { + // return last value or last error + let mut result = Err(CommandResults::UnknownCommand); + self.plugins.iter_mut().for_each(|plugin| { + match plugin.command_event(ecs, name, args, player) { + Ok(val) => result = Ok(val), + Err(CommandResults::UnknownCommand) => (), + Err(err) => { + if result.is_err() { + result = Err(err); + } + }, + } + }); + result + } +} + +/// Error returned by plugin based server commands +pub enum CommandResults { + UnknownCommand, + HostError(wasmtime::Error), + PluginError(String), } diff --git a/common/state/src/plugin/module.rs b/common/state/src/plugin/module.rs index b569a2d30e..1a56fdaa29 100644 --- a/common/state/src/plugin/module.rs +++ b/common/state/src/plugin/module.rs @@ -1,326 +1,314 @@ -use hashbrown::HashSet; -use std::{marker::PhantomData, sync::Arc}; - -use wasmer::{ - imports, AsStoreMut, AsStoreRef, Function, FunctionEnv, FunctionEnvMut, Instance, Memory, - Module, Store, TypedFunction, WasmPtr, -}; +use std::sync::Arc; use super::{ - errors::{PluginError, PluginModuleError}, - exports, - memory_manager::{self, EcsAccessManager, EcsWorld}, - wasm_env::HostFunctionEnvironment, - MemoryModel, + errors::{EcsAccessError, PluginModuleError}, + memory_manager::{EcsAccessManager, EcsWorld}, + CommandResults, }; +use hashbrown::HashSet; +use wasmtime::{ + component::{Component, Linker}, + Config, Engine, Store, +}; +use wasmtime_wasi::preview2::WasiView; -use plugin_api::{Action, EcsAccessError, Event, Retrieve, RetrieveError, RetrieveResult}; +wasmtime::component::bindgen!({ + path: "../../plugin/wit/veloren.wit", + async: true, + with: { + "veloren:plugin/information@0.0.1/entity": Entity, + }, +}); + +pub struct Entity { + uid: common::uid::Uid, +} + +use veloren::plugin::{actions, information, types}; -// #[derive(Clone)] /// This structure represent the WASM State of the plugin. pub struct PluginModule { ecs: Arc, - wasm_state: Arc, - events: HashSet, - allocator: TypedFunction<::Offset, WasmPtr>, - memory: Memory, - store: Store, + plugin: Plugin, + store: wasmtime::Store, #[allow(dead_code)] name: String, - pub(crate) exit_code: Option, +} + +struct WasiHostCtx { + preview2_ctx: wasmtime_wasi::preview2::WasiCtx, + preview2_table: wasmtime::component::ResourceTable, + ecs: Arc, + registered_commands: HashSet, +} + +impl wasmtime_wasi::preview2::WasiView for WasiHostCtx { + fn table(&self) -> &wasmtime::component::ResourceTable { &self.preview2_table } + + fn ctx(&self) -> &wasmtime_wasi::preview2::WasiCtx { &self.preview2_ctx } + + fn table_mut(&mut self) -> &mut wasmtime::component::ResourceTable { &mut self.preview2_table } + + fn ctx_mut(&mut self) -> &mut wasmtime_wasi::preview2::WasiCtx { &mut self.preview2_ctx } +} + +impl information::Host for WasiHostCtx {} + +impl types::Host for WasiHostCtx {} + +#[wasmtime::component::__internal::async_trait] +impl actions::Host for WasiHostCtx { + async fn register_command(&mut self, name: String) -> wasmtime::Result<()> { + tracing::info!("Plugin registers /{name}"); + self.registered_commands.insert(name); + Ok(()) + } + + async fn player_send_message( + &mut self, + uid: actions::Uid, + text: String, + ) -> wasmtime::Result<()> { + tracing::info!("Plugin sends message {text} to player {uid:?}"); + Ok(()) + } +} + +#[wasmtime::component::__internal::async_trait] +impl information::HostEntity for WasiHostCtx { + async fn find_entity( + &mut self, + uid: actions::Uid, + ) -> wasmtime::Result, ()>> { + let entry = self.table_mut().push(Entity { + uid: common::uid::Uid(uid), + })?; + Ok(Ok(entry)) + } + + async fn health( + &mut self, + self_: wasmtime::component::Resource, + ) -> wasmtime::Result { + let uid = self.table().get(&self_)?.uid; + // Safety: No reference is leaked out the function so it is safe. + let world = unsafe { + self.ecs + .get() + .ok_or(EcsAccessError::EcsPointerNotAvailable)? + }; + let player = world + .id_maps + .uid_entity(uid) + .ok_or(EcsAccessError::EcsEntityNotFound(uid))?; + world + .health + .get(player) + .map(|health| information::Health { + current: health.current(), + base_max: health.base_max(), + maximum: health.maximum(), + }) + .ok_or_else(|| EcsAccessError::EcsComponentNotFound(uid, "Health".to_owned()).into()) + } + + async fn name( + &mut self, + self_: wasmtime::component::Resource, + ) -> wasmtime::Result { + let uid = self.table().get(&self_)?.uid; + // Safety: No reference is leaked out the function so it is safe. + let world = unsafe { + self.ecs + .get() + .ok_or(EcsAccessError::EcsPointerNotAvailable)? + }; + let player = world + .id_maps + .uid_entity(uid) + .ok_or(EcsAccessError::EcsEntityNotFound(uid))?; + Ok(world + .player + .get(player) + .ok_or_else(|| EcsAccessError::EcsComponentNotFound(uid, "Player".to_owned()))? + .alias + .to_owned()) + } + + fn drop( + &mut self, + rep: wasmtime::component::Resource, + ) -> wasmtime::Result<()> { + Ok(self.table_mut().delete(rep).map(|_entity| ())?) + } +} + +struct InfoStream(String); + +impl wasmtime_wasi::preview2::HostOutputStream for InfoStream { + fn write(&mut self, bytes: bytes::Bytes) -> wasmtime_wasi::preview2::StreamResult<()> { + tracing::info!("{}: {}", self.0, String::from_utf8_lossy(bytes.as_ref())); + Ok(()) + } + + fn flush(&mut self) -> wasmtime_wasi::preview2::StreamResult<()> { Ok(()) } + + fn check_write(&mut self) -> wasmtime_wasi::preview2::StreamResult { Ok(1024) } +} + +#[async_trait::async_trait] +impl wasmtime_wasi::preview2::Subscribe for InfoStream { + async fn ready(&mut self) {} +} + +struct ErrorStream(String); + +impl wasmtime_wasi::preview2::HostOutputStream for ErrorStream { + fn write(&mut self, bytes: bytes::Bytes) -> wasmtime_wasi::preview2::StreamResult<()> { + tracing::error!("{}: {}", self.0, String::from_utf8_lossy(bytes.as_ref())); + Ok(()) + } + + fn flush(&mut self) -> wasmtime_wasi::preview2::StreamResult<()> { Ok(()) } + + fn check_write(&mut self) -> wasmtime_wasi::preview2::StreamResult { Ok(1024) } +} + +#[async_trait::async_trait] +impl wasmtime_wasi::preview2::Subscribe for ErrorStream { + async fn ready(&mut self) {} +} + +struct LogStream(String, tracing::Level); + +impl wasmtime_wasi::preview2::StdoutStream for LogStream { + fn stream(&self) -> Box { + if self.1 == tracing::Level::INFO { + Box::new(InfoStream(self.0.clone())) + } else { + Box::new(ErrorStream(self.0.clone())) + } + } + + fn isatty(&self) -> bool { true } } impl PluginModule { /// This function takes bytes from a WASM File and compile them pub fn new(name: String, wasm_data: &[u8]) -> Result { - // The store contains all data for a specific instance, including the linear - // memory - let mut store = Store::default(); - // We are compiling the WASM file in the previously generated environement - let module = Module::from_binary(store.engine(), wasm_data) - .map_err(PluginModuleError::CompileError)?; - - // This is the function imported into the wasm environement - fn raw_emit_actions( - env: FunctionEnvMut, - // store: &wasmer::StoreRef<'_>, - ptr: WasmPtr, - len: ::Offset, - ) { - handle_actions( - match env.data().read_serialized(&env.as_store_ref(), ptr, len) { - Ok(e) => e, - Err(e) => { - tracing::error!(?e, "Can't decode action"); - return; - }, - }, - ); - } - - fn raw_retrieve_action( - mut env: FunctionEnvMut, - // store: &wasmer::StoreRef<'_>, - ptr: WasmPtr, - len: ::Offset, - ) -> ::Offset { - let out = match env.data().read_serialized(&env.as_store_ref(), ptr, len) { - Ok(data) => retrieve_action(env.data().ecs(), data), - Err(e) => Err(RetrieveError::BincodeError(e.to_string())), - }; - - let data = env.data().clone(); - data.write_serialized_with_length(&mut env.as_store_mut(), &out) - .unwrap_or_else(|_e| - // return a null pointer so the WASM side can tell an error occured - WasmPtr::null()) - .offset() - } - - fn dbg(a: i32) { - println!("WASM DEBUG: {}", a); - } - let ecs = Arc::new(EcsAccessManager::default()); - // Environment to pass ecs and memory_manager to callbacks - let env = FunctionEnv::new( - &mut store, - HostFunctionEnvironment::new(name.clone(), Arc::clone(&ecs)), - ); - // Create an import object. - let import_object = imports! { - "env" => { - "raw_emit_actions" => Function::new_typed_with_env(&mut store, &env, raw_emit_actions), - "raw_retrieve_action" => Function::new_typed_with_env(&mut store, &env, raw_retrieve_action), - "dbg" => Function::new_typed(&mut store, dbg), - }, - "wasi_snapshot_preview1" => { - "fd_write" => Function::new_typed_with_env(&mut store, &env, exports::wasi_fd_write), - "environ_get" => Function::new_typed_with_env(&mut store, &env, exports::wasi_env_get), - "environ_sizes_get" => Function::new_typed_with_env(&mut store, &env, exports::wasi_env_sizes_get), - "proc_exit" => Function::new_typed_with_env(&mut store, &env, exports::wasi_proc_exit), - }, - }; + // configure the wasm runtime + let mut config = Config::new(); + config.async_support(true).wasm_component_model(true); + + let engine = Engine::new(&config).map_err(PluginModuleError::Wasmtime)?; + // create a WASI environment (std implementing system calls) + let wasi = wasmtime_wasi::preview2::WasiCtxBuilder::new() + .stdout(LogStream(name.clone(), tracing::Level::INFO)) + .stderr(LogStream(name.clone(), tracing::Level::ERROR)) + .build(); + let host_ctx = WasiHostCtx { + preview2_ctx: wasi, + preview2_table: wasmtime_wasi::preview2::ResourceTable::new(), + ecs: Arc::clone(&ecs), + registered_commands: HashSet::new(), + }; + // the store contains all data of a wasm instance + let mut store = Store::new(&engine, host_ctx); + + // load wasm from binary + let module = + Component::from_binary(&engine, wasm_data).map_err(PluginModuleError::Wasmtime)?; + + // register WASI and Veloren methods with the runtime + let mut linker = Linker::new(&engine); + wasmtime_wasi::preview2::command::add_to_linker(&mut linker) + .map_err(PluginModuleError::Wasmtime)?; + Plugin::add_to_linker(&mut linker, |x| x).map_err(PluginModuleError::Wasmtime)?; + + let instance_fut = Plugin::instantiate_async(&mut store, &module, &linker); + let (plugin, _instance) = + futures::executor::block_on(instance_fut).map_err(PluginModuleError::Wasmtime)?; - // Create an instance (Code execution environement) - let instance = Instance::new(&mut store, &module, &import_object) - .map_err(|err| PluginModuleError::InstantiationError(Box::new(err)))?; - let init_args = HostFunctionEnvironment::args_from_instance(&store, &instance) - .map_err(PluginModuleError::FindFunction)?; - env.as_mut(&mut store).init_with_instance(init_args); Ok(Self { + plugin, ecs, - memory: instance - .exports - .get_memory("memory") - .map_err(PluginModuleError::MemoryUninit)? - .clone(), - allocator: instance - .exports - .get_typed_function(&store, "wasm_prepare_buffer") - .map_err(PluginModuleError::MemoryUninit)?, - events: instance - .exports - .iter() - .map(|(name, _)| name.to_string()) - .collect(), - wasm_state: Arc::new(instance), store, name, - exit_code: None, }) } - /// This function tries to execute an event for the current module. Will - /// return None if the event doesn't exists - pub fn try_execute( - &mut self, - ecs: &EcsWorld, - request: &PreparedEventQuery, - ) -> Option> - where - T: Event, - { - if !self.events.contains(&request.function_name) { - return None; - } - // Store the ECS Pointer for later use in `retreives` - let s_ecs = self.ecs.clone(); - let bytes = match s_ecs.execute_with(ecs, || { - execute_raw(self, &request.function_name, &request.bytes) - }) { - Ok(e) => e, - Err(e) => return Some(Err(e)), - }; - Some(bincode::deserialize(&bytes).map_err(PluginModuleError::Encoding)) - } - pub fn name(&self) -> &str { &self.name } -} -/// This structure represent a Pre-encoded event object (Useful to avoid -/// reencoding for each module in every plugin) -pub struct PreparedEventQuery { - bytes: Vec, - function_name: String, - _phantom: PhantomData, -} + // Implementation of the commands called from veloren and provided in plugins + pub fn load_event( + &mut self, + ecs: &EcsWorld, + mode: common::resources::GameMode, + ) -> Result<(), PluginModuleError> { + let mode = match mode { + common::resources::GameMode::Server => types::GameMode::Server, + common::resources::GameMode::Client => types::GameMode::Client, + common::resources::GameMode::Singleplayer => types::GameMode::SinglePlayer, + }; + self.ecs + .execute_with(ecs, || { + let future = self + .plugin + .veloren_plugin_events() + .call_load(&mut self.store, mode); + futures::executor::block_on(future) + }) + .map_err(PluginModuleError::Wasmtime) + } -impl PreparedEventQuery { - /// Create a prepared query from an event reference (Encode to bytes the - /// struct) This Prepared Query is used by the `try_execute` method in - /// `PluginModule` - pub fn new(event: &T) -> Result - where - T: Event, - { - Ok(Self { - bytes: bincode::serialize(&event).map_err(PluginError::Encoding)?, - function_name: event.get_event_name(), - _phantom: PhantomData, + pub fn command_event( + &mut self, + ecs: &EcsWorld, + name: &str, + args: &[String], + player: common::uid::Uid, + ) -> Result, CommandResults> { + if !self.store.data().registered_commands.contains(name) { + return Err(CommandResults::UnknownCommand); + } + self.ecs.execute_with(ecs, || { + let future = self.plugin.veloren_plugin_events().call_command( + &mut self.store, + name, + args, + player.0, + ); + match futures::executor::block_on(future) { + Err(err) => Err(CommandResults::HostError(err)), + Ok(result) => result.map_err(CommandResults::PluginError), + } }) } - pub fn get_function_name(&self) -> &str { &self.function_name } -} - -// This function is not public because this function should not be used without -// an interface to limit unsafe behaviours -fn execute_raw( - module: &mut PluginModule, - // instance: &mut Instance, - event_name: &str, - bytes: &[u8], -) -> Result, PluginModuleError> { - // This write into memory `bytes` using allocation if necessary returning a - // pointer and a length - - let (ptr, len) = memory_manager::write_bytes( - &mut module.store.as_store_mut(), - &module.memory, - &module.allocator, - (bytes, &[]), - )?; - - // This gets the event function from module exports - - let func: TypedFunction< - ( - WasmPtr, - ::Offset, - ), - WasmPtr, - > = module - .wasm_state - .exports - .get_typed_function(&module.store.as_store_ref(), event_name) - .map_err(PluginModuleError::MemoryUninit)?; - - // We call the function with the pointer and the length - - let result_ptr = func - .call(&mut module.store.as_store_mut(), ptr, len) - .map_err(PluginModuleError::RunFunction)?; - - // The first bytes correspond to the length of the result - let result_len: [u8; std::mem::size_of::<::Offset>()] = - memory_manager::read_exact_bytes(&module.memory, &module.store.as_store_ref(), result_ptr) - .map_err(|_| PluginModuleError::InvalidPointer)?; - let result_len = ::Offset::from_le_bytes(result_len); - - // Read the result of the function with the pointer and the length - let bytes = memory_manager::read_bytes( - &module.memory, - &module.store.as_store_ref(), - WasmPtr::new( - result_ptr.offset() - + std::mem::size_of::<::Offset>() - as ::Offset, - ), - result_len, - )?; - Ok(bytes) -} - -fn retrieve_action( - ecs: &EcsAccessManager, - action: Retrieve, -) -> Result { - match action { - Retrieve::GetPlayerName(e) => { - // Safety: No reference is leaked out the function so it is safe. - let world = unsafe { - ecs.get().ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsPointerNotAvailable, - ))? - }; - let player = world - .id_maps - .uid_entity(e) - .ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsEntityNotFound(e), - ))?; - - Ok(RetrieveResult::GetPlayerName( - world - .player - .get(player) - .ok_or_else(|| { - RetrieveError::EcsAccessError(EcsAccessError::EcsComponentNotFound( - e, - "Player".to_owned(), - )) - })? - .alias - .to_owned(), - )) - }, - Retrieve::GetEntityHealth(e) => { - // Safety: No reference is leaked out the function so it is safe. - let world = unsafe { - ecs.get().ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsPointerNotAvailable, - ))? - }; - let player = world - .id_maps - .uid_entity(e) - .ok_or(RetrieveError::EcsAccessError( - EcsAccessError::EcsEntityNotFound(e), - ))?; - Ok(RetrieveResult::GetEntityHealth( - world - .health - .get(player) - .ok_or_else(|| { - RetrieveError::EcsAccessError(EcsAccessError::EcsComponentNotFound( - e, - "Health".to_owned(), - )) - })? - .clone(), - )) - }, - } -} - -fn handle_actions(actions: Vec) { - for action in actions { - match action { - Action::ServerClose => { - tracing::info!("Server closed by plugin"); - std::process::exit(-1); - }, - Action::Print(e) => { - tracing::info!("{}", e); - }, - Action::PlayerSendMessage(a, b) => { - tracing::info!("SendMessage {} -> {}", a, b); - }, - Action::KillEntity(e) => { - tracing::info!("Kill Entity {}", e); - }, - } + pub fn player_join_event( + &mut self, + ecs: &EcsWorld, + name: &str, + uuid: common::uuid::Uuid, + ) -> types::JoinResult { + self.ecs.execute_with(ecs, || { + let future = self.plugin.veloren_plugin_events().call_join( + &mut self.store, + name, + uuid.as_u64_pair(), + ); + match futures::executor::block_on(future) { + Ok(value) => { + tracing::info!("JoinResult {value:?}"); + value + }, + Err(err) => { + tracing::error!("join_event: {err:?}"); + types::JoinResult::None + }, + } + }) } } diff --git a/common/state/src/plugin/wasm_env.rs b/common/state/src/plugin/wasm_env.rs deleted file mode 100644 index 94df40beb8..0000000000 --- a/common/state/src/plugin/wasm_env.rs +++ /dev/null @@ -1,119 +0,0 @@ -use std::sync::Arc; - -use serde::{de::DeserializeOwned, Serialize}; -use wasmer::{ExportError, Instance, Memory, Store, StoreMut, StoreRef, TypedFunction, WasmPtr}; - -use super::{ - errors::PluginModuleError, - memory_manager::{self, EcsAccessManager}, - MemoryModel, -}; - -#[derive(Clone)] -pub struct HostFunctionEnvironment { - ecs: Arc, /* This represent the pointer to the ECS object (set to - * i32::MAX if to ECS is - * availible) */ - memory: Option, // This object represent the WASM Memory - allocator: Option< - TypedFunction<::Offset, WasmPtr>, - >, /* Linked to: wasm_prepare_buffer */ - name: String, // This represent the plugin name -} - -pub struct HostFunctionEnvironmentInit { - allocator: TypedFunction<::Offset, WasmPtr>, - memory: Memory, -} - -#[derive(Debug, Clone, Copy)] -// Exception thrown from a native wasm callback -pub enum HostFunctionException { - ProcessExit(i32), -} - -// needed for `std::error::Error` -impl core::fmt::Display for HostFunctionException { - fn fmt(&self, f: &mut core::fmt::Formatter) -> core::fmt::Result { write!(f, "{:?}", self) } -} - -impl std::error::Error for HostFunctionException {} - -impl HostFunctionEnvironment { - /// Create a new environment for functions providing functionality to WASM - pub fn new(name: String, ecs: Arc) -> Self { - Self { - ecs, - allocator: Default::default(), - memory: Default::default(), - name, - } - } - - #[inline] - pub(crate) fn ecs(&self) -> &Arc { &self.ecs } - - #[inline] - pub(crate) fn memory(&self) -> &Memory { self.memory.as_ref().unwrap() } - - #[inline] - pub(crate) fn allocator( - &self, - ) -> &TypedFunction<::Offset, WasmPtr> { - self.allocator.as_ref().unwrap() - } - - #[inline] - pub(crate) fn name(&self) -> &str { &self.name } - - /// This function is a safe interface to WASM memory that serializes and - /// writes an object to linear memory returning a pointer - pub(crate) fn write_serialized_with_length( - &self, - store: &mut StoreMut, - object: &T, - ) -> Result, PluginModuleError> { - memory_manager::write_serialized_with_length(store, self.memory(), self.allocator(), object) - } - - /// This function is a safe interface to WASM memory that reads memory from - /// pointer and length returning an object - pub(crate) fn read_serialized( - &self, - store: &StoreRef, - position: WasmPtr, - length: ::Offset, - ) -> Result { - memory_manager::read_serialized(self.memory(), store, position, length) - } - - /// This function is a safe interface to WASM memory that reads memory from - /// a pointer and a length and returns some bytes - pub(crate) fn read_bytes( - &self, - store: &StoreRef, - ptr: WasmPtr, - len: ::Offset, - ) -> Result, PluginModuleError> { - memory_manager::read_bytes(self.memory(), store, ptr, len) - } - - /// This function creates the argument for init_with_instance() from - /// exported symbol lookup - pub fn args_from_instance( - store: &Store, - instance: &Instance, - ) -> Result { - let memory = instance.exports.get_memory("memory")?.clone(); - let allocator = instance - .exports - .get_typed_function(store, "wasm_prepare_buffer")?; - Ok(HostFunctionEnvironmentInit { memory, allocator }) - } - - /// Initialize the wasm exports in the environment - pub fn init_with_instance(&mut self, args: HostFunctionEnvironmentInit) { - self.memory = Some(args.memory); - self.allocator = Some(args.allocator); - } -} diff --git a/common/state/src/state.rs b/common/state/src/state.rs index fada52ac8c..bd894e0758 100644 --- a/common/state/src/state.rs +++ b/common/state/src/state.rs @@ -349,11 +349,7 @@ impl State { id_maps: &ecs.read_resource::().into(), player: ecs.read_component().into(), }; - if let Err(e) = plugin_mgr - .execute_event(&ecs_world, &plugin_api::event::PluginLoadEvent { - game_mode, - }) - { + if let Err(e) = plugin_mgr.load_event(&ecs_world, game_mode) { tracing::debug!(?e, "Failed to run plugin init"); tracing::info!("Plugins disabled, enable debug logging for more information."); PluginMgr::default() diff --git a/network/Cargo.toml b/network/Cargo.toml index 7aca6938e6..929127fd84 100644 --- a/network/Cargo.toml +++ b/network/Cargo.toml @@ -40,7 +40,7 @@ quinn = { version = "0.10", optional = true } rustls = "0.21" lz-fear = { version = "0.1.1", optional = true } # async traits -async-trait = "0.1.42" +async-trait = { workspace = true } bytes = "^1" # faster HashMaps hashbrown = { workspace = true } diff --git a/network/protocol/Cargo.toml b/network/protocol/Cargo.toml index 3f9522c6b8..30ca70d8a7 100644 --- a/network/protocol/Cargo.toml +++ b/network/protocol/Cargo.toml @@ -22,7 +22,7 @@ prometheus = { workspace = true, optional = true } bitflags = { workspace = true } rand = { workspace = true } # async traits -async-trait = "0.1.42" +async-trait = { workspace = true } bytes = "^1" hashbrown = { workspace = true } diff --git a/plugin/api/Cargo.toml b/plugin/api/Cargo.toml deleted file mode 100644 index 8a72ecb897..0000000000 --- a/plugin/api/Cargo.toml +++ /dev/null @@ -1,9 +0,0 @@ -[package] -name = "veloren-plugin-api" -version = "0.1.0" -authors = ["ccgauche "] -edition = "2021" - -[dependencies] -serde = { workspace = true } -common = { package = "veloren-common", path = "../../common", features = ["no-assets"] } diff --git a/plugin/api/src/errors.rs b/plugin/api/src/errors.rs deleted file mode 100644 index 7b7715591d..0000000000 --- a/plugin/api/src/errors.rs +++ /dev/null @@ -1,71 +0,0 @@ -use common::uid::Uid; - -use serde::{Deserialize, Serialize}; - -#[derive(Debug, Serialize, Deserialize)] -pub enum RetrieveError { - EcsAccessError(EcsAccessError), - OtherError(String), - DataReadError, - BincodeError(String), - InvalidType, -} - -impl core::fmt::Display for RetrieveError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - RetrieveError::EcsAccessError(e) => { - write!(f, "RetrieveError: {}", e) - }, - RetrieveError::OtherError(e) => { - write!(f, "RetrieveError: Unknown error: {}", e) - }, - RetrieveError::DataReadError => { - write!( - f, - "RetrieveError: Can't pass data through WASM FFI: WASM Memory is corrupted" - ) - }, - RetrieveError::BincodeError(e) => { - write!(f, "RetrieveError: Bincode error: {}", e) - }, - RetrieveError::InvalidType => { - write!( - f, - "RetrieveError: This type wasn't expected as the result for this Retrieve" - ) - }, - } - } -} - -#[derive(Debug, Serialize, Deserialize)] -pub enum EcsAccessError { - EcsPointerNotAvailable, - EcsComponentNotFound(Uid, String), - EcsResourceNotFound(String), - EcsEntityNotFound(Uid), -} - -impl core::fmt::Display for EcsAccessError { - fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result { - match self { - EcsAccessError::EcsPointerNotAvailable => { - write!(f, "EcsAccessError can't read the ECS pointer") - }, - EcsAccessError::EcsComponentNotFound(a, b) => { - write!( - f, - "EcsAccessError can't find component {} for entity from UID {}", - b, a - ) - }, - EcsAccessError::EcsResourceNotFound(a) => { - write!(f, "EcsAccessError can't find resource {}", a) - }, - EcsAccessError::EcsEntityNotFound(a) => { - write!(f, "EcsAccessError can't find entity from UID {}", a) - }, - } - } -} diff --git a/plugin/api/src/lib.rs b/plugin/api/src/lib.rs deleted file mode 100644 index d859afa8c9..0000000000 --- a/plugin/api/src/lib.rs +++ /dev/null @@ -1,228 +0,0 @@ -pub extern crate common; - -pub use common::comp::Health; -use serde::{de::DeserializeOwned, Deserialize, Serialize}; - -pub use common::{resources::GameMode, uid::Uid}; - -mod errors; - -pub use errors::*; -pub use event::*; - -/// The [`Action`] enum represents a push modification that will be made in the -/// ECS in the next tick Note that all actions when sent are async and will not -/// be executed in order like [`Retrieve`] that are sync. All actions sent will -/// be executed in the send order in the ticking before the rest of the logic -/// applies. -/// -/// # Usage: -/// ```rust -/// # use veloren_plugin_api::*; -/// # pub fn emit_action(action: Action) { emit_actions(vec![action]) } -/// # pub fn emit_actions(_actions: Vec) {} -/// // Packing actions is better than sending multiple ones at the same time! -/// emit_actions(vec![ -/// Action::KillEntity(Uid(1)), -/// Action::PlayerSendMessage(Uid(0), "This is a test message".to_owned()), -/// ]); -/// // You can also use this to only send one action -/// emit_action(Action::KillEntity(Uid(1))); -/// ``` -#[derive(Deserialize, Serialize, Debug)] -pub enum Action { - ServerClose, - Print(String), - PlayerSendMessage(Uid, String), - KillEntity(Uid), -} - -/// The [`Retrieve`] enum represents read of the ECS is sync and blocking. -/// This enum shouldn't be used by itself. You should always prefer `get` -/// methods on Plugin API Types For instance, prefer this method: -/// ```rust -/// # use veloren_plugin_api::*; -/// # let entityid = Player {id: Uid(0)}; -/// # trait G { fn get_entity_health(&self) -> Option; } -/// # impl G for Player {fn get_entity_health(&self) -> Option {Some(1)}} -/// let life = entityid.get_entity_health().unwrap(); -/// // Do something with life -/// ``` -/// Over this one: -/// ```rust -/// # use common::comp::Body; -/// # use common::comp::body::humanoid; -/// # use veloren_plugin_api::*; -/// # let entityid = Uid(0); -/// # fn retrieve_action(r: &Retrieve) -> Result { Ok(RetrieveResult::GetEntityHealth(Health::new(Body::Humanoid(humanoid::Body::random()), 1))) } -/// let life = if let RetrieveResult::GetEntityHealth(e) = -/// retrieve_action(&Retrieve::GetEntityHealth(entityid)).unwrap() -/// { -/// e -/// } else { -/// unreachable!() -/// }; -/// // Do something with life -/// ``` -#[derive(Deserialize, Serialize, Debug)] -pub enum Retrieve { - GetPlayerName(Uid), - GetEntityHealth(Uid), -} - -/// The [`RetrieveResult`] struct is generated while using the `retrieve_action` -/// function -/// -/// You should always prefer using `get` methods available in Plugin API types. -/// -/// Example: -/// ```rust -/// # use common::comp::Body; -/// # use common::comp::body::humanoid; -/// # use veloren_plugin_api::*; -/// # let entityid = Uid(0); -/// # fn retrieve_action(r: &Retrieve) -> Result { Ok(RetrieveResult::GetEntityHealth(Health::new(Body::Humanoid(humanoid::Body::random()), 1)))} -/// let life = if let RetrieveResult::GetEntityHealth(e) = -/// retrieve_action(&Retrieve::GetEntityHealth(entityid)).unwrap() -/// { -/// e -/// } else { -/// unreachable!() -/// }; -/// // Do something with life -/// ``` -#[derive(Serialize, Deserialize, Debug)] -pub enum RetrieveResult { - GetPlayerName(String), - GetEntityHealth(Health), -} - -/// This trait is implement by all events and ensure type safety of FFI. -pub trait Event: Serialize + DeserializeOwned + Send + Sync { - type Response: Serialize + DeserializeOwned + Send + Sync; - - fn get_event_name(&self) -> String; -} - -/// This module contains all events from the api -pub mod event { - use super::*; - use serde::{Deserialize, Serialize}; - - /// This event is called when a chat command is run. - /// Your event should be named `on_command_` - /// - /// If you return an Error the displayed message will be the error message - /// in red You can return a Vec that will be print to player - /// chat as info - /// - /// # Example - /// ```ignore - /// #[event_handler] - /// pub fn on_command_testplugin(command: ChatCommandEvent) -> Result, String> { - /// Ok(vec![format!( - /// "Player of id {:?} named {} with {:?} sent command with args {:?}", - /// command.player.id, - /// command - /// .player - /// .get_player_name() - /// .expect("Can't get player name"), - /// command - /// .player - /// .get_entity_health() - /// .expect("Can't get player health"), - /// command.command_args - /// )]) - /// } - /// ``` - #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] - pub struct ChatCommandEvent { - pub command: String, - pub command_args: Vec, - pub player: Player, - } - - impl Event for ChatCommandEvent { - type Response = Result, String>; - - fn get_event_name(&self) -> String { format!("on_command_{}", self.command) } - } - - /// This struct represent a player - #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] - pub struct Player { - pub id: Uid, - } - - /// This event is called when a player connects. - /// Your event should be named `on_join` - /// - /// You can either return `CloseConnection` or `None` - /// If `CloseConnection` is returned the player will be kicked - /// - /// # Example - /// ```ignore - /// #[event_handler] - /// pub fn on_join(command: PlayerJoinEvent) -> PlayerJoinResult { - /// PlayerJoinResult::CloseConnection - /// } - /// ``` - #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] - pub struct PlayerJoinEvent { - pub player_name: String, - pub player_id: [u8; 16], - } - - impl Event for PlayerJoinEvent { - type Response = PlayerJoinResult; - - fn get_event_name(&self) -> String { "on_join".to_owned() } - } - - /// This is the return type of an `on_join` event. See [`PlayerJoinEvent`] - /// - /// Variants: - /// - `CloseConnection` will kick the player. - /// - `None` will let the player join the server. - #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] - #[repr(u8)] - pub enum PlayerJoinResult { - Kick(String), - None, - } - - impl Default for PlayerJoinResult { - fn default() -> Self { Self::None } - } - - /// This event is called when the plugin is loaded - /// Your event should be named `on_load` - /// - /// # Example - /// ```ignore - /// #[event_handler] - /// pub fn on_load(load: PluginLoadEvent) { - /// match load.game_mode { - /// GameMode::Server => emit_action(Action::Print("Hello, server!".to_owned())), - /// GameMode::Client => emit_action(Action::Print("Hello, client!".to_owned())), - /// GameMode::Singleplayer => emit_action(Action::Print("Hello, singleplayer!".to_owned())), - /// } - /// } - /// ``` - #[derive(Serialize, Deserialize, Debug, Clone, Eq, PartialEq)] - pub struct PluginLoadEvent { - pub game_mode: GameMode, - } - - impl Event for PluginLoadEvent { - type Response = (); - - fn get_event_name(&self) -> String { "on_load".to_owned() } - } - - // impl Default for PlayerJoinResult { - // fn default() -> Self { - // Self::None - // } - // } -} diff --git a/plugin/derive/Cargo.toml b/plugin/derive/Cargo.toml deleted file mode 100644 index 0b4fd1c296..0000000000 --- a/plugin/derive/Cargo.toml +++ /dev/null @@ -1,15 +0,0 @@ -[package] -name = "veloren-plugin-derive" -version = "0.1.0" -authors = ["ccgauche "] -edition = "2021" - -# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html - -[lib] -proc-macro = true - -[dependencies] -proc-macro2 = "1.0.24" -syn = { version = "2", features = ["full","extra-traits"]} -quote = "1.0.7" diff --git a/plugin/derive/src/lib.rs b/plugin/derive/src/lib.rs deleted file mode 100644 index 3ac534d03a..0000000000 --- a/plugin/derive/src/lib.rs +++ /dev/null @@ -1,76 +0,0 @@ -extern crate proc_macro; - -use proc_macro::TokenStream; -use quote::quote; -use syn::{parse_macro_input, ItemFn, ItemStruct}; - -#[proc_macro_attribute] -pub fn global_state(_args: TokenStream, item: TokenStream) -> TokenStream { - let parsed = parse_macro_input!(item as ItemStruct); - let name = &parsed.ident; - let out: proc_macro2::TokenStream = quote! { - #parsed - type PLUGIN_STATE_TYPE = #name; - - static mut PLUGIN_STATE: Option = None; - - static PLUGIN_STATE_GUARD: std::sync::atomic::AtomicBool = std::sync::atomic::AtomicBool::new(false); - }; - out.into() -} - -#[proc_macro_attribute] -pub fn event_handler(_args: TokenStream, item: TokenStream) -> TokenStream { - let parsed = parse_macro_input!(item as ItemFn); - let fn_body = parsed.block; // function body - let sig = parsed.sig; // function signature - let fn_name = sig.ident; // function name/identifier - let fn_args = sig.inputs; // comma separated args - let fn_return = sig.output; // comma separated args - - let out: proc_macro2::TokenStream = if fn_args.len() == 1 { - quote! { - #[no_mangle] - pub fn #fn_name(intern__ptr: i64, intern__len: i64) -> i64 { - let input = ::veloren_plugin_rt::read_input(intern__ptr as _,intern__len as _).unwrap(); - #[inline] - fn inner(#fn_args) #fn_return { - #fn_body - } - // Artificially force the event handler to be type-correct - fn force_event(event: E, inner: fn(E) -> E::Response) -> E::Response { - inner(event) - } - ::veloren_plugin_rt::write_output(&force_event(input, inner)) - } - } - } else { - quote! { - #[no_mangle] - pub fn #fn_name(intern__ptr: i64, intern__len: i64) -> i64 { - let input = ::veloren_plugin_rt::read_input(intern__ptr as _,intern__len as _).unwrap(); - #[inline] - fn inner(#fn_args) #fn_return { - #fn_body - } - // Artificially force the event handler to be type-correct - fn force_event(event: E, inner: fn(E, &mut PLUGIN_STATE_TYPE) -> E::Response) -> E::Response { - //let mut plugin_state = PLUGIN_STATE.lock().unwrap(); - - assert_eq!(PLUGIN_STATE_GUARD.swap(true, std::sync::atomic::Ordering::Acquire), false); - unsafe { - if PLUGIN_STATE.is_none() { - PLUGIN_STATE = Some(PLUGIN_STATE_TYPE::default()); - } - } - let out = inner(event, unsafe {PLUGIN_STATE.as_mut().unwrap()}); - PLUGIN_STATE_GUARD.store(false, std::sync::atomic::Ordering::Release); - out - - } - ::veloren_plugin_rt::write_output(&force_event(input, inner)) - } - } - }; - out.into() -} diff --git a/plugin/examples/hello/Cargo.lock b/plugin/examples/hello/Cargo.lock new file mode 100644 index 0000000000..1c13fe202f --- /dev/null +++ b/plugin/examples/hello/Cargo.lock @@ -0,0 +1,25 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "bitflags" +version = "2.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ed570934406eb16438a4e976b1b4500774099c13b8cb96eec99f620f05090ddf" + +[[package]] +name = "hello" +version = "0.1.0" +dependencies = [ + "wit-bindgen", +] + +[[package]] +name = "wit-bindgen" +version = "0.16.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b76f1d099678b4f69402a421e888bbe71bf20320c2f3f3565d0e7484dbe5bc20" +dependencies = [ + "bitflags", +] diff --git a/plugin/examples/hello/Cargo.toml b/plugin/examples/hello/Cargo.toml new file mode 100644 index 0000000000..8d8b838e78 --- /dev/null +++ b/plugin/examples/hello/Cargo.toml @@ -0,0 +1,22 @@ +[package] +name = "hello" +version = "0.1.0" +edition = "2021" + +[workspace] + +[package.metadata.component] +package = "component:hello" + +[package.metadata.component.target] +path = "../../wit/veloren.wit" + +[package.metadata.component.dependencies] + +# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html + +[dependencies] +wit-bindgen = { version = "0.16.0", default-features = false, features = ["realloc"] } + +[lib] +crate-type = ["cdylib"] diff --git a/plugin/examples/hello/src/lib.rs b/plugin/examples/hello/src/lib.rs new file mode 100644 index 0000000000..b5bdc46d5b --- /dev/null +++ b/plugin/examples/hello/src/lib.rs @@ -0,0 +1,54 @@ +#![feature(atomic_bool_fetch_not)] + +mod bindings; + +use bindings::{ + exports::veloren::plugin::events::Guest, + veloren::plugin::{ + actions, + information::Entity, + types::{GameMode, Health, JoinResult, PlayerId, Uid}, + }, +}; +use core::sync::atomic::{AtomicBool, Ordering}; + +#[derive(Default)] +struct Component {} + +static COUNTER: AtomicBool = AtomicBool::new(false); + +impl Guest for Component { + fn load(mode: GameMode) { + actions::register_command("test"); + match mode { + GameMode::Server => println!("Hello, server!"), + GameMode::Client => println!("Hello, client!"), + GameMode::SinglePlayer => println!("Hello, singleplayer!"), + } + } + + fn join(player_name: wit_bindgen::rt::string::String, player_id: PlayerId) -> JoinResult { + if COUNTER.fetch_not(Ordering::SeqCst) { + JoinResult::Kick(format!("Rejected user {player_name}, id {player_id:?}")) + } else { + JoinResult::None + } + } + + fn command( + command: wit_bindgen::rt::string::String, + command_args: wit_bindgen::rt::vec::Vec, + player: Uid, + ) -> Result, String> { + let entity: Result = Entity::find_entity(player); + let health = entity.as_ref().map(|e| e.health()).unwrap_or(Health { + base_max: 0.0, + maximum: 0.0, + current: 0.0, + }); + Ok(vec![format!( + "Player id {player:?} name {} with {health:?} command {command} args {command_args:?}", + entity.map(|e| e.name()).unwrap_or_default(), + )]) + } +} diff --git a/plugin/rt/Cargo.toml b/plugin/rt/Cargo.toml deleted file mode 100644 index 324cc8c9e7..0000000000 --- a/plugin/rt/Cargo.toml +++ /dev/null @@ -1,18 +0,0 @@ -[package] -name = "veloren-plugin-rt" -version = "0.1.0" -authors = ["Joshua Barretto "] -edition = "2021" - -[dependencies] -plugin-api = { package = "veloren-plugin-api", path = "../api" } -plugin-derive = { package = "veloren-plugin-derive", path = "../derive"} -serde = { workspace = true } -bincode = { workspace = true } - -[[example]] -name = "hello" -crate-type = ["cdylib"] - -[dev-dependencies] -plugin-derive = { package = "veloren-plugin-derive", path = "../derive"} diff --git a/plugin/rt/examples/hello.rs b/plugin/rt/examples/hello.rs deleted file mode 100644 index aa8f0c1b71..0000000000 --- a/plugin/rt/examples/hello.rs +++ /dev/null @@ -1,46 +0,0 @@ -use veloren_plugin_rt::{ - api::{event::*, Action, GameMode}, - *, -}; - -#[event_handler] -pub fn on_load(load: PluginLoadEvent) { - match load.game_mode { - GameMode::Server => emit_action(Action::Print("Hello, server!".to_owned())), - GameMode::Client => emit_action(Action::Print("Hello, client!".to_owned())), - GameMode::Singleplayer => emit_action(Action::Print("Hello, singleplayer!".to_owned())), - } -} - -#[event_handler] -pub fn on_command_testplugin(command: ChatCommandEvent) -> Result, String> { - Ok(vec![format!( - "Player of id {:?} named {} with {:?} sended command with args {:?}", - command.player.id, - command - .player - .get_player_name() - .expect("Can't get player name"), - command - .player - .get_entity_health() - .expect("Can't get player health"), - command.command_args - )]) -} - -#[global_state] -#[derive(Default)] -struct State { - counter: bool, -} - -#[event_handler] -pub fn on_join(input: PlayerJoinEvent, state: &mut State) -> PlayerJoinResult { - state.counter = !state.counter; - if !state.counter { - PlayerJoinResult::Kick(format!("You are a cheater {:?}", input)) - } else { - PlayerJoinResult::None - } -} diff --git a/plugin/rt/src/lib.rs b/plugin/rt/src/lib.rs deleted file mode 100644 index 9c24d41f1e..0000000000 --- a/plugin/rt/src/lib.rs +++ /dev/null @@ -1,106 +0,0 @@ -pub extern crate plugin_derive; - -pub mod retrieve; - -use api::RetrieveError; -pub use retrieve::*; - -use std::convert::TryInto; - -pub use plugin_api as api; -pub use plugin_derive::*; - -use serde::{de::DeserializeOwned, Serialize}; - -#[cfg(target_arch = "wasm32")] -extern "C" { - fn raw_emit_actions(ptr: i64, len: i64); - fn raw_retrieve_action(ptr: i64, len: i64) -> i64; - pub fn dbg(i: i32); -} - -pub fn retrieve_action(_actions: &api::Retrieve) -> Result { - #[cfg(target_arch = "wasm32")] - { - let ret = bincode::serialize(&_actions).expect("Can't serialize action in emit"); - unsafe { - let ptr = raw_retrieve_action(to_i64(ret.as_ptr() as _), to_i64(ret.len() as _)); - let ptr = from_i64(ptr); - let len = - u64::from_le_bytes(std::slice::from_raw_parts(ptr as _, 8).try_into().unwrap()); - let a = ::std::slice::from_raw_parts((ptr + 8) as _, len as _); - bincode::deserialize::>(&a) - .map_err(|x| RetrieveError::BincodeError(x.to_string()))? - } - } - #[cfg(not(target_arch = "wasm32"))] - unreachable!() -} - -pub fn emit_action(action: api::Action) { emit_actions(vec![action]) } - -pub fn emit_actions(_actions: Vec) { - #[cfg(target_arch = "wasm32")] - { - let ret = bincode::serialize(&_actions).expect("Can't serialize action in emit"); - unsafe { - raw_emit_actions(to_i64(ret.as_ptr() as _), to_i64(ret.len() as _)); - } - } -} - -pub fn read_input(ptr: i64, len: i64) -> Result -where - T: DeserializeOwned, -{ - let slice = unsafe { std::slice::from_raw_parts(from_i64(ptr) as _, from_i64(len) as _) }; - bincode::deserialize(slice).map_err(|_| "Failed to deserialize function input") -} - -/// This function split a u128 in two u64 encoding them as le bytes -pub fn from_u128(i: u128) -> (u64, u64) { - let i = i.to_le_bytes(); - ( - u64::from_le_bytes(i[0..8].try_into().unwrap()), - u64::from_le_bytes(i[8..16].try_into().unwrap()), - ) -} - -/// This function merge two u64 encoded as le in one u128 -pub fn to_u128(a: u64, b: u64) -> u128 { - let a = a.to_le_bytes(); - let b = b.to_le_bytes(); - u128::from_le_bytes([a, b].concat().try_into().unwrap()) -} - -/// This function encode a u64 into a i64 using le bytes -pub fn to_i64(i: u64) -> i64 { i64::from_le_bytes(i.to_le_bytes()) } - -/// This function decode a i64 into a u64 using le bytes -pub fn from_i64(i: i64) -> u64 { u64::from_le_bytes(i.to_le_bytes()) } - -static mut VEC: Vec = vec![]; -static mut DATA: Vec = vec![]; - -pub fn write_output(value: impl Serialize) -> i64 { - unsafe { - VEC = bincode::serialize(&value).expect("Can't serialize event output"); - DATA = [ - (VEC.as_ptr() as u64).to_le_bytes(), - (VEC.len() as u64).to_le_bytes(), - ] - .concat(); - to_i64(DATA.as_ptr() as u64) - } -} - -static mut BUFFERS: Vec = Vec::new(); - -/// Allocate buffer from wasm linear memory -/// # Safety -/// This function should never be used only intended to by used by the host -#[no_mangle] -pub unsafe fn wasm_prepare_buffer(size: i64) -> i64 { - BUFFERS = vec![0u8; size as usize]; - BUFFERS.as_ptr() as i64 -} diff --git a/plugin/rt/src/retrieve.rs b/plugin/rt/src/retrieve.rs deleted file mode 100644 index 823e974f54..0000000000 --- a/plugin/rt/src/retrieve.rs +++ /dev/null @@ -1,35 +0,0 @@ -use plugin_api::{Health, RetrieveError}; - -use crate::api::{Retrieve, RetrieveResult}; - -pub trait GetPlayerName { - fn get_player_name(&self) -> Result; -} - -pub trait GetEntityHealth { - fn get_entity_health(&self) -> Result; -} - -impl GetEntityHealth for crate::api::event::Player { - fn get_entity_health(&self) -> Result { - if let RetrieveResult::GetEntityHealth(e) = - crate::retrieve_action(&Retrieve::GetEntityHealth(self.id))? - { - Ok(e) - } else { - Err(RetrieveError::InvalidType) - } - } -} - -impl GetPlayerName for crate::api::event::Player { - fn get_player_name(&self) -> Result { - if let RetrieveResult::GetPlayerName(e) = - crate::retrieve_action(&Retrieve::GetPlayerName(self.id))? - { - Ok(e) - } else { - Err(RetrieveError::InvalidType) - } - } -} diff --git a/plugin/wit/veloren.wit b/plugin/wit/veloren.wit new file mode 100644 index 0000000000..4de1ed8aed --- /dev/null +++ b/plugin/wit/veloren.wit @@ -0,0 +1,56 @@ +package veloren:plugin@0.0.1; + +interface types { + enum game-mode { + server, + client, + single-player, + } + type uid = u64; + type player-id = tuple; + + record health { + current: f32, + base-max: f32, + maximum: f32, + } + + variant join-result { + kick(string), + none, + } +} + +interface events { + use types.{game-mode, uid, player-id, join-result}; + + load: func(mode: game-mode); + join: func(player-name: string, player-id: player-id) -> join-result; + command: func(command: string, command-args: list, player: uid) -> result, string>; +} + +interface actions { + use types.{uid}; + + register-command: func(name: string); + player-send-message: func(uid: uid, text: string); + // for print use the normal WASI stdout +} + +interface information { + use types.{uid, health}; + + resource entity { + // fallible constructor + find-entity: static func(uid: uid) -> result; + + health: func() -> health; + name: func() -> string; + } +} + +world plugin { + export events; + import actions; + import information; +} diff --git a/server/Cargo.toml b/server/Cargo.toml index ff50ae522d..0064e36f61 100644 --- a/server/Cargo.toml +++ b/server/Cargo.toml @@ -67,6 +67,4 @@ censor = "0.3" rusqlite = { version = "0.28.0", features = ["array", "vtab", "bundled", "trace"] } refinery = { version = "0.8.8", features = ["rusqlite"] } -# Plugins -plugin-api = { package = "veloren-plugin-api", path = "../plugin/api"} schnellru = "0.2.1" diff --git a/server/src/events/mounting.rs b/server/src/events/mounting.rs index 6e579484b8..d427646605 100644 --- a/server/src/events/mounting.rs +++ b/server/src/events/mounting.rs @@ -7,9 +7,8 @@ use common::{ link::Is, mounting::{Mounting, Rider, VolumeMounting, VolumeRider}, rtsim::RtSimEntity, - uid::IdMaps, + uid::{IdMaps, Uid}, }; -use plugin_api::Uid; use specs::WorldExt; use crate::{rtsim::RtSim, state_ext::StateExt, Server}; diff --git a/server/src/lib.rs b/server/src/lib.rs index a17a441b51..f8ebd32ae7 100644 --- a/server/src/lib.rs +++ b/server/src/lib.rs @@ -1315,66 +1315,45 @@ impl Server { ); return; }; - let rs = plugin_manager.execute_event( - &ecs_world, - &plugin_api::event::ChatCommandEvent { - command: name.clone(), - command_args: args.clone(), - player: plugin_api::event::Player { id: uid }, - }, - ); - match rs { - Ok(e) => { - if e.is_empty() { - self.notify_client( - entity, - ServerGeneral::server_msg( - comp::ChatType::CommandError, - format!( - "Unknown command '/{}'.\nType '/help' for available \ - commands", - name - ), + match plugin_manager.command_event(&ecs_world, &name, args.as_slice(), uid) { + Err(common_state::plugin::CommandResults::UnknownCommand) => self + .notify_client( + entity, + ServerGeneral::server_msg( + comp::ChatType::CommandError, + format!( + "Unknown command '/{name}'.\nType '/help' for available \ + commands", ), - ); - } else { - e.into_iter().for_each(|e| match e { - Ok(e) => { - if !e.is_empty() { - self.notify_client( - entity, - ServerGeneral::server_msg( - comp::ChatType::CommandInfo, - e.join("\n"), - ), - ); - } - }, - Err(e) => { - self.notify_client( - entity, - ServerGeneral::server_msg( - comp::ChatType::CommandError, - format!( - "Error occurred while executing command '/{}'.\n{}", - name, e - ), - ), - ); - }, - }); - } + ), + ), + Ok(value) => { + self.notify_client( + entity, + ServerGeneral::server_msg( + comp::ChatType::CommandInfo, + value.join("\n"), + ), + ); }, - Err(e) => { - error!(?e, "Can't execute command {} {:?}", name, args); + Err(common_state::plugin::CommandResults::PluginError(err)) => { + self.notify_client( + entity, + ServerGeneral::server_msg( + comp::ChatType::CommandError, + format!("Error occurred while executing command '/{name}'.\n{err}"), + ), + ); + }, + Err(common_state::plugin::CommandResults::HostError(err)) => { + error!(?err, ?name, ?args, "Can't execute command"); self.notify_client( entity, ServerGeneral::server_msg( comp::ChatType::CommandError, format!( - "Internal error while executing '/{}'.\nContact the server \ - administrator", - name + "Internal error {err:?} while executing '/{name}'.\nContact \ + the server administrator", ), ), ); diff --git a/server/src/sys/msg/register.rs b/server/src/sys/msg/register.rs index 0fdfa6b6ed..db4fb10286 100644 --- a/server/src/sys/msg/register.rs +++ b/server/src/sys/msg/register.rs @@ -6,7 +6,7 @@ use crate::{ EditableSettings, Settings, }; use common::{ - comp::{self, Admin, Player, Stats}, + comp::{self, Admin, Health, Player, Stats}, event::{ClientDisconnectEvent, EventBus, MakeAdminEvent}, recipe::{default_component_recipe_book, default_recipe_book, default_repair_recipe_book}, resources::TimeOfDay, @@ -21,7 +21,6 @@ use common_net::msg::{ }; use hashbrown::{hash_map, HashMap}; use itertools::Either; -use plugin_api::Health; use rayon::prelude::*; use specs::{ shred, Entities, Join, LendJoin, ParJoin, Read, ReadExpect, ReadStorage, SystemData,