diff --git a/CHANGELOG.md b/CHANGELOG.md
index d13dc3a0a..42ff92898 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -14,6 +14,17 @@ Unless otherwise specified, any version comparison below is the comparison of se
[Compare with 0.1.1](https://github.com/AllayMC/Allay/compare/0.1.1...HEAD)
+### Added
+
+- (API) Added an extra argument to `Dimension#breakBlock` method to control if the block breaking particle should be
+ played.
+
+### Fixed
+
+- (API) Corrected the return type of `Dimension#breakBlock(Vector3ic, ItemStack, Entity)` from `void` to `boolean`. Some
+ overloads for this method are also added.
+- Block breaking particle won't be sent if block is broken by flowing liquid.
+
## 0.1.1 (API 0.2.0)
[Compare with 0.1.0](https://github.com/AllayMC/Allay/compare/0.1.0...0.1.1)
diff --git a/api/src/main/java/org/allaymc/api/world/Dimension.java b/api/src/main/java/org/allaymc/api/world/Dimension.java
index 578c5eeb1..afa7960c7 100644
--- a/api/src/main/java/org/allaymc/api/world/Dimension.java
+++ b/api/src/main/java/org/allaymc/api/world/Dimension.java
@@ -982,22 +982,40 @@ default void dropXpOrb(Vector3fc pos, int xp, Vector3fc motion, int pickupDelay)
getEntityService().addEntity(entityXpOrb);
}
- default void breakBlock(Vector3ic pos, ItemStack usedItem, Entity entity) {
- breakBlock(pos.x(), pos.y(), pos.z(), usedItem, entity);
+ /**
+ * @see #breakBlock(int, int, int, ItemStack, Entity, boolean)
+ */
+ default boolean breakBlock(Vector3ic pos, ItemStack usedItem, Entity entity) {
+ return breakBlock(pos.x(), pos.y(), pos.z(), usedItem, entity);
+ }
+
+ /**
+ * @see #breakBlock(int, int, int, ItemStack, Entity, boolean)
+ */
+ default boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity) {
+ return breakBlock(x, y, z, usedItem, entity, true);
+ }
+
+ /**
+ * @see #breakBlock(int, int, int, ItemStack, Entity, boolean)
+ */
+ default boolean breakBlock(Vector3ic pos, ItemStack usedItem, Entity entity, boolean hasParticle) {
+ return breakBlock(pos.x(), pos.y(), pos.z(), usedItem, entity, hasParticle);
}
/**
* Break a block at the specified position.
*
- * @param x The x coordinate of the block.
- * @param y The y coordinate of the block.
- * @param z The z coordinate of the block.
- * @param usedItem The item used to break the block, can be {@code null}.
- * @param entity The player who breaks the block, can be {@code null}.
+ * @param x The x coordinate of the block.
+ * @param y The y coordinate of the block.
+ * @param z The z coordinate of the block.
+ * @param usedItem The item used to break the block, can be {@code null}.
+ * @param entity The player who breaks the block, can be {@code null}.
+ * @param sendParticle Whether to send the break particle.
*
* @return Whether the block is successfully broken.
*/
- boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity);
+ boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity, boolean sendParticle);
/**
* Get the height of the highest non-air block at the specified x and z coordinates.
diff --git a/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java b/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java
index 9a82d6961..366cc7ea7 100644
--- a/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java
+++ b/server/src/main/java/org/allaymc/server/block/component/BlockLiquidBaseComponentImpl.java
@@ -289,7 +289,7 @@ protected boolean flowInto(Dimension dimension, Vector3ic src, int srcLayer, Blo
if (removedOnTouch) {
switch (liquidReactionOnTouch) {
case BROKEN -> dimension.setBlockState(pos, BlockTypes.AIR.getDefaultState());
- case POPPED -> dimension.breakBlock(pos, null, null);
+ case POPPED -> dimension.breakBlock(pos, null, null, false);
}
}
setLiquidInWorld(dimension, pos, getLiquidBlockState(newDepth, falling));
diff --git a/server/src/main/java/org/allaymc/server/world/AllayDimension.java b/server/src/main/java/org/allaymc/server/world/AllayDimension.java
index 6670510c0..f8c2ed44a 100644
--- a/server/src/main/java/org/allaymc/server/world/AllayDimension.java
+++ b/server/src/main/java/org/allaymc/server/world/AllayDimension.java
@@ -139,7 +139,7 @@ public void setBlockState(int x, int y, int z, BlockState blockState, int layer,
}
@Override
- public boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity) {
+ public boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity, boolean sendParticle) {
var block = getBlockState(x, y, z);
if (block.getBlockType() == AIR) {
return false;
@@ -149,13 +149,17 @@ public boolean breakBlock(int x, int y, int z, ItemStack usedItem, Entity entity
new BlockStateWithPos(block, new Position3i(x, y, z, this), 0),
usedItem, entity
);
- if (!event.call()) return false;
+ if (!event.call()) {
+ return false;
+ }
- var pk = new LevelEventPacket();
- pk.setType(LevelEvent.PARTICLE_DESTROY_BLOCK);
- pk.setPosition(Vector3f.from(x + 0.5f, y + 0.5f, z + 0.5f));
- pk.setData(block.blockStateHash());
- getChunkService().getChunkByDimensionPos(x, z).addChunkPacket(pk);
+ if (sendParticle) {
+ var pk = new LevelEventPacket();
+ pk.setType(LevelEvent.PARTICLE_DESTROY_BLOCK);
+ pk.setPosition(Vector3f.from(x + 0.5f, y + 0.5f, z + 0.5f));
+ pk.setData(block.blockStateHash());
+ getChunkService().getChunkByDimensionPos(x, z).addChunkPacket(pk);
+ }
block.getBehavior().onBreak(
new BlockStateWithPos(block, new Position3i(x, y, z, this), 0),