Fix rust 1.89 warns

This commit is contained in:
Alexander Medvedev 2025-08-11 20:45:55 +02:00
parent 9f94ce1d0d
commit 7e3a1c0972
81 changed files with 612 additions and 648 deletions

View File

@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported to the community leaders responsible for enforcement at reported to the community leaders responsible for enforcement at
lilalexmed@proton.me. <lilalexmed@proton.me>.
All complaints will be reviewed and investigated promptly and fairly. All complaints will be reviewed and investigated promptly and fairly.
All community leaders are obligated to respect the privacy and security of the All community leaders are obligated to respect the privacy and security of the
@ -116,7 +116,7 @@ the community.
This Code of Conduct is adapted from the [Contributor Covenant][homepage], This Code of Conduct is adapted from the [Contributor Covenant][homepage],
version 2.0, available at version 2.0, available at
https://www.contributor-covenant.org/version/2/0/code_of_conduct.html. <https://www.contributor-covenant.org/version/2/0/code_of_conduct.html>.
Community Impact Guidelines were inspired by [Mozilla's code of conduct Community Impact Guidelines were inspired by [Mozilla's code of conduct
enforcement ladder](https://github.com/mozilla/diversity). enforcement ladder](https://github.com/mozilla/diversity).
@ -124,5 +124,5 @@ enforcement ladder](https://github.com/mozilla/diversity).
[homepage]: https://www.contributor-covenant.org [homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see the FAQ at For answers to common questions about this code of conduct, see the FAQ at
https://www.contributor-covenant.org/faq. Translations are available at <https://www.contributor-covenant.org/faq>. Translations are available at
https://www.contributor-covenant.org/translations. <https://www.contributor-covenant.org/translations>.

View File

@ -47,10 +47,10 @@ Note: Pumpkin's clippy settings are relatively strict, this can be may frustrati
- **No Clippy Warnings:** Address all warnings reported by the Clippy linter. You can check for warnings using `cargo clippy --all-targets`. - **No Clippy Warnings:** Address all warnings reported by the Clippy linter. You can check for warnings using `cargo clippy --all-targets`.
- **Passing Unit Tests:** All existing unit tests must pass successfully. You can run the tests with `cargo test`. - **Passing Unit Tests:** All existing unit tests must pass successfully. You can run the tests with `cargo test`.
**Best Practice** #### Best Practice
- **Writing Unit Tests:** When adding new features or modifying existing code, consider adding unit tests to prevent regressions in the future. Refer to the Rust documentation for guidance on writing tests: https://doc.rust-lang.org/book/ch11-01-writing-tests.html - **Writing Unit Tests:** When adding new features or modifying existing code, consider adding unit tests to prevent regressions in the future. Refer to the Rust documentation for guidance on writing tests: <https://doc.rust-lang.org/book/ch11-01-writing-tests.html>
- **Benchmarking:** If your changes might impact performance, consider adding benchmarks to track performance regressions or improvements. We use the Criterion library for benchmarking. Refer to their Quick Start guide for more information: https://github.com/bheisler/criterion.rs#quickstart - **Benchmarking:** If your changes might impact performance, consider adding benchmarks to track performance regressions or improvements. We use the Criterion library for benchmarking. Refer to their Quick Start guide for more information: <https://github.com/bheisler/criterion.rs#quickstart>
- **Clear and Concise Commit Messages:** Use clear and concise commit messages that describe the changes you've made. - **Clear and Concise Commit Messages:** Use clear and concise commit messages that describe the changes you've made.
- **Code Style:** Adhere to consistent coding style throughout your contributions. - **Code Style:** Adhere to consistent coding style throughout your contributions.
- **Documentation:** If your changes introduce new functionality, consider updating the relevant documentation. - **Documentation:** If your changes introduce new functionality, consider updating the relevant documentation.

47
Cargo.lock generated
View File

@ -419,7 +419,7 @@ version = "3.0.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e" checksum = "fde0e0ec90c9dfb3b4b1a0891a7dcd0e2bffde2f7efed5fe7c9bb00e5bfb915e"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -647,9 +647,9 @@ checksum = "460fbee9c2c2f33933d720630a6a0bac33ba7053db5344fac858d4b8952d77d5"
[[package]] [[package]]
name = "crypto-bigint" name = "crypto-bigint"
version = "0.7.0-pre.7" version = "0.7.0-rc.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "85ff38607b7ebe30e4715eeb0a0427ff42e3b6b47b2df55a775e767ef2658ccd" checksum = "737a2363b81de8cc95d8780d84aecb4b3c6f41e4473759da6636072b5514c875"
dependencies = [ dependencies = [
"num-traits", "num-traits",
"rand_core 0.9.3", "rand_core 0.9.3",
@ -866,7 +866,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad" checksum = "778e2ac28f6c47af28e4907f13ffd1e1ddbd400980a9abd7c8df189bf578a5ad"
dependencies = [ dependencies = [
"libc", "libc",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -1379,9 +1379,9 @@ dependencies = [
[[package]] [[package]]
name = "io-uring" name = "io-uring"
version = "0.7.8" version = "0.7.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b86e202f00093dcba4275d4636b93ef9dd75d025ae560d2521b45ea28ab49013" checksum = "d93587f37623a1a17d94ef2bc9ada592f5465fe7732084ab7beefabe5c77c0c4"
dependencies = [ dependencies = [
"bitflags", "bitflags",
"cfg-if", "cfg-if",
@ -2362,9 +2362,9 @@ dependencies = [
[[package]] [[package]]
name = "rsa" name = "rsa"
version = "0.10.0-rc.3" version = "0.10.0-rc.4"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7e8cb237ca3624409eda7d73de0d423815c9d91175ed5a62a8dd6549d2408cc2" checksum = "b311b61ea276fd51ccb77f6995c5f70084db933bab9655ba51fe5d831ea25b39"
dependencies = [ dependencies = [
"const-oid", "const-oid",
"crypto-bigint", "crypto-bigint",
@ -2391,9 +2391,9 @@ dependencies = [
[[package]] [[package]]
name = "rustc-demangle" name = "rustc-demangle"
version = "0.1.25" version = "0.1.26"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "989e6739f80c4ad5b13e0fd7fe89531180375b18520cc8c82080e4dc4035b84f" checksum = "56f7d92ca342cea22a06f2121d944b4fd82af56988c270852495420f961d4ace"
[[package]] [[package]]
name = "rustc-hash" name = "rustc-hash"
@ -2417,7 +2417,7 @@ dependencies = [
"errno", "errno",
"libc", "libc",
"linux-raw-sys", "linux-raw-sys",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -2648,18 +2648,18 @@ dependencies = [
[[package]] [[package]]
name = "signal-hook-registry" name = "signal-hook-registry"
version = "1.4.5" version = "1.4.6"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "9203b8055f63a2a00e2f593bb0510367fe707d7ff1e5c872de2f537b339e5410" checksum = "b2a4719bff48cee6b39d12c020eeb490953ad2443b7055bd0b21fca26bd8c28b"
dependencies = [ dependencies = [
"libc", "libc",
] ]
[[package]] [[package]]
name = "signature" name = "signature"
version = "3.0.0-rc.1" version = "3.0.0-rc.2"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b8852cecbd17ba45978bbbe43061ebe36a2ae376058c5c172e09f72888f8f7de" checksum = "4835c3b5ecb10171941a4998a95a3a76ecac1c5ae8e6954f2ad030acd1c7e8ab"
dependencies = [ dependencies = [
"digest 0.11.0-rc.0", "digest 0.11.0-rc.0",
"rand_core 0.9.3", "rand_core 0.9.3",
@ -2804,7 +2804,7 @@ dependencies = [
"fastrand", "fastrand",
"once_cell", "once_cell",
"rustix", "rustix",
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]
@ -2916,9 +2916,9 @@ dependencies = [
[[package]] [[package]]
name = "tokio" name = "tokio"
version = "1.47.0" version = "1.47.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "43864ed400b6043a4757a25c7a64a8efde741aed79a056a2fb348a406701bb35" checksum = "89e49afdadebb872d3145a5638b59eb0691ea23e46ca484037cfab3b76b95038"
dependencies = [ dependencies = [
"backtrace", "backtrace",
"bytes", "bytes",
@ -2958,15 +2958,14 @@ dependencies = [
[[package]] [[package]]
name = "tokio-util" name = "tokio-util"
version = "0.7.15" version = "0.7.16"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "66a539a9ad6d5d281510d5bd368c973d636c02dbf8a67300bfb6b950696ad7df" checksum = "14307c986784f72ef81c89db7d9e28d6ac26d16213b109ea501696195e6e3ce5"
dependencies = [ dependencies = [
"bytes", "bytes",
"futures-core", "futures-core",
"futures-sink", "futures-sink",
"futures-util", "futures-util",
"hashbrown 0.15.4",
"pin-project-lite", "pin-project-lite",
"tokio", "tokio",
] ]
@ -3255,9 +3254,9 @@ checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821"
[[package]] [[package]]
name = "uuid" name = "uuid"
version = "1.17.0" version = "1.18.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3cf4199d1e5d15ddd86a694e4d0dffa9c323ce759fea589f00fef9d81cc1931d" checksum = "f33196643e165781c20a5ead5582283a7dacbb87855d867fbc2df3f81eddc1be"
dependencies = [ dependencies = [
"getrandom 0.3.3", "getrandom 0.3.3",
"js-sys", "js-sys",
@ -3410,7 +3409,7 @@ version = "0.1.9"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb" checksum = "cf221c93e13a30d793f7645a0e7762c55d169dbb0a49671918a2319d289b10bb"
dependencies = [ dependencies = [
"windows-sys 0.52.0", "windows-sys 0.59.0",
] ]
[[package]] [[package]]

View File

@ -51,7 +51,7 @@ futures = { version = "0.3", default-features = false, features = ["executor"] }
rayon = "1.10" rayon = "1.10"
crossbeam = "0.8" crossbeam = "0.8"
uuid = { version = "1.17", features = ["serde", "v3", "v4"] } uuid = { version = "1.18", features = ["serde", "v3", "v4"] }
serde = { version = "1.0", features = ["derive"] } serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0" serde_json = "1.0"

View File

@ -7,13 +7,12 @@
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Current version)](https://img.shields.io/badge/current_version-1.21.8-blue) ![Current version)](https://img.shields.io/badge/current_version-1.21.8-blue)
</div> </div>
[Pumpkin](https://pumpkinmc.org/) is a Minecraft server built entirely in Rust, offering a fast, efficient, [Pumpkin](https://pumpkinmc.org/) is a Minecraft server built entirely in Rust, offering a fast, efficient,
and customizable experience. It prioritizes performance and player enjoyment while adhering to the core mechanics of the game. and customizable experience. It prioritizes performance and player enjoyment while adhering to the core mechanics of the game.
<div align="center"> <div align="center">
![chunk loading](/assets/pumpkin_chunk_loading.GIF) ![chunk loading](/assets/pumpkin_chunk_loading.GIF)
</div> </div>
@ -49,7 +48,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
- [x] World Loading - [x] World Loading
- [x] World Time - [x] World Time
- [x] World Borders - [x] World Borders
- [x] World Saving - [x] World Saving
- [x] Lighting - [x] Lighting
- [x] Entity Spawning - [x] Entity Spawning
- [x] Item drops (W.I.P) - [x] Item drops (W.I.P)
@ -74,7 +73,7 @@ and customizable experience. It prioritizes performance and player enjoyment whi
- [x] Experience - [x] Experience
- [x] Hunger - [x] Hunger
- [X] Off Hand - [X] Off Hand
- [ ] Advancements - [ ] Advancements
- [ ] Eating - [ ] Eating
- Entities - Entities
- [x] Non-Living (Minecart, Eggs...) (W.I.P) - [x] Non-Living (Minecart, Eggs...) (W.I.P)
@ -113,7 +112,7 @@ Contributions are welcome! See [CONTRIBUTING.md](CONTRIBUTING.md)
## Docs ## Docs
Pumpkin's documentation can be found at https://pumpkinmc.org/ Pumpkin's documentation can be found at <https://pumpkinmc.org/>
## Communication ## Communication

View File

@ -83,13 +83,13 @@ pub fn send_cancellable(input: TokenStream) -> TokenStream {
if let Stmt::Expr(expr, _) = stmt { if let Stmt::Expr(expr, _) = stmt {
if event.is_none() { if event.is_none() {
event = Some(expr); event = Some(expr);
} else if let Expr::Block(b) = expr { } else if let Expr::Block(b) = expr
if let Some(ref label) = b.label { && let Some(ref label) = b.label
if label.name.ident == "after" { {
after_block = Some(b); if label.name.ident == "after" {
} else if label.name.ident == "cancelled" { after_block = Some(b);
cancelled_block = Some(b); } else if label.name.ident == "cancelled" {
} cancelled_block = Some(b);
} }
} }
} }

View File

@ -119,23 +119,21 @@ gen_from!(i16);
gen_from!(u16); gen_from!(u16);
gen_from!(u32); gen_from!(u32);
macro_rules! gen_try_from { macro_rules! gen_from {
($ty: ty) => { ($ty: ty) => {
impl TryFrom<$ty> for VarUInt { impl From<$ty> for VarUInt {
type Error = <i32 as TryFrom<$ty>>::Error; fn from(value: $ty) -> Self {
VarUInt(value as u32)
fn try_from(value: $ty) -> Result<Self, Self::Error> {
Ok(VarUInt(value as u32))
} }
} }
}; };
} }
gen_try_from!(i32); gen_from!(i32);
gen_try_from!(i64); gen_from!(i64);
gen_try_from!(u64); gen_from!(u64);
gen_try_from!(isize); gen_from!(isize);
gen_try_from!(usize); gen_from!(usize);
impl Serialize for VarUInt { impl Serialize for VarUInt {
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> { fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {

View File

@ -339,12 +339,11 @@ impl<'de> serde::Deserialize<'de> for Vector3<i32> {
self, self,
mut seq: A, mut seq: A,
) -> Result<Self::Value, A::Error> { ) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<i32>()? { if let Some(x) = seq.next_element::<i32>()?
if let Some(y) = seq.next_element::<i32>()? { && let Some(y) = seq.next_element::<i32>()?
if let Some(z) = seq.next_element::<i32>()? { && let Some(z) = seq.next_element::<i32>()?
return Ok(Vector3::new(x, y, z)); {
} return Ok(Vector3::new(x, y, z));
}
} }
Err(serde::de::Error::custom("Failed to read Vector<i32>")) Err(serde::de::Error::custom("Failed to read Vector<i32>"))
} }
@ -369,12 +368,11 @@ impl<'de> serde::Deserialize<'de> for Vector3<f32> {
self, self,
mut seq: A, mut seq: A,
) -> Result<Self::Value, A::Error> { ) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<f32>()? { if let Some(x) = seq.next_element::<f32>()?
if let Some(y) = seq.next_element::<f32>()? { && let Some(y) = seq.next_element::<f32>()?
if let Some(z) = seq.next_element::<f32>()? { && let Some(z) = seq.next_element::<f32>()?
return Ok(Vector3::new(x, y, z)); {
} return Ok(Vector3::new(x, y, z));
}
} }
Err(serde::de::Error::custom("Failed to read Vector<f32>")) Err(serde::de::Error::custom("Failed to read Vector<f32>"))
} }
@ -399,12 +397,11 @@ impl<'de> serde::Deserialize<'de> for Vector3<f64> {
self, self,
mut seq: A, mut seq: A,
) -> Result<Self::Value, A::Error> { ) -> Result<Self::Value, A::Error> {
if let Some(x) = seq.next_element::<f64>()? { if let Some(x) = seq.next_element::<f64>()?
if let Some(y) = seq.next_element::<f64>()? { && let Some(y) = seq.next_element::<f64>()?
if let Some(z) = seq.next_element::<f64>()? { && let Some(z) = seq.next_element::<f64>()?
return Ok(Vector3::new(x, y, z)); {
} return Ok(Vector3::new(x, y, z));
}
} }
Err(serde::de::Error::custom("Failed to read Vector<f64>")) Err(serde::de::Error::custom("Failed to read Vector<f64>"))
} }

View File

@ -197,10 +197,10 @@ impl PermissionManager {
// Check for inherited permissions from parent nodes // Check for inherited permissions from parent nodes
for (node, value) in attachment.get_permissions() { for (node, value) in attachment.get_permissions() {
if let Some(permission) = reg.get_permission(node) { if let Some(permission) = reg.get_permission(node)
if permission.children.contains_key(permission_node) { && permission.children.contains_key(permission_node)
return *value && *permission.children.get(permission_node).unwrap(); {
} return *value && *permission.children.get(permission_node).unwrap();
} }
} }
} }

View File

@ -45,7 +45,7 @@ derive-getters = "0.5.0"
thread_local = "1.1.9" thread_local = "1.1.9"
lru = "0.16.0" lru = "0.16.0"
tokio-util = { version = "0.7.15", features = ["rt"] } tokio-util = { version = "0.7.16", features = ["rt"] }
rand = "0.9.2" rand = "0.9.2"
[dev-dependencies] [dev-dependencies]

View File

@ -70,7 +70,7 @@ impl DropperBlockEntity {
dirty: AtomicBool::new(false), dirty: AtomicBool::new(false),
} }
} }
pub async fn get_random_slot(&self) -> Option<MutexGuard<ItemStack>> { pub async fn get_random_slot(&self) -> Option<MutexGuard<'_, ItemStack>> {
// this.unpackLootTable(null); // this.unpackLootTable(null);
let mut ret = None; let mut ret = None;
let mut j = 1; let mut j = 1;

View File

@ -85,14 +85,12 @@ impl FurnaceBlockEntity {
if let Some(recipe_output_item) = if let Some(recipe_output_item) =
Item::from_registry_key(recipe.result.id.strip_prefix("minecraft:").unwrap()) Item::from_registry_key(recipe.result.id.strip_prefix("minecraft:").unwrap())
&& !is_top_items_empty
&& recipe_output_item.id == side_item_stack.item.id
&& side_item_stack.item_count < max_count
&& side_item_stack.item_count < side_item_stack.get_max_stack_size()
{ {
if !is_top_items_empty return true;
&& recipe_output_item.id == side_item_stack.item.id
&& side_item_stack.item_count < max_count
&& side_item_stack.item_count < side_item_stack.get_max_stack_size()
{
return true;
}
} }
false false
} }

View File

@ -163,24 +163,24 @@ impl HopperBlockEntity {
async fn suck_in_items(&self, world: &Arc<dyn SimpleWorld>) -> bool { async fn suck_in_items(&self, world: &Arc<dyn SimpleWorld>) -> bool {
// TODO getEntityContainer // TODO getEntityContainer
let pos_up = &self.position.up(); let pos_up = &self.position.up();
if let Some(entity) = world.get_block_entity(pos_up).await { if let Some(entity) = world.get_block_entity(pos_up).await
if let Some(container) = entity.get_inventory() { && let Some(container) = entity.get_inventory()
// TODO check WorldlyContainer {
for i in 0..container.size() { // TODO check WorldlyContainer
let bind = container.get_stack(i).await; for i in 0..container.size() {
let mut item = bind.lock().await; let bind = container.get_stack(i).await;
if !item.is_empty() && container.can_transfer_to(self, i, &item) { let mut item = bind.lock().await;
//TODO WorldlyContainer if !item.is_empty() && container.can_transfer_to(self, i, &item) {
let backup = item.clone(); //TODO WorldlyContainer
let one_item = item.split(1); let backup = item.clone();
if Self::add_one_item(container.as_ref(), self, one_item).await { let one_item = item.split(1);
return true; if Self::add_one_item(container.as_ref(), self, one_item).await {
} return true;
*item = backup;
} }
*item = backup;
} }
return false;
} }
return false;
} }
let (block, state) = world.get_block_and_state(pos_up).await; let (block, state) = world.get_block_and_state(pos_up).await;
if !(state.is_solid() if !(state.is_solid()
@ -200,32 +200,31 @@ impl HopperBlockEntity {
if let Some(entity) = world if let Some(entity) = world
.get_block_entity(&self.position.offset(to_offset(&self.facing))) .get_block_entity(&self.position.offset(to_offset(&self.facing)))
.await .await
&& let Some(container) = entity.get_inventory()
{ {
if let Some(container) = entity.get_inventory() { // TODO check WorldlyContainer
// TODO check WorldlyContainer let mut is_full = true;
let mut is_full = true; for i in 0..container.size() {
for i in 0..container.size() { let bind = container.get_stack(i).await;
let bind = container.get_stack(i).await; let item = bind.lock().await;
let item = bind.lock().await; if item.item_count < item.get_max_stack_size() {
if item.item_count < item.get_max_stack_size() { is_full = false;
is_full = false; break;
break;
}
} }
if is_full { }
return false; if is_full {
} return false;
for i in &self.items { }
let mut item = i.lock().await; for i in &self.items {
if !item.is_empty() { let mut item = i.lock().await;
//TODO WorldlyContainer if !item.is_empty() {
let backup = item.clone(); //TODO WorldlyContainer
let one_item = item.split(1); let backup = item.clone();
if Self::add_one_item(self, container.as_ref(), one_item).await { let one_item = item.split(1);
return true; if Self::add_one_item(self, container.as_ref(), one_item).await {
} return true;
*item = backup;
} }
*item = backup;
} }
} }
} }
@ -247,37 +246,34 @@ impl HopperBlockEntity {
success = true; success = true;
} }
if success { if success {
if to_empty { if to_empty
if let Some(hopper) = to.as_any().downcast_ref::<HopperBlockEntity>() { && let Some(hopper) = to.as_any().downcast_ref::<HopperBlockEntity>()
if hopper && hopper
.cooldown_time
.load(std::sync::atomic::Ordering::Relaxed)
<= 8
{
if let Some(from_hopper) = from.as_any().downcast_ref::<HopperBlockEntity>()
{
if from_hopper
.cooldown_time .cooldown_time
.load(std::sync::atomic::Ordering::Relaxed) .load(std::sync::atomic::Ordering::Relaxed)
<= 8 >= hopper
.cooldown_time
.load(std::sync::atomic::Ordering::Relaxed)
{ {
if let Some(from_hopper) = hopper
from.as_any().downcast_ref::<HopperBlockEntity>() .cooldown_time
{ .store(7, std::sync::atomic::Ordering::Relaxed);
if from_hopper } else {
.cooldown_time hopper
.load(std::sync::atomic::Ordering::Relaxed) .cooldown_time
>= hopper .store(8, std::sync::atomic::Ordering::Relaxed);
.cooldown_time
.load(std::sync::atomic::Ordering::Relaxed)
{
hopper
.cooldown_time
.store(7, std::sync::atomic::Ordering::Relaxed);
} else {
hopper
.cooldown_time
.store(8, std::sync::atomic::Ordering::Relaxed);
}
} else {
hopper
.cooldown_time
.store(8, std::sync::atomic::Ordering::Relaxed);
}
} }
} else {
hopper
.cooldown_time
.store(8, std::sync::atomic::Ordering::Relaxed);
} }
} }
to.mark_dirty(); to.mark_dirty();

View File

@ -28,10 +28,10 @@ impl PlayerDataStorage {
/// Creates a new `PlayerDataStorage` with the specified data path and cache expiration time. /// Creates a new `PlayerDataStorage` with the specified data path and cache expiration time.
pub fn new(data_path: impl Into<PathBuf>) -> Self { pub fn new(data_path: impl Into<PathBuf>) -> Self {
let path = data_path.into(); let path = data_path.into();
if !path.exists() { if !path.exists()
if let Err(e) = create_dir_all(&path) { && let Err(e) = create_dir_all(&path)
log::error!("Failed to create player data directory at {path:?}: {e}"); {
} log::error!("Failed to create player data directory at {path:?}: {e}");
} }
Self { Self {
@ -126,11 +126,11 @@ impl PlayerDataStorage {
let path = self.get_player_data_path(uuid); let path = self.get_player_data_path(uuid);
// Ensure parent directory exists // Ensure parent directory exists
if let Some(parent) = path.parent() { if let Some(parent) = path.parent()
if let Err(e) = create_dir_all(parent) { && let Err(e) = create_dir_all(parent)
log::error!("Failed to create player data directory for {uuid}: {e}"); {
return Err(PlayerDataError::Io(e)); log::error!("Failed to create player data directory for {uuid}: {e}");
} return Err(PlayerDataError::Io(e));
} }
// Create the file and write directly with GZip compression // Create the file and write directly with GZip compression

View File

@ -63,15 +63,15 @@ pub trait Inventory: Send + Sync + Debug + Clearable {
) { ) {
if let Some(inventory_list) = nbt.get_list("Items") { if let Some(inventory_list) = nbt.get_list("Items") {
for tag in inventory_list { for tag in inventory_list {
if let Some(item_compound) = tag.extract_compound() { if let Some(item_compound) = tag.extract_compound()
if let Some(slot_byte) = item_compound.get_byte("Slot") { && let Some(slot_byte) = item_compound.get_byte("Slot")
let slot = slot_byte as usize; {
if slot < stacks.len() { let slot = slot_byte as usize;
if let Some(item_stack) = ItemStack::read_item_stack(item_compound) { if slot < stacks.len()
// This won't error cause it's only called on initialization && let Some(item_stack) = ItemStack::read_item_stack(item_compound)
*stacks[slot].try_lock().unwrap() = item_stack; {
} // This won't error cause it's only called on initialization
} *stacks[slot].try_lock().unwrap() = item_stack;
} }
} }
} }

View File

@ -50,7 +50,7 @@ num-bigint = "0.4"
rustyline-async = "0.4.7" rustyline-async = "0.4.7"
# encryption # encryption
rsa = { version = "=0.10.0-rc.3", features = ["sha1"] } rsa = { version = "=0.10.0-rc.4", features = ["sha1"] }
rsa-der = "0.3" rsa-der = "0.3"
# authentication # authentication
@ -77,7 +77,7 @@ libloading = "0.8"
rustc-hash = "2.1.1" rustc-hash = "2.1.1"
# Task handling # Task handling
tokio-util = { version = "0.7.15", features = ["rt"] } tokio-util = { version = "0.7.16", features = ["rt"] }
# Memory profiling # Memory profiling
dhat = { version = "0.3.3", optional = true } dhat = { version = "0.3.3", optional = true }

View File

@ -27,14 +27,14 @@ pub struct CandleBlock;
#[async_trait] #[async_trait]
impl BlockBehaviour for CandleBlock { impl BlockBehaviour for CandleBlock {
async fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId { async fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
if args.player.get_entity().pose.load() != EntityPose::Crouching { if args.player.get_entity().pose.load() != EntityPose::Crouching
if let BlockIsReplacing::Itself(state_id) = args.replacing { && let BlockIsReplacing::Itself(state_id) = args.replacing
let mut properties = CandleLikeProperties::from_state_id(state_id, args.block); {
if properties.candles.to_index() < 3 { let mut properties = CandleLikeProperties::from_state_id(state_id, args.block);
properties.candles = Integer1To4::from_index(properties.candles.to_index() + 1); if properties.candles.to_index() < 3 {
} properties.candles = Integer1To4::from_index(properties.candles.to_index() + 1);
return properties.to_state_id(args.block);
} }
return properties.to_state_id(args.block);
} }
let mut properties = CandleLikeProperties::default(args.block); let mut properties = CandleLikeProperties::default(args.block);

View File

@ -48,22 +48,21 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) { if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) {
if Self::is_slot_used(properties, slot) { if Self::is_slot_used(properties, slot) {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(block_entity) = block_entity && let Some(block_entity) = block_entity
.as_any() .as_any()
.downcast_ref::<ChiseledBookshelfBlockEntity>() .downcast_ref::<ChiseledBookshelfBlockEntity>()
{ {
Self::try_remove_book( Self::try_remove_book(
args.world, args.world,
args.player, args.player,
args.position, args.position,
block_entity, block_entity,
properties, properties,
slot, slot,
) )
.await; .await;
return BlockActionResult::Success; return BlockActionResult::Success;
}
} }
} else { } else {
return BlockActionResult::Consume; return BlockActionResult::Consume;
@ -88,23 +87,22 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) { if let Some(slot) = Self::get_slot_for_hit(args.hit, properties.facing) {
if Self::is_slot_used(properties, slot) { if Self::is_slot_used(properties, slot) {
return BlockActionResult::PassToDefaultBlockAction; return BlockActionResult::PassToDefaultBlockAction;
} else if let Some(block_entity) = args.world.get_block_entity(args.position).await { } else if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(block_entity) = block_entity && let Some(block_entity) = block_entity
.as_any() .as_any()
.downcast_ref::<ChiseledBookshelfBlockEntity>() .downcast_ref::<ChiseledBookshelfBlockEntity>()
{ {
Self::try_add_book( Self::try_add_book(
args.world, args.world,
args.player, args.player,
args.position, args.position,
block_entity, block_entity,
properties, properties,
slot, slot,
args.item_stack, args.item_stack,
) )
.await; .await;
return BlockActionResult::Success; return BlockActionResult::Success;
}
} }
} }
@ -117,13 +115,12 @@ impl BlockBehaviour for ChiseledBookshelfBlock {
} }
async fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> { async fn get_comparator_output(&self, args: GetComparatorOutputArgs<'_>) -> Option<u8> {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(block_entity) = block_entity && let Some(block_entity) = block_entity
.as_any() .as_any()
.downcast_ref::<ChiseledBookshelfBlockEntity>() .downcast_ref::<ChiseledBookshelfBlockEntity>()
{ {
return Some((block_entity.last_interacted_slot.load(Ordering::Relaxed) + 1) as u8); return Some((block_entity.last_interacted_slot.load(Ordering::Relaxed) + 1) as u8);
}
} }
None None
} }

View File

@ -74,19 +74,19 @@ impl BlockBehaviour for CommandBlock {
} }
async fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) { async fn on_scheduled_tick(&self, args: OnScheduledTickArgs<'_>) {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if block_entity.resource_location() != CommandBlockEntity::ID { && block_entity.resource_location() != CommandBlockEntity::ID
return; {
} return;
// TODO
} }
// TODO
} }
async fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool { async fn can_place_at(&self, args: CanPlaceAtArgs<'_>) -> bool {
if let Some(player) = args.player { if let Some(player) = args.player
if player.gamemode.load() == GameMode::Creative { && player.gamemode.load() == GameMode::Creative
return true; {
} return true;
} }
false false

View File

@ -50,24 +50,16 @@ impl BlockBehaviour for ComposterBlock {
self.clear_composter(args.world, args.position, state_id, args.block) self.clear_composter(args.world, args.position, state_id, args.block)
.await; .await;
} }
if level < 7 { if level < 7
if let Some(chance) = && let Some(chance) =
get_composter_increase_chance_from_item_id(args.item_stack.lock().await.item.id) get_composter_increase_chance_from_item_id(args.item_stack.lock().await.item.id)
{ && (level == 0 || rand::rng().random_bool(f64::from(chance)))
if level == 0 || rand::rng().random_bool(f64::from(chance)) { {
self.update_level_composter( self.update_level_composter(args.world, args.position, state_id, args.block, level + 1)
args.world, .await;
args.position, args.world
state_id, .sync_world_event(WorldEvent::ComposterUsed, *args.position, 1)
args.block, .await;
level + 1,
)
.await;
args.world
.sync_world_event(WorldEvent::ComposterUsed, *args.position, 1)
.await;
}
}
} }
BlockActionResult::Consume BlockActionResult::Consume
} }

View File

@ -175,15 +175,13 @@ impl BlockBehaviour for FireBlock {
let dimension = args.world.dimension_type; let dimension = args.world.dimension_type;
// First lets check if we are in OverWorld or Nether, its not possible to place an Nether portal in other dimensions in Vanilla // First lets check if we are in OverWorld or Nether, its not possible to place an Nether portal in other dimensions in Vanilla
if dimension == VanillaDimensionType::Overworld if (dimension == VanillaDimensionType::Overworld
|| dimension == VanillaDimensionType::TheNether || dimension == VanillaDimensionType::TheNether)
{ && let Some(portal) =
if let Some(portal) =
NetherPortal::get_new_portal(args.world, args.position, HorizontalAxis::X).await NetherPortal::get_new_portal(args.world, args.position, HorizontalAxis::X).await
{ {
portal.create(args.world).await; portal.create(args.world).await;
return; return;
}
} }
args.world args.world

View File

@ -61,13 +61,13 @@ impl BlockBehaviour for FurnaceBlock {
&self, &self,
args: crate::block::NormalUseArgs<'_>, args: crate::block::NormalUseArgs<'_>,
) -> crate::block::registry::BlockActionResult { ) -> crate::block::registry::BlockActionResult {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(inventory) = block_entity.clone().get_inventory() { && let Some(inventory) = block_entity.clone().get_inventory()
let furnace_screen_factory = FurnaceScreenFactory::new(inventory, block_entity); {
args.player let furnace_screen_factory = FurnaceScreenFactory::new(inventory, block_entity);
.open_handled_screen(&furnace_screen_factory) args.player
.await; .open_handled_screen(&furnace_screen_factory)
} .await;
} }
crate::block::registry::BlockActionResult::Consume crate::block::registry::BlockActionResult::Consume
} }

View File

@ -52,12 +52,12 @@ type HopperLikeProperties = pumpkin_data::block_properties::HopperLikeProperties
#[async_trait] #[async_trait]
impl BlockBehaviour for HopperBlock { impl BlockBehaviour for HopperBlock {
async fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult { async fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(inventory) = block_entity.get_inventory() { && let Some(inventory) = block_entity.get_inventory()
args.player {
.open_handled_screen(&HopperBlockScreenFactory(inventory)) args.player
.await; .open_handled_screen(&HopperBlockScreenFactory(inventory))
} .await;
} }
BlockActionResult::Success BlockActionResult::Success

View File

@ -200,13 +200,13 @@ impl BlockBehaviour for PistonBlock {
let pos = pos.offset_dir(dir.to_offset(), 2); let pos = pos.offset_dir(dir.to_offset(), 2);
let (block, state) = world.get_block_and_state(&pos).await; let (block, state) = world.get_block_and_state(&pos).await;
let mut bl2 = false; let mut bl2 = false;
if block == &Block::MOVING_PISTON { if block == &Block::MOVING_PISTON
if let Some(entity) = world.get_block_entity(&pos).await { && let Some(entity) = world.get_block_entity(&pos).await
let piston = entity.as_any().downcast_ref::<PistonBlockEntity>().unwrap(); {
if piston.facing == dir && piston.extending { let piston = entity.as_any().downcast_ref::<PistonBlockEntity>().unwrap();
piston.finish(world.clone()).await; if piston.facing == dir && piston.extending {
bl2 = true; piston.finish(world.clone()).await;
} bl2 = true;
} }
} }
if !bl2 { if !bl2 {
@ -295,15 +295,15 @@ async fn try_move(world: &Arc<World>, block: &Block, block_pos: &BlockPos) {
if new_block == &Block::MOVING_PISTON { if new_block == &Block::MOVING_PISTON {
let new_props = MovingPistonLikeProperties::from_state_id(new_state, new_block); let new_props = MovingPistonLikeProperties::from_state_id(new_state, new_block);
if new_props.facing == props.facing { if new_props.facing == props.facing
if let Some(entity) = world.get_block_entity(&new_pos).await { && let Some(entity) = world.get_block_entity(&new_pos).await
let piston = entity.as_any().downcast_ref::<PistonBlockEntity>().unwrap(); {
if piston.extending && piston.current_progress.load() < 0.5 let piston = entity.as_any().downcast_ref::<PistonBlockEntity>().unwrap();
// TODO: more stuff... if piston.extending && piston.current_progress.load() < 0.5
{ // TODO: more stuff...
// Piston reduced too quickly, if its a stick piston no blocks will be dragged {
r#type = 2; // Piston reduced too quickly, if its a stick piston no blocks will be dragged
} r#type = 2;
} }
} }
} }

View File

@ -107,18 +107,18 @@ impl BlockBehaviour for SeaPickleBlock {
} }
async fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId { async fn on_place(&self, args: OnPlaceArgs<'_>) -> BlockStateId {
if args.player.get_entity().pose.load() != EntityPose::Crouching { if args.player.get_entity().pose.load() != EntityPose::Crouching
if let BlockIsReplacing::Itself(state_id) = args.replacing { && let BlockIsReplacing::Itself(state_id) = args.replacing
let mut sea_pickle_prop = SeaPickleProperties::from_state_id(state_id, args.block); {
if sea_pickle_prop.pickles != Integer1To4::L4 { let mut sea_pickle_prop = SeaPickleProperties::from_state_id(state_id, args.block);
sea_pickle_prop.pickles = match sea_pickle_prop.pickles { if sea_pickle_prop.pickles != Integer1To4::L4 {
Integer1To4::L1 => Integer1To4::L2, sea_pickle_prop.pickles = match sea_pickle_prop.pickles {
Integer1To4::L2 => Integer1To4::L3, Integer1To4::L1 => Integer1To4::L2,
_ => Integer1To4::L4, Integer1To4::L2 => Integer1To4::L3,
}; _ => Integer1To4::L4,
} };
return sea_pickle_prop.to_state_id(args.block);
} }
return sea_pickle_prop.to_state_id(args.block);
} }
let mut sea_pickle_prop = SeaPickleProperties::default(args.block); let mut sea_pickle_prop = SeaPickleProperties::default(args.block);

View File

@ -136,14 +136,14 @@ impl RedstoneGateBlockProperties for ComparatorLikeProperties {
#[async_trait] #[async_trait]
impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock { impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
async fn get_output_level(&self, world: &World, pos: BlockPos) -> u8 { async fn get_output_level(&self, world: &World, pos: BlockPos) -> u8 {
if let Some(blockentity) = world.get_block_entity(&pos).await { if let Some(blockentity) = world.get_block_entity(&pos).await
if blockentity.resource_location() == ComparatorBlockEntity::ID { && blockentity.resource_location() == ComparatorBlockEntity::ID
let comparator = blockentity {
.as_any() let comparator = blockentity
.downcast_ref::<ComparatorBlockEntity>() .as_any()
.unwrap(); .downcast_ref::<ComparatorBlockEntity>()
return comparator.output_signal.load(Ordering::Relaxed); .unwrap();
} return comparator.output_signal.load(Ordering::Relaxed);
} }
0 0
} }
@ -219,8 +219,8 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
let source_pos = pos.offset(facing.to_offset()); let source_pos = pos.offset(facing.to_offset());
let (source_block, source_state) = world.get_block_and_state(&source_pos).await; let (source_block, source_state) = world.get_block_and_state(&source_pos).await;
if let Some(pumpkin_block) = world.block_registry.get_pumpkin_block(source_block) { if let Some(pumpkin_block) = world.block_registry.get_pumpkin_block(source_block)
if let Some(level) = pumpkin_block && let Some(level) = pumpkin_block
.get_comparator_output(GetComparatorOutputArgs { .get_comparator_output(GetComparatorOutputArgs {
world, world,
block: source_block, block: source_block,
@ -228,9 +228,8 @@ impl RedstoneGateBlock<ComparatorLikeProperties> for ComparatorBlock {
position: &source_pos, position: &source_pos,
}) })
.await .await
{ {
return level; return level;
}
} }
if redstone_level < 15 && source_state.is_solid() { if redstone_level < 15 && source_state.is_solid() {
@ -322,11 +321,11 @@ impl ComparatorBlock {
entity.get_entity().entity_type == &EntityType::ITEM_FRAME entity.get_entity().entity_type == &EntityType::ITEM_FRAME
&& entity.get_entity().get_horizontal_facing() == facing && entity.get_entity().get_horizontal_facing() == facing
}); });
if let Some(_itemframe) = itemframes.next() { if let Some(_itemframe) = itemframes.next()
if itemframes.next().is_none() { && itemframes.next().is_none()
// TODO itemframe.getComparatorPower() {
return Some(1); // TODO itemframe.getComparatorPower()
} return Some(1);
} }
None None
} }
@ -334,17 +333,17 @@ impl ComparatorBlock {
async fn update(&self, world: &Arc<World>, pos: BlockPos, state: &BlockState, block: &Block) { async fn update(&self, world: &Arc<World>, pos: BlockPos, state: &BlockState, block: &Block) {
let future_level = i32::from(self.calculate_output_signal(world, pos, state, block).await); let future_level = i32::from(self.calculate_output_signal(world, pos, state, block).await);
let mut now_level = 0; let mut now_level = 0;
if let Some(blockentity) = world.get_block_entity(&pos).await { if let Some(blockentity) = world.get_block_entity(&pos).await
if blockentity.resource_location() == ComparatorBlockEntity::ID { && blockentity.resource_location() == ComparatorBlockEntity::ID
let comparator = blockentity {
.as_any() let comparator = blockentity
.downcast_ref::<ComparatorBlockEntity>() .as_any()
.unwrap(); .downcast_ref::<ComparatorBlockEntity>()
now_level = i32::from(comparator.output_signal.load(Ordering::Relaxed)); .unwrap();
comparator now_level = i32::from(comparator.output_signal.load(Ordering::Relaxed));
.output_signal comparator
.store(future_level as u8, Ordering::Relaxed); .output_signal
} .store(future_level as u8, Ordering::Relaxed);
} }
let mut props = ComparatorLikeProperties::from_state_id(state.id, block); let mut props = ComparatorLikeProperties::from_state_id(state.id, block);
if now_level != future_level || props.mode == ComparatorMode::Compare { if now_level != future_level || props.mode == ComparatorMode::Compare {

View File

@ -84,12 +84,12 @@ const fn to_data3d(facing: Facing) -> i32 {
#[async_trait] #[async_trait]
impl BlockBehaviour for DropperBlock { impl BlockBehaviour for DropperBlock {
async fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult { async fn normal_use(&self, args: NormalUseArgs<'_>) -> BlockActionResult {
if let Some(block_entity) = args.world.get_block_entity(args.position).await { if let Some(block_entity) = args.world.get_block_entity(args.position).await
if let Some(inventory) = block_entity.get_inventory() { && let Some(inventory) = block_entity.get_inventory()
args.player {
.open_handled_screen(&DropperScreenFactory(inventory)) args.player
.await; .open_handled_screen(&DropperScreenFactory(inventory))
} .await;
} }
BlockActionResult::Success BlockActionResult::Success
} }
@ -157,32 +157,30 @@ impl BlockBehaviour for DropperBlock {
.offset(props.facing.to_block_direction().to_offset()), .offset(props.facing.to_block_direction().to_offset()),
) )
.await .await
&& let Some(container) = entity.get_inventory()
{ {
if let Some(container) = entity.get_inventory() { // TODO check WorldlyContainer
// TODO check WorldlyContainer let mut is_full = true;
let mut is_full = true; for i in 0..container.size() {
for i in 0..container.size() { let bind = container.get_stack(i).await;
let bind = container.get_stack(i).await; let item = bind.lock().await;
let item = bind.lock().await; if item.item_count < item.get_max_stack_size() {
if item.item_count < item.get_max_stack_size() { is_full = false;
is_full = false; break;
break;
}
} }
if is_full { }
return; if is_full {
}
//TODO WorldlyContainer
let backup = item.clone();
let one_item = item.split(1);
if HopperBlockEntity::add_one_item(dropper, container.as_ref(), one_item)
.await
{
return;
}
*item = backup;
return; return;
} }
//TODO WorldlyContainer
let backup = item.clone();
let one_item = item.split(1);
if HopperBlockEntity::add_one_item(dropper, container.as_ref(), one_item).await
{
return;
}
*item = backup;
return;
} }
let drop_item = item.split(1); let drop_item = item.split(1);
let facing = to_normal(props.facing); let facing = to_normal(props.facing);

View File

@ -29,10 +29,10 @@ pub(super) async fn rail_placement_is_valid(world: &World, block: &Block, pos: &
_ => None, _ => None,
}; };
if let Some(direction) = rail_leaning_direction { if let Some(direction) = rail_leaning_direction
if !can_place_rail_at(world, &pos.offset(direction.to_offset()).up()).await { && !can_place_rail_at(world, &pos.offset(direction.to_offset()).up()).await
return false; {
} return false;
} }
true true

View File

@ -108,28 +108,24 @@ async fn compute_stair_shape(
if let Some(other_stair_props) = if let Some(other_stair_props) =
get_stair_properties_if_exists(world, &block_pos.offset(facing.to_offset())).await get_stair_properties_if_exists(world, &block_pos.offset(facing.to_offset())).await
&& other_stair_props.half == half
{ {
if other_stair_props.half == half { if !left_locked && other_stair_props.facing == facing.rotate_clockwise() {
if !left_locked && other_stair_props.facing == facing.rotate_clockwise() { return StairShape::OuterRight;
return StairShape::OuterRight; } else if !right_locked && other_stair_props.facing == facing.rotate_counter_clockwise() {
} else if !right_locked && other_stair_props.facing == facing.rotate_counter_clockwise() return StairShape::OuterLeft;
{
return StairShape::OuterLeft;
}
} }
} }
if let Some(other_stair_props) = if let Some(other_stair_props) =
get_stair_properties_if_exists(world, &block_pos.offset(facing.opposite().to_offset())) get_stair_properties_if_exists(world, &block_pos.offset(facing.opposite().to_offset()))
.await .await
&& other_stair_props.half == half
{ {
if other_stair_props.half == half { if !right_locked && other_stair_props.facing == facing.rotate_clockwise() {
if !right_locked && other_stair_props.facing == facing.rotate_clockwise() { return StairShape::InnerRight;
return StairShape::InnerRight; } else if !left_locked && other_stair_props.facing == facing.rotate_counter_clockwise() {
} else if !left_locked && other_stair_props.facing == facing.rotate_counter_clockwise() return StairShape::InnerLeft;
{
return StairShape::InnerLeft;
}
} }
} }

View File

@ -91,14 +91,13 @@ pub trait FlowingFluid {
let state_id = world.get_block_state_id(pos).await; let state_id = world.get_block_state_id(pos).await;
// Check if the block has waterlogged property and if it's true // Check if the block has waterlogged property and if it's true
if let Some(properties) = block.properties(state_id) { if let Some(properties) = block.properties(state_id)
if properties && properties
.to_props() .to_props()
.iter() .iter()
.any(|(key, value)| key == "waterlogged" && value == "true") .any(|(key, value)| key == "waterlogged" && value == "true")
{ {
return Some(state_id); return Some(state_id);
}
} }
None None
} }

View File

@ -313,14 +313,12 @@ pub async fn drop_loot(
} }
} }
if experience { if experience && let Some(experience) = &block.experience {
if let Some(experience) = &block.experience { let mut random = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed()));
let mut random = RandomGenerator::Xoroshiro(Xoroshiro::from_seed(get_seed())); let amount = experience.experience.get(&mut random);
let amount = experience.experience.get(&mut random); // TODO: Silk touch gives no exp
// TODO: Silk touch gives no exp if amount > 0 {
if amount > 0 { ExperienceOrbEntity::spawn(world, pos.to_f64(), amount as u32).await;
ExperienceOrbEntity::spawn(world, pos.to_f64(), amount as u32).await;
}
} }
} }
} }

View File

@ -17,7 +17,7 @@ use super::{
pub struct BlockArgumentConsumer; pub struct BlockArgumentConsumer;
impl GetClientSideArgParser for BlockArgumentConsumer { impl GetClientSideArgParser for BlockArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::BlockState ArgumentType::BlockState
} }
@ -92,7 +92,7 @@ pub enum BlockPredicate {
} }
impl GetClientSideArgParser for BlockPredicateArgumentConsumer { impl GetClientSideArgParser for BlockPredicateArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::BlockPredicate ArgumentType::BlockPredicate
} }

View File

@ -9,7 +9,7 @@ use pumpkin_protocol::java::client::play::{ArgumentType, CommandSuggestion, Sugg
pub struct BoolArgConsumer; pub struct BoolArgConsumer;
impl GetClientSideArgParser for BoolArgConsumer { impl GetClientSideArgParser for BoolArgConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Bool ArgumentType::Bool
} }

View File

@ -12,7 +12,7 @@ use pumpkin_protocol::java::client::play::{ArgumentType, CommandSuggestion, Sugg
pub struct BossbarColorArgumentConsumer; pub struct BossbarColorArgumentConsumer;
impl GetClientSideArgParser for BossbarColorArgumentConsumer { impl GetClientSideArgParser for BossbarColorArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// Not sure if this is right... // Not sure if this is right...
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -12,7 +12,7 @@ use pumpkin_protocol::java::client::play::{ArgumentType, CommandSuggestion, Sugg
pub struct BossbarStyleArgumentConsumer; pub struct BossbarStyleArgumentConsumer;
impl GetClientSideArgParser for BossbarStyleArgumentConsumer { impl GetClientSideArgParser for BossbarStyleArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// Not sure if this is right... // Not sure if this is right...
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -34,22 +34,22 @@ where
) -> Option<Arg<'a>> { ) -> Option<Arg<'a>> {
let x = args.pop()?.parse::<T>().ok()?; let x = args.pop()?.parse::<T>().ok()?;
if let Some(max) = self.max_inclusive { if let Some(max) = self.max_inclusive
if x > max { && x > max
return Some(Arg::Num(Err(NotInBounds::UpperBound( {
x.to_number(), return Some(Arg::Num(Err(NotInBounds::UpperBound(
max.to_number(), x.to_number(),
)))); max.to_number(),
} ))));
} }
if let Some(min) = self.min_inclusive { if let Some(min) = self.min_inclusive
if x < min { && x < min
return Some(Arg::Num(Err(NotInBounds::LowerBound( {
x.to_number(), return Some(Arg::Num(Err(NotInBounds::LowerBound(
min.to_number(), x.to_number(),
)))); min.to_number(),
} ))));
} }
Some(Arg::Num(Ok(x.to_number()))) Some(Arg::Num(Ok(x.to_number())))
@ -198,7 +198,7 @@ impl ToFromNumber for f64 {
} }
impl GetClientSideArgParser for BoundedNumArgumentConsumer<f64> { impl GetClientSideArgParser for BoundedNumArgumentConsumer<f64> {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Double { ArgumentType::Double {
min: self.min_inclusive, min: self.min_inclusive,
max: self.max_inclusive, max: self.max_inclusive,
@ -226,7 +226,7 @@ impl ToFromNumber for f32 {
} }
impl GetClientSideArgParser for BoundedNumArgumentConsumer<f32> { impl GetClientSideArgParser for BoundedNumArgumentConsumer<f32> {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Float { ArgumentType::Float {
min: self.min_inclusive, min: self.min_inclusive,
max: self.max_inclusive, max: self.max_inclusive,
@ -254,7 +254,7 @@ impl ToFromNumber for i32 {
} }
impl GetClientSideArgParser for BoundedNumArgumentConsumer<i32> { impl GetClientSideArgParser for BoundedNumArgumentConsumer<i32> {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Integer { ArgumentType::Integer {
min: self.min_inclusive, min: self.min_inclusive,
max: self.max_inclusive, max: self.max_inclusive,
@ -282,7 +282,7 @@ impl ToFromNumber for i64 {
} }
impl GetClientSideArgParser for BoundedNumArgumentConsumer<i64> { impl GetClientSideArgParser for BoundedNumArgumentConsumer<i64> {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Long { ArgumentType::Long {
min: self.min_inclusive, min: self.min_inclusive,
max: self.max_inclusive, max: self.max_inclusive,

View File

@ -18,7 +18,7 @@ use super::{Arg, ArgumentConsumer, DefaultNameArgConsumer, FindArg, GetClientSid
pub struct CommandTreeArgumentConsumer; pub struct CommandTreeArgumentConsumer;
impl GetClientSideArgParser for CommandTreeArgumentConsumer { impl GetClientSideArgParser for CommandTreeArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::String(StringProtoArgBehavior::SingleWord) ArgumentType::String(StringProtoArgBehavior::SingleWord)
} }

View File

@ -14,7 +14,7 @@ use super::{Arg, ArgumentConsumer, DefaultNameArgConsumer, FindArg, GetClientSid
pub struct DifficultyArgumentConsumer; pub struct DifficultyArgumentConsumer;
impl GetClientSideArgParser for DifficultyArgumentConsumer { impl GetClientSideArgParser for DifficultyArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::String( ArgumentType::String(
pumpkin_protocol::java::client::play::StringProtoArgBehavior::SingleWord, pumpkin_protocol::java::client::play::StringProtoArgBehavior::SingleWord,
) )

View File

@ -227,9 +227,9 @@ impl FromStr for TargetSelector {
} }
Ok(selector) Ok(selector)
} else if let Ok(uuid) = Uuid::parse_str(arg) { } else if let Ok(uuid) = Uuid::parse_str(arg) {
return Ok(Self::new(EntitySelectorType::Uuid(uuid))); Ok(Self::new(EntitySelectorType::Uuid(uuid)))
} else { } else {
return Ok(Self::new(EntitySelectorType::NamedPlayer(arg.to_string()))); Ok(Self::new(EntitySelectorType::NamedPlayer(arg.to_string())))
} }
} }
} }
@ -240,7 +240,7 @@ impl FromStr for TargetSelector {
pub struct EntitiesArgumentConsumer; pub struct EntitiesArgumentConsumer;
impl GetClientSideArgParser for EntitiesArgumentConsumer { impl GetClientSideArgParser for EntitiesArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// todo: investigate why this does not accept target selectors // todo: investigate why this does not accept target selectors
ArgumentType::Entity { flags: 0 } ArgumentType::Entity { flags: 0 }
} }

View File

@ -20,7 +20,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct EntityArgumentConsumer; pub struct EntityArgumentConsumer;
impl GetClientSideArgParser for EntityArgumentConsumer { impl GetClientSideArgParser for EntityArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// todo: investigate why this does not accept target selectors // todo: investigate why this does not accept target selectors
ArgumentType::Entity { ArgumentType::Entity {
flags: ArgumentType::ENTITY_FLAG_ONLY_SINGLE, flags: ArgumentType::ENTITY_FLAG_ONLY_SINGLE,

View File

@ -14,7 +14,7 @@ use super::{Arg, ArgumentConsumer, DefaultNameArgConsumer, FindArg, GetClientSid
pub struct GamemodeArgumentConsumer; pub struct GamemodeArgumentConsumer;
impl GetClientSideArgParser for GamemodeArgumentConsumer { impl GetClientSideArgParser for GamemodeArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Gamemode ArgumentType::Gamemode
} }
@ -33,10 +33,10 @@ impl ArgumentConsumer for GamemodeArgumentConsumer {
) -> Option<Arg<'a>> { ) -> Option<Arg<'a>> {
let s = args.pop()?; let s = args.pop()?;
if let Ok(id) = s.parse::<i8>() { if let Ok(id) = s.parse::<i8>()
if let Ok(gamemode) = GameMode::try_from(id) { && let Ok(gamemode) = GameMode::try_from(id)
return Some(Arg::GameMode(gamemode)); {
} return Some(Arg::GameMode(gamemode));
} }
GameMode::from_str(s).map_or_else(|_| None, |gamemode| Some(Arg::GameMode(gamemode))) GameMode::from_str(s).map_or_else(|_| None, |gamemode| Some(Arg::GameMode(gamemode)))

View File

@ -17,7 +17,7 @@ use super::{
pub struct MsgArgConsumer; pub struct MsgArgConsumer;
impl GetClientSideArgParser for MsgArgConsumer { impl GetClientSideArgParser for MsgArgConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::String(StringProtoArgBehavior::GreedyPhrase) ArgumentType::String(StringProtoArgBehavior::GreedyPhrase)
} }

View File

@ -73,7 +73,7 @@ pub trait ArgumentConsumer: Sync + GetClientSideArgParser {
pub trait GetClientSideArgParser { pub trait GetClientSideArgParser {
/// Return the parser the client should use while typing a command in chat. /// Return the parser the client should use while typing a command in chat.
fn get_client_side_parser(&self) -> ArgumentType; fn get_client_side_parser(&self) -> ArgumentType<'_>;
/// Usually this should return None. This can be used to force suggestions to be processed on serverside. /// Usually this should return None. This can be used to force suggestions to be processed on serverside.
fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders>; fn get_client_side_suggestion_type_override(&self) -> Option<SuggestionProviders>;
} }

View File

@ -16,7 +16,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct PlayersArgumentConsumer; pub struct PlayersArgumentConsumer;
impl GetClientSideArgParser for PlayersArgumentConsumer { impl GetClientSideArgParser for PlayersArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// todo: investigate why this does not accept target selectors // todo: investigate why this does not accept target selectors
ArgumentType::Entity { ArgumentType::Entity {
flags: ArgumentType::ENTITY_FLAG_PLAYERS_ONLY, flags: ArgumentType::ENTITY_FLAG_PLAYERS_ONLY,

View File

@ -18,7 +18,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct Position2DArgumentConsumer; pub struct Position2DArgumentConsumer;
impl GetClientSideArgParser for Position2DArgumentConsumer { impl GetClientSideArgParser for Position2DArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Vec2 ArgumentType::Vec2
} }

View File

@ -15,7 +15,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct Position3DArgumentConsumer; pub struct Position3DArgumentConsumer;
impl GetClientSideArgParser for Position3DArgumentConsumer { impl GetClientSideArgParser for Position3DArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Vec3 ArgumentType::Vec3
} }

View File

@ -16,7 +16,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct BlockPosArgumentConsumer; pub struct BlockPosArgumentConsumer;
impl GetClientSideArgParser for BlockPosArgumentConsumer { impl GetClientSideArgParser for BlockPosArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::BlockPos ArgumentType::BlockPos
} }

View File

@ -16,7 +16,7 @@ use crate::server::Server;
pub struct DamageTypeArgumentConsumer; pub struct DamageTypeArgumentConsumer;
impl GetClientSideArgParser for DamageTypeArgumentConsumer { impl GetClientSideArgParser for DamageTypeArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Resource { ArgumentType::Resource {
identifier: "damage_type", identifier: "damage_type",
} }

View File

@ -16,7 +16,7 @@ use crate::server::Server;
pub struct EffectTypeArgumentConsumer; pub struct EffectTypeArgumentConsumer;
impl GetClientSideArgParser for EffectTypeArgumentConsumer { impl GetClientSideArgParser for EffectTypeArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Resource { ArgumentType::Resource {
identifier: "mob_effect", identifier: "mob_effect",
} }

View File

@ -16,7 +16,7 @@ use crate::server::Server;
pub struct EnchantmentArgumentConsumer; pub struct EnchantmentArgumentConsumer;
impl GetClientSideArgParser for EnchantmentArgumentConsumer { impl GetClientSideArgParser for EnchantmentArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Resource { ArgumentType::Resource {
identifier: "enchantment", identifier: "enchantment",
} }

View File

@ -17,7 +17,7 @@ use crate::server::Server;
pub struct ItemArgumentConsumer; pub struct ItemArgumentConsumer;
impl GetClientSideArgParser for ItemArgumentConsumer { impl GetClientSideArgParser for ItemArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Resource { identifier: "item" } ArgumentType::Resource { identifier: "item" }
} }

View File

@ -16,7 +16,7 @@ use crate::server::Server;
pub struct ParticleArgumentConsumer; pub struct ParticleArgumentConsumer;
impl GetClientSideArgParser for ParticleArgumentConsumer { impl GetClientSideArgParser for ParticleArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Resource { ArgumentType::Resource {
identifier: "particle_type", identifier: "particle_type",
} }

View File

@ -13,7 +13,7 @@ pub struct ResourceLocationArgumentConsumer {
} }
impl GetClientSideArgParser for ResourceLocationArgumentConsumer { impl GetClientSideArgParser for ResourceLocationArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -13,7 +13,7 @@ use super::{Arg, DefaultNameArgConsumer, FindArg, GetClientSideArgParser};
pub struct RotationArgumentConsumer; pub struct RotationArgumentConsumer;
impl GetClientSideArgParser for RotationArgumentConsumer { impl GetClientSideArgParser for RotationArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Rotation ArgumentType::Rotation
} }

View File

@ -18,7 +18,7 @@ use super::{
pub struct SimpleArgConsumer; pub struct SimpleArgConsumer;
impl GetClientSideArgParser for SimpleArgConsumer { impl GetClientSideArgParser for SimpleArgConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::String(StringProtoArgBehavior::SingleWord) ArgumentType::String(StringProtoArgBehavior::SingleWord)
} }

View File

@ -16,7 +16,7 @@ use super::{
pub struct SoundArgumentConsumer; pub struct SoundArgumentConsumer;
impl GetClientSideArgParser for SoundArgumentConsumer { impl GetClientSideArgParser for SoundArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -13,7 +13,7 @@ use pumpkin_protocol::java::client::play::{ArgumentType, CommandSuggestion, Sugg
pub struct SoundCategoryArgumentConsumer; pub struct SoundCategoryArgumentConsumer;
impl GetClientSideArgParser for SoundCategoryArgumentConsumer { impl GetClientSideArgParser for SoundCategoryArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
// ResourceLocation is used for enumerated string values // ResourceLocation is used for enumerated string values
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -16,7 +16,7 @@ use super::{
pub struct SummonableEntitiesArgumentConsumer; pub struct SummonableEntitiesArgumentConsumer;
impl GetClientSideArgParser for SummonableEntitiesArgumentConsumer { impl GetClientSideArgParser for SummonableEntitiesArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::ResourceLocation ArgumentType::ResourceLocation
} }

View File

@ -10,7 +10,7 @@ use pumpkin_util::text::TextComponent;
pub struct TextComponentArgConsumer; pub struct TextComponentArgConsumer;
impl GetClientSideArgParser for TextComponentArgConsumer { impl GetClientSideArgParser for TextComponentArgConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Component ArgumentType::Component
} }

View File

@ -12,7 +12,7 @@ use crate::server::Server;
pub struct TimeArgumentConsumer; pub struct TimeArgumentConsumer;
impl GetClientSideArgParser for TimeArgumentConsumer { impl GetClientSideArgParser for TimeArgumentConsumer {
fn get_client_side_parser(&self) -> ArgumentType { fn get_client_side_parser(&self) -> ArgumentType<'_> {
ArgumentType::Time { min: 0 } ArgumentType::Time { min: 0 }
} }

View File

@ -86,10 +86,10 @@ impl CommandExecutor for Executor {
for y in start_y..=end_y { for y in start_y..=end_y {
for z in start_z..=end_z { for z in start_z..=end_z {
let block_position = BlockPos(Vector3::new(x, y, z)); let block_position = BlockPos(Vector3::new(x, y, z));
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) { && not_in_filter(filter, world.get_block(&block_position).await)
continue; {
} continue;
} }
world world
.break_block( .break_block(
@ -116,10 +116,10 @@ impl CommandExecutor for Executor {
for y in start_y..=end_y { for y in start_y..=end_y {
for z in start_z..=end_z { for z in start_z..=end_z {
let block_position = BlockPos(Vector3::new(x, y, z)); let block_position = BlockPos(Vector3::new(x, y, z));
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) { && not_in_filter(filter, world.get_block(&block_position).await)
continue; {
} continue;
} }
world world
.set_block_state( .set_block_state(
@ -141,11 +141,10 @@ impl CommandExecutor for Executor {
let block_position = BlockPos(Vector3::new(x, y, z)); let block_position = BlockPos(Vector3::new(x, y, z));
let old_state = world.get_block_state(&block_position).await; let old_state = world.get_block_state(&block_position).await;
if old_state.is_air() { if old_state.is_air() {
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) && not_in_filter(filter, world.get_block(&block_position).await)
{ {
continue; continue;
}
} }
world world
.set_block_state( .set_block_state(
@ -172,10 +171,10 @@ impl CommandExecutor for Executor {
|| y == end_y || y == end_y
|| z == start_z || z == start_z
|| z == end_z; || z == end_z;
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) { && not_in_filter(filter, world.get_block(&block_position).await)
continue; {
} continue;
} }
if is_edge { if is_edge {
world world
@ -210,10 +209,10 @@ impl CommandExecutor for Executor {
if !is_edge { if !is_edge {
continue; continue;
} }
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) { && not_in_filter(filter, world.get_block(&block_position).await)
continue; {
} continue;
} }
world world
.set_block_state( .set_block_state(
@ -233,10 +232,10 @@ impl CommandExecutor for Executor {
for y in start_y..=end_y { for y in start_y..=end_y {
for z in start_z..=end_z { for z in start_z..=end_z {
let block_position = BlockPos(Vector3::new(x, y, z)); let block_position = BlockPos(Vector3::new(x, y, z));
if let Some(filter) = &option_filter { if let Some(filter) = &option_filter
if not_in_filter(filter, world.get_block(&block_position).await) { && not_in_filter(filter, world.get_block(&block_position).await)
continue; {
} continue;
} }
world world
.set_block_state( .set_block_state(

View File

@ -428,10 +428,10 @@ impl CommandDispatcher {
for (key, value) in &self.commands { for (key, value) in &self.commands {
if key == name { if key == name {
to_remove.push(key.clone()); to_remove.push(key.clone());
} else if let Command::Alias(target) = value { } else if let Command::Alias(target) = value
if target == name { && target == name
to_remove.push(key.clone()); {
} to_remove.push(key.clone());
} }
} }

View File

@ -141,12 +141,12 @@ impl Goal for LookAtEntityGoal {
async fn tick(&self, mob: &dyn Mob) { async fn tick(&self, mob: &dyn Mob) {
let mob = mob.get_mob_entity(); let mob = mob.get_mob_entity();
if let Some(target) = self.target.lock().await.as_ref() { if let Some(target) = self.target.lock().await.as_ref()
if target.get_entity().is_alive() { && target.get_entity().is_alive()
let target_pos = target.get_entity().pos.load(); {
mob.living_entity.entity.look_at(target_pos).await; let target_pos = target.get_entity().pos.load();
self.look_time.fetch_sub(1, Relaxed); mob.living_entity.entity.look_at(target_pos).await;
} self.look_time.fetch_sub(1, Relaxed);
} }
} }

View File

@ -702,12 +702,14 @@ impl LivingEntity {
) -> TextComponent { ) -> TextComponent {
match damage_type.death_message_type { match damage_type.death_message_type {
DeathMessageType::Default => { DeathMessageType::Default => {
if cause.is_some() && source.is_some() { if let Some(cause) = cause
&& source.is_some()
{
TextComponent::translate( TextComponent::translate(
format!("death.attack.{}.player", damage_type.message_id), format!("death.attack.{}.player", damage_type.message_id),
[ [
dyn_self.get_display_name().await, dyn_self.get_display_name().await,
cause.unwrap().get_display_name().await, cause.get_display_name().await,
], ],
) )
} else { } else {

View File

@ -990,13 +990,11 @@ impl Entity {
let in_lava = in_fluid[1]; let in_lava = in_fluid[1];
if in_lava { if in_lava && let Some(living) = caller.get_living_entity() {
if let Some(living) = caller.get_living_entity() { let halved_fall = living.fall_distance.load() / 2.0;
let halved_fall = living.fall_distance.load() / 2.0;
if halved_fall != 0.0 { if halved_fall != 0.0 {
living.fall_distance.store(halved_fall); living.fall_distance.store(halved_fall);
}
} }
} }

View File

@ -541,10 +541,11 @@ impl Player {
block_pos: BlockPos, block_pos: BlockPos,
yaw: f32, yaw: f32,
) -> bool { ) -> bool {
if let Some(respawn_point) = self.respawn_point.load() { if let Some(respawn_point) = self.respawn_point.load()
if dimension == respawn_point.dimension && block_pos == respawn_point.position { && dimension == respawn_point.dimension
return false; && block_pos == respawn_point.position
} {
return false;
} }
self.respawn_point.store(Some(RespawnPoint { self.respawn_point.store(Some(RespawnPoint {
@ -802,10 +803,10 @@ impl Player {
} }
self.tick_counter.fetch_add(1, Ordering::Relaxed); self.tick_counter.fetch_add(1, Ordering::Relaxed);
if let Some(sleeping_since) = self.sleeping_since.load() { if let Some(sleeping_since) = self.sleeping_since.load()
if sleeping_since < 101 { && sleeping_since < 101
self.sleeping_since.store(Some(sleeping_since + 1)); {
} self.sleeping_since.store(Some(sleeping_since + 1));
} }
if self.mining.load(Ordering::Relaxed) { if self.mining.load(Ordering::Relaxed) {
@ -2006,46 +2007,46 @@ impl NBTStorage for PlayerInventory {
// Process inventory list // Process inventory list
if let Some(inventory_list) = nbt.get_list("Inventory") { if let Some(inventory_list) = nbt.get_list("Inventory") {
for tag in inventory_list { for tag in inventory_list {
if let Some(item_compound) = tag.extract_compound() { if let Some(item_compound) = tag.extract_compound()
if let Some(slot_byte) = item_compound.get_byte("Slot") { && let Some(slot_byte) = item_compound.get_byte("Slot")
let slot = slot_byte as usize; {
if let Some(item_stack) = ItemStack::read_item_stack(item_compound) { let slot = slot_byte as usize;
self.set_stack(slot, item_stack).await; if let Some(item_stack) = ItemStack::read_item_stack(item_compound) {
} self.set_stack(slot, item_stack).await;
} }
} }
} }
} }
if let Some(equipment) = nbt.get_compound("equipment") { if let Some(equipment) = nbt.get_compound("equipment") {
if let Some(offhand) = equipment.get_compound("offhand") { if let Some(offhand) = equipment.get_compound("offhand")
if let Some(item_stack) = ItemStack::read_item_stack(offhand) { && let Some(item_stack) = ItemStack::read_item_stack(offhand)
self.set_stack(40, item_stack).await; {
} self.set_stack(40, item_stack).await;
} }
if let Some(head) = equipment.get_compound("head") { if let Some(head) = equipment.get_compound("head")
if let Some(item_stack) = ItemStack::read_item_stack(head) { && let Some(item_stack) = ItemStack::read_item_stack(head)
self.set_stack(39, item_stack).await; {
} self.set_stack(39, item_stack).await;
} }
if let Some(chest) = equipment.get_compound("chest") { if let Some(chest) = equipment.get_compound("chest")
if let Some(item_stack) = ItemStack::read_item_stack(chest) { && let Some(item_stack) = ItemStack::read_item_stack(chest)
self.set_stack(38, item_stack).await; {
} self.set_stack(38, item_stack).await;
} }
if let Some(legs) = equipment.get_compound("legs") { if let Some(legs) = equipment.get_compound("legs")
if let Some(item_stack) = ItemStack::read_item_stack(legs) { && let Some(item_stack) = ItemStack::read_item_stack(legs)
self.set_stack(37, item_stack).await; {
} self.set_stack(37, item_stack).await;
} }
if let Some(feet) = equipment.get_compound("feet") { if let Some(feet) = equipment.get_compound("feet")
if let Some(item_stack) = ItemStack::read_item_stack(feet) { && let Some(item_stack) = ItemStack::read_item_stack(feet)
self.set_stack(36, item_stack).await; {
} self.set_stack(36, item_stack).await;
} }
} }
} }

View File

@ -22,7 +22,6 @@ use crate::world::World;
pub struct EmptyBucketItem; pub struct EmptyBucketItem;
pub struct FilledBucketItem; pub struct FilledBucketItem;
pub struct MilkBucketItem;
impl ItemMetadata for EmptyBucketItem { impl ItemMetadata for EmptyBucketItem {
fn ids() -> Box<[u16]> { fn ids() -> Box<[u16]> {
@ -47,11 +46,11 @@ impl ItemMetadata for FilledBucketItem {
} }
} }
impl ItemMetadata for MilkBucketItem { // impl ItemMetadata for MilkBucketItem {
fn ids() -> Box<[u16]> { // fn ids() -> Box<[u16]> {
[Item::MILK_BUCKET.id].into() // [Item::MILK_BUCKET.id].into()
} // }
} // }
fn get_start_and_end_pos(player: &Player) -> (Vector3<f64>, Vector3<f64>) { fn get_start_and_end_pos(player: &Player) -> (Vector3<f64>, Vector3<f64>) {
let start_pos = player.eye_position(); let start_pos = player.eye_position();

View File

@ -35,11 +35,11 @@ impl ItemBehaviour for HoneyCombItem {
// First we try to strip the block. by getting his equivalent and applying it the axis. // First we try to strip the block. by getting his equivalent and applying it the axis.
let replacement_block = get_waxed_equivalent(block); let replacement_block = get_waxed_equivalent(block);
// If there is a strip equivalent. // If there is a strip equivalent.
if replacement_block.is_some() { if let Some(replacement_block) = replacement_block {
// get block state of the old log. // get block state of the old log.
// get the log properties // get the log properties
// create new properties for the new log. // create new properties for the new log.
let new_block = &Block::from_id(replacement_block.unwrap()); let new_block = &Block::from_id(replacement_block);
let new_state_id = if block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_DOORS) let new_state_id = if block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_DOORS)
&& block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_DOORS) && block.is_tagged_with_by_tag(&tag::Block::MINECRAFT_DOORS)

View File

@ -175,18 +175,18 @@ impl PumpkinServer {
let mut ticker = Ticker::new(); let mut ticker = Ticker::new();
if advanced_config().commands.use_console { if advanced_config().commands.use_console
if let Some((wrapper, _)) = &*LOGGER_IMPL { && let Some((wrapper, _)) = &*LOGGER_IMPL
if let Some(rl) = wrapper.take_readline() { {
setup_console(rl, server.clone()); if let Some(rl) = wrapper.take_readline() {
} else { setup_console(rl, server.clone());
if advanced_config().commands.use_tty { } else {
log::warn!( if advanced_config().commands.use_tty {
"The input is not a TTY; falling back to simple logger and ignoring `use_tty` setting" log::warn!(
); "The input is not a TTY; falling back to simple logger and ignoring `use_tty` setting"
} );
setup_stdin_console(server.clone()).await;
} }
setup_stdin_console(server.clone()).await;
} }
} }
@ -311,10 +311,10 @@ impl PumpkinServer {
log::info!("Completed save!"); log::info!("Completed save!");
// Explicitly drop the line reader to return the terminal to the original state. // Explicitly drop the line reader to return the terminal to the original state.
if let Some((wrapper, _)) = &*LOGGER_IMPL { if let Some((wrapper, _)) = &*LOGGER_IMPL
if let Some(rl) = wrapper.take_readline() { && let Some(rl) = wrapper.take_readline()
let _ = rl; {
} let _ = rl;
} }
} }

View File

@ -213,19 +213,19 @@ impl ReadlineLogWrapper {
impl Log for ReadlineLogWrapper { impl Log for ReadlineLogWrapper {
fn log(&self, record: &log::Record) { fn log(&self, record: &log::Record) {
self.internal.log(record); self.internal.log(record);
if let Ok(mut lock) = self.readline.lock() { if let Ok(mut lock) = self.readline.lock()
if let Some(rl) = lock.as_mut() { && let Some(rl) = lock.as_mut()
let _ = rl.flush(); {
} let _ = rl.flush();
} }
} }
fn flush(&self) { fn flush(&self) {
self.internal.flush(); self.internal.flush();
if let Ok(mut lock) = self.readline.lock() { if let Ok(mut lock) = self.readline.lock()
if let Some(rl) = lock.as_mut() { && let Some(rl) = lock.as_mut()
let _ = rl.flush(); {
} let _ = rl.flush();
} }
} }

View File

@ -31,7 +31,7 @@ impl BedrockClient {
&CConnectionRequestAccepted::new( &CConnectionRequestAccepted::new(
self.address, self.address,
0, 0,
[SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::new(0, 0, 0, 0), 19132)); 10], [SocketAddr::V4(SocketAddrV4::new(Ipv4Addr::UNSPECIFIED, 19132)); 10],
packet.time, packet.time,
UNIX_EPOCH.elapsed().unwrap().as_millis() as u64, UNIX_EPOCH.elapsed().unwrap().as_millis() as u64,
), ),

View File

@ -170,13 +170,13 @@ impl BedrockClient {
pub async fn process_packet(self: &Arc<Self>, server: &Server, packet: Cursor<Vec<u8>>) { pub async fn process_packet(self: &Arc<Self>, server: &Server, packet: Cursor<Vec<u8>>) {
let packet = self.get_packet_payload(packet).await; let packet = self.get_packet_payload(packet).await;
if let Some(packet) = packet { if let Some(packet) = packet
if let Err(error) = self.handle_packet_payload(server, packet).await { && let Err(error) = self.handle_packet_payload(server, packet).await
let _text = format!("Error while reading incoming packet {error}"); {
log::error!("Failed to read incoming packet with : {error}"); let _text = format!("Error while reading incoming packet {error}");
self.kick(DisconnectReason::BadPacket, error.to_string()) log::error!("Failed to read incoming packet with : {error}");
.await; self.kick(DisconnectReason::BadPacket, error.to_string())
} .await;
} }
} }

View File

@ -756,10 +756,10 @@ impl JavaClient {
gameprofile.id, gameprofile.id,
err err
); );
if err.is_kick() { if err.is_kick()
if let Some(reason) = err.client_kick_reason() { && let Some(reason) = err.client_kick_reason()
self.kick(TextComponent::text(reason)).await; {
} self.kick(TextComponent::text(reason)).await;
} }
return; return;
} }
@ -879,10 +879,10 @@ impl JavaClient {
player.gameprofile.id, player.gameprofile.id,
err err
); );
if err.is_kick() { if err.is_kick()
if let Some(reason) = err.client_kick_reason() { && let Some(reason) = err.client_kick_reason()
self.kick(TextComponent::text(reason)).await; {
} self.kick(TextComponent::text(reason)).await;
} }
return; return;
} }

View File

@ -108,75 +108,74 @@ async fn handle_packet(
} }
} }
PacketType::Status => { PacketType::Status => {
if let Ok(packet) = SStatusRequest::decode(&mut raw_packet).await { if let Ok(packet) = SStatusRequest::decode(&mut raw_packet).await
if clients && clients
.read() .read()
.await .await
.get(&packet.challenge_token) .get(&packet.challenge_token)
.is_some_and(|token_bound_ip: &SocketAddr| token_bound_ip == &addr) .is_some_and(|token_bound_ip: &SocketAddr| token_bound_ip == &addr)
{ {
if packet.is_full_request { if packet.is_full_request {
// Get 4 players // Get 4 players
let mut players: Vec<CString> = Vec::new(); let mut players: Vec<CString> = Vec::new();
for world in server.worlds.read().await.iter() { for world in server.worlds.read().await.iter() {
let mut world_players = world let mut world_players = world
.players .players
.read() .read()
.await
// Although there is no documented limit, we will limit to 4 players
.values()
.take(4 - players.len())
.map(|player| {
CString::new(player.gameprofile.name.as_str()).unwrap()
})
.collect::<Vec<_>>();
players.append(&mut world_players); // Append players from this world
if players.len() >= 4 {
break; // Stop if we've collected 4 players
}
}
let plugins = PLUGIN_MANAGER
.active_plugins()
.await .await
.into_iter() // Although there is no documented limit, we will limit to 4 players
.map(|meta| meta.name.to_string()) .values()
.reduce(|acc, name| format!("{acc}, {name}")) .take(4 - players.len())
.unwrap_or_default(); .map(|player| {
CString::new(player.gameprofile.name.as_str()).unwrap()
})
.collect::<Vec<_>>();
let response = CFullStatus { players.append(&mut world_players); // Append players from this world
session_id: packet.session_id,
hostname: CString::new(BASIC_CONFIG.motd.as_str())?,
version: CString::new(CURRENT_MC_VERSION)?,
plugins: CString::new(plugins)?,
map: CString::new("world")?, // TODO: Get actual world name
num_players: server.get_player_count().await,
max_players: BASIC_CONFIG.max_players as usize,
host_port: bound_addr.port(),
host_ip: CString::new(bound_addr.ip().to_string())?,
players,
};
let _ = socket if players.len() >= 4 {
.send_to(response.encode().await.as_slice(), addr) break; // Stop if we've collected 4 players
.await; }
} else {
let response = CBasicStatus {
session_id: packet.session_id,
motd: CString::new(BASIC_CONFIG.motd.as_str())?,
map: CString::new("world")?,
num_players: server.get_player_count().await,
max_players: BASIC_CONFIG.max_players as usize,
host_port: bound_addr.port(),
host_ip: CString::new(bound_addr.ip().to_string())?,
};
let _ = socket
.send_to(response.encode().await.as_slice(), addr)
.await;
} }
let plugins = PLUGIN_MANAGER
.active_plugins()
.await
.into_iter()
.map(|meta| meta.name.to_string())
.reduce(|acc, name| format!("{acc}, {name}"))
.unwrap_or_default();
let response = CFullStatus {
session_id: packet.session_id,
hostname: CString::new(BASIC_CONFIG.motd.as_str())?,
version: CString::new(CURRENT_MC_VERSION)?,
plugins: CString::new(plugins)?,
map: CString::new("world")?, // TODO: Get actual world name
num_players: server.get_player_count().await,
max_players: BASIC_CONFIG.max_players as usize,
host_port: bound_addr.port(),
host_ip: CString::new(bound_addr.ip().to_string())?,
players,
};
let _ = socket
.send_to(response.encode().await.as_slice(), addr)
.await;
} else {
let response = CBasicStatus {
session_id: packet.session_id,
motd: CString::new(BASIC_CONFIG.motd.as_str())?,
map: CString::new("world")?,
num_players: server.get_player_count().await,
max_players: BASIC_CONFIG.max_players as usize,
host_port: bound_addr.port(),
host_ip: CString::new(bound_addr.ip().to_string())?,
};
let _ = socket
.send_to(response.encode().await.as_slice(), addr)
.await;
} }
} }
} }

View File

@ -46,7 +46,7 @@ impl CachedBranding {
cached_server_brand, cached_server_brand,
} }
} }
pub fn get_branding(&self) -> CPluginMessage { pub fn get_branding(&self) -> CPluginMessage<'_> {
CPluginMessage::new("minecraft:brand", &self.cached_server_brand) CPluginMessage::new("minecraft:brand", &self.cached_server_brand)
} }
const BRAND: &str = "Pumpkin"; const BRAND: &str = "Pumpkin";

View File

@ -62,10 +62,10 @@ impl Ticker {
Duration::from_nanos(manager.nanoseconds_per_tick() as u64) Duration::from_nanos(manager.nanoseconds_per_tick() as u64)
}; };
if let Some(sleep_time) = tick_interval.checked_sub(elapsed) { if let Some(sleep_time) = tick_interval.checked_sub(elapsed)
if !sleep_time.is_zero() { && !sleep_time.is_zero()
sleep(sleep_time).await; {
} sleep(sleep_time).await;
} }
self.last_tick = Instant::now(); self.last_tick = Instant::now();

View File

@ -108,7 +108,7 @@ impl CustomBossbars {
&mut self, &mut self,
server: &Server, server: &Server,
resource_location: String, resource_location: String,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_cloned(&resource_location); let bossbar = self.custom_bossbars.get_cloned(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
self.custom_bossbars.remove(&resource_location); self.custom_bossbars.remove(&resource_location);
@ -144,7 +144,7 @@ impl CustomBossbars {
resource_location: String, resource_location: String,
max_value: u32, max_value: u32,
value: u32, value: u32,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(&resource_location); let bossbar = self.custom_bossbars.get_mut(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
if bossbar.value == value && bossbar.max == max_value { if bossbar.value == value && bossbar.max == max_value {
@ -193,7 +193,7 @@ impl CustomBossbars {
server: &Server, server: &Server,
resource_location: String, resource_location: String,
new_visibility: bool, new_visibility: bool,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(&resource_location); let bossbar = self.custom_bossbars.get_mut(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
if bossbar.visible == new_visibility && new_visibility { if bossbar.visible == new_visibility && new_visibility {
@ -232,7 +232,7 @@ impl CustomBossbars {
server: &Server, server: &Server,
resource_location: &str, resource_location: &str,
new_title: TextComponent, new_title: TextComponent,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(resource_location); let bossbar = self.custom_bossbars.get_mut(resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
if bossbar.bossbar_data.title == new_title { if bossbar.bossbar_data.title == new_title {
@ -271,7 +271,7 @@ impl CustomBossbars {
server: &Server, server: &Server,
resource_location: String, resource_location: String,
new_color: BossbarColor, new_color: BossbarColor,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(&resource_location); let bossbar = self.custom_bossbars.get_mut(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
if bossbar.bossbar_data.color == new_color { if bossbar.bossbar_data.color == new_color {
@ -311,7 +311,7 @@ impl CustomBossbars {
server: &Server, server: &Server,
resource_location: String, resource_location: String,
new_division: BossbarDivisions, new_division: BossbarDivisions,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(&resource_location); let bossbar = self.custom_bossbars.get_mut(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
if bossbar.bossbar_data.division == new_division { if bossbar.bossbar_data.division == new_division {
@ -351,7 +351,7 @@ impl CustomBossbars {
server: &Server, server: &Server,
resource_location: String, resource_location: String,
new_players: Vec<Uuid>, new_players: Vec<Uuid>,
) -> Result<(), BossbarUpdateError> { ) -> Result<(), BossbarUpdateError<'_>> {
let bossbar = self.custom_bossbars.get_mut(&resource_location); let bossbar = self.custom_bossbars.get_mut(&resource_location);
if let Some(bossbar) = bossbar { if let Some(bossbar) = bossbar {
// Get the difference between the old and new player list and remove bossbars from old players. // Get the difference between the old and new player list and remove bossbars from old players.

View File

@ -53,20 +53,20 @@ trait LootPoolEntryExt {
impl LootPoolEntryExt for LootPoolEntry { impl LootPoolEntryExt for LootPoolEntry {
fn get_loot(&self, params: &LootContextParameters) -> Option<Vec<ItemStack>> { fn get_loot(&self, params: &LootContextParameters) -> Option<Vec<ItemStack>> {
if let Some(conditions) = self.conditions { if let Some(conditions) = self.conditions
if !conditions.iter().all(|cond| cond.is_fulfilled(params)) { && !conditions.iter().all(|cond| cond.is_fulfilled(params))
return None; {
} return None;
} }
let mut stacks = self.content.get_stacks(params); let mut stacks = self.content.get_stacks(params);
if let Some(functions) = self.functions { if let Some(functions) = self.functions {
for function in functions { for function in functions {
if let Some(conditions) = function.conditions { if let Some(conditions) = function.conditions
if !conditions.iter().all(|cond| cond.is_fulfilled(params)) { && !conditions.iter().all(|cond| cond.is_fulfilled(params))
continue; {
} continue;
} }
match &function.content { match &function.content {

View File

@ -3061,10 +3061,10 @@ impl World {
let mut block = BlockPos::floored(from.x, from.y, from.z); let mut block = BlockPos::floored(from.x, from.y, from.z);
let (collision, direction) = self.ray_outline_check(&block, from, to).await; let (collision, direction) = self.ray_outline_check(&block, from, to).await;
if let Some(dir) = direction { if let Some(dir) = direction
if collision { && collision
return Some((block, dir)); {
} return Some((block, dir));
} }
let difference = to.sub(&from); let difference = to.sub(&from);

View File

@ -16,10 +16,10 @@ impl EndPortal {
pub async fn get_new_portal(world: &Arc<World>, pos: BlockPos) { pub async fn get_new_portal(world: &Arc<World>, pos: BlockPos) {
let mid_pos = Self::get_mid_pos(world, pos); let mid_pos = Self::get_mid_pos(world, pos);
if let Some(mid_pos) = mid_pos.await { if let Some(mid_pos) = mid_pos.await
if Self::is_valid_portal(world, mid_pos).await { && Self::is_valid_portal(world, mid_pos).await
Self::create_portal(world, mid_pos).await; {
} Self::create_portal(world, mid_pos).await;
} }
} }

View File

@ -71,20 +71,22 @@ impl NetherPortal {
first_axis: HorizontalAxis, first_axis: HorizontalAxis,
) -> Option<Self> { ) -> Option<Self> {
// We check both axis here X and Z // We check both axis here X and Z
if let Some(portal) = Self::get_on_axis(world, pos, first_axis).await { if let Some(portal) = Self::get_on_axis(world, pos, first_axis).await
if portal.is_valid() && portal.found_portal_blocks == 0 { && portal.is_valid()
return Some(portal); && portal.found_portal_blocks == 0
} {
return Some(portal);
} }
let next_axis = if first_axis == HorizontalAxis::X { let next_axis = if first_axis == HorizontalAxis::X {
HorizontalAxis::Z HorizontalAxis::Z
} else { } else {
HorizontalAxis::X HorizontalAxis::X
}; };
if let Some(portal) = Self::get_on_axis(world, pos, next_axis).await { if let Some(portal) = Self::get_on_axis(world, pos, next_axis).await
if portal.is_valid() && portal.found_portal_blocks == 0 { && portal.is_valid()
return Some(portal); && portal.found_portal_blocks == 0
} {
return Some(portal);
} }
None None
} }