enforce clippy lints and rustfmt

This commit is contained in:
Alexander Medvedev 2026-02-03 21:00:51 +01:00
parent 9f92bf25e9
commit e8d53a458e
22 changed files with 620 additions and 243 deletions

View File

@ -28,6 +28,12 @@ jobs:
run: ./gradlew jar run: ./gradlew jar
working-directory: java working-directory: java
- name: Check Formatting
run: cargo fmt --all -- --check
working-directory: rust
- name: Lint with Clippy
run: cargo clippy -- -D warnings
working-directory: rust
- name: Build rust - name: Build rust
run: cargo build --verbose run: cargo build --verbose
working-directory: rust working-directory: rust

View File

@ -7,7 +7,7 @@
plugins { plugins {
// Apply the foojay-resolver plugin to allow automatic download of JDKs // Apply the foojay-resolver plugin to allow automatic download of JDKs
id("org.gradle.toolchains.foojay-resolver-convention") version "0.8.0" id("org.gradle.toolchains.foojay-resolver-convention") version "1.0.0"
} }
rootProject.name = "patchbukkit" rootProject.name = "patchbukkit"

336
rust/Cargo.lock generated
View File

@ -2,6 +2,15 @@
# It is not intended for manual editing. # It is not intended for manual editing.
version = 4 version = 4
[[package]]
name = "addr2line"
version = "0.25.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "1b5d307320b3181d6d7954e663bd7c774a838b8220fe0593c86d9fb09f498b4b"
dependencies = [
"gimli",
]
[[package]] [[package]]
name = "adler2" name = "adler2"
version = "2.0.1" version = "2.0.1"
@ -54,7 +63,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "16e4850548ff4a25a77ce3bda7241874e17fb702ea551f0cc62a2dbe052f1272" checksum = "16e4850548ff4a25a77ce3bda7241874e17fb702ea551f0cc62a2dbe052f1272"
dependencies = [ dependencies = [
"anstyle", "anstyle",
"unicode-width", "unicode-width 0.2.2",
] ]
[[package]] [[package]]
@ -149,12 +158,45 @@ dependencies = [
"tokio", "tokio",
] ]
[[package]]
name = "atomic"
version = "0.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a89cbf775b137e9b968e67227ef7f775587cde3fd31b0d8599dbd0f598a48340"
dependencies = [
"bytemuck",
]
[[package]] [[package]]
name = "autocfg" name = "autocfg"
version = "1.5.0" version = "1.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8" checksum = "c08606f8c3cbf4ce6ec8e28fb0014a2c086708fe954eaa885384a6165172e7e8"
[[package]]
name = "backtrace"
version = "0.3.76"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bb531853791a215d7c62a30daf0dde835f381ab5de4589cfe7c649d2cbe92bd6"
dependencies = [
"addr2line",
"cfg-if",
"libc",
"miniz_oxide",
"object",
"rustc-demangle",
"windows-link",
]
[[package]]
name = "backtrace-ext"
version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "537beee3be4a18fb023b570f80e3ae28003db9167a751266b259926e25539d50"
dependencies = [
"backtrace",
]
[[package]] [[package]]
name = "base16ct" name = "base16ct"
version = "0.2.0" version = "0.2.0"
@ -209,6 +251,12 @@ version = "3.19.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510" checksum = "5dd9dc738b7a8311c7ade152424974d8115f2cdad61e8dab8dac9f2362298510"
[[package]]
name = "bytemuck"
version = "1.25.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c8efb64bd706a16a1bdde310ae86b351e4d21550d98d056f22f8a7f7a2183fec"
[[package]] [[package]]
name = "bytes" name = "bytes"
version = "1.11.0" version = "1.11.0"
@ -224,6 +272,15 @@ dependencies = [
"libbz2-rs-sys", "libbz2-rs-sys",
] ]
[[package]]
name = "castaway"
version = "0.2.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "dec551ab6e7578819132c713a93c022a05d60159dc86e7a7050223577484c55a"
dependencies = [
"rustversion",
]
[[package]] [[package]]
name = "cc" name = "cc"
version = "1.2.55" version = "1.2.55"
@ -314,6 +371,20 @@ dependencies = [
"windows-sys 0.61.2", "windows-sys 0.61.2",
] ]
[[package]]
name = "compact_str"
version = "0.8.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b79c4069c6cad78e2e0cdfcbd26275770669fb39fd308a752dc110e83b9af32"
dependencies = [
"castaway",
"cfg-if",
"itoa",
"rustversion",
"ryu",
"static_assertions",
]
[[package]] [[package]]
name = "compression-codecs" name = "compression-codecs"
version = "0.4.36" version = "0.4.36"
@ -552,6 +623,41 @@ dependencies = [
"cmov", "cmov",
] ]
[[package]]
name = "darling"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc7f46116c46ff9ab3eb1597a45688b6715c6e628b5c133e288e709a29bcb4ee"
dependencies = [
"darling_core",
"darling_macro",
]
[[package]]
name = "darling_core"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "0d00b9596d185e565c2207a0b01f8bd1a135483d02d9b7b0a54b11da8d53412e"
dependencies = [
"fnv",
"ident_case",
"proc-macro2",
"quote",
"strsim",
"syn",
]
[[package]]
name = "darling_macro"
version = "0.20.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fc34b93ccb385b40dc71c6fceac4b2ad23662c7eeb248cf10d529b7e055b6ead"
dependencies = [
"darling_core",
"quote",
"syn",
]
[[package]] [[package]]
name = "dashmap" name = "dashmap"
version = "6.1.0" version = "6.1.0"
@ -823,6 +929,18 @@ dependencies = [
"subtle", "subtle",
] ]
[[package]]
name = "figment"
version = "0.10.19"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8cb01cd46b0cf372153850f4c6c272d9cbea2da513e07538405148f95bd789f3"
dependencies = [
"atomic",
"serde",
"uncased",
"version_check",
]
[[package]] [[package]]
name = "find-msvc-tools" name = "find-msvc-tools"
version = "0.1.9" version = "0.1.9"
@ -840,6 +958,12 @@ dependencies = [
"zlib-rs", "zlib-rs",
] ]
[[package]]
name = "fnv"
version = "1.0.7"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1"
[[package]] [[package]]
name = "foldhash" name = "foldhash"
version = "0.1.5" version = "0.1.5"
@ -956,6 +1080,28 @@ dependencies = [
"slab", "slab",
] ]
[[package]]
name = "garde"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3a74b56a4039a46e8c91cc9d84e8a7df4e1f8b24239ca57d1304b3263cb599b9"
dependencies = [
"compact_str",
"garde_derive",
"smallvec 1.15.1",
]
[[package]]
name = "garde_derive"
version = "0.22.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7224c08ec489e2840af29ed882b47f7f6ac8f4ce15c275d9fc0d6d1b94578ae6"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "generic-array" name = "generic-array"
version = "0.14.7" version = "0.14.7"
@ -1006,6 +1152,12 @@ dependencies = [
"wasip3", "wasip3",
] ]
[[package]]
name = "gimli"
version = "0.32.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e629b9b98ef3dd8afe6ca2bd0f89306cec16d43d907889945bc5d6687f2f13c7"
[[package]] [[package]]
name = "glob" name = "glob"
version = "0.3.3" version = "0.3.3"
@ -1209,6 +1361,12 @@ version = "2.3.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954" checksum = "3d3067d79b975e8844ca9eb072e16b31c3c1c36928edf9c6789548c524d0d954"
[[package]]
name = "ident_case"
version = "1.0.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39"
[[package]] [[package]]
name = "idna" name = "idna"
version = "1.1.0" version = "1.1.0"
@ -1251,6 +1409,12 @@ dependencies = [
"generic-array", "generic-array",
] ]
[[package]]
name = "is_ci"
version = "1.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7655c9839580ee829dfacba1d1278c2b7883e50a277ff7541299489d6bdfdc45"
[[package]] [[package]]
name = "is_terminal_polyfill" name = "is_terminal_polyfill"
version = "1.70.2" version = "1.70.2"
@ -1518,6 +1682,36 @@ version = "2.7.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273" checksum = "f52b00d39961fc5b2736ea853c9cc86238e165017a493d1d5c8eac6bdc4cc273"
[[package]]
name = "miette"
version = "7.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5f98efec8807c63c752b5bd61f862c165c115b0a35685bdcfd9238c7aeb592b7"
dependencies = [
"backtrace",
"backtrace-ext",
"cfg-if",
"miette-derive",
"owo-colors",
"supports-color",
"supports-hyperlinks",
"supports-unicode",
"terminal_size",
"textwrap",
"unicode-width 0.1.14",
]
[[package]]
name = "miette-derive"
version = "7.6.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "db5b29714e950dbb20d5e6f74f9dcec4edbcc1067bb7f8ed198c097b8c1a818b"
dependencies = [
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "miniz_oxide" name = "miniz_oxide"
version = "0.8.9" version = "0.8.9"
@ -1630,6 +1824,15 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "object"
version = "0.37.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ff76201f031d8863c38aa7f905eca4f53abbfa15f609db4277d44cd8938f33fe"
dependencies = [
"memchr",
]
[[package]] [[package]]
name = "once_cell" name = "once_cell"
version = "1.21.3" version = "1.21.3"
@ -1648,6 +1851,12 @@ version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d" checksum = "04744f49eae99ab78e0d5c0b603ab218f515ea8cfe5a456d7629ad883a3b6e7d"
[[package]]
name = "owo-colors"
version = "4.2.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9c6901729fa79e91a0913333229e9ca5dc725089d1c363b2f4b4760709dc4a52"
[[package]] [[package]]
name = "p384" name = "p384"
version = "0.13.1" version = "0.13.1"
@ -2370,6 +2579,12 @@ dependencies = [
"walkdir", "walkdir",
] ]
[[package]]
name = "rustc-demangle"
version = "0.1.27"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b50b8869d9fc858ce7266cce0194bd74df58b9d0e3f6df3a9fc8eb470d95c09d"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
version = "2.1.1" version = "2.1.1"
@ -2447,7 +2662,7 @@ dependencies = [
"nix", "nix",
"radix_trie", "radix_trie",
"unicode-segmentation", "unicode-segmentation",
"unicode-width", "unicode-width 0.2.2",
"utf8parse", "utf8parse",
"windows-sys 0.60.2", "windows-sys 0.60.2",
] ]
@ -2461,6 +2676,12 @@ dependencies = [
"twox-hash 2.1.2", "twox-hash 2.1.2",
] ]
[[package]]
name = "ryu"
version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a50f4cf475b65d88e057964e0e9bb1f0aa9bbb2036dc65c64596b42932536984"
[[package]] [[package]]
name = "same-file" name = "same-file"
version = "1.0.6" version = "1.0.6"
@ -2472,9 +2693,9 @@ dependencies = [
[[package]] [[package]]
name = "saphyr-parser-bw" name = "saphyr-parser-bw"
version = "0.0.605" version = "0.0.607"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "5e1aee7486406df3541b5a657204a11be97175a467d77bc98e6d94a66289fb80" checksum = "2f9bae8d059bf1ca32753cf3cdafbf5d391502de2fc2ca54510811fe9c100d90"
dependencies = [ dependencies = [
"arraydeque", "arraydeque",
"smallvec 2.0.0-alpha.12", "smallvec 2.0.0-alpha.12",
@ -2519,14 +2740,18 @@ dependencies = [
[[package]] [[package]]
name = "serde-saphyr" name = "serde-saphyr"
version = "0.0.16" version = "0.0.17"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4db5a4a562bcc0017c34cd0efbabf447be783f00576a2a516947f884e6a7ed57" checksum = "bc14a55107113a16346915d7e3d78acc539a923458385db89670e22cac106d7a"
dependencies = [ dependencies = [
"ahash", "ahash",
"annotate-snippets", "annotate-snippets",
"base64", "base64",
"encoding_rs_io", "encoding_rs_io",
"figment",
"garde",
"getrandom 0.3.4",
"miette",
"nohash-hasher", "nohash-hasher",
"num-traits", "num-traits",
"regex", "regex",
@ -2534,6 +2759,7 @@ dependencies = [
"serde", "serde",
"serde_json", "serde_json",
"smallvec 2.0.0-alpha.12", "smallvec 2.0.0-alpha.12",
"validator",
"zmij", "zmij",
] ]
@ -2789,12 +3015,39 @@ version = "1.1.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f" checksum = "a2eb9349b6444b326872e140eb1cf5e7c522154d69e7a0ffb0fb81c06b37543f"
[[package]]
name = "strsim"
version = "0.11.1"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f"
[[package]] [[package]]
name = "subtle" name = "subtle"
version = "2.6.1" version = "2.6.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292"
[[package]]
name = "supports-color"
version = "3.0.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c64fc7232dd8d2e4ac5ce4ef302b1d81e0b80d055b9d77c7c4f51f6aa4c867d6"
dependencies = [
"is_ci",
]
[[package]]
name = "supports-hyperlinks"
version = "3.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e396b6523b11ccb83120b115a0b7366de372751aa6edf19844dfb13a6af97e91"
[[package]]
name = "supports-unicode"
version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7401a30af6cb5818bb64852270bb722533397edcfc7344954a38f420819ece2"
[[package]] [[package]]
name = "syn" name = "syn"
version = "2.0.114" version = "2.0.114"
@ -2832,6 +3085,26 @@ dependencies = [
"winapi-util", "winapi-util",
] ]
[[package]]
name = "terminal_size"
version = "0.4.3"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "60b8cb979cb11c32ce1603f8137b22262a9d131aaa5c37b5678025f22b8becd0"
dependencies = [
"rustix",
"windows-sys 0.60.2",
]
[[package]]
name = "textwrap"
version = "0.16.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "c13547615a44dc9c452a8a534638acdf07120d4b6847c8178705da06306a3057"
dependencies = [
"unicode-linebreak",
"unicode-width 0.2.2",
]
[[package]] [[package]]
name = "thiserror" name = "thiserror"
version = "2.0.18" version = "2.0.18"
@ -3019,18 +3292,39 @@ version = "0.1.7"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971"
[[package]]
name = "uncased"
version = "0.9.10"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "e1b88fcfe09e89d3866a5c11019378088af2d24c3fbd4f0543f96b479ec90697"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "unicode-ident" name = "unicode-ident"
version = "1.0.22" version = "1.0.22"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5" checksum = "9312f7c4f6ff9069b165498234ce8be658059c6728633667c526e27dc2cf1df5"
[[package]]
name = "unicode-linebreak"
version = "0.1.5"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3b09c83c3c29d37506a3e260c08c03743a6bb66a9cd432c6934ab501a190571f"
[[package]] [[package]]
name = "unicode-segmentation" name = "unicode-segmentation"
version = "1.12.0" version = "1.12.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493" checksum = "f6ccf251212114b54433ec949fd6a7841275f9ada20dddd2f29e9ceea4501493"
[[package]]
name = "unicode-width"
version = "0.1.14"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7dd6e30e90baa6f72411720665d41d89b9a3d039dc45b8faea1ddd07f617f6af"
[[package]] [[package]]
name = "unicode-width" name = "unicode-width"
version = "0.2.2" version = "0.2.2"
@ -3124,6 +3418,36 @@ dependencies = [
"wasm-bindgen", "wasm-bindgen",
] ]
[[package]]
name = "validator"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43fb22e1a008ece370ce08a3e9e4447a910e92621bb49b85d6e48a45397e7cfa"
dependencies = [
"idna",
"once_cell",
"regex",
"serde",
"serde_derive",
"serde_json",
"url",
"validator_derive",
]
[[package]]
name = "validator_derive"
version = "0.20.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b7df16e474ef958526d1205f6dda359fdfab79d9aa6d54bafcb92dcd07673dca"
dependencies = [
"darling",
"once_cell",
"proc-macro-error2",
"proc-macro2",
"quote",
"syn",
]
[[package]] [[package]]
name = "version_check" name = "version_check"
version = "0.9.5" version = "0.9.5"

View File

@ -27,7 +27,7 @@ uuid = "1.20.0"
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"
serde-saphyr = "0.0.16" serde-saphyr = "0.0.17"
rand = { git = "https://github.com/rust-random/rand"} rand = { git = "https://github.com/rust-random/rand"}
@ -38,3 +38,16 @@ log = "0.4"
[profile.release] [profile.release]
lto = true lto = true
[lints.clippy]
# Groups
all = { level = "deny", priority = -1 }
# nursery = { level = "deny", priority = -1 }
# pedantic = { level = "deny", priority = -1 }
# cargo = { level = "deny", priority = -1 }
multiple_crate_versions = "allow"
unnecessary_fallible_conversions = "allow"
not_unsafe_ptr_arg_deref = "allow" # Not sure about this one

View File

@ -1,8 +1,9 @@
use std::{collections::HashSet, error::Error, fs, path::PathBuf}; use std::{collections::HashSet, fs, path::PathBuf};
use j4rs::{JvmBuilder, LocalJarArtifact, MavenArtifact, MavenArtifactRepo, MavenSettings}; use j4rs::{JvmBuilder, LocalJarArtifact, MavenArtifact, MavenArtifactRepo, MavenSettings};
fn main() -> Result<(), Box<dyn Error>> { #[expect(clippy::too_many_lines)]
fn main() {
println!("cargo::rerun-if-changed=rust/src/build.rs"); println!("cargo::rerun-if-changed=rust/src/build.rs");
println!("cargo::rerun-if-changed=java/build/libs/"); println!("cargo::rerun-if-changed=java/build/libs/");
env_logger::init(); env_logger::init();
@ -93,7 +94,7 @@ fn main() -> Result<(), Box<dyn Error>> {
.skip_setting_native_lib() .skip_setting_native_lib()
.with_base_path(resources) .with_base_path(resources)
.build() .build()
.map_err(|err| format!("jvm failed to init: {:?}", err)) .map_err(|err| format!("jvm failed to init: {err:?}"))
.unwrap(); .unwrap();
let expected: HashSet<String> = dependencies let expected: HashSet<String> = dependencies
@ -130,7 +131,7 @@ fn main() -> Result<(), Box<dyn Error>> {
} }
} }
let mut java_path = base.clone(); let mut java_path = base;
java_path.pop(); java_path.pop();
let java_path = java_path.join("java"); let java_path = java_path.join("java");
@ -140,12 +141,11 @@ fn main() -> Result<(), Box<dyn Error>> {
.join("libs") .join("libs")
.join("patchbukkit.jar"); .join("patchbukkit.jar");
println!("patchbukkit_jar: {:?}", patchbukkit_jar); println!("patchbukkit_jar: {}", patchbukkit_jar.display());
if !&patchbukkit_jar.exists() { assert!(
panic!( !!&patchbukkit_jar.exists(),
"Failed to find patchbukkit.jar, build the java library first by running `gradle build` in the java directory!" "Failed to find patchbukkit.jar, build the java library first by running `gradle build` in the java directory!"
); );
}
jvm.deploy_artifact(&LocalJarArtifact::new(&patchbukkit_jar.to_string_lossy())) jvm.deploy_artifact(&LocalJarArtifact::new(&patchbukkit_jar.to_string_lossy()))
.unwrap(); .unwrap();
@ -153,18 +153,16 @@ fn main() -> Result<(), Box<dyn Error>> {
let cdylib = std::env::var("CARGO_CDYLIB_FILE_J4RS").unwrap(); let cdylib = std::env::var("CARGO_CDYLIB_FILE_J4RS").unwrap();
let cdylib = PathBuf::from(cdylib); let cdylib = PathBuf::from(cdylib);
let mut cdylib_to = deps.clone(); let mut cdylib_to = deps;
fs::create_dir_all(&cdylib_to).unwrap(); fs::create_dir_all(&cdylib_to).unwrap();
let original_name = cdylib.file_name().unwrap().to_string_lossy(); let original_name = cdylib.file_name().unwrap().to_string_lossy();
let stem = original_name.split('-').next().unwrap(); // before the first '-' let stem = original_name.split('-').next().unwrap(); // before the first '-'
let ext = cdylib.extension().unwrap().to_string_lossy(); let ext = cdylib.extension().unwrap().to_string_lossy();
cdylib_to.push(format!("{}.{}", stem, ext)); cdylib_to.push(format!("{stem}.{ext}"));
fs::copy(&cdylib, &cdylib_to) fs::copy(&cdylib, &cdylib_to)
.map_err(|err| format!("Failed to copy j4rs native lib: {:?}", err)) .map_err(|err| format!("Failed to copy j4rs native lib: {err:?}"))
.unwrap(); .unwrap();
Ok(())
} }

View File

@ -104,20 +104,17 @@ impl ArgumentConsumer for AnyCommandNode {
.await .await
.unwrap(); .unwrap();
let suggestion = rx.await.unwrap(); rx.await.unwrap()
suggestion
}) })
} }
} }
impl Into<SimpleCommandSender> for &CommandSender { impl From<&CommandSender> for SimpleCommandSender {
fn into(self) -> SimpleCommandSender { fn from(val: &CommandSender) -> Self {
match self { match val {
CommandSender::Rcon(_mutex) => todo!(), CommandSender::Rcon(_mutex) => todo!(),
CommandSender::Console => SimpleCommandSender::Console, CommandSender::Console => Self::Console,
CommandSender::Player(player) => { CommandSender::Player(player) => Self::Player(player.gameprofile.id.to_string()),
SimpleCommandSender::Player(player.gameprofile.id.to_string())
}
CommandSender::CommandBlock(_block_entity, _world) => todo!(), CommandSender::CommandBlock(_block_entity, _world) => todo!(),
} }
} }
@ -139,7 +136,7 @@ impl CommandExecutor for JavaCommandExecutor {
let (tx, _rx) = oneshot::channel(); let (tx, _rx) = oneshot::channel();
self.command_tx self.command_tx
.send(JvmCommand::TriggerCommand { .send(JvmCommand::TriggerCommand {
full_command: full_command, full_command,
respond_to: tx, respond_to: tx,
command_sender: sender.into(), command_sender: sender.into(),
}) })

View File

@ -4,7 +4,7 @@ use std::collections::HashMap;
pub const PAPER_PLUGIN_CONFIG: &str = "paper-plugin.yml"; pub const PAPER_PLUGIN_CONFIG: &str = "paper-plugin.yml";
/// Represents the load order for a dependency /// Represents the load order for a dependency
#[derive(Debug, Deserialize, Default, Clone, PartialEq)] #[derive(Debug, Deserialize, Default, Clone, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")] #[serde(rename_all = "UPPERCASE")]
pub enum LoadOrder { pub enum LoadOrder {
/// Load the dependency before this plugin /// Load the dependency before this plugin
@ -36,7 +36,7 @@ pub struct PaperDependency {
pub join_classpath: bool, pub join_classpath: bool,
} }
fn default_true() -> bool { const fn default_true() -> bool {
true true
} }
@ -64,6 +64,7 @@ pub struct PaperDependencies {
impl PaperDependencies { impl PaperDependencies {
/// Get all bootstrap dependencies /// Get all bootstrap dependencies
#[must_use]
pub fn get_bootstrap_deps(&self) -> Vec<(&String, &PaperDependency)> { pub fn get_bootstrap_deps(&self) -> Vec<(&String, &PaperDependency)> {
self.bootstrap self.bootstrap
.as_ref() .as_ref()
@ -72,6 +73,7 @@ impl PaperDependencies {
} }
/// Get all server dependencies /// Get all server dependencies
#[must_use]
pub fn get_server_deps(&self) -> Vec<(&String, &PaperDependency)> { pub fn get_server_deps(&self) -> Vec<(&String, &PaperDependency)> {
self.server self.server
.as_ref() .as_ref()
@ -80,6 +82,7 @@ impl PaperDependencies {
} }
/// Get all required bootstrap dependencies /// Get all required bootstrap dependencies
#[must_use]
pub fn get_required_bootstrap_deps(&self) -> Vec<&String> { pub fn get_required_bootstrap_deps(&self) -> Vec<&String> {
self.bootstrap self.bootstrap
.as_ref() .as_ref()
@ -93,6 +96,7 @@ impl PaperDependencies {
} }
/// Get all required server dependencies /// Get all required server dependencies
#[must_use]
pub fn get_required_server_deps(&self) -> Vec<&String> { pub fn get_required_server_deps(&self) -> Vec<&String> {
self.server self.server
.as_ref() .as_ref()
@ -106,19 +110,19 @@ impl PaperDependencies {
} }
/// Check if a plugin is a bootstrap dependency /// Check if a plugin is a bootstrap dependency
#[must_use]
pub fn has_bootstrap_dep(&self, name: &str) -> bool { pub fn has_bootstrap_dep(&self, name: &str) -> bool {
self.bootstrap self.bootstrap
.as_ref() .as_ref()
.map(|deps| deps.contains_key(name)) .is_some_and(|deps| deps.contains_key(name))
.unwrap_or(false)
} }
/// Check if a plugin is a server dependency /// Check if a plugin is a server dependency
#[must_use]
pub fn has_server_dep(&self, name: &str) -> bool { pub fn has_server_dep(&self, name: &str) -> bool {
self.server self.server
.as_ref() .as_ref()
.map(|deps| deps.contains_key(name)) .is_some_and(|deps| deps.contains_key(name))
.unwrap_or(false)
} }
} }
@ -132,7 +136,7 @@ pub struct PaperPluginYml {
/// The current version of the plugin /// The current version of the plugin
pub version: String, pub version: String,
/// The main class of your plugin (extends JavaPlugin) /// The main class of your plugin (extends `JavaPlugin`)
pub main: String, pub main: String,
// Optional metadata fields // Optional metadata fields
@ -163,11 +167,11 @@ pub struct PaperPluginYml {
pub api_version: Option<String>, pub api_version: Option<String>,
// Paper-specific fields // Paper-specific fields
/// The bootstrapper class that implements PluginBootstrap /// The bootstrapper class that implements `PluginBootstrap`
#[serde(default)] #[serde(default)]
pub bootstrapper: Option<String>, pub bootstrapper: Option<String>,
/// The loader class that implements PluginLoader /// The loader class that implements `PluginLoader`
#[serde(default)] #[serde(default)]
pub loader: Option<String>, pub loader: Option<String>,
@ -184,11 +188,12 @@ pub struct PaperPluginYml {
impl PaperPluginYml { impl PaperPluginYml {
/// Parse a paper-plugin.yml from a YAML string /// Parse a paper-plugin.yml from a YAML string
pub fn from_str(yaml: &str) -> Result<Self, serde_saphyr::Error> { pub fn parse(yaml: &str) -> Result<Self, serde_saphyr::Error> {
serde_saphyr::from_str(yaml) serde_saphyr::from_str(yaml)
} }
/// Get all authors (combines author and authors fields) /// Get all authors (combines author and authors fields)
#[must_use]
pub fn get_all_authors(&self) -> Vec<String> { pub fn get_all_authors(&self) -> Vec<String> {
let mut result = Vec::new(); let mut result = Vec::new();
if let Some(ref author) = self.author { if let Some(ref author) = self.author {
@ -201,44 +206,47 @@ impl PaperPluginYml {
} }
/// Check if this plugin has a bootstrapper /// Check if this plugin has a bootstrapper
pub fn has_bootstrapper(&self) -> bool { #[must_use]
pub const fn has_bootstrapper(&self) -> bool {
self.bootstrapper.is_some() self.bootstrapper.is_some()
} }
/// Check if this plugin has a custom loader /// Check if this plugin has a custom loader
pub fn has_loader(&self) -> bool { #[must_use]
pub const fn has_loader(&self) -> bool {
self.loader.is_some() self.loader.is_some()
} }
/// Get dependencies (returns default if none specified) /// Get dependencies (returns default if none specified)
#[must_use]
pub fn get_dependencies(&self) -> PaperDependencies { pub fn get_dependencies(&self) -> PaperDependencies {
self.dependencies.clone().unwrap_or_default() self.dependencies.clone().unwrap_or_default()
} }
/// Check if a plugin is required (in either bootstrap or server) /// Check if a plugin is required (in either bootstrap or server)
#[must_use]
pub fn requires_plugin(&self, name: &str) -> bool { pub fn requires_plugin(&self, name: &str) -> bool {
if let Some(ref deps) = self.dependencies { if let Some(ref deps) = self.dependencies {
// Check bootstrap dependencies // Check bootstrap dependencies
if let Some(ref bootstrap) = deps.bootstrap { if let Some(ref bootstrap) = deps.bootstrap
if let Some(dep) = bootstrap.get(name) { && let Some(dep) = bootstrap.get(name)
if dep.required { && dep.required
return true; {
} return true;
}
} }
// Check server dependencies // Check server dependencies
if let Some(ref server) = deps.server { if let Some(ref server) = deps.server
if let Some(dep) = server.get(name) { && let Some(dep) = server.get(name)
if dep.required { && dep.required
return true; {
} return true;
}
} }
} }
false false
} }
/// Get all plugins that should load BEFORE this plugin /// Get all plugins that should load BEFORE this plugin
#[must_use]
pub fn get_load_before_deps(&self) -> Vec<String> { pub fn get_load_before_deps(&self) -> Vec<String> {
let mut result = Vec::new(); let mut result = Vec::new();
if let Some(ref deps) = self.dependencies { if let Some(ref deps) = self.dependencies {
@ -261,6 +269,7 @@ impl PaperPluginYml {
} }
/// Get all plugins that should load AFTER this plugin /// Get all plugins that should load AFTER this plugin
#[must_use]
pub fn get_load_after_deps(&self) -> Vec<String> { pub fn get_load_after_deps(&self) -> Vec<String> {
let mut result = Vec::new(); let mut result = Vec::new();
if let Some(ref deps) = self.dependencies { if let Some(ref deps) = self.dependencies {

View File

@ -5,7 +5,7 @@ use serde::Deserialize;
pub const SPIGOT_PLUGIN_CONFIG: &str = "plugin.yml"; pub const SPIGOT_PLUGIN_CONFIG: &str = "plugin.yml";
/// Represents when a plugin should be loaded /// Represents when a plugin should be loaded
#[derive(Debug, Deserialize, Default, Clone, PartialEq)] #[derive(Debug, Deserialize, Default, Clone, PartialEq, Eq)]
#[serde(rename_all = "UPPERCASE")] #[serde(rename_all = "UPPERCASE")]
pub enum LoadOrder { pub enum LoadOrder {
#[serde(alias = "startup", alias = "Startup")] #[serde(alias = "startup", alias = "Startup")]
@ -16,9 +16,11 @@ pub enum LoadOrder {
} }
/// Represents the default permission value /// Represents the default permission value
#[derive(Debug, Deserialize, Clone, PartialEq)] #[derive(Debug, Deserialize, Clone, PartialEq, Eq)]
#[serde(rename_all = "lowercase")] #[serde(rename_all = "lowercase")]
#[derive(Default)]
pub enum DefaultPermission { pub enum DefaultPermission {
#[default]
Op, Op,
#[serde(alias = "notop")] #[serde(alias = "notop")]
NotOp, NotOp,
@ -26,12 +28,6 @@ pub enum DefaultPermission {
False, False,
} }
impl Default for DefaultPermission {
fn default() -> Self {
DefaultPermission::Op
}
}
/// Represents a permission node definition /// Represents a permission node definition
#[derive(Debug, Deserialize, Clone)] #[derive(Debug, Deserialize, Clone)]
pub struct Permission { pub struct Permission {
@ -69,10 +65,11 @@ pub enum StringOrList {
impl StringOrList { impl StringOrList {
/// Convert to a Vec<String> regardless of the variant /// Convert to a Vec<String> regardless of the variant
#[must_use]
pub fn to_vec(&self) -> Vec<String> { pub fn to_vec(&self) -> Vec<String> {
match self { match self {
StringOrList::Single(s) => vec![s.clone()], Self::Single(s) => vec![s.clone()],
StringOrList::Multiple(v) => v.clone(), Self::Multiple(v) => v.clone(),
} }
} }
} }
@ -85,7 +82,7 @@ pub struct SpigotPluginYml {
pub name: String, pub name: String,
/// The current version of the plugin /// The current version of the plugin
pub version: String, pub version: String,
/// The main class of your plugin (extends JavaPlugin) /// The main class of your plugin (extends `JavaPlugin`)
pub main: String, pub main: String,
// Optional metadata fields // Optional metadata fields
@ -161,11 +158,12 @@ pub struct SpigotPluginYml {
impl SpigotPluginYml { impl SpigotPluginYml {
/// Parse a plugin.yml from a YAML string /// Parse a plugin.yml from a YAML string
pub fn from_str(yaml: &str) -> Result<Self, serde_saphyr::Error> { pub fn parse(yaml: &str) -> Result<Self, serde_saphyr::Error> {
serde_saphyr::from_str(yaml) serde_saphyr::from_str(yaml)
} }
/// Get all authors (combines author and authors fields) /// Get all authors (combines author and authors fields)
#[must_use]
pub fn get_all_authors(&self) -> Vec<String> { pub fn get_all_authors(&self) -> Vec<String> {
let mut result = Vec::new(); let mut result = Vec::new();
if let Some(ref author) = self.author { if let Some(ref author) = self.author {
@ -178,6 +176,7 @@ impl SpigotPluginYml {
} }
/// Check if this plugin depends on another plugin /// Check if this plugin depends on another plugin
#[must_use]
pub fn depends_on(&self, plugin_name: &str) -> bool { pub fn depends_on(&self, plugin_name: &str) -> bool {
if let Some(ref deps) = self.depend { if let Some(ref deps) = self.depend {
return deps.iter().any(|d| d == plugin_name); return deps.iter().any(|d| d == plugin_name);
@ -186,6 +185,7 @@ impl SpigotPluginYml {
} }
/// Check if this plugin soft-depends on another plugin /// Check if this plugin soft-depends on another plugin
#[must_use]
pub fn soft_depends_on(&self, plugin_name: &str) -> bool { pub fn soft_depends_on(&self, plugin_name: &str) -> bool {
if let Some(ref deps) = self.softdepend { if let Some(ref deps) = self.softdepend {
return deps.iter().any(|d| d == plugin_name); return deps.iter().any(|d| d == plugin_name);

View File

@ -20,10 +20,10 @@ pub fn setup_directories(server: &Context) -> Result<PatchBukkitDirectories, Str
let jassets = j4rs.join("jassets"); let jassets = j4rs.join("jassets");
fs::create_dir_all(&jassets) fs::create_dir_all(&jassets)
.map_err(|err| format!("Failed to create jassets folder: {:?}", err))?; .map_err(|err| format!("Failed to create jassets folder: {err:?}"))?;
fs::create_dir_all(&plugins) fs::create_dir_all(&plugins)
.map_err(|err| format!("Failed to create patchbukkit-plugins folder: {:?}", err))?; .map_err(|err| format!("Failed to create patchbukkit-plugins folder: {err:?}"))?;
Ok(PatchBukkitDirectories { Ok(PatchBukkitDirectories {
base, base,

View File

@ -19,13 +19,13 @@ pub enum PatchBukkitEvent {
} }
pub trait IntoEventData { pub trait IntoEventData {
fn into_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent; fn get_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent;
} }
impl IntoEventData for pumpkin::plugin::player::player_join::PlayerJoinEvent { impl IntoEventData for pumpkin::plugin::player::player_join::PlayerJoinEvent {
fn into_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent { fn get_patch_bukkit_event(&self, server: Arc<Server>) -> PatchBukkitEvent {
PatchBukkitEvent::PlayerJoinEvent { PatchBukkitEvent::PlayerJoinEvent {
server: server, server,
player: self.player.clone(), player: self.player.clone(),
join_message: self.join_message.clone().get_text(), join_message: self.join_message.clone().get_text(),
} }
@ -39,7 +39,8 @@ pub struct PatchBukkitEventHandler<E: IntoEventData> {
} }
impl<E: IntoEventData> PatchBukkitEventHandler<E> { impl<E: IntoEventData> PatchBukkitEventHandler<E> {
pub fn new(plugin_name: String, command_tx: mpsc::Sender<JvmCommand>) -> Self { #[must_use]
pub const fn new(plugin_name: String, command_tx: mpsc::Sender<JvmCommand>) -> Self {
Self { Self {
plugin_name, plugin_name,
command_tx, command_tx,
@ -64,13 +65,13 @@ where
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
if let Err(e) = command_tx if let Err(e) = command_tx
.send(JvmCommand::FireEvent { .send(JvmCommand::FireEvent {
patchbukkit_event: event.into_patch_bukkit_event(server.clone()), patchbukkit_event: event.get_patch_bukkit_event(server.clone()),
respond_to: tx, respond_to: tx,
plugin: self.plugin_name.clone(), plugin: self.plugin_name.clone(),
}) })
.await .await
{ {
log::error!("Failed to send event to JVM worker: {}", e); log::error!("Failed to send event to JVM worker: {e}");
return; return;
} }

View File

@ -10,17 +10,17 @@ use zip::ZipArchive;
use crate::config::{paper::PAPER_PLUGIN_CONFIG, spigot::SPIGOT_PLUGIN_CONFIG}; use crate::config::{paper::PAPER_PLUGIN_CONFIG, spigot::SPIGOT_PLUGIN_CONFIG};
pub fn discover_jar_files(plugin_folder: &PathBuf) -> impl Iterator<Item = PathBuf> { pub fn discover_jar_files(plugin_folder: &Path) -> impl Iterator<Item = PathBuf> {
let pattern = format!("{}/**/*.jar", plugin_folder.display()); let pattern = format!("{}/**/*.jar", plugin_folder.display());
glob(&pattern) glob(&pattern)
.expect("Invalid glob pattern") .expect("Invalid glob pattern")
.filter_map(|entry| { .filter_map(|entry| {
entry entry
.map_err(|e| log::error!("Glob error: {:?}", e)) .map_err(|e| log::error!("Glob error: {e:?}"))
.ok()? .ok()?
.canonicalize() .canonicalize()
.map_err(|e| log::error!("Canonicalize error: {:?}", e)) .map_err(|e| log::error!("Canonicalize error: {e:?}"))
.ok() .ok()
}) })
} }

View File

@ -22,7 +22,7 @@ pub enum JvmCommand {
j4rs_path: PathBuf, j4rs_path: PathBuf,
respond_to: oneshot::Sender<Result<()>>, respond_to: oneshot::Sender<Result<()>>,
context: Arc<Context>, context: Arc<Context>,
command_tx: mpsc::Sender<JvmCommand>, command_tx: mpsc::Sender<Self>,
}, },
LoadPlugin { LoadPlugin {
plugin_path: PathBuf, plugin_path: PathBuf,
@ -31,7 +31,7 @@ pub enum JvmCommand {
InstantiateAllPlugins { InstantiateAllPlugins {
respond_to: oneshot::Sender<Result<()>>, respond_to: oneshot::Sender<Result<()>>,
server: Arc<Context>, server: Arc<Context>,
command_tx: mpsc::Sender<JvmCommand>, command_tx: mpsc::Sender<Self>,
}, },
EnableAllPlugins { EnableAllPlugins {
respond_to: oneshot::Sender<Result<()>>, respond_to: oneshot::Sender<Result<()>>,
@ -66,8 +66,9 @@ pub struct Rotation {
} }
impl Rotation { impl Rotation {
pub fn new(yaw: f32, pitch: f32) -> Self { #[must_use]
Rotation { yaw, pitch } pub const fn new(yaw: f32, pitch: f32) -> Self {
Self { yaw, pitch }
} }
} }
@ -80,8 +81,9 @@ pub struct Location {
} }
impl Location { impl Location {
pub fn new(world: Uuid, x: f64, y: f64, z: f64, rotation: Option<Rotation>) -> Self { #[must_use]
Location { pub const fn new(world: Uuid, x: f64, y: f64, z: f64, rotation: Option<Rotation>) -> Self {
Self {
world, world,
x, x,
y, y,

View File

@ -23,6 +23,7 @@ pub struct JvmWorker {
} }
impl JvmWorker { impl JvmWorker {
#[must_use]
pub fn new(command_rx: mpsc::Receiver<JvmCommand>) -> Self { pub fn new(command_rx: mpsc::Receiver<JvmCommand>) -> Self {
Self { Self {
command_rx, command_rx,
@ -61,13 +62,13 @@ impl JvmWorker {
} => { } => {
let _ = match read_configs_from_jar(&plugin_path) { let _ = match read_configs_from_jar(&plugin_path) {
Ok(configs) => match configs { Ok(configs) => match configs {
(Some(paper_plugin_config), spigot @ _) => { (Some(paper_plugin_config), spigot) => {
match self.plugin_manager.load_paper_plugin( match self.plugin_manager.load_paper_plugin(
&plugin_path, &plugin_path,
&paper_plugin_config, &paper_plugin_config,
&spigot, &spigot,
) { ) {
Ok(_) => { Ok(()) => {
respond_to.send(LoadPluginResult::SuccessfullyLoadedPaper) respond_to.send(LoadPluginResult::SuccessfullyLoadedPaper)
} }
Err(err) => respond_to Err(err) => respond_to
@ -79,7 +80,7 @@ impl JvmWorker {
.plugin_manager .plugin_manager
.load_spigot_plugin(&plugin_path, &spigot) .load_spigot_plugin(&plugin_path, &spigot)
{ {
Ok(_) => { Ok(()) => {
respond_to.send(LoadPluginResult::SuccessfullyLoadedSpigot) respond_to.send(LoadPluginResult::SuccessfullyLoadedSpigot)
} }
Err(err) => respond_to Err(err) => respond_to
@ -151,7 +152,7 @@ impl JvmWorker {
{ {
Ok(c) => c, Ok(c) => c,
Err(e) => { Err(e) => {
log::error!("Failed to fire event: {}", e); log::error!("Failed to fire event: {e}");
false false
} }
}; };
@ -201,7 +202,7 @@ impl JvmWorker {
} }
fn initialize_jvm(&mut self, j4rs_path: &PathBuf) -> anyhow::Result<()> { fn initialize_jvm(&mut self, j4rs_path: &PathBuf) -> anyhow::Result<()> {
log::info!("Initializing JVM with path: {:?}", j4rs_path); log::info!("Initializing JVM with path: {j4rs_path:?}");
let jvm = JvmBuilder::new().with_base_path(j4rs_path).build()?; let jvm = JvmBuilder::new().with_base_path(j4rs_path).build()?;

View File

@ -51,10 +51,10 @@ pub extern "C" fn rust_set_abilities(
server_abilities.invulnerable = (*abilities).invulnerable; server_abilities.invulnerable = (*abilities).invulnerable;
server_abilities.walk_speed = (*abilities).walk_speed; server_abilities.walk_speed = (*abilities).walk_speed;
} }
}) });
}); });
let player = player.clone(); let player = player;
ctx.runtime.spawn(async move { ctx.runtime.spawn(async move {
player.send_abilities_update().await; player.send_abilities_update().await;
}); });

View File

@ -31,16 +31,12 @@ pub extern "C" fn rust_register_event(
}; };
log::info!( log::info!(
"Plugin '{}' registering listener for '{}' (priority={:?}, blocking={})", "Plugin '{plugin_name}' registering listener for '{event_type}' (priority={priority:?}, blocking={blocking})"
plugin_name,
event_type,
priority,
blocking
); );
let command_tx = ctx.command_tx.clone(); let command_tx = ctx.command_tx.clone();
let context = ctx.plugin_context.clone(); let context = ctx.plugin_context.clone();
let event_type_owned = event_type.clone(); let event_type_owned = event_type;
tokio::task::block_in_place(|| { tokio::task::block_in_place(|| {
ctx.runtime.block_on(async { ctx.runtime.block_on(async {
@ -62,8 +58,7 @@ pub extern "C" fn rust_register_event(
} }
_ => { _ => {
log::warn!( log::warn!(
"Unsupported Bukkit event type '{}' from plugin '{}'", "Unsupported Bukkit event type '{event_type_owned}' from plugin '{plugin_name}'"
event_type_owned, plugin_name
); );
} }
} }
@ -83,47 +78,38 @@ pub extern "C" fn rust_call_event(
return false; return false;
}; };
log::debug!( log::debug!("Java calling event '{event_type}' with data: {event_data_json}");
"Java calling event '{}' with data: {}",
event_type,
event_data_json
);
let event_data: serde_json::Value = match serde_json::from_str(&event_data_json) { let event_data: serde_json::Value = match serde_json::from_str(&event_data_json) {
Ok(v) => v, Ok(v) => v,
Err(e) => { Err(e) => {
log::error!("Failed to parse event data JSON: {}", e); log::error!("Failed to parse event data JSON: {e}");
return false; return false;
} }
}; };
let context = ctx.plugin_context.clone(); let context = ctx.plugin_context.clone();
let handled = tokio::task::block_in_place(|| { tokio::task::block_in_place(|| {
ctx.runtime.block_on(async { ctx.runtime.block_on(async {
match event_type.as_str() { if event_type.as_str() == "org.bukkit.event.player.PlayerJoinEvent" {
"org.bukkit.event.player.PlayerJoinEvent" => { let player_uuid_str = event_data["playerUuid"].as_str().unwrap_or("");
let player_uuid_str = event_data["playerUuid"].as_str().unwrap_or(""); let join_message_str = event_data["joinMessage"].as_str().unwrap_or("");
let join_message_str = event_data["joinMessage"].as_str().unwrap_or(""); if let Ok(uuid) = uuid::Uuid::parse_str(player_uuid_str)
if let Ok(uuid) = uuid::Uuid::parse_str(player_uuid_str) { && let Some(player) = context.server.get_player_by_uuid(uuid)
if let Some(player) = context.server.get_player_by_uuid(uuid) { {
let pumpkin_event = PlayerJoinEvent::new( let pumpkin_event = PlayerJoinEvent::new(
player, player,
TextComponent::from_legacy_string(join_message_str), TextComponent::from_legacy_string(join_message_str),
); );
context.server.plugin_manager.fire(pumpkin_event).await; context.server.plugin_manager.fire(pumpkin_event).await;
return true; return true;
}
}
false
}
_ => {
log::warn!("Unknown event type for Pumpkin: {}", event_type);
false
} }
false
} else {
log::warn!("Unknown event type for Pumpkin: {event_type}");
false
} }
}) })
}); })
handled
} }

View File

@ -12,11 +12,12 @@ struct Registry {
} }
impl Registry { impl Registry {
pub fn new(entries: Vec<Value>, tags: HashMap<String, Vec<String>>) -> Self { pub const fn new(entries: Vec<Value>, tags: HashMap<String, Vec<String>>) -> Self {
Registry { entries, tags } Self { entries, tags }
} }
} }
#[must_use]
pub extern "C" fn rust_get_registry_data(registry_name: *const c_char) -> *const c_char { pub extern "C" fn rust_get_registry_data(registry_name: *const c_char) -> *const c_char {
let name = get_string(registry_name); let name = get_string(registry_name);
@ -44,7 +45,7 @@ pub extern "C" fn rust_get_registry_data(registry_name: *const c_char) -> *const
let json_str = match serde_json::to_string(&registry) { let json_str = match serde_json::to_string(&registry) {
Ok(json_str) => json_str, Ok(json_str) => json_str,
Err(err) => { Err(err) => {
log::error!("Failed to serialize registry: {}", err); log::error!("Failed to serialize registry: {err}");
return std::ptr::null(); return std::ptr::null();
} }
}; };
@ -52,8 +53,8 @@ pub extern "C" fn rust_get_registry_data(registry_name: *const c_char) -> *const
match CString::new(json_str) { match CString::new(json_str) {
Ok(cstring) => cstring.into_raw(), Ok(cstring) => cstring.into_raw(),
Err(err) => { Err(err) => {
log::error!("Failed to convert registry string to CString: {}", err); log::error!("Failed to convert registry string to CString: {err}");
return std::ptr::null_mut(); std::ptr::null_mut()
} }
} }
} }

View File

@ -1,5 +1,6 @@
use std::ffi::{CStr, c_char}; use std::ffi::{CStr, c_char};
#[must_use]
pub fn get_string(str_ptr: *const c_char) -> String { pub fn get_string(str_ptr: *const c_char) -> String {
unsafe { CStr::from_ptr(str_ptr).to_string_lossy().into_owned() } unsafe { CStr::from_ptr(str_ptr).to_string_lossy().into_owned() }
} }

View File

@ -20,8 +20,15 @@ pub struct CommandManager {
command_map: Option<Instance>, command_map: Option<Instance>,
} }
impl Default for CommandManager {
fn default() -> Self {
Self::new()
}
}
impl CommandManager { impl CommandManager {
pub fn new() -> Self { #[must_use]
pub const fn new() -> Self {
Self { command_map: None } Self { command_map: None }
} }
@ -66,7 +73,7 @@ impl CommandManager {
let command_map = match self.command_map { let command_map = match self.command_map {
Some(ref command_map) => command_map, Some(ref command_map) => command_map,
None => match self.init(jvm) { None => match self.init(jvm) {
Ok(_) => self.command_map.as_ref().unwrap(), Ok(()) => self.command_map.as_ref().unwrap(),
Err(_) => return Ok(None), Err(_) => return Ok(None),
}, },
}; };
@ -145,7 +152,7 @@ impl CommandManager {
let command_map = match self.command_map { let command_map = match self.command_map {
Some(ref command_map) => command_map, Some(ref command_map) => command_map,
None => match self.init(jvm) { None => match self.init(jvm) {
Ok(_) => self.command_map.as_ref().unwrap(), Ok(()) => self.command_map.as_ref().unwrap(),
Err(err) => return Err(err), Err(err) => return Err(err),
}, },
}; };
@ -164,7 +171,7 @@ impl CommandManager {
log::info!("Registering Bukkit command: {}", &cmd_name); log::info!("Registering Bukkit command: {}", &cmd_name);
{ {
let cmd_lock = j_plugin_cmd.lock().unwrap(); let cmd_lock = j_plugin_cmd.lock().unwrap();
let j_plugin_cmd_owned = jvm.clone_instance(&*cmd_lock)?; let j_plugin_cmd_owned = jvm.clone_instance(&cmd_lock)?;
jvm.invoke( jvm.invoke(
command_map, command_map,
"register", "register",
@ -189,7 +196,7 @@ impl CommandManager {
// } else { // } else {
// format!("patchbukkit:{}", cmd_name) // TODO // format!("patchbukkit:{}", cmd_name) // TODO
// }; // };
let permission = format!("patchbukkit:{}", cmd_name); let permission = format!("patchbukkit:{cmd_name}");
context context
.register_permission(Permission::new( .register_permission(Permission::new(
@ -214,7 +221,7 @@ impl CommandManager {
let command_map = match self.command_map { let command_map = match self.command_map {
Some(ref command_map) => command_map, Some(ref command_map) => command_map,
None => match self.init(jvm) { None => match self.init(jvm) {
Ok(_) => self.command_map.as_ref().unwrap(), Ok(()) => self.command_map.as_ref().unwrap(),
Err(err) => return Err(err), Err(err) => return Err(err),
}, },
}; };

View File

@ -8,8 +8,15 @@ use crate::events::handler::PatchBukkitEvent;
pub struct EventManager {} pub struct EventManager {}
impl Default for EventManager {
fn default() -> Self {
Self::new()
}
}
impl EventManager { impl EventManager {
pub fn new() -> Self { #[must_use]
pub const fn new() -> Self {
Self {} Self {}
} }
@ -29,7 +36,7 @@ impl EventManager {
player, player,
join_message, join_message,
} => { } => {
EventManager::register_player(jvm, &patch_server, &player, &server)?; Self::register_player(jvm, &patch_server, &player, &server)?;
jvm.invoke_static( jvm.invoke_static(
"org.patchbukkit.events.PatchBukkitEventFactory", "org.patchbukkit.events.PatchBukkitEventFactory",
"createPlayerJoinEvent", "createPlayerJoinEvent",
@ -57,16 +64,17 @@ impl EventManager {
&[InvocationArg::from(jvm.clone_instance(&j_event)?)], &[InvocationArg::from(jvm.clone_instance(&j_event)?)],
)?)?; )?)?;
let cancelled = match is_cancellable { let cancelled = if is_cancellable {
true => match jvm.invoke( match jvm.invoke(
&jvm.clone_instance(&j_event)?, &jvm.clone_instance(&j_event)?,
"isCancelled", "isCancelled",
InvocationArg::empty(), InvocationArg::empty(),
) { ) {
Ok(instance) => jvm.to_rust::<bool>(instance).unwrap_or(false), Ok(instance) => jvm.to_rust::<bool>(instance).unwrap_or(false),
Err(_) => false, Err(_) => false,
}, }
false => false, } else {
false
}; };
Ok(cancelled) Ok(cancelled)
@ -84,7 +92,7 @@ impl EventManager {
"fromString", "fromString",
&[InvocationArg::try_from(player.gameprofile.id.to_string())?], &[InvocationArg::try_from(player.gameprofile.id.to_string())?],
) )
.map_err(|e| format!("Failed to create Java UUID: {}", e)) .map_err(|e| format!("Failed to create Java UUID: {e}"))
.unwrap(); .unwrap();
let j_player = jvm.create_instance( let j_player = jvm.create_instance(
@ -105,10 +113,10 @@ impl EventManager {
.into_primitive() .into_primitive()
.unwrap()], .unwrap()],
)?; )?;
}; }
jvm.invoke( jvm.invoke(
&patch_server, patch_server,
"registerPlayer", "registerPlayer",
&[InvocationArg::from(j_player)], &[InvocationArg::from(j_player)],
)?; )?;

View File

@ -31,6 +31,7 @@ pub enum PluginState {
Errored, Errored,
} }
#[expect(clippy::large_enum_variant)]
#[derive(Debug)] #[derive(Debug)]
pub enum PluginType { pub enum PluginType {
Paper(PaperPluginData), Paper(PaperPluginData),
@ -85,7 +86,14 @@ pub struct PluginManager {
pub plugins: HashMap<String, Plugin>, pub plugins: HashMap<String, Plugin>,
} }
impl Default for PluginManager {
fn default() -> Self {
Self::new()
}
}
impl PluginManager { impl PluginManager {
#[must_use]
pub fn new() -> Self { pub fn new() -> Self {
Self { Self {
plugins: HashMap::new(), plugins: HashMap::new(),
@ -110,13 +118,21 @@ impl PluginManager {
paper_plugin_config: &str, paper_plugin_config: &str,
spigot_plugin_config: &Option<String>, spigot_plugin_config: &Option<String>,
) -> Result<()> { ) -> Result<()> {
let parsed_paper_plugin = PaperPluginYml::from_str(paper_plugin_config)?; let parsed_paper_plugin = PaperPluginYml::parse(paper_plugin_config)?;
let parsed_spigot_plugin = match spigot_plugin_config { let parsed_spigot_plugin = match spigot_plugin_config {
Some(config) => Some(SpigotPluginYml::from_str(config)?), Some(config) => Some(SpigotPluginYml::parse(config)?),
None => None, None => None,
}; };
let (spigot_depends, spigot_soft_depends, spigot_load_before, spigot_load_after, spigot_provides, spigot_libraries, spigot_skip_libraries) = match &parsed_spigot_plugin { let (
spigot_depends,
spigot_soft_depends,
spigot_load_before,
spigot_load_after,
spigot_provides,
spigot_libraries,
spigot_skip_libraries,
) = match &parsed_spigot_plugin {
Some(config) => ( Some(config) => (
normalize_names(config.depend.clone()), normalize_names(config.depend.clone()),
normalize_names(config.softdepend.clone()), normalize_names(config.softdepend.clone()),
@ -126,7 +142,15 @@ impl PluginManager {
config.libraries.clone().unwrap_or_default(), config.libraries.clone().unwrap_or_default(),
config.paper_skip_libraries.unwrap_or(false), config.paper_skip_libraries.unwrap_or(false),
), ),
None => (Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), Vec::new(), false), None => (
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
Vec::new(),
false,
),
}; };
let mut paper_depends = Vec::new(); let mut paper_depends = Vec::new();
@ -181,10 +205,11 @@ impl PluginManager {
let classpath_deps = paper_classpath; let classpath_deps = paper_classpath;
let commands = match &parsed_spigot_plugin { let commands = parsed_spigot_plugin
Some(config) => config.commands.clone().unwrap_or_default(), .as_ref()
None => HashMap::new(), .map_or_else(HashMap::new, |config| {
}; config.commands.clone().unwrap_or_default()
});
let libraries = if spigot_skip_libraries { let libraries = if spigot_skip_libraries {
Vec::new() Vec::new()
@ -231,7 +256,7 @@ impl PluginManager {
jar_path: P, jar_path: P,
spigot_plugin_config: &str, spigot_plugin_config: &str,
) -> Result<()> { ) -> Result<()> {
let parsed_spigot_plugin = SpigotPluginYml::from_str(spigot_plugin_config)?; let parsed_spigot_plugin = SpigotPluginYml::parse(spigot_plugin_config)?;
let depends = normalize_names(parsed_spigot_plugin.depend.clone()); let depends = normalize_names(parsed_spigot_plugin.depend.clone());
let soft_depends = normalize_names(parsed_spigot_plugin.softdepend.clone()); let soft_depends = normalize_names(parsed_spigot_plugin.softdepend.clone());
@ -247,7 +272,7 @@ impl PluginManager {
let version = parsed_spigot_plugin.version.clone(); let version = parsed_spigot_plugin.version.clone();
let main_class = parsed_spigot_plugin.main.clone(); let main_class = parsed_spigot_plugin.main.clone();
let spigot_config = parsed_spigot_plugin.clone(); let spigot_config = parsed_spigot_plugin.clone();
let commands = parsed_spigot_plugin.commands.clone().unwrap_or_default(); let commands = parsed_spigot_plugin.commands.unwrap_or_default();
let plugin = Plugin { let plugin = Plugin {
name, name,
@ -275,18 +300,18 @@ impl PluginManager {
} }
pub fn enable_all_plugins(&mut self, jvm: &Jvm) -> Result<()> { pub fn enable_all_plugins(&mut self, jvm: &Jvm) -> Result<()> {
// IMPORANT: enable trough PluginManager not manually // IMPORTANT: enable trough PluginManager not manually
let plugin_manager = jvm.invoke_static( let plugin_manager = jvm.invoke_static(
"org.bukkit.Bukkit", "org.bukkit.Bukkit",
"getPluginManager", "getPluginManager",
InvocationArg::empty(), InvocationArg::empty(),
)?; )?;
for (_plugin_name, plugin) in &mut self.plugins { for plugin in self.plugins.values_mut() {
if plugin.instance.is_none() { if plugin.instance.is_none() {
continue; continue;
} }
let plugin_instance = plugin.instance.as_ref().unwrap(); let plugin_instance = plugin.instance.as_ref().unwrap();
let plugin_instance = jvm.clone_instance(&plugin_instance).unwrap(); let plugin_instance = jvm.clone_instance(plugin_instance).unwrap();
let result = jvm.invoke( let result = jvm.invoke(
&plugin_manager, &plugin_manager,
@ -318,12 +343,12 @@ impl PluginManager {
"getPluginManager", "getPluginManager",
InvocationArg::empty(), InvocationArg::empty(),
)?; )?;
for (_plugin_name, plugin) in &mut self.plugins { for plugin in self.plugins.values_mut() {
if plugin.instance.is_none() { if plugin.instance.is_none() {
continue; continue;
} }
let plugin_instance = plugin.instance.as_ref().unwrap(); let plugin_instance = plugin.instance.as_ref().unwrap();
let plugin_instance = jvm.clone_instance(&plugin_instance).unwrap(); let plugin_instance = jvm.clone_instance(plugin_instance).unwrap();
let result = jvm.invoke( let result = jvm.invoke(
&plugin_manager, &plugin_manager,
@ -362,7 +387,7 @@ impl PluginManager {
let (classpath, libraries) = match self.plugins.get(&plugin_key) { let (classpath, libraries) = match self.plugins.get(&plugin_key) {
Some(plugin) => ( Some(plugin) => (
self.classpath_string_for(plugin), self.classpath_string_for(plugin),
self.library_string_for(plugin), Self::library_string_for(plugin),
), ),
None => continue, None => continue,
}; };
@ -386,16 +411,16 @@ impl PluginManager {
for (cmd_name, cmd_data) in &plugin.commands { for (cmd_name, cmd_data) in &plugin.commands {
match command_manager match command_manager
.register_command( .register_command(
&jvm, jvm,
server, server,
&plugin, plugin,
cmd_name.clone(), cmd_name.clone(),
cmd_data, cmd_data,
command_tx.clone(), command_tx.clone(),
) )
.await .await
{ {
Ok(_) => (), Ok(()) => (),
Err(e) => { Err(e) => {
log::error!( log::error!(
"Failed to register command {} for plugin {}: {:?}", "Failed to register command {} for plugin {}: {:?}",
@ -438,7 +463,9 @@ impl PluginManager {
if provide.is_empty() { if provide.is_empty() {
continue; continue;
} }
provides_map.entry(provide.clone()).or_insert_with(|| key.clone()); provides_map
.entry(provide.clone())
.or_insert_with(|| key.clone());
} }
} }
@ -470,8 +497,7 @@ impl PluginManager {
} }
let mut edges: HashMap<String, HashSet<String>> = HashMap::new(); let mut edges: HashMap<String, HashSet<String>> = HashMap::new();
let mut indegree: HashMap<String, usize> = let mut indegree: HashMap<String, usize> = active.iter().map(|k| (k.clone(), 0)).collect();
active.iter().map(|k| (k.clone(), 0)).collect();
for (key, plugin) in &self.plugins { for (key, plugin) in &self.plugins {
if !active.contains(key) { if !active.contains(key) {
@ -479,15 +505,12 @@ impl PluginManager {
} }
let mut before = Vec::new(); let mut before = Vec::new();
for dep in plugin for dep in plugin.depends.iter().chain(plugin.soft_depends.iter()) {
.depends if let Some(resolved) = self.resolve_dependency_name(dep, &provides_map)
.iter() && resolved != *key
.chain(plugin.soft_depends.iter()) && active.contains(&resolved)
{ {
if let Some(resolved) = self.resolve_dependency_name(dep, &provides_map) { before.push(resolved);
if resolved != *key && active.contains(&resolved) {
before.push(resolved);
}
} }
} }
@ -496,18 +519,20 @@ impl PluginManager {
} }
for target in &plugin.load_before { for target in &plugin.load_before {
if let Some(resolved) = self.resolve_dependency_name(target, &provides_map) { if let Some(resolved) = self.resolve_dependency_name(target, &provides_map)
if resolved != *key && active.contains(&resolved) { && resolved != *key
add_edge(&mut edges, &mut indegree, key, &resolved); && active.contains(&resolved)
} {
add_edge(&mut edges, &mut indegree, key, &resolved);
} }
} }
for target in &plugin.load_after { for target in &plugin.load_after {
if let Some(resolved) = self.resolve_dependency_name(target, &provides_map) { if let Some(resolved) = self.resolve_dependency_name(target, &provides_map)
if resolved != *key && active.contains(&resolved) { && resolved != *key
add_edge(&mut edges, &mut indegree, &resolved, key); && active.contains(&resolved)
} {
add_edge(&mut edges, &mut indegree, &resolved, key);
} }
} }
} }
@ -541,10 +566,8 @@ impl PluginManager {
} }
if order.len() != active.len() { if order.len() != active.len() {
let mut remaining: Vec<String> = active let mut remaining: Vec<String> =
.into_iter() active.into_iter().filter(|k| !order.contains(k)).collect();
.filter(|k| !order.contains(k))
.collect();
remaining.sort(); remaining.sort();
log::warn!( log::warn!(
"Detected plugin dependency cycle(s). Loading remaining plugins in name order: {}", "Detected plugin dependency cycle(s). Loading remaining plugins in name order: {}",
@ -567,23 +590,25 @@ impl PluginManager {
if provide.is_empty() { if provide.is_empty() {
continue; continue;
} }
provides_map.entry(provide.clone()).or_insert_with(|| key.clone()); provides_map
.entry(provide.clone())
.or_insert_with(|| key.clone());
} }
} }
let mut paths = Vec::new(); let mut paths = Vec::new();
for dep in &plugin.classpath_deps { for dep in &plugin.classpath_deps {
if let Some(resolved) = self.resolve_dependency_name(dep, &provides_map) { if let Some(resolved) = self.resolve_dependency_name(dep, &provides_map)
if let Some(dep_plugin) = self.plugins.get(&resolved) { && let Some(dep_plugin) = self.plugins.get(&resolved)
paths.push(dep_plugin.path.to_string_lossy().to_string()); {
} paths.push(dep_plugin.path.to_string_lossy().to_string());
} }
} }
paths.join(";") paths.join(";")
} }
fn library_string_for(&self, plugin: &Plugin) -> String { fn library_string_for(plugin: &Plugin) -> String {
if plugin.libraries.is_empty() { if plugin.libraries.is_empty() {
return String::new(); return String::new();
} }
@ -640,9 +665,9 @@ fn add_edge(
return; return;
} }
let entry = edges.entry(from.to_string()).or_default(); let entry = edges.entry(from.to_string()).or_default();
if entry.insert(to.to_string()) { if entry.insert(to.to_string())
if let Some(count) = indegree.get_mut(to) { && let Some(count) = indegree.get_mut(to)
*count += 1; {
} *count += 1;
} }
} }

View File

@ -18,17 +18,17 @@ pub fn cleanup_stale_files(j4rs_folder: &PathBuf) {
for entry in walkdir::WalkDir::new(j4rs_folder) for entry in walkdir::WalkDir::new(j4rs_folder)
.into_iter() .into_iter()
.filter_map(|e| e.ok()) .filter_map(std::result::Result::ok)
.filter(|e| e.file_type().is_file()) .filter(|e| e.file_type().is_file())
{ {
let path = entry.path(); let path = entry.path();
if let Ok(rel_path) = path.strip_prefix(j4rs_folder) { if let Ok(rel_path) = path.strip_prefix(j4rs_folder)
if !allowed.contains(rel_path) { && !allowed.contains(rel_path)
log::warn!("Removing stale j4rs file: {}", rel_path.display()); {
if let Err(e) = fs::remove_file(path) { log::warn!("Removing stale j4rs file: {}", rel_path.display());
log::error!("Failed to remove stale file {}: {}", path.display(), e); if let Err(e) = fs::remove_file(path) {
} log::error!("Failed to remove stale file {}: {}", path.display(), e);
} }
} }
} }
@ -39,11 +39,11 @@ pub fn sync_embedded_resources(j4rs_folder: &Path) -> Result<(), String> {
let resource_path = j4rs_folder.join(resource_path_str.to_string()); let resource_path = j4rs_folder.join(resource_path_str.to_string());
let resource = Resources::get(&resource_path_str).unwrap(); let resource = Resources::get(&resource_path_str).unwrap();
if !resource_path.exists() { if resource_path.exists() {
update_resource_if_changed(&resource_path, &resource.data)?;
} else {
log::info!("Extracting new resource: {}", resource_path.display()); log::info!("Extracting new resource: {}", resource_path.display());
write_resource(&resource_path, &resource.data)?; write_resource(&resource_path, &resource.data)?;
} else {
update_resource_if_changed(&resource_path, &resource.data)?;
} }
} }
Ok(()) Ok(())
@ -62,9 +62,7 @@ fn write_resource(path: &Path, data: &[u8]) -> Result<(), String> {
fn update_resource_if_changed(path: &Path, new_data: &[u8]) -> Result<(), String> { fn update_resource_if_changed(path: &Path, new_data: &[u8]) -> Result<(), String> {
// Quick check: If file sizes differ, it's definitely changed, TODO: use Hash ? // Quick check: If file sizes differ, it's definitely changed, TODO: use Hash ?
let metadata = fs::metadata(path).ok(); let metadata = fs::metadata(path).ok();
let size_matches = metadata let size_matches = metadata.is_some_and(|m| m.len() == new_data.len() as u64);
.map(|m| m.len() == new_data.len() as u64)
.unwrap_or(false);
if !size_matches || fs::read(path).map_err(|e| e.to_string())? != new_data { if !size_matches || fs::read(path).map_err(|e| e.to_string())? != new_data {
log::debug!("Updating changed resource: {}", path.display()); log::debug!("Updating changed resource: {}", path.display());

View File

@ -1,3 +1,5 @@
#![allow(clippy::async_yields_async)]
use std::sync::Arc; use std::sync::Arc;
use pumpkin::plugin::Context; use pumpkin::plugin::Context;
@ -24,7 +26,7 @@ use crate::java::jvm::{
worker::JvmWorker, worker::JvmWorker,
}; };
async fn on_load_inner(plugin: &mut PatchBukkitPlugin, server: Arc<Context>) -> Result<(), String> { async fn on_load_inner(plugin: &PatchBukkitPlugin, server: Arc<Context>) -> Result<(), String> {
server.init_log(); server.init_log();
log::info!("Starting PatchBukkit"); log::info!("Starting PatchBukkit");
@ -53,37 +55,37 @@ async fn on_load_inner(plugin: &mut PatchBukkitPlugin, server: Arc<Context>) ->
match rx.await { match rx.await {
Ok(result) => match result { Ok(result) => match result {
LoadPluginResult::SuccessfullyLoadedSpigot => { LoadPluginResult::SuccessfullyLoadedSpigot => {
log::info!("Loaded Spigot plugin from JAR `{}`", jar_path.display()) log::info!("Loaded Spigot plugin from JAR `{}`", jar_path.display());
} }
LoadPluginResult::SuccessfullyLoadedPaper => { LoadPluginResult::SuccessfullyLoadedPaper => {
log::info!("Loaded Paper plugin from JAR `{}`", jar_path.display()) log::info!("Loaded Paper plugin from JAR `{}`", jar_path.display());
} }
LoadPluginResult::FailedToLoadSpigotPlugin(error) => { LoadPluginResult::FailedToLoadSpigotPlugin(error) => {
log::error!( log::error!(
"Failed to load Spigot plugin from JAR `{}` with error: {}", "Failed to load Spigot plugin from JAR `{}` with error: {}",
jar_path.display(), jar_path.display(),
error error
) );
} }
LoadPluginResult::FailedToLoadPaperPlugin(error) => { LoadPluginResult::FailedToLoadPaperPlugin(error) => {
log::error!( log::error!(
"Failed to load Paper plugin from JAR `{}` with error: {}", "Failed to load Paper plugin from JAR `{}` with error: {}",
jar_path.display(), jar_path.display(),
error error
) );
} }
LoadPluginResult::FailedToReadConfigurationFile(error) => { LoadPluginResult::FailedToReadConfigurationFile(error) => {
log::error!( log::error!(
"Failed to read configuration file from JAR `{}`: {}", "Failed to read configuration file from JAR `{}`: {}",
jar_path.display(), jar_path.display(),
error error
) );
} }
LoadPluginResult::NoConfigurationFile => { LoadPluginResult::NoConfigurationFile => {
log::warn!( log::warn!(
"No configuration file found for plugin from JAR `{}`", "No configuration file found for plugin from JAR `{}`",
jar_path.display() jar_path.display()
) );
} }
}, },
Err(e) => log::error!( Err(e) => log::error!(
@ -110,10 +112,10 @@ async fn on_load_inner(plugin: &mut PatchBukkitPlugin, server: Arc<Context>) ->
command_tx: plugin.command_tx.clone(), command_tx: plugin.command_tx.clone(),
}) })
.await .await
.map_err(|e| format!("Failed to send command to initialize J4RS: {}", e))?; .map_err(|e| format!("Failed to send command to initialize J4RS: {e}"))?;
rx.await rx.await
.map_err(|e| format!("Unable to receive response from J4RS initialization: {}", e))? .map_err(|e| format!("Unable to receive response from J4RS initialization: {e}"))?
.map_err(|e| format!("Failed to initialize all plugins: {}", e))?; .map_err(|e| format!("Failed to initialize all plugins: {e}"))?;
} }
{ {
@ -126,10 +128,10 @@ async fn on_load_inner(plugin: &mut PatchBukkitPlugin, server: Arc<Context>) ->
command_tx: plugin.command_tx.clone(), command_tx: plugin.command_tx.clone(),
}) })
.await .await
.map_err(|e| format!("Failed to send command to instantiate plugins: {}", e))?; .map_err(|e| format!("Failed to send command to instantiate plugins: {e}"))?;
rx.await rx.await
.map_err(|e| format!("Unable to receive response from instantiate plugins: {}", e))? .map_err(|e| format!("Unable to receive response from instantiate plugins: {e}"))?
.map_err(|e| format!("Failed to instantiate all plugins: {}", e))?; .map_err(|e| format!("Failed to instantiate all plugins: {e}"))?;
} }
{ {
@ -138,29 +140,26 @@ async fn on_load_inner(plugin: &mut PatchBukkitPlugin, server: Arc<Context>) ->
.command_tx .command_tx
.send(JvmCommand::EnableAllPlugins { respond_to: tx }) .send(JvmCommand::EnableAllPlugins { respond_to: tx })
.await .await
.map_err(|e| format!("Failed to send command to enable all plugins: {}", e))?; .map_err(|e| format!("Failed to send command to enable all plugins: {e}"))?;
rx.await rx.await
.map_err(|e| format!("Unable to receive response from enable all plugins: {}", e))? .map_err(|e| format!("Unable to receive response from enable all plugins: {e}"))?
.map_err(|e| format!("Failed to enable all plugins: {}", e))?; .map_err(|e| format!("Failed to enable all plugins: {e}"))?;
}; };
Ok(()) Ok(())
} }
async fn on_unload_inner( async fn on_unload_inner(plugin: &PatchBukkitPlugin, _server: Arc<Context>) -> Result<(), String> {
plugin: &mut PatchBukkitPlugin,
_server: Arc<Context>,
) -> Result<(), String> {
{ {
let (tx, rx) = oneshot::channel(); let (tx, rx) = oneshot::channel();
plugin plugin
.command_tx .command_tx
.send(JvmCommand::DisableAllPlugins { respond_to: tx }) .send(JvmCommand::DisableAllPlugins { respond_to: tx })
.await .await
.map_err(|e| format!("Failed to send command to disable all plugins: {}", e))?; .map_err(|e| format!("Failed to send command to disable all plugins: {e}"))?;
rx.await rx.await
.map_err(|e| format!("Unable to receive response from disable all plugins: {}", e))? .map_err(|e| format!("Unable to receive response from disable all plugins: {e}"))?
.map_err(|e| format!("Failed to disable all plugins: {}", e))?; .map_err(|e| format!("Failed to disable all plugins: {e}"))?;
} }
{ {
@ -169,10 +168,10 @@ async fn on_unload_inner(
.command_tx .command_tx
.send(JvmCommand::Shutdown { respond_to: tx }) .send(JvmCommand::Shutdown { respond_to: tx })
.await .await
.map_err(|e| format!("Failed to send command to shutdown: {}", e))?; .map_err(|e| format!("Failed to send command to shutdown: {e}"))?;
rx.await rx.await
.map_err(|e| format!("Unable to receive response from shutdown: {}", e))? .map_err(|e| format!("Unable to receive response from shutdown: {e}"))?
.map_err(|e| format!("Failed to shutdown: {}", e))?; .map_err(|e| format!("Failed to shutdown: {e}"))?;
} }
Ok(()) Ok(())
@ -194,6 +193,7 @@ pub struct PatchBukkitPlugin {
} }
impl PatchBukkitPlugin { impl PatchBukkitPlugin {
#[must_use]
pub fn new() -> Self { pub fn new() -> Self {
let (tx, rx) = mpsc::channel(100); let (tx, rx) = mpsc::channel(100);
@ -208,7 +208,7 @@ impl PatchBukkitPlugin {
jvm_thread_task(rx); jvm_thread_task(rx);
}) })
.unwrap(); .unwrap();
PatchBukkitPlugin { command_tx: tx } Self { command_tx: tx }
} }
} }