You've already forked AstralRinth
forked from didirus/AstralRinth
Merge commit '175b90be5a42e5bfd3289ffdfbf7b201404f82a8' into beta
This commit is contained in:
289
Cargo.lock
generated
289
Cargo.lock
generated
@@ -87,7 +87,7 @@ dependencies = [
|
||||
"mime",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"sha1",
|
||||
"smallvec",
|
||||
"tokio",
|
||||
@@ -182,7 +182,7 @@ dependencies = [
|
||||
"futures-core",
|
||||
"futures-util",
|
||||
"mio",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tracing",
|
||||
]
|
||||
@@ -244,7 +244,7 @@ dependencies = [
|
||||
"serde_json",
|
||||
"serde_urlencoded",
|
||||
"smallvec",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"time",
|
||||
"tracing",
|
||||
"url",
|
||||
@@ -508,7 +508,7 @@ dependencies = [
|
||||
"enumflags2",
|
||||
"futures-channel",
|
||||
"futures-util",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"raw-window-handle",
|
||||
"serde",
|
||||
"serde_repr",
|
||||
@@ -590,9 +590,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-fs"
|
||||
version = "2.1.2"
|
||||
version = "2.1.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ebcd09b382f40fcd159c2d695175b2ae620ffa5f3bd6f664131efff4e8b9e04a"
|
||||
checksum = "09f7e37c0ed80b2a977691c47dae8625cfb21e205827106c64f7c588766b2e50"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"blocking",
|
||||
@@ -601,9 +601,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-io"
|
||||
version = "2.4.1"
|
||||
version = "2.5.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1237c0ae75a0f3765f58910ff9cdd0a12eeb39ab2f4c7de23262f337f0aacbb3"
|
||||
checksum = "19634d6336019ef220f09fd31168ce5c184b295cbf80345437cc36094ef223ca"
|
||||
dependencies = [
|
||||
"async-lock",
|
||||
"cfg-if",
|
||||
@@ -614,8 +614,7 @@ dependencies = [
|
||||
"polling",
|
||||
"rustix 1.0.8",
|
||||
"slab",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -631,9 +630,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-process"
|
||||
version = "2.3.1"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cde3f4e40e6021d7acffc90095cbd6dc54cb593903d1de5832f435eb274b85dc"
|
||||
checksum = "65daa13722ad51e6ab1a1b9c01299142bc75135b337923cfa10e79bbbd669f00"
|
||||
dependencies = [
|
||||
"async-channel 2.5.0",
|
||||
"async-io",
|
||||
@@ -645,7 +644,6 @@ dependencies = [
|
||||
"event-listener 5.4.0",
|
||||
"futures-lite 2.6.0",
|
||||
"rustix 1.0.8",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -661,9 +659,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "async-signal"
|
||||
version = "0.2.11"
|
||||
version = "0.2.12"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d7605a4e50d4b06df3898d5a70bf5fde51ed9059b0434b73105193bc27acce0d"
|
||||
checksum = "f567af260ef69e1d52c2b560ce0ea230763e6fbb9214a85d768760a920e3e3c1"
|
||||
dependencies = [
|
||||
"async-io",
|
||||
"async-lock",
|
||||
@@ -674,7 +672,7 @@ dependencies = [
|
||||
"rustix 1.0.8",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -1287,19 +1285,19 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "cargo_toml"
|
||||
version = "0.22.1"
|
||||
version = "0.22.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257"
|
||||
checksum = "374b7c592d9c00c1f4972ea58390ac6b18cbb6ab79011f3bdc90a0b82ca06b77"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"toml 0.8.23",
|
||||
"toml 0.9.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "cc"
|
||||
version = "1.2.29"
|
||||
version = "1.2.30"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5c1599538de2394445747c8cf7935946e3cc27e9625f889d979bfb2aaf569362"
|
||||
checksum = "deec109607ca693028562ed836a5f1c4b8bd77755c4e132fc5ce11b0b6211ae7"
|
||||
dependencies = [
|
||||
"jobserver",
|
||||
"libc",
|
||||
@@ -2313,9 +2311,9 @@ checksum = "92773504d58c093f6de2459af4af33faa518c13451eb8f2b5698ed3d36e7c813"
|
||||
|
||||
[[package]]
|
||||
name = "dyn-clone"
|
||||
version = "1.0.19"
|
||||
version = "1.0.20"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1c7a8fb8a9fbf66c1f703fe16184d10ca0ee9d23be5b4436400408ba54a95005"
|
||||
checksum = "d0881ea181b1df73ff77ffaaf9c7544ecc11e82fba9b5f27b262a3c73a332555"
|
||||
|
||||
[[package]]
|
||||
name = "ecdsa"
|
||||
@@ -3417,7 +3415,7 @@ dependencies = [
|
||||
"idna",
|
||||
"ipnet",
|
||||
"once_cell",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"ring",
|
||||
"thiserror 2.0.12",
|
||||
"tinyvec",
|
||||
@@ -3439,7 +3437,7 @@ dependencies = [
|
||||
"moka",
|
||||
"once_cell",
|
||||
"parking_lot",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"resolv-conf",
|
||||
"smallvec",
|
||||
"thiserror 2.0.12",
|
||||
@@ -3615,7 +3613,7 @@ dependencies = [
|
||||
"httpdate",
|
||||
"itoa",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
"tracing",
|
||||
@@ -3674,7 +3672,7 @@ dependencies = [
|
||||
"tokio",
|
||||
"tokio-rustls 0.26.2",
|
||||
"tower-service",
|
||||
"webpki-roots 1.0.1",
|
||||
"webpki-roots 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -3692,9 +3690,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "hyper-util"
|
||||
version = "0.1.15"
|
||||
version = "0.1.16"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7f66d5bd4c6f02bf0542fad85d626775bab9258cf795a4256dcaf3161114d1df"
|
||||
checksum = "8d9b05277c7e8da2c93a568989bb6207bef0112e8d17df7a6eda4a3cf143bc5e"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"bytes",
|
||||
@@ -3708,7 +3706,7 @@ dependencies = [
|
||||
"libc",
|
||||
"percent-encoding",
|
||||
"pin-project-lite",
|
||||
"socket2",
|
||||
"socket2 0.6.0",
|
||||
"system-configuration",
|
||||
"tokio",
|
||||
"tower-service",
|
||||
@@ -4022,9 +4020,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "io-uring"
|
||||
version = "0.7.8"
|
||||
version = "0.7.9"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013"
|
||||
checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"cfg-if",
|
||||
@@ -4037,7 +4035,7 @@ version = "0.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b58db92f96b720de98181bbbe63c831e87005ab460c1bf306eb2622b4707997f"
|
||||
dependencies = [
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"widestring",
|
||||
"windows-sys 0.48.0",
|
||||
"winreg 0.50.0",
|
||||
@@ -4176,7 +4174,7 @@ dependencies = [
|
||||
"libc",
|
||||
"mappings",
|
||||
"once_cell",
|
||||
"pprof_util",
|
||||
"pprof_util 0.7.0",
|
||||
"tempfile",
|
||||
"tikv-jemalloc-ctl",
|
||||
"tokio",
|
||||
@@ -4440,9 +4438,9 @@ checksum = "03087c2bad5e1034e8cace5926dec053fb3790248370865f5117a7d0213354c8"
|
||||
|
||||
[[package]]
|
||||
name = "lettre"
|
||||
version = "0.11.17"
|
||||
version = "0.11.18"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "cb2a0354e9ece2fcdcf9fa53417f6de587230c0c248068eb058fa26c4a753179"
|
||||
checksum = "5cb54db6ff7a89efac87dba5baeac57bb9ccd726b49a9b6f21fb92b3966aaf56"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"chumsky",
|
||||
@@ -4459,7 +4457,7 @@ dependencies = [
|
||||
"quoted_printable",
|
||||
"rustls 0.23.29",
|
||||
"rustls-native-certs 0.8.1",
|
||||
"socket2",
|
||||
"socket2 0.6.0",
|
||||
"tokio",
|
||||
"url",
|
||||
]
|
||||
@@ -4527,7 +4525,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "07033963ba89ebaf1584d767badaa2e8fcec21aedea6b8c0346d487d49c28667"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"windows-targets 0.53.2",
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -4538,9 +4536,9 @@ checksum = "f9fbbcab51052fe104eb5e5d351cf728d30a5be1fe14d9be8a3b097481fb97de"
|
||||
|
||||
[[package]]
|
||||
name = "libredox"
|
||||
version = "0.1.4"
|
||||
version = "0.1.8"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1580801010e535496706ba011c15f8532df6b42297d2e471fec38ceadd8c0638"
|
||||
checksum = "360e552c93fa0e8152ab463bc4c4837fce76a225df11dfaeea66c313de5e61f7"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"libc",
|
||||
@@ -4597,9 +4595,9 @@ checksum = "241eaef5fd12c88705a01fc1066c48c4b36e0dd4377dcdc7ec3942cea7a69956"
|
||||
|
||||
[[package]]
|
||||
name = "litrs"
|
||||
version = "0.4.1"
|
||||
version = "0.4.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b4ce301924b7887e9d637144fdade93f9dfff9b60981d4ac161db09720d39aa5"
|
||||
checksum = "f5e54036fe321fd421e10d732f155734c4e4afd610dd556d9a82833ab3ee0bed"
|
||||
|
||||
[[package]]
|
||||
name = "local-channel"
|
||||
@@ -4676,14 +4674,14 @@ checksum = "c41e0c4fef86961ac6d6f8a82609f55f31b05e4fce149ac5710e439df7619ba4"
|
||||
|
||||
[[package]]
|
||||
name = "mappings"
|
||||
version = "0.7.0"
|
||||
version = "0.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e434981a332777c2b3062652d16a55f8e74fa78e6b1882633f0d77399c84fc2a"
|
||||
checksum = "db4d277bb50d4508057e7bddd7fcd19ef4a4cc38051b6a5a36868d75ae2cbeb9"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"pprof_util",
|
||||
"pprof_util 0.8.0",
|
||||
"tracing",
|
||||
]
|
||||
|
||||
@@ -5757,6 +5755,17 @@ dependencies = [
|
||||
"phf_shared 0.11.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "913273894cec178f401a31ec4b656318d95473527be05c0752cc41cdc32be8b7"
|
||||
dependencies = [
|
||||
"phf_macros 0.12.1",
|
||||
"phf_shared 0.12.1",
|
||||
"serde",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_codegen"
|
||||
version = "0.8.0"
|
||||
@@ -5807,6 +5816,16 @@ dependencies = [
|
||||
"rand 0.8.5",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_generator"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "2cbb1126afed61dd6368748dae63b1ee7dc480191c6262a3b4ff1e29d86a6c5b"
|
||||
dependencies = [
|
||||
"fastrand 2.3.0",
|
||||
"phf_shared 0.12.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.10.0"
|
||||
@@ -5834,6 +5853,19 @@ dependencies = [
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_macros"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "d713258393a82f091ead52047ca779d37e5766226d009de21696c4e667044368"
|
||||
dependencies = [
|
||||
"phf_generator 0.12.1",
|
||||
"phf_shared 0.12.1",
|
||||
"proc-macro2",
|
||||
"quote",
|
||||
"syn 2.0.104",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.8.0"
|
||||
@@ -5861,6 +5893,15 @@ dependencies = [
|
||||
"siphasher 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "phf_shared"
|
||||
version = "0.12.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "06005508882fb681fd97892ecff4b7fd0fee13ef1aa569f8695dae7ab9099981"
|
||||
dependencies = [
|
||||
"siphasher 1.0.1",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pin-project"
|
||||
version = "1.1.10"
|
||||
@@ -5959,17 +6000,16 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "polling"
|
||||
version = "3.8.0"
|
||||
version = "3.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b53a684391ad002dd6a596ceb6c74fd004fdce75f4be2e3f615068abbea5fd50"
|
||||
checksum = "8ee9b2fa7a4517d2c91ff5bc6c297a427a96749d15f98fcdbb22c05571a4d4b7"
|
||||
dependencies = [
|
||||
"cfg-if",
|
||||
"concurrent-queue",
|
||||
"hermit-abi",
|
||||
"pin-project-lite",
|
||||
"rustix 1.0.8",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
"windows-sys 0.60.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -6008,6 +6048,19 @@ dependencies = [
|
||||
"prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "pprof_util"
|
||||
version = "0.8.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f9aba4251d95ac86f14c33e688d57a9344bfcff29e9b0c5a063fc66b5facc8a1"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"flate2",
|
||||
"num",
|
||||
"paste",
|
||||
"prost",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "ppv-lite86"
|
||||
version = "0.2.21"
|
||||
@@ -6372,7 +6425,7 @@ dependencies = [
|
||||
"quinn-udp",
|
||||
"rustc-hash",
|
||||
"rustls 0.23.29",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"thiserror 2.0.12",
|
||||
"tokio",
|
||||
"tracing",
|
||||
@@ -6388,7 +6441,7 @@ dependencies = [
|
||||
"bytes",
|
||||
"getrandom 0.3.3",
|
||||
"lru-slab",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"ring",
|
||||
"rustc-hash",
|
||||
"rustls 0.23.29",
|
||||
@@ -6409,7 +6462,7 @@ dependencies = [
|
||||
"cfg_aliases",
|
||||
"libc",
|
||||
"once_cell",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tracing",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
@@ -6479,9 +6532,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rand"
|
||||
version = "0.9.1"
|
||||
version = "0.9.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9fbfd9d094a40bf3ae768db9361049ace4c0e04a4fd6b359518bd7b73a73dd97"
|
||||
checksum = "6db2770f06117d490610c7488547d543617b21bfa07796d7a12f6f1bd53850d1"
|
||||
dependencies = [
|
||||
"rand_chacha 0.9.0",
|
||||
"rand_core 0.9.3",
|
||||
@@ -6656,7 +6709,7 @@ dependencies = [
|
||||
"r2d2",
|
||||
"ryu",
|
||||
"sha1_smol",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tokio-util",
|
||||
"url",
|
||||
@@ -6664,9 +6717,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "redox_syscall"
|
||||
version = "0.5.13"
|
||||
version = "0.5.17"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0d04b7d0ee6b4a0207a0a7adb104d23ecb0b47d6beae7152d0fa34b692b29fd6"
|
||||
checksum = "5407465600fb0548f1442edf71dd20683c6ed326200ace4b1ef0763521bb3b77"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
]
|
||||
@@ -6825,7 +6878,7 @@ dependencies = [
|
||||
"wasm-bindgen-futures",
|
||||
"wasm-streams",
|
||||
"web-sys",
|
||||
"webpki-roots 1.0.1",
|
||||
"webpki-roots 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -7035,9 +7088,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "rustc-demangle"
|
||||
version = "0.1.25"
|
||||
version = "0.1.26"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f"
|
||||
checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
|
||||
|
||||
[[package]]
|
||||
name = "rustc-hash"
|
||||
@@ -7476,7 +7529,7 @@ version = "0.41.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "00e9bd2cadaeda3af41e9fa5d14645127d6f6a4aec73da3ae38e477ecafd3682"
|
||||
dependencies = [
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"sentry-types",
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -7523,7 +7576,7 @@ checksum = "a08e7154abe2cd557f26fd70038452810748aefdf39bc973f674421224b147c1"
|
||||
dependencies = [
|
||||
"debugid",
|
||||
"hex",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"serde_json",
|
||||
"thiserror 2.0.12",
|
||||
@@ -7618,9 +7671,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "serde_json"
|
||||
version = "1.0.140"
|
||||
version = "1.0.141"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "20068b6e96dc6c9bd23e01df8827e6c7e1f2fddd43c21810382803c136b99373"
|
||||
checksum = "30b9eff21ebe718216c6ec64e1d9ac57087aad11efc64e32002bce4a0d4c03d3"
|
||||
dependencies = [
|
||||
"itoa",
|
||||
"memchr",
|
||||
@@ -7937,6 +7990,16 @@ dependencies = [
|
||||
"windows-sys 0.52.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "socket2"
|
||||
version = "0.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "233504af464074f9d066d7b5416c5f9b894a5862a6506e306f7b816cdd6f1807"
|
||||
dependencies = [
|
||||
"libc",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "softbuffer"
|
||||
version = "0.4.6"
|
||||
@@ -8247,9 +8310,9 @@ checksum = "9091b6114800a5f2141aee1d1b9d6ca3592ac062dc5decb3764ec5895a47b4eb"
|
||||
|
||||
[[package]]
|
||||
name = "strfmt"
|
||||
version = "0.2.4"
|
||||
version = "0.2.5"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "7a8348af2d9fc3258c8733b8d9d8db2e56f54b2363a4b5b81585c7875ed65e65"
|
||||
checksum = "29fdc163db75f7b5ffa3daf0c5a7136fb0d4b2f35523cd1769da05e034159feb"
|
||||
|
||||
[[package]]
|
||||
name = "string_cache"
|
||||
@@ -8513,9 +8576,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
||||
|
||||
[[package]]
|
||||
name = "tauri"
|
||||
version = "2.6.2"
|
||||
version = "2.7.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "124e129c9c0faa6bec792c5948c89e86c90094133b0b9044df0ce5f0a8efaa0d"
|
||||
checksum = "352a4bc7bf6c25f5624227e3641adf475a6535707451b09bb83271df8b7a6ac7"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"bytes",
|
||||
@@ -8564,9 +8627,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-build"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "12f025c389d3adb83114bec704da973142e82fc6ec799c7c750c5e21cefaec83"
|
||||
checksum = "182d688496c06bf08ea896459bf483eb29cdff35c1c4c115fb14053514303064"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"cargo_toml",
|
||||
@@ -8588,9 +8651,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-codegen"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f5df493a1075a241065bc865ed5ef8d0fbc1e76c7afdc0bf0eccfaa7d4f0e406"
|
||||
checksum = "b54a99a6cd8e01abcfa61508177e6096a4fe2681efecee9214e962f2f073ae4a"
|
||||
dependencies = [
|
||||
"base64 0.22.1",
|
||||
"brotli",
|
||||
@@ -8615,9 +8678,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-macros"
|
||||
version = "2.3.1"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f237fbea5866fa5f2a60a21bea807a2d6e0379db070d89c3a10ac0f2d4649bbc"
|
||||
checksum = "7945b14dc45e23532f2ded6e120170bbdd4af5ceaa45784a6b33d250fbce3f9e"
|
||||
dependencies = [
|
||||
"heck 0.5.0",
|
||||
"proc-macro2",
|
||||
@@ -8629,9 +8692,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin"
|
||||
version = "2.3.0"
|
||||
version = "2.3.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1d9a0bd00bf1930ad1a604d08b0eb6b2a9c1822686d65d7f4731a7723b8901d3"
|
||||
checksum = "5bd5c1e56990c70a906ef67a9851bbdba9136d26075ee9a2b19c8b46986b3e02"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"glob",
|
||||
@@ -8646,9 +8709,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-deep-link"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "ab261eb006db10ab478e3fbb5a4e2692df3f7eb3e28300ee2b64428979167ed0"
|
||||
checksum = "1fec67f32d7a06d80bd3dc009fdb678c35a66116d9cb8cd2bb32e406c2b5bbd2"
|
||||
dependencies = [
|
||||
"dunce",
|
||||
"rust-ini",
|
||||
@@ -8666,9 +8729,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-dialog"
|
||||
version = "2.3.0"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "1aefb14219b492afb30b12647b5b1247cadd2c0603467310c36e0f7ae1698c28"
|
||||
checksum = "37e5858cc7b455a73ab4ea2ebc08b5be33682c00ff1bf4cad5537d4fb62499d9"
|
||||
dependencies = [
|
||||
"log",
|
||||
"raw-window-handle",
|
||||
@@ -8684,9 +8747,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-fs"
|
||||
version = "2.4.0"
|
||||
version = "2.4.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c341290d31991dbca38b31d412c73dfbdb070bb11536784f19dd2211d13b778f"
|
||||
checksum = "8c6ef84ee2f2094ce093e55106d90d763ba343fad57566992962e8f76d113f99"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"dunce",
|
||||
@@ -8706,9 +8769,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-http"
|
||||
version = "2.5.0"
|
||||
version = "2.5.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b0c1a38da944b357ffa23bafd563b1579f18e6fbd118fcd84769406d35dcc5c7"
|
||||
checksum = "fcde333d97e565a7765aad82f32d8672458f7bd77b6ee653830d5dded9d7b5c2"
|
||||
dependencies = [
|
||||
"bytes",
|
||||
"cookie_store",
|
||||
@@ -8770,9 +8833,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-single-instance"
|
||||
version = "2.3.0"
|
||||
version = "2.3.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "b441b6d5d1a194e9fee0b358fe0d602ded845d0f580e1f8c8ef78ebc3c8b225d"
|
||||
checksum = "50a0e5a4ce43cb3a733c3aef85e8478bc769dac743c615e26639cbf5d953faf7"
|
||||
dependencies = [
|
||||
"serde",
|
||||
"serde_json",
|
||||
@@ -8817,9 +8880,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-plugin-window-state"
|
||||
version = "2.3.0"
|
||||
version = "2.4.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "5a3d22b21b9cec73601b512a868f7c74f93c044d44fd6ca1c84e9d6afb6b1559"
|
||||
checksum = "2d5f6fe3291bfa609c7e0b0ee3bedac294d94c7018934086ce782c1d0f2a468e"
|
||||
dependencies = [
|
||||
"bitflags 2.9.1",
|
||||
"log",
|
||||
@@ -8832,9 +8895,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-runtime"
|
||||
version = "2.7.0"
|
||||
version = "2.7.1"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "9e7bb73d1bceac06c20b3f755b2c8a2cb13b20b50083084a8cf3700daf397ba4"
|
||||
checksum = "2b1cc885be806ea15ff7b0eb47098a7b16323d9228876afda329e34e2d6c4676"
|
||||
dependencies = [
|
||||
"cookie 0.18.1",
|
||||
"dpi",
|
||||
@@ -8854,9 +8917,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-runtime-wry"
|
||||
version = "2.7.1"
|
||||
version = "2.7.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "902b5aa9035e16f342eb64f8bf06ccdc2808e411a2525ed1d07672fa4e780bad"
|
||||
checksum = "fe653a2fbbef19fe898efc774bc52c8742576342a33d3d028c189b57eb1d2439"
|
||||
dependencies = [
|
||||
"gtk",
|
||||
"http 1.3.1",
|
||||
@@ -8881,9 +8944,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "tauri-utils"
|
||||
version = "2.5.0"
|
||||
version = "2.6.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "41743bbbeb96c3a100d234e5a0b60a46d5aa068f266160862c7afdbf828ca02e"
|
||||
checksum = "9330c15cabfe1d9f213478c9e8ec2b0c76dab26bb6f314b8ad1c8a568c1d186e"
|
||||
dependencies = [
|
||||
"anyhow",
|
||||
"brotli",
|
||||
@@ -8999,6 +9062,7 @@ dependencies = [
|
||||
"notify-debouncer-mini",
|
||||
"p256",
|
||||
"paste",
|
||||
"phf 0.12.1",
|
||||
"png",
|
||||
"quartz_nbt",
|
||||
"quick-xml 0.37.5",
|
||||
@@ -9232,9 +9296,9 @@ checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20"
|
||||
|
||||
[[package]]
|
||||
name = "tokio"
|
||||
version = "1.46.1"
|
||||
version = "1.47.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "0cc3a2344dafbe23a245241fe8b09735b521110d30fcefbbd5feb1797ca35d17"
|
||||
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35"
|
||||
dependencies = [
|
||||
"backtrace",
|
||||
"bytes",
|
||||
@@ -9245,10 +9309,10 @@ dependencies = [
|
||||
"pin-project-lite",
|
||||
"signal-hook-registry",
|
||||
"slab",
|
||||
"socket2",
|
||||
"socket2 0.6.0",
|
||||
"tokio-macros",
|
||||
"tracing",
|
||||
"windows-sys 0.52.0",
|
||||
"windows-sys 0.59.0",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -9430,7 +9494,7 @@ dependencies = [
|
||||
"percent-encoding",
|
||||
"pin-project",
|
||||
"prost",
|
||||
"socket2",
|
||||
"socket2 0.5.10",
|
||||
"tokio",
|
||||
"tokio-stream",
|
||||
"tower 0.4.13",
|
||||
@@ -9448,7 +9512,7 @@ dependencies = [
|
||||
"base32",
|
||||
"constant_time_eq",
|
||||
"hmac",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"sha1",
|
||||
"sha2",
|
||||
]
|
||||
@@ -9643,7 +9707,7 @@ dependencies = [
|
||||
"http 1.3.1",
|
||||
"httparse",
|
||||
"log",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"rustls 0.23.29",
|
||||
"rustls-pki-types",
|
||||
"sha1",
|
||||
@@ -9881,7 +9945,7 @@ checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d"
|
||||
dependencies = [
|
||||
"getrandom 0.3.3",
|
||||
"js-sys",
|
||||
"rand 0.9.1",
|
||||
"rand 0.9.2",
|
||||
"serde",
|
||||
"wasm-bindgen",
|
||||
]
|
||||
@@ -10268,14 +10332,14 @@ version = "0.26.11"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "521bc38abb08001b01866da9f51eb7c5d647a19260e00054a8c7fd5f9e57f7a9"
|
||||
dependencies = [
|
||||
"webpki-roots 1.0.1",
|
||||
"webpki-roots 1.0.2",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
name = "webpki-roots"
|
||||
version = "1.0.1"
|
||||
version = "1.0.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "8782dd5a41a24eed3a4f40b606249b3e236ca61adf1f25ea4d45c73de122b502"
|
||||
checksum = "7e8983c3ab33d6fb807cfcdad2491c4ea8cbc8ed839181c7dfd9c67c83e261b2"
|
||||
dependencies = [
|
||||
"rustls-pki-types",
|
||||
]
|
||||
@@ -10562,7 +10626,7 @@ version = "0.60.2"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "f2f500e4d28234f72040990ec9d39e3a6b950f9f22d3dba18416c35882612bcb"
|
||||
dependencies = [
|
||||
"windows-targets 0.53.2",
|
||||
"windows-targets 0.53.3",
|
||||
]
|
||||
|
||||
[[package]]
|
||||
@@ -10613,10 +10677,11 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "windows-targets"
|
||||
version = "0.53.2"
|
||||
version = "0.53.3"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "c66f69fcc9ce11da9966ddb31a40968cad001c5bedeb5c2b82ede4253ab48aef"
|
||||
checksum = "d5fe6031c4041849d7c496a8ded650796e7b6ecc19df1a431c1a363342e5dc91"
|
||||
dependencies = [
|
||||
"windows-link",
|
||||
"windows_aarch64_gnullvm 0.53.0",
|
||||
"windows_aarch64_msvc 0.53.0",
|
||||
"windows_i686_gnu 0.53.0",
|
||||
@@ -11047,9 +11112,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zbus"
|
||||
version = "5.8.0"
|
||||
version = "5.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "597f45e98bc7e6f0988276012797855613cd8269e23b5be62cc4e5d28b7e515d"
|
||||
checksum = "4bb4f9a464286d42851d18a605f7193b8febaf5b0919d71c6399b7b26e5b0aad"
|
||||
dependencies = [
|
||||
"async-broadcast",
|
||||
"async-executor",
|
||||
@@ -11081,9 +11146,9 @@ dependencies = [
|
||||
|
||||
[[package]]
|
||||
name = "zbus_macros"
|
||||
version = "5.8.0"
|
||||
version = "5.9.0"
|
||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||
checksum = "e5c8e4e14dcdd9d97a98b189cd1220f30e8394ad271e8c987da84f73693862c2"
|
||||
checksum = "ef9859f68ee0c4ee2e8cde84737c78e3f4c54f946f2a38645d0d4c7a95327659"
|
||||
dependencies = [
|
||||
"proc-macro-crate 3.3.0",
|
||||
"proc-macro2",
|
||||
|
||||
@@ -99,6 +99,7 @@ notify = { version = "8.0.0", default-features = false }
|
||||
notify-debouncer-mini = { version = "0.6.0", default-features = false }
|
||||
p256 = "0.13.2"
|
||||
paste = "1.0.15"
|
||||
phf = { version = "0.12.1", features = ["macros"] }
|
||||
png = "0.17.16"
|
||||
prometheus = "0.14.0"
|
||||
quartz_nbt = "0.2.9"
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
<script setup lang="ts">
|
||||
import {
|
||||
type ProtocolVersion,
|
||||
type ServerWorld,
|
||||
type ServerData,
|
||||
type WorldWithProfile,
|
||||
@@ -33,7 +34,7 @@ const theme = useTheming()
|
||||
|
||||
const jumpBackInItems = ref<JumpBackInItem[]>([])
|
||||
const serverData = ref<Record<string, ServerData>>({})
|
||||
const protocolVersions = ref<Record<string, number | null>>({})
|
||||
const protocolVersions = ref<Record<string, ProtocolVersion | null>>({})
|
||||
|
||||
const MIN_JUMP_BACK_IN = 3
|
||||
const MAX_JUMP_BACK_IN = 6
|
||||
@@ -121,11 +122,8 @@ async function populateJumpBackIn() {
|
||||
}
|
||||
})
|
||||
|
||||
// fetch each server's data
|
||||
Promise.all(
|
||||
servers.map(({ instancePath, address }) =>
|
||||
refreshServerData(serverData.value[address], protocolVersions.value[instancePath], address),
|
||||
),
|
||||
servers.forEach(({ instancePath, address }) =>
|
||||
refreshServerData(serverData.value[address], protocolVersions.value[instancePath], address),
|
||||
)
|
||||
}
|
||||
|
||||
@@ -150,8 +148,8 @@ async function populateJumpBackIn() {
|
||||
.slice(0, MAX_JUMP_BACK_IN)
|
||||
}
|
||||
|
||||
async function refreshServer(address: string, instancePath: string) {
|
||||
await refreshServerData(serverData.value[address], protocolVersions.value[instancePath], address)
|
||||
function refreshServer(address: string, instancePath: string) {
|
||||
refreshServerData(serverData.value[address], protocolVersions.value[instancePath], address)
|
||||
}
|
||||
|
||||
async function joinWorld(world: WorldWithProfile) {
|
||||
|
||||
@@ -1,7 +1,14 @@
|
||||
<script setup lang="ts">
|
||||
import dayjs from 'dayjs'
|
||||
import type { ServerStatus, ServerWorld, SingleplayerWorld, World } from '@/helpers/worlds.ts'
|
||||
import { set_world_display_status, getWorldIdentifier } from '@/helpers/worlds.ts'
|
||||
import type {
|
||||
ProtocolVersion,
|
||||
ServerStatus,
|
||||
ServerWorld,
|
||||
SingleplayerWorld,
|
||||
World,
|
||||
set_world_display_status,
|
||||
getWorldIdentifier,
|
||||
} from '@/helpers/worlds.ts'
|
||||
import { formatNumber, getPingLevel } from '@modrinth/utils'
|
||||
import {
|
||||
useRelativeTime,
|
||||
@@ -55,7 +62,7 @@ const props = withDefaults(
|
||||
playingWorld?: boolean
|
||||
startingInstance?: boolean
|
||||
supportsQuickPlay?: boolean
|
||||
currentProtocol?: number | null
|
||||
currentProtocol?: ProtocolVersion | null
|
||||
highlighted?: boolean
|
||||
|
||||
// Server only
|
||||
@@ -102,7 +109,8 @@ const serverIncompatible = computed(
|
||||
!!props.serverStatus &&
|
||||
!!props.serverStatus.version?.protocol &&
|
||||
!!props.currentProtocol &&
|
||||
props.serverStatus.version.protocol !== props.currentProtocol,
|
||||
(props.serverStatus.version.protocol !== props.currentProtocol.version ||
|
||||
props.serverStatus.version.legacy !== props.currentProtocol.legacy),
|
||||
)
|
||||
|
||||
const locked = computed(() => props.world.type === 'singleplayer' && props.world.locked)
|
||||
|
||||
@@ -51,6 +51,7 @@ export type ServerStatus = {
|
||||
version?: {
|
||||
name: string
|
||||
protocol: number
|
||||
legacy: boolean
|
||||
}
|
||||
favicon?: string
|
||||
enforces_secure_chat: boolean
|
||||
@@ -70,11 +71,17 @@ export interface Chat {
|
||||
|
||||
export type ServerData = {
|
||||
refreshing: boolean
|
||||
lastSuccessfulRefresh?: number
|
||||
status?: ServerStatus
|
||||
rawMotd?: string | Chat
|
||||
renderedMotd?: string
|
||||
}
|
||||
|
||||
export type ProtocolVersion = {
|
||||
version: number
|
||||
legacy: boolean
|
||||
}
|
||||
|
||||
export async function get_recent_worlds(
|
||||
limit: number,
|
||||
displayStatuses?: DisplayStatus[],
|
||||
@@ -156,13 +163,13 @@ export async function remove_server_from_profile(path: string, index: number): P
|
||||
return await invoke('plugin:worlds|remove_server_from_profile', { path, index })
|
||||
}
|
||||
|
||||
export async function get_profile_protocol_version(path: string): Promise<number | null> {
|
||||
export async function get_profile_protocol_version(path: string): Promise<ProtocolVersion | null> {
|
||||
return await invoke('plugin:worlds|get_profile_protocol_version', { path })
|
||||
}
|
||||
|
||||
export async function get_server_status(
|
||||
address: string,
|
||||
protocolVersion: number | null = null,
|
||||
protocolVersion: ProtocolVersion | null = null,
|
||||
): Promise<ServerStatus> {
|
||||
return await invoke('plugin:worlds|get_server_status', { address, protocolVersion })
|
||||
}
|
||||
@@ -206,30 +213,39 @@ export function isServerWorld(world: World): world is ServerWorld {
|
||||
|
||||
export async function refreshServerData(
|
||||
serverData: ServerData,
|
||||
protocolVersion: number | null,
|
||||
protocolVersion: ProtocolVersion | null,
|
||||
address: string,
|
||||
): Promise<void> {
|
||||
const refreshTime = Date.now()
|
||||
serverData.refreshing = true
|
||||
await get_server_status(address, protocolVersion)
|
||||
.then((status) => {
|
||||
if (serverData.lastSuccessfulRefresh && serverData.lastSuccessfulRefresh > refreshTime) {
|
||||
// Don't update if there was a more recent successful refresh
|
||||
return
|
||||
}
|
||||
serverData.lastSuccessfulRefresh = Date.now()
|
||||
serverData.status = status
|
||||
if (status.description) {
|
||||
serverData.rawMotd = status.description
|
||||
serverData.renderedMotd = autoToHTML(status.description)
|
||||
}
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Refreshing addr: ${address}`, err)
|
||||
})
|
||||
.finally(() => {
|
||||
serverData.refreshing = false
|
||||
})
|
||||
.catch((err) => {
|
||||
console.error(`Refreshing addr ${address}`, protocolVersion, err)
|
||||
if (!protocolVersion?.legacy) {
|
||||
refreshServerData(serverData, { version: 74, legacy: true }, address)
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
export async function refreshServers(
|
||||
export function refreshServers(
|
||||
worlds: World[],
|
||||
serverData: Record<string, ServerData>,
|
||||
protocolVersion: number | null,
|
||||
protocolVersion: ProtocolVersion | null,
|
||||
) {
|
||||
const servers = worlds.filter(isServerWorld)
|
||||
servers.forEach((server) => {
|
||||
@@ -243,10 +259,8 @@ export async function refreshServers(
|
||||
})
|
||||
|
||||
// noinspection ES6MissingAwait - handled with .then by refreshServerData already
|
||||
Promise.all(
|
||||
Object.keys(serverData).map((address) =>
|
||||
refreshServerData(serverData[address], protocolVersion, address),
|
||||
),
|
||||
Object.keys(serverData).forEach((address) =>
|
||||
refreshServerData(serverData[address], protocolVersion, address),
|
||||
)
|
||||
}
|
||||
|
||||
|
||||
@@ -134,6 +134,7 @@ import {
|
||||
} from '@modrinth/ui'
|
||||
import { PlusIcon, SpinnerIcon, UpdatedIcon, SearchIcon, XIcon } from '@modrinth/assets'
|
||||
import {
|
||||
type ProtocolVersion,
|
||||
type SingleplayerWorld,
|
||||
type World,
|
||||
type ServerWorld,
|
||||
@@ -210,7 +211,9 @@ const worldPlaying = ref<World>()
|
||||
const worlds = ref<World[]>([])
|
||||
const serverData = ref<Record<string, ServerData>>({})
|
||||
|
||||
const protocolVersion = ref<number | null>(await get_profile_protocol_version(instance.value.path))
|
||||
const protocolVersion = ref<ProtocolVersion | null>(
|
||||
await get_profile_protocol_version(instance.value.path),
|
||||
)
|
||||
|
||||
const unlistenProfile = await profile_listener(async (e: ProfileEvent) => {
|
||||
if (e.profile_path_id !== instance.value.path) return
|
||||
@@ -246,7 +249,7 @@ async function refreshAllWorlds() {
|
||||
worlds.value = await refreshWorlds(instance.value.path).finally(
|
||||
() => (refreshingAll.value = false),
|
||||
)
|
||||
await refreshServers(worlds.value, serverData.value, protocolVersion.value)
|
||||
refreshServers(worlds.value, serverData.value, protocolVersion.value)
|
||||
|
||||
const hasNoWorlds = worlds.value.length === 0
|
||||
|
||||
|
||||
@@ -5,8 +5,8 @@ use tauri::{AppHandle, Manager, Runtime};
|
||||
use theseus::prelude::ProcessMetadata;
|
||||
use theseus::profile::{QuickPlayType, get_full_path};
|
||||
use theseus::worlds::{
|
||||
DisplayStatus, ServerPackStatus, ServerStatus, World, WorldType,
|
||||
WorldWithProfile,
|
||||
DisplayStatus, ProtocolVersion, ServerPackStatus, ServerStatus, World,
|
||||
WorldType, WorldWithProfile,
|
||||
};
|
||||
use theseus::{profile, worlds};
|
||||
|
||||
@@ -183,14 +183,16 @@ pub async fn remove_server_from_profile(
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_profile_protocol_version(path: &str) -> Result<Option<i32>> {
|
||||
pub async fn get_profile_protocol_version(
|
||||
path: &str,
|
||||
) -> Result<Option<ProtocolVersion>> {
|
||||
Ok(worlds::get_profile_protocol_version(path).await?)
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
pub async fn get_server_status(
|
||||
address: &str,
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<ProtocolVersion>,
|
||||
) -> Result<ServerStatus> {
|
||||
Ok(worlds::get_server_status(address, protocol_version).await?)
|
||||
}
|
||||
|
||||
@@ -1,29 +1,28 @@
|
||||
<script setup lang="ts">
|
||||
import { ButtonStyled } from "@modrinth/ui";
|
||||
import { MailIcon, CheckIcon } from "@modrinth/assets";
|
||||
import { ref, watchEffect } from "vue";
|
||||
import { ref } from "vue";
|
||||
import { useBaseFetch } from "~/composables/fetch.js";
|
||||
|
||||
const auth = await useAuth();
|
||||
const showSubscriptionConfirmation = ref(false);
|
||||
const subscribed = ref(false);
|
||||
|
||||
async function checkSubscribed() {
|
||||
if (auth.value?.user) {
|
||||
try {
|
||||
const { data } = await useBaseFetch("auth/email/subscribe", {
|
||||
method: "GET",
|
||||
});
|
||||
subscribed.value = data?.subscribed || false;
|
||||
} catch {
|
||||
subscribed.value = false;
|
||||
const showSubscribeButton = useAsyncData(
|
||||
async () => {
|
||||
if (auth.value?.user) {
|
||||
try {
|
||||
const { subscribed } = await useBaseFetch("auth/email/subscribe", {
|
||||
method: "GET",
|
||||
});
|
||||
return !subscribed;
|
||||
} catch {
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
watchEffect(() => {
|
||||
checkSubscribed();
|
||||
});
|
||||
},
|
||||
{ watch: [auth], server: false },
|
||||
);
|
||||
|
||||
async function subscribe() {
|
||||
try {
|
||||
@@ -35,14 +34,19 @@ async function subscribe() {
|
||||
} finally {
|
||||
setTimeout(() => {
|
||||
showSubscriptionConfirmation.value = false;
|
||||
subscribed.value = true;
|
||||
showSubscribeButton.status.value = "success";
|
||||
showSubscribeButton.data.value = false;
|
||||
}, 2500);
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<template>
|
||||
<ButtonStyled v-if="auth?.user && !subscribed" color="brand" type="outlined">
|
||||
<ButtonStyled
|
||||
v-if="showSubscribeButton.status.value === 'success' && showSubscribeButton.data.value"
|
||||
color="brand"
|
||||
type="outlined"
|
||||
>
|
||||
<button v-tooltip="`Subscribe to the Modrinth newsletter`" @click="subscribe">
|
||||
<template v-if="!showSubscriptionConfirmation"> <MailIcon /> Subscribe </template>
|
||||
<template v-else> <CheckIcon /> Subscribed! </template>
|
||||
|
||||
@@ -1,13 +1,21 @@
|
||||
<template>
|
||||
<template v-if="moderation">
|
||||
<Chips v-model="reasonFilter" :items="reasons" />
|
||||
<p v-if="reports.length === MAX_REPORTS" class="text-red">
|
||||
There are at least {{ MAX_REPORTS }} open reports. This page is at its max reports and will
|
||||
not show any more recent ones.
|
||||
</p>
|
||||
<p v-else-if="reasonFilter === 'All'">There are {{ filteredReports.length }} open reports.</p>
|
||||
<p v-else>
|
||||
There are {{ filteredReports.length }}/{{ reports.length }} open '{{ reasonFilter }}' reports.
|
||||
</p>
|
||||
</template>
|
||||
<ReportInfo
|
||||
v-for="report in reports.filter(
|
||||
(x) =>
|
||||
(moderation || x.reporterUser.id === auth.user.id) &&
|
||||
(viewMode === 'open' ? x.open : !x.open),
|
||||
)"
|
||||
v-for="report in filteredReports"
|
||||
:key="report.id"
|
||||
:report="report"
|
||||
:thread="report.thread"
|
||||
:show-message="false"
|
||||
:moderation="moderation"
|
||||
raised
|
||||
:auth="auth"
|
||||
@@ -16,11 +24,12 @@
|
||||
<p v-if="reports.length === 0">You don't have any active reports.</p>
|
||||
</template>
|
||||
<script setup>
|
||||
import { Chips } from "@modrinth/ui";
|
||||
import ReportInfo from "~/components/ui/report/ReportInfo.vue";
|
||||
import { addReportMessage } from "~/helpers/threads.js";
|
||||
import { asEncodedJsonArray, fetchSegmented } from "~/utils/fetch-helpers.ts";
|
||||
|
||||
defineProps({
|
||||
const props = defineProps({
|
||||
moderation: {
|
||||
type: Boolean,
|
||||
default: false,
|
||||
@@ -32,9 +41,14 @@ defineProps({
|
||||
});
|
||||
|
||||
const viewMode = ref("open");
|
||||
const reasonFilter = ref("All");
|
||||
const reports = ref([]);
|
||||
|
||||
let { data: rawReports } = await useAsyncData("report", () => useBaseFetch("report?count=1000"));
|
||||
const MAX_REPORTS = 1500;
|
||||
|
||||
let { data: rawReports } = await useAsyncData("report", () =>
|
||||
useBaseFetch(`report?count=${MAX_REPORTS}`),
|
||||
);
|
||||
|
||||
rawReports = rawReports.value.map((report) => {
|
||||
report.item_id = report.item_id.replace(/"/g, "");
|
||||
@@ -51,6 +65,7 @@ const userIds = [...new Set(reporterUsers.concat(reportedUsers))];
|
||||
const threadIds = [
|
||||
...new Set(rawReports.filter((report) => report.thread_id).map((report) => report.thread_id)),
|
||||
];
|
||||
const reasons = ["All", ...new Set(rawReports.map((report) => report.report_type))];
|
||||
|
||||
const [{ data: users }, { data: versions }, { data: threads }] = await Promise.all([
|
||||
await useAsyncData(`users?ids=${JSON.stringify(userIds)}`, () =>
|
||||
@@ -93,4 +108,13 @@ reports.value = rawReports.map((report) => {
|
||||
report.open = true;
|
||||
return report;
|
||||
});
|
||||
|
||||
const filteredReports = computed(() =>
|
||||
reports.value?.filter(
|
||||
(x) =>
|
||||
(props.moderation || x.reporterUser.id === props.auth.user.id) &&
|
||||
(viewMode.value === "open" ? x.open : !x.open) &&
|
||||
(reasonFilter.value === "All" || reasonFilter.value === x.report_type),
|
||||
),
|
||||
);
|
||||
</script>
|
||||
|
||||
@@ -66,6 +66,27 @@
|
||||
<UiServersPanelSpinner />
|
||||
Your server's hardware is currently being upgraded and will be back online shortly.
|
||||
</div>
|
||||
<div
|
||||
v-else-if="status === 'suspended' && suspension_reason === 'cancelled'"
|
||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||
>
|
||||
<div class="flex flex-row gap-2">
|
||||
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been cancelled. Please
|
||||
update your billing information or contact Modrinth Support for more information.
|
||||
</div>
|
||||
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="status === 'suspended' && suspension_reason"
|
||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||
>
|
||||
<div class="flex flex-row gap-2">
|
||||
<UiServersIconsPanelErrorIcon class="!size-5" /> Your server has been suspended:
|
||||
{{ suspension_reason }}. Please update your billing information or contact Modrinth Support
|
||||
for more information.
|
||||
</div>
|
||||
<CopyCode :text="`${props.server_id}`" class="ml-auto" />
|
||||
</div>
|
||||
<div
|
||||
v-else-if="status === 'suspended'"
|
||||
class="relative -mt-4 flex w-full flex-col gap-2 rounded-b-3xl bg-bg-red p-4 text-sm font-bold text-contrast"
|
||||
@@ -87,7 +108,8 @@ import { Avatar, CopyCode } from "@modrinth/ui";
|
||||
|
||||
const props = defineProps<Partial<Server>>();
|
||||
|
||||
if (props.server_id) {
|
||||
if (props.server_id && props.status === "available") {
|
||||
// Necessary only to get server icon
|
||||
await useModrinthServers(props.server_id, ["general"]);
|
||||
}
|
||||
|
||||
@@ -109,11 +131,6 @@ if (props.upstream) {
|
||||
}
|
||||
|
||||
const image = useState<string | undefined>(`server-icon-${props.server_id}`, () => undefined);
|
||||
|
||||
if (import.meta.server && projectData.value?.icon_url) {
|
||||
await useModrinthServers(props.server_id!, ["general"]);
|
||||
}
|
||||
|
||||
const iconUrl = computed(() => projectData.value?.icon_url || undefined);
|
||||
const isConfiguring = computed(() => props.flows?.intro);
|
||||
</script>
|
||||
|
||||
@@ -34,6 +34,38 @@
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<Modal ref="modalReply" header="Reply to thread">
|
||||
<div class="modal-submit universal-body">
|
||||
<span>
|
||||
Your project is already approved. As such, the moderation team does not actively monitor
|
||||
this thread. However, they may still see your message if there is a problem with your
|
||||
project.
|
||||
</span>
|
||||
<span>
|
||||
If you need to get in contact with the moderation team, please use the
|
||||
<a class="text-link" href="https://support.modrinth.com" target="_blank">
|
||||
Modrinth Help Center
|
||||
</a>
|
||||
and click the green bubble to contact support.
|
||||
</span>
|
||||
<Checkbox
|
||||
v-model="replyConfirmation"
|
||||
description="Confirm moderators do not actively monitor this"
|
||||
>
|
||||
I acknowledge that the moderators do not actively monitor the thread.
|
||||
</Checkbox>
|
||||
<div class="input-group push-right">
|
||||
<button
|
||||
class="btn btn-primary"
|
||||
:disabled="!replyConfirmation"
|
||||
@click="sendReplyFromModal()"
|
||||
>
|
||||
<ReplyIcon aria-hidden="true" />
|
||||
Reply to thread
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</Modal>
|
||||
<div v-if="flags.developerMode" class="thread-id">
|
||||
Thread ID:
|
||||
<CopyCode :text="thread.id" />
|
||||
@@ -71,12 +103,17 @@
|
||||
v-if="sortedMessages.length > 0"
|
||||
class="btn btn-primary"
|
||||
:disabled="!replyBody"
|
||||
@click="sendReply()"
|
||||
@click="isApproved(project) && !isStaff(auth.user) ? openReplyModal() : sendReply()"
|
||||
>
|
||||
<ReplyIcon aria-hidden="true" />
|
||||
Reply
|
||||
</button>
|
||||
<button v-else class="btn btn-primary" :disabled="!replyBody" @click="sendReply()">
|
||||
<button
|
||||
v-else
|
||||
class="btn btn-primary"
|
||||
:disabled="!replyBody"
|
||||
@click="isApproved(project) && !isStaff(auth.user) ? openReplyModal() : sendReply()"
|
||||
>
|
||||
<SendIcon aria-hidden="true" />
|
||||
Send
|
||||
</button>
|
||||
@@ -289,6 +326,7 @@ const sortedMessages = computed(() => {
|
||||
});
|
||||
|
||||
const modalSubmit = ref(null);
|
||||
const modalReply = ref(null);
|
||||
|
||||
async function updateThreadLocal() {
|
||||
let threadId = null;
|
||||
@@ -316,6 +354,11 @@ async function onUploadImage(file) {
|
||||
return response.url;
|
||||
}
|
||||
|
||||
async function sendReplyFromModal(status = null, privateMessage = false) {
|
||||
modalReply.value.hide();
|
||||
await sendReply(status, privateMessage);
|
||||
}
|
||||
|
||||
async function sendReply(status = null, privateMessage = false) {
|
||||
try {
|
||||
const body = {
|
||||
@@ -398,6 +441,7 @@ async function reopenReport() {
|
||||
|
||||
const replyWithSubmission = ref(false);
|
||||
const submissionConfirmation = ref(false);
|
||||
const replyConfirmation = ref(false);
|
||||
|
||||
function openResubmitModal(reply) {
|
||||
submissionConfirmation.value = false;
|
||||
@@ -405,6 +449,11 @@ function openResubmitModal(reply) {
|
||||
modalSubmit.value.show();
|
||||
}
|
||||
|
||||
function openReplyModal(reply) {
|
||||
replyConfirmation.value = false;
|
||||
modalReply.value.show();
|
||||
}
|
||||
|
||||
async function resubmit() {
|
||||
if (replyWithSubmission.value) {
|
||||
await sendReply("processing");
|
||||
|
||||
@@ -182,9 +182,6 @@
|
||||
"collection.button.unfollow-project": {
|
||||
"message": "Unfollow project"
|
||||
},
|
||||
"collection.button.upload-icon": {
|
||||
"message": "Upload icon"
|
||||
},
|
||||
"collection.delete-modal.description": {
|
||||
"message": "This will remove this collection forever. This action cannot be undone."
|
||||
},
|
||||
|
||||
@@ -951,14 +951,7 @@ import {
|
||||
useRelativeTime,
|
||||
} from "@modrinth/ui";
|
||||
import VersionSummary from "@modrinth/ui/src/components/version/VersionSummary.vue";
|
||||
import {
|
||||
formatCategory,
|
||||
formatProjectType,
|
||||
isRejected,
|
||||
isStaff,
|
||||
isUnderReview,
|
||||
renderString,
|
||||
} from "@modrinth/utils";
|
||||
import { formatCategory, formatProjectType, renderString } from "@modrinth/utils";
|
||||
import dayjs from "dayjs";
|
||||
import { Tooltip } from "floating-vue";
|
||||
import { useLocalStorage } from "@vueuse/core";
|
||||
@@ -1646,9 +1639,7 @@ const navLinks = computed(() => {
|
||||
{
|
||||
label: formatMessage(messages.moderationTab),
|
||||
href: `${projectUrl}/moderation`,
|
||||
shown:
|
||||
!!currentMember.value &&
|
||||
(isRejected(project.value) || isUnderReview(project.value) || isStaff(auth.value.user)),
|
||||
shown: !!currentMember.value,
|
||||
},
|
||||
];
|
||||
});
|
||||
|
||||
@@ -76,8 +76,15 @@
|
||||
<p>
|
||||
This is a private conversation thread with the Modrinth moderators. They may message you
|
||||
with issues concerning this project. This thread is only checked when you submit your
|
||||
project for review. For additional inquiries, contact
|
||||
<a href="https://support.modrinth.com">Modrinth Support</a>.
|
||||
project for review. For additional inquiries, please go to the
|
||||
<a class="text-link" href="https://support.modrinth.com" target="_blank">
|
||||
Modrinth Help Center
|
||||
</a>
|
||||
and click the green bubble to contact support.
|
||||
</p>
|
||||
<p v-if="isApproved(project)" class="warning">
|
||||
<IssuesIcon /> The moderators do not actively monitor this chat. However, they may still see
|
||||
messages here if there is a problem with your project.
|
||||
</p>
|
||||
<ConversationThread
|
||||
v-if="thread"
|
||||
|
||||
@@ -58,6 +58,41 @@
|
||||
</div>
|
||||
</div>
|
||||
</NewModal>
|
||||
<NewModal ref="modifyModal">
|
||||
<template #title>
|
||||
<span class="text-lg font-extrabold text-contrast">Modify charge</span>
|
||||
</template>
|
||||
<div class="flex flex-col gap-3">
|
||||
<div class="flex flex-col gap-2">
|
||||
<label for="cancel" class="flex flex-col gap-1">
|
||||
<span class="text-lg font-semibold text-contrast">
|
||||
Cancel server
|
||||
<span class="text-brand-red">*</span>
|
||||
</span>
|
||||
<span>
|
||||
Whether or not the subscription should be cancelled. Submitting this as "true" will
|
||||
cancel the subscription, while submitting it as "false" will force another charge
|
||||
attempt to be made.
|
||||
</span>
|
||||
</label>
|
||||
<Toggle id="cancel" v-model="cancel" />
|
||||
</div>
|
||||
<div class="flex gap-2">
|
||||
<ButtonStyled color="brand">
|
||||
<button :disabled="modifying" @click="modifyCharge">
|
||||
<CheckIcon aria-hidden="true" />
|
||||
Modify charge
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled>
|
||||
<button @click="modifyModal.hide()">
|
||||
<XIcon aria-hidden="true" />
|
||||
Cancel
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</NewModal>
|
||||
<div class="page experimental-styles-within">
|
||||
<div
|
||||
class="mb-4 flex items-center justify-between border-0 border-b border-solid border-divider pb-4"
|
||||
@@ -201,6 +236,12 @@
|
||||
Refund options
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
<ButtonStyled v-else-if="charge.status === 'failed'" color="red" color-fill="text">
|
||||
<button @click="showModifyModal(subscription)">
|
||||
<CurrencyIcon />
|
||||
Modify charge
|
||||
</button>
|
||||
</ButtonStyled>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -234,7 +275,6 @@ import { products } from "~/generated/state.json";
|
||||
import ModrinthServersIcon from "~/components/ui/servers/ModrinthServersIcon.vue";
|
||||
|
||||
const route = useRoute();
|
||||
const data = useNuxtApp();
|
||||
const vintl = useVIntl();
|
||||
|
||||
const { formatMessage } = vintl;
|
||||
@@ -304,6 +344,10 @@ const refundTypes = ref(["full", "partial", "none"]);
|
||||
const refundAmount = ref(0);
|
||||
const unprovision = ref(true);
|
||||
|
||||
const modifying = ref(false);
|
||||
const modifyModal = ref();
|
||||
const cancel = ref(false);
|
||||
|
||||
function showRefundModal(charge) {
|
||||
selectedCharge.value = charge;
|
||||
refundType.value = "full";
|
||||
@@ -312,6 +356,12 @@ function showRefundModal(charge) {
|
||||
refundModal.value.show();
|
||||
}
|
||||
|
||||
function showModifyModal(charge) {
|
||||
selectedCharge.value = charge;
|
||||
cancel.value = false;
|
||||
modifyModal.value.show();
|
||||
}
|
||||
|
||||
async function refundCharge() {
|
||||
refunding.value = true;
|
||||
try {
|
||||
@@ -327,8 +377,7 @@ async function refundCharge() {
|
||||
await refreshCharges();
|
||||
refundModal.value.hide();
|
||||
} catch (err) {
|
||||
data.$notify({
|
||||
group: "main",
|
||||
addNotification({
|
||||
title: "Error refunding",
|
||||
text: err.data?.description ?? err,
|
||||
type: "error",
|
||||
@@ -337,6 +386,32 @@ async function refundCharge() {
|
||||
refunding.value = false;
|
||||
}
|
||||
|
||||
async function modifyCharge() {
|
||||
modifying.value = true;
|
||||
try {
|
||||
await useBaseFetch(`billing/subscription/${selectedCharge.value.id}`, {
|
||||
method: "PATCH",
|
||||
body: JSON.stringify({
|
||||
cancelled: cancel.value,
|
||||
}),
|
||||
internal: true,
|
||||
});
|
||||
addNotification({
|
||||
title: "Resubscription request submitted",
|
||||
text: "If the server is currently suspended, it may take up to 10 minutes for another charge attempt to be made.",
|
||||
type: "success",
|
||||
});
|
||||
await refreshCharges();
|
||||
} catch (err) {
|
||||
addNotification({
|
||||
title: "Error reattempting charge",
|
||||
text: err.data?.description ?? err,
|
||||
type: "error",
|
||||
});
|
||||
}
|
||||
modifying.value = false;
|
||||
}
|
||||
|
||||
const chargeStatuses = {
|
||||
open: {
|
||||
color: "bg-blue",
|
||||
|
||||
@@ -40,7 +40,6 @@
|
||||
@change="showPreviewImage"
|
||||
>
|
||||
<UploadIcon aria-hidden="true" />
|
||||
{{ formatMessage(messages.uploadIconButton) }}
|
||||
</FileInput>
|
||||
<Button
|
||||
v-if="!deletedIcon && (previewImage || collection.icon_url)"
|
||||
@@ -479,10 +478,6 @@ const messages = defineMessages({
|
||||
id: "collection.label.updated-at",
|
||||
defaultMessage: "Updated {ago}",
|
||||
},
|
||||
uploadIconButton: {
|
||||
id: "collection.button.upload-icon",
|
||||
defaultMessage: "Upload icon",
|
||||
},
|
||||
});
|
||||
|
||||
const data = useNuxtApp();
|
||||
|
||||
@@ -96,16 +96,7 @@
|
||||
<UiServersServerListing
|
||||
v-for="server in filteredData"
|
||||
:key="server.server_id"
|
||||
:server_id="server.server_id"
|
||||
:name="server.name"
|
||||
:status="server.status"
|
||||
:game="server.game"
|
||||
:loader="server.loader"
|
||||
:loader_version="server.loader_version"
|
||||
:mc_version="server.mc_version"
|
||||
:upstream="server.upstream"
|
||||
:net="server.net"
|
||||
:flows="server.flows"
|
||||
v-bind="server"
|
||||
/>
|
||||
<LazyUiServersServerListingSkeleton v-if="isPollingForNewServers" />
|
||||
</ul>
|
||||
|
||||
@@ -208,15 +208,7 @@
|
||||
<div class="flex flex-col gap-2">
|
||||
<UiServersServerListing
|
||||
v-if="subscription.serverInfo"
|
||||
:server_id="subscription.serverInfo.server_id"
|
||||
:name="subscription.serverInfo.name"
|
||||
:status="subscription.serverInfo.status"
|
||||
:game="subscription.serverInfo.game"
|
||||
:loader="subscription.serverInfo.loader"
|
||||
:loader_version="subscription.serverInfo.loader_version"
|
||||
:mc_version="subscription.serverInfo.mc_version"
|
||||
:upstream="subscription.serverInfo.upstream"
|
||||
:net="subscription.serverInfo.net"
|
||||
v-bind="subscription.serverInfo"
|
||||
/>
|
||||
<div v-else class="w-fit">
|
||||
<p>
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id FROM reports\n WHERE closed = FALSE\n ORDER BY created ASC\n LIMIT $1;\n ",
|
||||
"query": "\n SELECT id FROM reports\n WHERE closed = FALSE\n ORDER BY created ASC\n OFFSET $2\n LIMIT $1\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -11,6 +11,7 @@
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
@@ -18,5 +19,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "29e171bd746ac5dc1fabae4c9f81c3d1df4e69c860b7d0f6a907377664199217"
|
||||
"hash": "1aea0d5e6936b043cb7727b779d60598aa812c8ef0f5895fa740859321092a1c"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id FROM reports\n WHERE closed = FALSE AND reporter = $1\n ORDER BY created ASC\n LIMIT $2;\n ",
|
||||
"query": "\n SELECT id FROM reports\n WHERE closed = FALSE AND reporter = $1\n ORDER BY created ASC\n OFFSET $3\n LIMIT $2\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -11,6 +11,7 @@
|
||||
],
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Int8",
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
@@ -19,5 +20,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "f17a109913015a7a5ab847bb2e73794d6261a08d450de24b450222755e520881"
|
||||
"hash": "be8a5dd2b71fdc279a6fa68fe5384da31afd91d4b480527e2dd8402aef36f12c"
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"db_name": "PostgreSQL",
|
||||
"query": "\n SELECT id FROM mods\n WHERE status = $1\n ORDER BY queued ASC\n LIMIT $2;\n ",
|
||||
"query": "\n SELECT id FROM mods\n WHERE status = $1\n ORDER BY queued ASC\n OFFSET $3\n LIMIT $2\n ",
|
||||
"describe": {
|
||||
"columns": [
|
||||
{
|
||||
@@ -12,6 +12,7 @@
|
||||
"parameters": {
|
||||
"Left": [
|
||||
"Text",
|
||||
"Int8",
|
||||
"Int8"
|
||||
]
|
||||
},
|
||||
@@ -19,5 +20,5 @@
|
||||
false
|
||||
]
|
||||
},
|
||||
"hash": "3baabc9f08401801fa290866888c540746fc50c1d79911f08f3322b605ce5c30"
|
||||
"hash": "ccb0315ff52ea4402f53508334a7288fc9f8e77ffd7bce665441ff682384cbf9"
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
CREATE INDEX reports_closed ON reports (closed);
|
||||
@@ -315,9 +315,13 @@ pub async fn filter_enlisted_version_ids(
|
||||
pub async fn is_visible_collection(
|
||||
collection_data: &DBCollection,
|
||||
user_option: &Option<User>,
|
||||
hide_unlisted: bool,
|
||||
) -> Result<bool, ApiError> {
|
||||
let mut authorized = !collection_data.status.is_hidden()
|
||||
&& !collection_data.projects.is_empty();
|
||||
let mut authorized = (if hide_unlisted {
|
||||
collection_data.status.is_searchable()
|
||||
} else {
|
||||
!collection_data.status.is_hidden()
|
||||
}) && !collection_data.projects.is_empty();
|
||||
if let Some(user) = &user_option {
|
||||
if !authorized
|
||||
&& (user.role.is_mod() || user.id == collection_data.user_id.into())
|
||||
@@ -331,12 +335,17 @@ pub async fn is_visible_collection(
|
||||
pub async fn filter_visible_collections(
|
||||
collections: Vec<DBCollection>,
|
||||
user_option: &Option<User>,
|
||||
hide_unlisted: bool,
|
||||
) -> Result<Vec<crate::models::collections::Collection>, ApiError> {
|
||||
let mut return_collections = Vec::new();
|
||||
let mut check_collections = Vec::new();
|
||||
|
||||
for collection in collections {
|
||||
if (!collection.status.is_hidden() && !collection.projects.is_empty())
|
||||
if ((if hide_unlisted {
|
||||
collection.status.is_searchable()
|
||||
} else {
|
||||
!collection.status.is_hidden()
|
||||
}) && !collection.projects.is_empty())
|
||||
|| user_option.as_ref().is_some_and(|x| x.role.is_mod())
|
||||
{
|
||||
return_collections.push(collection.into());
|
||||
|
||||
@@ -92,7 +92,7 @@ impl CollectionStatus {
|
||||
}
|
||||
}
|
||||
|
||||
// Project pages + info cannot be viewed
|
||||
// Collection pages + info cannot be viewed
|
||||
pub fn is_hidden(&self) -> bool {
|
||||
match self {
|
||||
CollectionStatus::Rejected => true,
|
||||
@@ -103,6 +103,11 @@ impl CollectionStatus {
|
||||
}
|
||||
}
|
||||
|
||||
// Collection can be displayed in on user page
|
||||
pub fn is_searchable(&self) -> bool {
|
||||
matches!(self, CollectionStatus::Listed)
|
||||
}
|
||||
|
||||
pub fn is_approved(&self) -> bool {
|
||||
match self {
|
||||
CollectionStatus::Listed => true,
|
||||
|
||||
@@ -276,7 +276,11 @@ pub async fn refund_charge(
|
||||
subscription_interval: charge.subscription_interval,
|
||||
payment_platform: charge.payment_platform,
|
||||
payment_platform_id: id,
|
||||
parent_charge_id: Some(charge.id),
|
||||
parent_charge_id: if refund_amount != 0 {
|
||||
Some(charge.id)
|
||||
} else {
|
||||
None
|
||||
},
|
||||
net,
|
||||
}
|
||||
.upsert(&mut transaction)
|
||||
|
||||
@@ -18,12 +18,14 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
}
|
||||
|
||||
#[derive(Deserialize)]
|
||||
pub struct ResultCount {
|
||||
pub struct ProjectsRequestOptions {
|
||||
#[serde(default = "default_count")]
|
||||
pub count: i16,
|
||||
pub count: u16,
|
||||
#[serde(default)]
|
||||
pub offset: u32,
|
||||
}
|
||||
|
||||
fn default_count() -> i16 {
|
||||
fn default_count() -> u16 {
|
||||
100
|
||||
}
|
||||
|
||||
@@ -31,7 +33,7 @@ pub async fn get_projects(
|
||||
req: HttpRequest,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
count: web::Query<ResultCount>,
|
||||
request_opts: web::Query<ProjectsRequestOptions>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
check_is_moderator_from_headers(
|
||||
@@ -50,10 +52,12 @@ pub async fn get_projects(
|
||||
SELECT id FROM mods
|
||||
WHERE status = $1
|
||||
ORDER BY queued ASC
|
||||
LIMIT $2;
|
||||
OFFSET $3
|
||||
LIMIT $2
|
||||
",
|
||||
ProjectStatus::Processing.as_str(),
|
||||
count.count as i64
|
||||
request_opts.count as i64,
|
||||
request_opts.offset as i64
|
||||
)
|
||||
.fetch(&**pool)
|
||||
.map_ok(|m| database::models::DBProjectId(m.id))
|
||||
|
||||
@@ -15,10 +15,10 @@ pub fn config(cfg: &mut web::ServiceConfig) {
|
||||
#[derive(Deserialize)]
|
||||
pub struct ResultCount {
|
||||
#[serde(default = "default_count")]
|
||||
pub count: i16,
|
||||
pub count: u16,
|
||||
}
|
||||
|
||||
fn default_count() -> i16 {
|
||||
fn default_count() -> u16 {
|
||||
100
|
||||
}
|
||||
|
||||
@@ -34,7 +34,10 @@ pub async fn get_projects(
|
||||
req,
|
||||
pool.clone(),
|
||||
redis.clone(),
|
||||
web::Query(internal::moderation::ResultCount { count: count.count }),
|
||||
web::Query(internal::moderation::ProjectsRequestOptions {
|
||||
count: count.count,
|
||||
offset: 0,
|
||||
}),
|
||||
session_queue,
|
||||
)
|
||||
.await
|
||||
|
||||
@@ -43,12 +43,12 @@ pub async fn report_create(
|
||||
#[derive(Deserialize)]
|
||||
pub struct ReportsRequestOptions {
|
||||
#[serde(default = "default_count")]
|
||||
count: i16,
|
||||
count: u16,
|
||||
#[serde(default = "default_all")]
|
||||
all: bool,
|
||||
}
|
||||
|
||||
fn default_count() -> i16 {
|
||||
fn default_count() -> u16 {
|
||||
100
|
||||
}
|
||||
fn default_all() -> bool {
|
||||
@@ -60,7 +60,7 @@ pub async fn reports(
|
||||
req: HttpRequest,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
count: web::Query<ReportsRequestOptions>,
|
||||
request_opts: web::Query<ReportsRequestOptions>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let response = v3::reports::reports(
|
||||
@@ -68,8 +68,9 @@ pub async fn reports(
|
||||
pool,
|
||||
redis,
|
||||
web::Query(v3::reports::ReportsRequestOptions {
|
||||
count: count.count,
|
||||
all: count.all,
|
||||
count: request_opts.count,
|
||||
offset: 0,
|
||||
all: request_opts.all,
|
||||
}),
|
||||
session_queue,
|
||||
)
|
||||
|
||||
@@ -163,7 +163,8 @@ pub async fn collections_get(
|
||||
.ok();
|
||||
|
||||
let collections =
|
||||
filter_visible_collections(collections_data, &user_option).await?;
|
||||
filter_visible_collections(collections_data, &user_option, false)
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(collections))
|
||||
}
|
||||
@@ -192,7 +193,7 @@ pub async fn collection_get(
|
||||
.ok();
|
||||
|
||||
if let Some(data) = collection_data {
|
||||
if is_visible_collection(&data, &user_option).await? {
|
||||
if is_visible_collection(&data, &user_option, false).await? {
|
||||
return Ok(HttpResponse::Ok().json(Collection::from(data)));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -222,12 +222,14 @@ pub async fn report_create(
|
||||
#[derive(Deserialize)]
|
||||
pub struct ReportsRequestOptions {
|
||||
#[serde(default = "default_count")]
|
||||
pub count: i16,
|
||||
pub count: u16,
|
||||
#[serde(default)]
|
||||
pub offset: u32,
|
||||
#[serde(default = "default_all")]
|
||||
pub all: bool,
|
||||
}
|
||||
|
||||
fn default_count() -> i16 {
|
||||
fn default_count() -> u16 {
|
||||
100
|
||||
}
|
||||
fn default_all() -> bool {
|
||||
@@ -238,7 +240,7 @@ pub async fn reports(
|
||||
req: HttpRequest,
|
||||
pool: web::Data<PgPool>,
|
||||
redis: web::Data<RedisPool>,
|
||||
count: web::Query<ReportsRequestOptions>,
|
||||
request_opts: web::Query<ReportsRequestOptions>,
|
||||
session_queue: web::Data<AuthQueue>,
|
||||
) -> Result<HttpResponse, ApiError> {
|
||||
let user = get_user_from_headers(
|
||||
@@ -253,15 +255,17 @@ pub async fn reports(
|
||||
|
||||
use futures::stream::TryStreamExt;
|
||||
|
||||
let report_ids = if user.role.is_mod() && count.all {
|
||||
let report_ids = if user.role.is_mod() && request_opts.all {
|
||||
sqlx::query!(
|
||||
"
|
||||
SELECT id FROM reports
|
||||
WHERE closed = FALSE
|
||||
ORDER BY created ASC
|
||||
LIMIT $1;
|
||||
OFFSET $2
|
||||
LIMIT $1
|
||||
",
|
||||
count.count as i64
|
||||
request_opts.count as i64,
|
||||
request_opts.offset as i64
|
||||
)
|
||||
.fetch(&**pool)
|
||||
.map_ok(|m| crate::database::models::ids::DBReportId(m.id))
|
||||
@@ -273,10 +277,12 @@ pub async fn reports(
|
||||
SELECT id FROM reports
|
||||
WHERE closed = FALSE AND reporter = $1
|
||||
ORDER BY created ASC
|
||||
LIMIT $2;
|
||||
OFFSET $3
|
||||
LIMIT $2
|
||||
",
|
||||
user.id.0 as i64,
|
||||
count.count as i64
|
||||
request_opts.count as i64,
|
||||
request_opts.offset as i64
|
||||
)
|
||||
.fetch(&**pool)
|
||||
.map_ok(|m| crate::database::models::ids::DBReportId(m.id))
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
use std::{collections::HashMap, sync::Arc};
|
||||
|
||||
use super::{ApiError, oauth_clients::get_user_clients};
|
||||
use crate::file_hosting::FileHostPublicity;
|
||||
use crate::util::img::delete_old_images;
|
||||
use crate::{
|
||||
auth::{filter_visible_projects, get_user_from_headers},
|
||||
auth::{
|
||||
filter_visible_collections, filter_visible_projects,
|
||||
get_user_from_headers,
|
||||
},
|
||||
database::{models::DBUser, redis::RedisPool},
|
||||
file_hosting::FileHost,
|
||||
file_hosting::{FileHost, FileHostPublicity},
|
||||
models::{
|
||||
collections::{Collection, CollectionStatus},
|
||||
notifications::Notification,
|
||||
pats::Scopes,
|
||||
projects::Project,
|
||||
@@ -16,7 +16,7 @@ use crate::{
|
||||
},
|
||||
queue::session::AuthQueue,
|
||||
util::{
|
||||
routes::read_limited_from_payload,
|
||||
img::delete_old_images, routes::read_limited_from_payload,
|
||||
validate::validation_errors_to_string,
|
||||
},
|
||||
};
|
||||
@@ -244,27 +244,19 @@ pub async fn collections_list(
|
||||
let id_option = DBUser::get(&info.into_inner().0, &**pool, &redis).await?;
|
||||
|
||||
if let Some(id) = id_option.map(|x| x.id) {
|
||||
let user_id: UserId = id.into();
|
||||
|
||||
let can_view_private =
|
||||
user.is_some_and(|y| y.role.is_mod() || y.id == user_id);
|
||||
|
||||
let project_data = DBUser::get_collections(id, &**pool).await?;
|
||||
let collection_data = DBUser::get_collections(id, &**pool).await?;
|
||||
|
||||
let response: Vec<_> = crate::database::models::DBCollection::get_many(
|
||||
&project_data,
|
||||
&collection_data,
|
||||
&**pool,
|
||||
&redis,
|
||||
)
|
||||
.await?
|
||||
.into_iter()
|
||||
.filter(|x| {
|
||||
can_view_private || matches!(x.status, CollectionStatus::Listed)
|
||||
})
|
||||
.map(Collection::from)
|
||||
.collect();
|
||||
.await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(response))
|
||||
let collections =
|
||||
filter_visible_collections(response, &user, true).await?;
|
||||
|
||||
Ok(HttpResponse::Ok().json(collections))
|
||||
} else {
|
||||
Err(ApiError::NotFound)
|
||||
}
|
||||
|
||||
@@ -27,6 +27,7 @@ hashlink.workspace = true
|
||||
png.workspace = true
|
||||
bytemuck.workspace = true
|
||||
rgb.workspace = true
|
||||
phf.workspace = true
|
||||
|
||||
chrono = { workspace = true, features = ["serde"] }
|
||||
daedalus.workspace = true
|
||||
|
||||
@@ -5,6 +5,8 @@ use crate::state::attached_world_data::AttachedWorldData;
|
||||
use crate::state::{
|
||||
Profile, ProfileInstallStage, attached_world_data, server_join_log,
|
||||
};
|
||||
use crate::util::protocol_version::OLD_PROTOCOL_VERSIONS;
|
||||
pub use crate::util::protocol_version::ProtocolVersion;
|
||||
pub use crate::util::server_ping::{
|
||||
ServerGameProfile, ServerPlayers, ServerStatus, ServerVersion,
|
||||
};
|
||||
@@ -835,7 +837,7 @@ mod servers_data {
|
||||
|
||||
pub async fn get_profile_protocol_version(
|
||||
profile: &str,
|
||||
) -> Result<Option<i32>> {
|
||||
) -> Result<Option<ProtocolVersion>> {
|
||||
let mut profile = super::profile::get(profile).await?.ok_or_else(|| {
|
||||
ErrorKind::UnmanagedProfileError(format!(
|
||||
"Could not find profile {profile}"
|
||||
@@ -846,7 +848,12 @@ pub async fn get_profile_protocol_version(
|
||||
}
|
||||
|
||||
if let Some(protocol_version) = profile.protocol_version {
|
||||
return Ok(Some(protocol_version));
|
||||
return Ok(Some(ProtocolVersion::modern(protocol_version)));
|
||||
}
|
||||
if let Some(protocol_version) =
|
||||
OLD_PROTOCOL_VERSIONS.get(&profile.game_version)
|
||||
{
|
||||
return Ok(Some(*protocol_version));
|
||||
}
|
||||
|
||||
let minecraft = crate::api::metadata::get_minecraft_versions().await?;
|
||||
@@ -854,7 +861,7 @@ pub async fn get_profile_protocol_version(
|
||||
.versions
|
||||
.iter()
|
||||
.position(|it| it.id == profile.game_version)
|
||||
.ok_or(crate::ErrorKind::LauncherError(format!(
|
||||
.ok_or(ErrorKind::LauncherError(format!(
|
||||
"Invalid game version: {}",
|
||||
profile.game_version
|
||||
)))?;
|
||||
@@ -890,16 +897,19 @@ pub async fn get_profile_protocol_version(
|
||||
profile.protocol_version = version;
|
||||
profile.upsert(&state.pool).await?;
|
||||
}
|
||||
Ok(version)
|
||||
Ok(version.map(ProtocolVersion::modern))
|
||||
}
|
||||
|
||||
pub async fn get_server_status(
|
||||
address: &str,
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<ProtocolVersion>,
|
||||
) -> Result<ServerStatus> {
|
||||
let (original_host, original_port) = parse_server_address(address)?;
|
||||
let (host, port) =
|
||||
resolve_server_address(original_host, original_port).await?;
|
||||
tracing::debug!(
|
||||
"Pinging {address} with protocol version {protocol_version:?}"
|
||||
);
|
||||
server_ping::get_server_status(
|
||||
&(&host as &str, port),
|
||||
(original_host, original_port),
|
||||
|
||||
@@ -422,7 +422,7 @@ pub async fn install_minecraft(
|
||||
|
||||
pub async fn read_protocol_version_from_jar(
|
||||
path: PathBuf,
|
||||
) -> crate::Result<Option<i32>> {
|
||||
) -> crate::Result<Option<u32>> {
|
||||
let zip = async_zip::tokio::read::fs::ZipFileReader::new(path).await?;
|
||||
let Some(entry_index) = zip
|
||||
.file()
|
||||
@@ -435,7 +435,7 @@ pub async fn read_protocol_version_from_jar(
|
||||
|
||||
#[derive(Deserialize, Debug)]
|
||||
struct VersionData {
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<u32>,
|
||||
}
|
||||
|
||||
let mut data = vec![];
|
||||
|
||||
@@ -32,7 +32,7 @@ pub struct Profile {
|
||||
pub icon_path: Option<String>,
|
||||
|
||||
pub game_version: String,
|
||||
pub protocol_version: Option<i32>,
|
||||
pub protocol_version: Option<u32>,
|
||||
pub loader: ModLoader,
|
||||
pub loader_version: Option<String>,
|
||||
|
||||
@@ -320,7 +320,7 @@ impl TryFrom<ProfileQueryResult> for Profile {
|
||||
name: x.name,
|
||||
icon_path: x.icon_path,
|
||||
game_version: x.game_version,
|
||||
protocol_version: x.protocol_version.map(|x| x as i32),
|
||||
protocol_version: x.protocol_version.map(|x| x as u32),
|
||||
loader: ModLoader::from_string(&x.mod_loader),
|
||||
loader_version: x.mod_loader_version,
|
||||
groups: serde_json::from_value(x.groups).unwrap_or_default(),
|
||||
|
||||
@@ -4,4 +4,5 @@ pub mod io;
|
||||
pub mod jre;
|
||||
pub mod platform;
|
||||
pub mod utils; // [AR] Feature
|
||||
pub mod protocol_version;
|
||||
pub mod server_ping;
|
||||
|
||||
478
packages/app-lib/src/util/protocol_version.rs
Normal file
478
packages/app-lib/src/util/protocol_version.rs
Normal file
@@ -0,0 +1,478 @@
|
||||
use phf::phf_map;
|
||||
use serde::{Deserialize, Serialize};
|
||||
|
||||
#[derive(Deserialize, Serialize, Debug, Copy, Clone)]
|
||||
pub struct ProtocolVersion {
|
||||
pub version: u32,
|
||||
pub legacy: bool,
|
||||
}
|
||||
|
||||
impl ProtocolVersion {
|
||||
pub const fn modern(version: u32) -> Self {
|
||||
Self {
|
||||
version,
|
||||
legacy: false,
|
||||
}
|
||||
}
|
||||
|
||||
pub const fn legacy(version: u32) -> Self {
|
||||
Self {
|
||||
version,
|
||||
legacy: true,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The map of protocol versions from before version.json was added. For newer versions, the
|
||||
/// protocol version can just be read from version.json.
|
||||
pub const OLD_PROTOCOL_VERSIONS: phf::Map<&str, ProtocolVersion> = phf_map! {
|
||||
// April fools versions
|
||||
"1.RV-Pre1" => ProtocolVersion::modern(108),
|
||||
"15w14a" => ProtocolVersion::modern(48),
|
||||
"2point0_purple" => ProtocolVersion::legacy(92),
|
||||
"2point0_red" => ProtocolVersion::legacy(91),
|
||||
"2point0_blue" => ProtocolVersion::legacy(90),
|
||||
|
||||
// Normal versions
|
||||
"18w47a" => ProtocolVersion::modern(446),
|
||||
"18w46a" => ProtocolVersion::modern(445),
|
||||
"18w45a" => ProtocolVersion::modern(444),
|
||||
"18w44a" => ProtocolVersion::modern(443),
|
||||
"18w43c" => ProtocolVersion::modern(442),
|
||||
"18w43b" => ProtocolVersion::modern(441),
|
||||
"18w43a" => ProtocolVersion::modern(440),
|
||||
"1.13.2" => ProtocolVersion::modern(404),
|
||||
"1.13.2-pre2" => ProtocolVersion::modern(403),
|
||||
"1.13.2-pre1" => ProtocolVersion::modern(402),
|
||||
"1.13.1" => ProtocolVersion::modern(401),
|
||||
"1.13.1-pre2" => ProtocolVersion::modern(400),
|
||||
"1.13.1-pre1" => ProtocolVersion::modern(399),
|
||||
"18w33a" => ProtocolVersion::modern(398),
|
||||
"18w32a" => ProtocolVersion::modern(397),
|
||||
"18w31a" => ProtocolVersion::modern(396),
|
||||
"18w30b" => ProtocolVersion::modern(395),
|
||||
"18w30a" => ProtocolVersion::modern(394),
|
||||
"1.13" => ProtocolVersion::modern(393),
|
||||
"1.13-pre10" => ProtocolVersion::modern(392),
|
||||
"1.13-pre9" => ProtocolVersion::modern(391),
|
||||
"1.13-pre8" => ProtocolVersion::modern(390),
|
||||
"1.13-pre7" => ProtocolVersion::modern(389),
|
||||
"1.13-pre6" => ProtocolVersion::modern(388),
|
||||
"1.13-pre5" => ProtocolVersion::modern(387),
|
||||
"1.13-pre4" => ProtocolVersion::modern(386),
|
||||
"1.13-pre3" => ProtocolVersion::modern(385),
|
||||
"1.13-pre2" => ProtocolVersion::modern(384),
|
||||
"1.13-pre1" => ProtocolVersion::modern(383),
|
||||
"18w22c" => ProtocolVersion::modern(382),
|
||||
"18w22b" => ProtocolVersion::modern(381),
|
||||
"18w22a" => ProtocolVersion::modern(380),
|
||||
"18w21b" => ProtocolVersion::modern(379),
|
||||
"18w21a" => ProtocolVersion::modern(378),
|
||||
"18w20c" => ProtocolVersion::modern(377),
|
||||
"18w20b" => ProtocolVersion::modern(376),
|
||||
"18w20a" => ProtocolVersion::modern(375),
|
||||
"18w19b" => ProtocolVersion::modern(374),
|
||||
"18w19a" => ProtocolVersion::modern(373),
|
||||
"18w16a" => ProtocolVersion::modern(372),
|
||||
"18w15a" => ProtocolVersion::modern(371),
|
||||
"18w14b" => ProtocolVersion::modern(370),
|
||||
"18w14a" => ProtocolVersion::modern(369),
|
||||
"18w11a" => ProtocolVersion::modern(368),
|
||||
"18w10d" => ProtocolVersion::modern(367),
|
||||
"18w10c" => ProtocolVersion::modern(366),
|
||||
"18w10b" => ProtocolVersion::modern(365),
|
||||
"18w10a" => ProtocolVersion::modern(364),
|
||||
"18w09a" => ProtocolVersion::modern(363),
|
||||
"18w08b" => ProtocolVersion::modern(362),
|
||||
"18w08a" => ProtocolVersion::modern(361),
|
||||
"18w07c" => ProtocolVersion::modern(360),
|
||||
"18w07b" => ProtocolVersion::modern(359),
|
||||
"18w07a" => ProtocolVersion::modern(358),
|
||||
"18w06a" => ProtocolVersion::modern(357),
|
||||
"18w05a" => ProtocolVersion::modern(356),
|
||||
"18w03b" => ProtocolVersion::modern(355),
|
||||
"18w03a" => ProtocolVersion::modern(354),
|
||||
"18w02a" => ProtocolVersion::modern(353),
|
||||
"18w01a" => ProtocolVersion::modern(352),
|
||||
"17w50a" => ProtocolVersion::modern(351),
|
||||
"17w49b" => ProtocolVersion::modern(350),
|
||||
"17w49a" => ProtocolVersion::modern(349),
|
||||
"17w48a" => ProtocolVersion::modern(348),
|
||||
"17w47b" => ProtocolVersion::modern(347),
|
||||
"17w47a" => ProtocolVersion::modern(346),
|
||||
"17w46a" => ProtocolVersion::modern(345),
|
||||
"17w45b" => ProtocolVersion::modern(344),
|
||||
"17w45a" => ProtocolVersion::modern(343),
|
||||
"17w43b" => ProtocolVersion::modern(342),
|
||||
"17w43a" => ProtocolVersion::modern(341),
|
||||
"1.12.2" => ProtocolVersion::modern(340),
|
||||
"1.21.2-pre2" => ProtocolVersion::modern(339),
|
||||
"1.21.2-pre1" => ProtocolVersion::modern(339),
|
||||
"1.12.1" => ProtocolVersion::modern(338),
|
||||
"1.12.1-pre1" => ProtocolVersion::modern(337),
|
||||
"17w31a" => ProtocolVersion::modern(336),
|
||||
"1.12" => ProtocolVersion::modern(335),
|
||||
"1.12-pre7" => ProtocolVersion::modern(334),
|
||||
"1.12-pre6" => ProtocolVersion::modern(333),
|
||||
"1.12-pre5" => ProtocolVersion::modern(332),
|
||||
"1.12-pre4" => ProtocolVersion::modern(331),
|
||||
"1.12-pre3" => ProtocolVersion::modern(330),
|
||||
"1.12-pre2" => ProtocolVersion::modern(329),
|
||||
"1.12-pre1" => ProtocolVersion::modern(328),
|
||||
"17w18b" => ProtocolVersion::modern(327),
|
||||
"17w18a" => ProtocolVersion::modern(326),
|
||||
"17w17b" => ProtocolVersion::modern(325),
|
||||
"17w17a" => ProtocolVersion::modern(324),
|
||||
"17w16b" => ProtocolVersion::modern(323),
|
||||
"17w16a" => ProtocolVersion::modern(322),
|
||||
"17w15a" => ProtocolVersion::modern(321),
|
||||
"17w14a" => ProtocolVersion::modern(320),
|
||||
"17w13b" => ProtocolVersion::modern(319),
|
||||
"17w13a" => ProtocolVersion::modern(318),
|
||||
"17w06a" => ProtocolVersion::modern(317),
|
||||
"1.11.2" => ProtocolVersion::modern(316),
|
||||
"1.11.1" => ProtocolVersion::modern(316),
|
||||
"16w50a" => ProtocolVersion::modern(316),
|
||||
"1.11" => ProtocolVersion::modern(315),
|
||||
"1.11-pre1" => ProtocolVersion::modern(314),
|
||||
"16w44a" => ProtocolVersion::modern(313),
|
||||
"16w43a" => ProtocolVersion::modern(313),
|
||||
"16w42a" => ProtocolVersion::modern(312),
|
||||
"16w41a" => ProtocolVersion::modern(311),
|
||||
"16w40a" => ProtocolVersion::modern(310),
|
||||
"16w39c" => ProtocolVersion::modern(309),
|
||||
"16w39b" => ProtocolVersion::modern(308),
|
||||
"16w39a" => ProtocolVersion::modern(307),
|
||||
"16w38a" => ProtocolVersion::modern(306),
|
||||
"16w36a" => ProtocolVersion::modern(305),
|
||||
"16w35a" => ProtocolVersion::modern(304),
|
||||
"16w33a" => ProtocolVersion::modern(303),
|
||||
"16w32b" => ProtocolVersion::modern(302),
|
||||
"16w32a" => ProtocolVersion::modern(301),
|
||||
"1.10.2" => ProtocolVersion::modern(210),
|
||||
"1.10.1" => ProtocolVersion::modern(210),
|
||||
"1.10" => ProtocolVersion::modern(210),
|
||||
"1.10-pre2" => ProtocolVersion::modern(205),
|
||||
"1.10-pre1" => ProtocolVersion::modern(204),
|
||||
"16w21b" => ProtocolVersion::modern(203),
|
||||
"16w21a" => ProtocolVersion::modern(202),
|
||||
"16w20a" => ProtocolVersion::modern(201),
|
||||
"1.9.4" => ProtocolVersion::modern(110),
|
||||
"1.9.3" => ProtocolVersion::modern(110),
|
||||
"1.9.3-pre3" => ProtocolVersion::modern(110),
|
||||
"1.9.3-pre2" => ProtocolVersion::modern(110),
|
||||
"1.9.3-pre1" => ProtocolVersion::modern(109),
|
||||
"16w15b" => ProtocolVersion::modern(109),
|
||||
"16w15a" => ProtocolVersion::modern(109),
|
||||
"16w14a" => ProtocolVersion::modern(109),
|
||||
"1.9.2" => ProtocolVersion::modern(109),
|
||||
"1.9.1" => ProtocolVersion::modern(108),
|
||||
"1.9.1-pre3" => ProtocolVersion::modern(108),
|
||||
"1.9.1-pre2" => ProtocolVersion::modern(108),
|
||||
"1.9.1-pre1" => ProtocolVersion::modern(107),
|
||||
"1.9" => ProtocolVersion::modern(107),
|
||||
"1.9-pre4" => ProtocolVersion::modern(106),
|
||||
"1.9-pre3" => ProtocolVersion::modern(105),
|
||||
"1.9-pre2" => ProtocolVersion::modern(104),
|
||||
"1.9-pre1" => ProtocolVersion::modern(103),
|
||||
"16w07b" => ProtocolVersion::modern(102),
|
||||
"16w07a" => ProtocolVersion::modern(101),
|
||||
"16w06a" => ProtocolVersion::modern(100),
|
||||
"16w05b" => ProtocolVersion::modern(99),
|
||||
"16w05a" => ProtocolVersion::modern(98),
|
||||
"16w04a" => ProtocolVersion::modern(97),
|
||||
"16w03a" => ProtocolVersion::modern(96),
|
||||
"16w02a" => ProtocolVersion::modern(95),
|
||||
"15w51b" => ProtocolVersion::modern(94),
|
||||
"15w51a" => ProtocolVersion::modern(93),
|
||||
"15w50a" => ProtocolVersion::modern(92),
|
||||
"15w49b" => ProtocolVersion::modern(91),
|
||||
"15w49a" => ProtocolVersion::modern(90),
|
||||
"15w47c" => ProtocolVersion::modern(89),
|
||||
"15w47b" => ProtocolVersion::modern(88),
|
||||
"15w47a" => ProtocolVersion::modern(87),
|
||||
"15w46a" => ProtocolVersion::modern(86),
|
||||
"15w45a" => ProtocolVersion::modern(85),
|
||||
"15w44b" => ProtocolVersion::modern(84),
|
||||
"15w44a" => ProtocolVersion::modern(83),
|
||||
"15w43c" => ProtocolVersion::modern(82),
|
||||
"15w43b" => ProtocolVersion::modern(81),
|
||||
"15w43a" => ProtocolVersion::modern(80),
|
||||
"15w42a" => ProtocolVersion::modern(79),
|
||||
"15w41b" => ProtocolVersion::modern(78),
|
||||
"15w41a" => ProtocolVersion::modern(77),
|
||||
"15w40b" => ProtocolVersion::modern(76),
|
||||
"15w40a" => ProtocolVersion::modern(75),
|
||||
"15w39c" => ProtocolVersion::modern(74),
|
||||
"15w39b" => ProtocolVersion::modern(74),
|
||||
"15w39a" => ProtocolVersion::modern(74),
|
||||
"15w38b" => ProtocolVersion::modern(73),
|
||||
"15w38a" => ProtocolVersion::modern(72),
|
||||
"15w37a" => ProtocolVersion::modern(71),
|
||||
"15w36d" => ProtocolVersion::modern(70),
|
||||
"15w36c" => ProtocolVersion::modern(69),
|
||||
"15w36b" => ProtocolVersion::modern(68),
|
||||
"15w36a" => ProtocolVersion::modern(67),
|
||||
"15w35e" => ProtocolVersion::modern(66),
|
||||
"15w35d" => ProtocolVersion::modern(65),
|
||||
"15w35c" => ProtocolVersion::modern(64),
|
||||
"15w35b" => ProtocolVersion::modern(63),
|
||||
"15w35a" => ProtocolVersion::modern(62),
|
||||
"15w34d" => ProtocolVersion::modern(61),
|
||||
"15w34c" => ProtocolVersion::modern(60),
|
||||
"15w34b" => ProtocolVersion::modern(59),
|
||||
"15w34a" => ProtocolVersion::modern(58),
|
||||
"15w33c" => ProtocolVersion::modern(57),
|
||||
"15w33b" => ProtocolVersion::modern(56),
|
||||
"15w33a" => ProtocolVersion::modern(55),
|
||||
"15w32c" => ProtocolVersion::modern(54),
|
||||
"15w32b" => ProtocolVersion::modern(53),
|
||||
"15w32a" => ProtocolVersion::modern(52),
|
||||
"15w31c" => ProtocolVersion::modern(51),
|
||||
"15w31b" => ProtocolVersion::modern(50),
|
||||
"15w31a" => ProtocolVersion::modern(49),
|
||||
"1.8.9" => ProtocolVersion::modern(47),
|
||||
"1.8.8" => ProtocolVersion::modern(47),
|
||||
"1.8.7" => ProtocolVersion::modern(47),
|
||||
"1.8.6" => ProtocolVersion::modern(47),
|
||||
"1.8.5" => ProtocolVersion::modern(47),
|
||||
"1.8.4" => ProtocolVersion::modern(47),
|
||||
"1.8.3" => ProtocolVersion::modern(47),
|
||||
"1.8.2" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre7" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre6" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre5" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre4" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre3" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre2" => ProtocolVersion::modern(47),
|
||||
"1.8.2-pre1" => ProtocolVersion::modern(47),
|
||||
"1.8.1" => ProtocolVersion::modern(47),
|
||||
"1.8.1-pre5" => ProtocolVersion::modern(47),
|
||||
"1.8.1-pre4" => ProtocolVersion::modern(47),
|
||||
"1.8.1-pre3" => ProtocolVersion::modern(47),
|
||||
"1.8.1-pre2" => ProtocolVersion::modern(47),
|
||||
"1.8.1-pre1" => ProtocolVersion::modern(47),
|
||||
"1.8" => ProtocolVersion::modern(47),
|
||||
"1.8-pre3" => ProtocolVersion::modern(46),
|
||||
"1.8-pre2" => ProtocolVersion::modern(45),
|
||||
"1.8-pre1" => ProtocolVersion::modern(44),
|
||||
"14w34d" => ProtocolVersion::modern(43),
|
||||
"14w34c" => ProtocolVersion::modern(42),
|
||||
"14w34b" => ProtocolVersion::modern(41),
|
||||
"14w34a" => ProtocolVersion::modern(40),
|
||||
"14w33c" => ProtocolVersion::modern(39),
|
||||
"14w33b" => ProtocolVersion::modern(38),
|
||||
"14w33a" => ProtocolVersion::modern(37),
|
||||
"14w32d" => ProtocolVersion::modern(36),
|
||||
"14w32c" => ProtocolVersion::modern(35),
|
||||
"14w32b" => ProtocolVersion::modern(34),
|
||||
"14w32a" => ProtocolVersion::modern(33),
|
||||
"14w31a" => ProtocolVersion::modern(32),
|
||||
"14w30c" => ProtocolVersion::modern(31),
|
||||
"14w30b" => ProtocolVersion::modern(30),
|
||||
"14w30a" => ProtocolVersion::modern(30),
|
||||
"14w29b" => ProtocolVersion::modern(29),
|
||||
"14w29a" => ProtocolVersion::modern(29),
|
||||
"14w28b" => ProtocolVersion::modern(28),
|
||||
"14w28a" => ProtocolVersion::modern(27),
|
||||
"14w27b" => ProtocolVersion::modern(26),
|
||||
"14w27a" => ProtocolVersion::modern(26),
|
||||
"14w26c" => ProtocolVersion::modern(25),
|
||||
"14w26b" => ProtocolVersion::modern(24),
|
||||
"14w26a" => ProtocolVersion::modern(23),
|
||||
"14w25b" => ProtocolVersion::modern(22),
|
||||
"14w25a" => ProtocolVersion::modern(21),
|
||||
"14w21b" => ProtocolVersion::modern(20),
|
||||
"14w21a" => ProtocolVersion::modern(19),
|
||||
"14w20b" => ProtocolVersion::modern(18),
|
||||
"14w20a" => ProtocolVersion::modern(18),
|
||||
"14w19a" => ProtocolVersion::modern(17),
|
||||
"14w18b" => ProtocolVersion::modern(16),
|
||||
"14w18a" => ProtocolVersion::modern(16),
|
||||
"14w17a" => ProtocolVersion::modern(15),
|
||||
"14w11b" => ProtocolVersion::modern(14),
|
||||
"14w11a" => ProtocolVersion::modern(14),
|
||||
"14w10c" => ProtocolVersion::modern(13),
|
||||
"14w10b" => ProtocolVersion::modern(13),
|
||||
"14w10a" => ProtocolVersion::modern(13),
|
||||
"14w08a" => ProtocolVersion::modern(12),
|
||||
"14w07a" => ProtocolVersion::modern(11),
|
||||
"14w06b" => ProtocolVersion::modern(10),
|
||||
"14w06a" => ProtocolVersion::modern(10),
|
||||
"14w05b" => ProtocolVersion::modern(9),
|
||||
"14w05a" => ProtocolVersion::modern(9),
|
||||
"14w04b" => ProtocolVersion::modern(8),
|
||||
"14w04a" => ProtocolVersion::modern(7),
|
||||
"14w03b" => ProtocolVersion::modern(6),
|
||||
"14w03a" => ProtocolVersion::modern(6),
|
||||
"14w02c" => ProtocolVersion::modern(5),
|
||||
"14w02b" => ProtocolVersion::modern(5),
|
||||
"14w02a" => ProtocolVersion::modern(5),
|
||||
"1.7.10" => ProtocolVersion::modern(5),
|
||||
"1.7.10-pre4" => ProtocolVersion::modern(5),
|
||||
"1.7.10-pre3" => ProtocolVersion::modern(5),
|
||||
"1.7.10-pre2" => ProtocolVersion::modern(5),
|
||||
"1.7.10-pre1" => ProtocolVersion::modern(5),
|
||||
"1.7.9" => ProtocolVersion::modern(5),
|
||||
"1.7.8" => ProtocolVersion::modern(5),
|
||||
"1.7.7" => ProtocolVersion::modern(5),
|
||||
"1.7.6" => ProtocolVersion::modern(5),
|
||||
"1.7.6-pre2" => ProtocolVersion::modern(5),
|
||||
"1.7.6-pre1" => ProtocolVersion::modern(5),
|
||||
"1.7.5" => ProtocolVersion::modern(4),
|
||||
"1.7.4" => ProtocolVersion::modern(4),
|
||||
"1.7.3" => ProtocolVersion::modern(4),
|
||||
"13w49a" => ProtocolVersion::modern(4),
|
||||
"13w48b" => ProtocolVersion::modern(4),
|
||||
"13w48a" => ProtocolVersion::modern(4),
|
||||
"13w47e" => ProtocolVersion::modern(4),
|
||||
"13w47d" => ProtocolVersion::modern(4),
|
||||
"13w47c" => ProtocolVersion::modern(4),
|
||||
"13w47b" => ProtocolVersion::modern(4),
|
||||
"13w47a" => ProtocolVersion::modern(4),
|
||||
"1.7.2" => ProtocolVersion::modern(4),
|
||||
"1.7.1" => ProtocolVersion::modern(3),
|
||||
"1.7" => ProtocolVersion::modern(3),
|
||||
"13w43a" => ProtocolVersion::modern(2),
|
||||
"13w42b" => ProtocolVersion::modern(1),
|
||||
"13w42a" => ProtocolVersion::modern(1),
|
||||
"13w41b" => ProtocolVersion::modern(0),
|
||||
"13w41a" => ProtocolVersion::modern(0),
|
||||
"13w39b" => ProtocolVersion::legacy(80),
|
||||
"13w39a" => ProtocolVersion::legacy(80),
|
||||
"13w38c" => ProtocolVersion::legacy(79),
|
||||
"13w38b" => ProtocolVersion::legacy(79),
|
||||
"13w38a" => ProtocolVersion::legacy(79),
|
||||
"1.6.4" => ProtocolVersion::legacy(78),
|
||||
"1.6.3" => ProtocolVersion::legacy(77),
|
||||
"13w37b" => ProtocolVersion::legacy(76),
|
||||
"13w37a" => ProtocolVersion::legacy(76),
|
||||
"13w36b" => ProtocolVersion::legacy(75),
|
||||
"13w36a" => ProtocolVersion::legacy(75),
|
||||
"1.6.2" => ProtocolVersion::legacy(74),
|
||||
"1.6.1" => ProtocolVersion::legacy(73),
|
||||
"1.6" => ProtocolVersion::legacy(72),
|
||||
"13w26a" => ProtocolVersion::legacy(72),
|
||||
"13w25c" => ProtocolVersion::legacy(71),
|
||||
"13w25b" => ProtocolVersion::legacy(71),
|
||||
"13w25a" => ProtocolVersion::legacy(71),
|
||||
"13w24b" => ProtocolVersion::legacy(70),
|
||||
"13w24a" => ProtocolVersion::legacy(69),
|
||||
"13w23b" => ProtocolVersion::legacy(68),
|
||||
"13w23a" => ProtocolVersion::legacy(67),
|
||||
"13w22a" => ProtocolVersion::legacy(67),
|
||||
"13w21b" => ProtocolVersion::legacy(67),
|
||||
"13w21a" => ProtocolVersion::legacy(67),
|
||||
"13w19a" => ProtocolVersion::legacy(66),
|
||||
"13w18c" => ProtocolVersion::legacy(65),
|
||||
"13w18b" => ProtocolVersion::legacy(65),
|
||||
"13w18a" => ProtocolVersion::legacy(65),
|
||||
"13w17a" => ProtocolVersion::legacy(64),
|
||||
"13w16b" => ProtocolVersion::legacy(63),
|
||||
"13w16a" => ProtocolVersion::legacy(62),
|
||||
"1.5.2" => ProtocolVersion::legacy(61),
|
||||
"1.5.1" => ProtocolVersion::legacy(60),
|
||||
"13w12~" => ProtocolVersion::legacy(60),
|
||||
"13w11a" => ProtocolVersion::legacy(60),
|
||||
"1.5" => ProtocolVersion::legacy(60),
|
||||
"13w10b" => ProtocolVersion::legacy(60),
|
||||
"13w10a" => ProtocolVersion::legacy(60),
|
||||
"13w09c" => ProtocolVersion::legacy(60),
|
||||
"13w09b" => ProtocolVersion::legacy(59),
|
||||
"13w09a" => ProtocolVersion::legacy(59),
|
||||
"13w07a" => ProtocolVersion::legacy(58),
|
||||
"13w06a" => ProtocolVersion::legacy(58),
|
||||
"13w05b" => ProtocolVersion::legacy(56),
|
||||
"13w05a" => ProtocolVersion::legacy(56),
|
||||
"13w04a" => ProtocolVersion::legacy(55),
|
||||
"13w03a" => ProtocolVersion::legacy(54),
|
||||
"13w02b" => ProtocolVersion::legacy(53),
|
||||
"13w02a" => ProtocolVersion::legacy(53),
|
||||
"13w01b" => ProtocolVersion::legacy(52),
|
||||
"13w01a" => ProtocolVersion::legacy(52),
|
||||
"1.4.7" => ProtocolVersion::legacy(51),
|
||||
"1.4.6" => ProtocolVersion::legacy(51),
|
||||
"12w50b" => ProtocolVersion::legacy(51),
|
||||
"12w50a" => ProtocolVersion::legacy(51),
|
||||
"12w49a" => ProtocolVersion::legacy(50),
|
||||
"1.4.5" => ProtocolVersion::legacy(49),
|
||||
"1.4.4" => ProtocolVersion::legacy(49),
|
||||
"1.4.3" => ProtocolVersion::legacy(48),
|
||||
"1.4.2" => ProtocolVersion::legacy(47),
|
||||
"1.4.1" => ProtocolVersion::legacy(47),
|
||||
"1.4" => ProtocolVersion::legacy(47),
|
||||
"12w42b" => ProtocolVersion::legacy(47),
|
||||
"12w42a" => ProtocolVersion::legacy(46),
|
||||
"12w41b" => ProtocolVersion::legacy(46),
|
||||
"12w41a" => ProtocolVersion::legacy(46),
|
||||
"12w40b" => ProtocolVersion::legacy(45),
|
||||
"12w40a" => ProtocolVersion::legacy(44),
|
||||
"12w39b" => ProtocolVersion::legacy(43),
|
||||
"12w39a" => ProtocolVersion::legacy(43),
|
||||
"12w38b" => ProtocolVersion::legacy(43),
|
||||
"12w38a" => ProtocolVersion::legacy(43),
|
||||
"12w37a" => ProtocolVersion::legacy(42),
|
||||
"12w36a" => ProtocolVersion::legacy(42),
|
||||
"12w34b" => ProtocolVersion::legacy(42),
|
||||
"12w34a" => ProtocolVersion::legacy(41),
|
||||
"12w32a" => ProtocolVersion::legacy(40),
|
||||
"1.3.2" => ProtocolVersion::legacy(39),
|
||||
"1.3.1" => ProtocolVersion::legacy(39),
|
||||
"1.3" => ProtocolVersion::legacy(39),
|
||||
"12w30e" => ProtocolVersion::legacy(39),
|
||||
"12w30d" => ProtocolVersion::legacy(39),
|
||||
"12w30c" => ProtocolVersion::legacy(39),
|
||||
"12w30b" => ProtocolVersion::legacy(38),
|
||||
"12w30a" => ProtocolVersion::legacy(38),
|
||||
"12w27a" => ProtocolVersion::legacy(38),
|
||||
"12w26a" => ProtocolVersion::legacy(37),
|
||||
"12w25a" => ProtocolVersion::legacy(37),
|
||||
"12w24a" => ProtocolVersion::legacy(36),
|
||||
"12w23b" => ProtocolVersion::legacy(35),
|
||||
"12w23a" => ProtocolVersion::legacy(35),
|
||||
"12w22a" => ProtocolVersion::legacy(34),
|
||||
"12w21b" => ProtocolVersion::legacy(33),
|
||||
"12w21a" => ProtocolVersion::legacy(33),
|
||||
"12w19a" => ProtocolVersion::legacy(32),
|
||||
"12w18a" => ProtocolVersion::legacy(32),
|
||||
"12w17a" => ProtocolVersion::legacy(31),
|
||||
"12w16a" => ProtocolVersion::legacy(30),
|
||||
"12w15a" => ProtocolVersion::legacy(29),
|
||||
"1.2.5" => ProtocolVersion::legacy(29),
|
||||
"1.2.4" => ProtocolVersion::legacy(29),
|
||||
"1.2.3" => ProtocolVersion::legacy(28),
|
||||
"1.2.2" => ProtocolVersion::legacy(28),
|
||||
"1.2.1" => ProtocolVersion::legacy(28),
|
||||
"1.2" => ProtocolVersion::legacy(28),
|
||||
"12w08a" => ProtocolVersion::legacy(28),
|
||||
"12w07b" => ProtocolVersion::legacy(27),
|
||||
"12w07a" => ProtocolVersion::legacy(27),
|
||||
"12w06a" => ProtocolVersion::legacy(25),
|
||||
"12w05b" => ProtocolVersion::legacy(24),
|
||||
"12w05a" => ProtocolVersion::legacy(24),
|
||||
"12w04a" => ProtocolVersion::legacy(24),
|
||||
"12w03a" => ProtocolVersion::legacy(24),
|
||||
"1.1" => ProtocolVersion::legacy(23),
|
||||
"12w01a" => ProtocolVersion::legacy(23),
|
||||
"11w50a" => ProtocolVersion::legacy(22),
|
||||
"11w49a" => ProtocolVersion::legacy(22),
|
||||
"11w48a" => ProtocolVersion::legacy(22),
|
||||
"11w47a" => ProtocolVersion::legacy(22),
|
||||
"1.0.1" => ProtocolVersion::legacy(22),
|
||||
"1.0.0" => ProtocolVersion::legacy(22),
|
||||
"1.0.0-rc2-1" => ProtocolVersion::legacy(22),
|
||||
"1.0.0-rc2-2" => ProtocolVersion::legacy(22),
|
||||
"1.0.0-rc2-3" => ProtocolVersion::legacy(22),
|
||||
"1.0.0-rc1" => ProtocolVersion::legacy(22),
|
||||
"b1.9-pre6" => ProtocolVersion::legacy(22),
|
||||
"b1.9-pre5" => ProtocolVersion::legacy(21),
|
||||
"b1.9-pre4" => ProtocolVersion::legacy(20),
|
||||
"b1.9-pre3" => ProtocolVersion::legacy(19),
|
||||
"b1.9-pre2" => ProtocolVersion::legacy(19),
|
||||
"b1.9-pre1" => ProtocolVersion::legacy(18),
|
||||
"b1.8.1" => ProtocolVersion::legacy(17),
|
||||
"b1.8" => ProtocolVersion::legacy(17),
|
||||
"b1.8-pre2" => ProtocolVersion::legacy(16),
|
||||
"b1.8-pre1-1" => ProtocolVersion::legacy(15),
|
||||
"b1.8-pre1-2" => ProtocolVersion::legacy(15),
|
||||
};
|
||||
@@ -1,5 +1,6 @@
|
||||
use crate::ErrorKind;
|
||||
use crate::error::Result;
|
||||
use crate::util::protocol_version::ProtocolVersion;
|
||||
use serde::{Deserialize, Serialize};
|
||||
use serde_json::value::RawValue;
|
||||
use std::time::Duration;
|
||||
@@ -42,16 +43,23 @@ pub struct ServerGameProfile {
|
||||
#[derive(Deserialize, Serialize, Debug, Clone)]
|
||||
pub struct ServerVersion {
|
||||
pub name: String,
|
||||
pub protocol: i32,
|
||||
pub protocol: u32,
|
||||
#[serde(skip_deserializing)]
|
||||
pub legacy: bool,
|
||||
}
|
||||
|
||||
pub async fn get_server_status(
|
||||
address: &impl ToSocketAddrs,
|
||||
original_address: (&str, u16),
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<ProtocolVersion>,
|
||||
) -> Result<ServerStatus> {
|
||||
select! {
|
||||
res = modern::status(address, original_address, protocol_version) => res,
|
||||
res = async {
|
||||
match protocol_version {
|
||||
Some(ProtocolVersion { legacy: true, version }) => legacy::status(address, original_address, Some(version as u8)).await,
|
||||
protocol => modern::status(address, original_address, protocol.map(|v| v.version)).await,
|
||||
}
|
||||
} => res,
|
||||
_ = tokio::time::sleep(Duration::from_secs(30)) => Err(ErrorKind::OtherError(
|
||||
format!("Ping of {}:{} timed out", original_address.0, original_address.1)
|
||||
).into())
|
||||
@@ -68,7 +76,7 @@ mod modern {
|
||||
pub async fn status(
|
||||
address: &impl ToSocketAddrs,
|
||||
original_address: (&str, u16),
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<u32>,
|
||||
) -> crate::Result<ServerStatus> {
|
||||
let mut stream = TcpStream::connect(address).await?;
|
||||
handshake(&mut stream, original_address, protocol_version).await?;
|
||||
@@ -80,10 +88,10 @@ mod modern {
|
||||
async fn handshake(
|
||||
stream: &mut TcpStream,
|
||||
original_address: (&str, u16),
|
||||
protocol_version: Option<i32>,
|
||||
protocol_version: Option<u32>,
|
||||
) -> crate::Result<()> {
|
||||
let (host, port) = original_address;
|
||||
let protocol_version = protocol_version.unwrap_or(-1);
|
||||
let protocol_version = protocol_version.map_or(-1, |x| x as i32);
|
||||
|
||||
const PACKET_ID: i32 = 0;
|
||||
const NEXT_STATE: i32 = 1;
|
||||
@@ -221,3 +229,95 @@ mod modern {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mod legacy {
|
||||
use super::ServerStatus;
|
||||
use crate::worlds::{ServerPlayers, ServerVersion};
|
||||
use crate::{Error, ErrorKind};
|
||||
use serde_json::value::to_raw_value;
|
||||
use tokio::io::{AsyncReadExt, AsyncWriteExt};
|
||||
use tokio::net::{TcpStream, ToSocketAddrs};
|
||||
|
||||
pub async fn status(
|
||||
address: &impl ToSocketAddrs,
|
||||
original_address: (&str, u16),
|
||||
protocol_version: Option<u8>,
|
||||
) -> crate::Result<ServerStatus> {
|
||||
let protocol_version = protocol_version.unwrap_or(74);
|
||||
|
||||
let mut packet = vec![0xfe];
|
||||
if protocol_version >= 47 {
|
||||
packet.push(0x01);
|
||||
}
|
||||
if protocol_version >= 73 {
|
||||
packet.push(0xfa);
|
||||
write_legacy(&mut packet, "MC|PingHost");
|
||||
|
||||
let (host, port) = original_address;
|
||||
let len_index = packet.len();
|
||||
packet.push(protocol_version);
|
||||
write_legacy(&mut packet, host);
|
||||
packet.extend_from_slice(&(port as u32).to_be_bytes());
|
||||
packet.splice(
|
||||
len_index..len_index,
|
||||
((packet.len() - len_index) as u16).to_be_bytes(),
|
||||
);
|
||||
}
|
||||
|
||||
let mut stream = TcpStream::connect(address).await?;
|
||||
stream.write_all(&packet).await?;
|
||||
stream.flush().await?;
|
||||
|
||||
let packet_id = stream.read_u8().await?;
|
||||
if packet_id != 0xff {
|
||||
return Err(Error::from(ErrorKind::InputError(
|
||||
"Unexpected legacy status response".to_string(),
|
||||
)));
|
||||
}
|
||||
|
||||
let data_length = stream.read_u16().await?;
|
||||
let mut data = vec![0u8; data_length as usize * 2];
|
||||
stream.read_exact(&mut data).await?;
|
||||
|
||||
drop(stream);
|
||||
|
||||
let data = String::from_utf16_lossy(
|
||||
&data
|
||||
.chunks_exact(2)
|
||||
.map(|a| u16::from_be_bytes([a[0], a[1]]))
|
||||
.collect::<Vec<u16>>(),
|
||||
);
|
||||
let mut ancient_server = false;
|
||||
let mut parts = data.split('\0');
|
||||
if parts.next() != Some("§1") {
|
||||
ancient_server = true;
|
||||
parts = data.split('§');
|
||||
}
|
||||
|
||||
Ok(ServerStatus {
|
||||
version: (!ancient_server).then(|| ServerVersion {
|
||||
protocol: parts
|
||||
.next()
|
||||
.and_then(|x| x.parse().ok())
|
||||
.unwrap_or(0),
|
||||
name: parts.next().unwrap_or("").to_owned(),
|
||||
legacy: true,
|
||||
}),
|
||||
description: parts.next().and_then(|x| to_raw_value(x).ok()),
|
||||
players: Some(ServerPlayers {
|
||||
online: parts.next().and_then(|x| x.parse().ok()).unwrap_or(-1),
|
||||
max: parts.next().and_then(|x| x.parse().ok()).unwrap_or(-1),
|
||||
sample: vec![],
|
||||
}),
|
||||
favicon: None,
|
||||
enforces_secure_chat: false,
|
||||
ping: None,
|
||||
})
|
||||
}
|
||||
|
||||
fn write_legacy(out: &mut Vec<u8>, text: &str) {
|
||||
let encoded = text.encode_utf16().collect::<Vec<_>>();
|
||||
out.extend_from_slice(&(encoded.len() as u16).to_be_bytes());
|
||||
out.extend(encoded.into_iter().flat_map(u16::to_be_bytes));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
**Client:** `%PROJECT_CLIENT_SIDE%` \
|
||||
**Server:** `%PROJECT_SERVER_SIDE%`
|
||||
@@ -1,3 +1,5 @@
|
||||
## Misuse of Slug
|
||||
## Misuse of custom URL
|
||||
|
||||
Per section 5.2 of %RULES% must accurately represent your project.
|
||||
We ask that you ensure your project's %PROJECT_SLUG_FLINK% accurately represents your project.
|
||||
Your current slug of `%PROJECT_SLUG%` may not accurately match your project's Name or contain excess information.
|
||||
A mismatched URL may make it more difficult for users to find your content. Abbreviations or similar are fine to use if applicable. If your preferred URL is not available, and you cannot find a matching public project, let us know in this moderation thread when you resubmit your project, and our moderation team may be able to free it up for your project.
|
||||
|
||||
@@ -3,6 +3,6 @@
|
||||
## Private Use
|
||||
|
||||
Under normal circumstances, your project would be rejected due to the issues listed above.
|
||||
However, since your project is not intended for for public use, these requirements will be waived and your project will be unlisted. This means it will remain accessible through a direct link without appearing in public search results, allowing you to share it privately.
|
||||
However, since your project is not intended for public use, these requirements will be waived and your project will be unlisted. This means it will remain accessible through a direct link without appearing in public search results, allowing you to share it privately.
|
||||
If you're okay with this, or submitted your project to be unlisted already, than no further action is necessary.
|
||||
If you would like to publish your project publicly, please address all moderation concerns before resubmitting this project.
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
## Unsupported Project
|
||||
|
||||
Unfortunately, Modrinth does not currently support the upload of %INVALID_TYPE%.
|
||||
|
||||
If you would like to publish this project in the future and help Modrinth grow, consider creating an [issue](https://github.com/modrinth/code/issues) suggesting support for this type of content.
|
||||
|
||||
We appreciate your understanding and look forward to hosting your other creations.
|
||||
@@ -31,7 +31,9 @@ const categories: Stage = {
|
||||
weight: 701,
|
||||
suggestedStatus: 'flagged',
|
||||
severity: 'low',
|
||||
shouldShow: (project) => project.categories.includes('optimization'),
|
||||
shouldShow: (project) =>
|
||||
project.categories.includes('optimization') ||
|
||||
project.additional_categories.includes('optimization'),
|
||||
message: async () =>
|
||||
(await import('../messages/categories/inaccurate.md?raw')).default +
|
||||
(await import('../messages/categories/optimization_misused.md?raw')).default,
|
||||
|
||||
@@ -25,6 +25,7 @@ const gallery: Stage = {
|
||||
weight: 901,
|
||||
suggestedStatus: 'flagged',
|
||||
severity: 'low',
|
||||
shouldShow: (project) => project.gallery && project.gallery.length > 0,
|
||||
message: async () => (await import('../messages/gallery/not-relevant.md?raw')).default,
|
||||
} as ButtonAction,
|
||||
],
|
||||
|
||||
@@ -7,7 +7,8 @@ const sideTypes: Stage = {
|
||||
id: 'environment',
|
||||
icon: GlobeIcon,
|
||||
guidance_url: 'https://modrinth.com/legal/rules#miscellaneous',
|
||||
navigate: '/settings#side-types',
|
||||
navigate: '/settings',
|
||||
text: async () => (await import('../messages/checklist-text/side_types.md?raw')).default,
|
||||
actions: [
|
||||
{
|
||||
id: 'side_types_inaccurate_modpack',
|
||||
|
||||
@@ -150,7 +150,24 @@ const versions: Stage = {
|
||||
severity: `medium`,
|
||||
weight: 1004,
|
||||
message: async () => (await import('../messages/versions/broken_version.md?raw')).default,
|
||||
},
|
||||
} as ButtonAction,
|
||||
{
|
||||
id: 'unsupported_project_type',
|
||||
type: 'button',
|
||||
label: `Unsupported`,
|
||||
suggestedStatus: `rejected`,
|
||||
severity: `medium`,
|
||||
weight: 1005,
|
||||
message: async () =>
|
||||
(await import('../messages/versions/unsupported_project.md?raw')).default,
|
||||
relevantExtraInput: [
|
||||
{
|
||||
label: 'Project Type',
|
||||
required: true,
|
||||
variable: 'INVALID_TYPE',
|
||||
},
|
||||
],
|
||||
} as ButtonAction,
|
||||
],
|
||||
}
|
||||
|
||||
|
||||
@@ -317,6 +317,11 @@ export function flattenProjectVariables(project: Project): Record<string, string
|
||||
vars[`PROJECT_PERMANENT_LINK`] = `https://modrinth.com/project/${project.id}`
|
||||
vars[`PROJECT_SETTINGS_LINK`] = `https://modrinth.com/project/${project.id}/settings`
|
||||
vars[`PROJECT_SETTINGS_FLINK`] = `[Settings](https://modrinth.com/project/${project.id}/settings)`
|
||||
vars[`PROJECT_TITLE_FLINK`] = `[Name](https://modrinth.com/project/${project.id}/settings)`
|
||||
vars[`PROJECT_SLUG_FLINK`] = `[URL](https://modrinth.com/project/${project.id}/settings)`
|
||||
vars[`PROJECT_SUMMARY_FLINK`] = `[Summary](https://modrinth.com/project/${project.id}/settings)`
|
||||
vars[`PROJECT_ENVIRONMENT_FLINK`] =
|
||||
`[Environment Information](https://modrinth.com/project/${project.id}/settings)`
|
||||
vars[`PROJECT_TAGS_LINK`] = `https://modrinth.com/project/${project.id}/settings/tags`
|
||||
vars[`PROJECT_TAGS_FLINK`] = `[Tags](https://modrinth.com/project/${project.id}/settings/tags)`
|
||||
vars[`PROJECT_DESCRIPTION_LINK`] =
|
||||
|
||||
Reference in New Issue
Block a user