Compare commits

...

13 Commits

Author SHA1 Message Date
Helvetica Volubi fa1ab90579 fix a ConcurrentModificationException caused by ServuxStructuresProtocol
Update Luminol
2025-11-30 15:53:28 +08:00
Creeam fc9c6937b6 Add LeavesConfig dummy class (#99)
For some plugin detections
2025-11-30 07:28:01 +00:00
Helvetica Volubi 12d8ba9050 Update Luminol 2025-11-29 06:03:01 +08:00
Helvetica Volubi 38a1ce0443 fix: fix crash caused by uncheck data access 2025-11-26 22:32:20 +08:00
dependabot[bot] a5a415e495 build(deps): bump actions/checkout from 5 to 6 (#93)
Bumps [actions/checkout](https://github.com/actions/checkout) from 5 to 6.
- [Release notes](https://github.com/actions/checkout/releases)
- [Changelog](https://github.com/actions/checkout/blob/main/CHANGELOG.md)
- [Commits](https://github.com/actions/checkout/compare/v5...v6)

---
updated-dependencies:
- dependency-name: actions/checkout
  dependency-version: '6'
  dependency-type: direct:production
  update-type: version-update:semver-major
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2025-11-24 08:21:49 +00:00
Helvetica Volubi b7bf1b5916 Update Luminol 2025-11-24 00:16:50 +08:00
Helvetica Volubi 4a8888c578 try fixes bugs caused by Bukkit.getScheduler().runTaskLater
we use (FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed to instead of Bukkit.getScheduler().runTaskLater, and we also provided a brand-new way to cancel task by task id
2025-11-22 01:57:16 +08:00
Helvetica Volubi 2c59a32afe [ci skip] Update context 2025-11-20 15:36:46 +08:00
Helvetica Volubi cc5382977d Update Luminol 2025-11-20 15:32:41 +08:00
xiaoxijun c07dde1c0b feat: CCE Update Suppression support and other dependences (#84)
add cce update suppression & prevent crashes caused by update suppres & dustTrapdoorReintroduced & instantBlockUpdater & old Block remove behaviour & do not reset placed block on exception & do not prevent block entity and entity crash at LevelChunk (#84)

* add cce update suppression & prevent crashes caused by update suppression

* no need for this transformed flag

* Add Redstone ignore upwards update

* fix up license

* move config

* instant Block Updater

* feat: Update Suppression!

* Leaves: Do not reset placed block on exception & Do not prevent block entity and entity crash at LevelChunk

---------

Co-authored-by: Helvetica Volubi <suisuroru@blue-millennium.fun>
Co-authored-by: Helvetica Volubi <88063803+Suisuroru@users.noreply.github.com>
2025-11-19 00:04:34 +08:00
Helvetica Volubi 871a003a2e Update Luminol to fix open-gui bug 2025-11-17 17:54:27 +08:00
Helvetica Volubi d6a981a6e9 [ci skip] skip release and push in unexpect branch
See https://github.com/LuminolMC/Luminol/commit/ec746a66f0813f60eb59de11b8207f773fc4728c
2025-11-17 17:26:24 +08:00
Helvetica Volubi bc166a9fb6 [ci skip] refactor code 2025-11-16 21:22:06 +08:00
30 changed files with 1488 additions and 29 deletions
+2 -2
View File
@@ -1,7 +1,7 @@
name: Bug反馈 Bug report
description:
报告Bug,插件不兼容情况,以及其他相关问题。
Report issues with plugin incompatbility or other behavior related issues.
Report issues with plugin incompatibility or other behavior related issues.
labels:
- bug
- pending
@@ -41,7 +41,7 @@ body:
attributes:
label: 观测到的实际行为 Observed/Actual behavior
description: 你实际看到的。 What you actually saw.
placeholder: e.g. 使用 /tpsbar [NAME] 命令切换不了TPSBAR
placeholder: e.g. 使用 /tpsbar 命令切换不了TPSBAR
validations:
required: true
- type: textarea
+1 -1
View File
@@ -28,7 +28,7 @@ body:
validations:
required: true
- type: textarea
id: othre
id: other
attributes:
label: 其他 Other
description: 添加其他的信息。 Add any other context or screenshots about the feature request below.
+14 -3
View File
@@ -30,7 +30,7 @@ jobs:
environment: default
steps:
- name: Checkout Git Repository
uses: actions/checkout@v5
uses: actions/checkout@v6
- name: Set Up JDK
uses: actions/setup-java@v5
@@ -84,8 +84,19 @@ jobs:
fi
echo "release_exists=${release_exists}" >> $GITHUB_ENV
- name: Check If Branch In Expectations
if: github.event_name != 'pull_request'
run: |
if [[ "$GITHUB_REF_NAME" == ver/* ]] || [[ "$GITHUB_REF_NAME" == exp/* ]] || [[ "$GITHUB_REF_NAME" == dev/* ]]; then
echo "Branch is in expected prefixes"
echo "unexpect=false" >> $GITHUB_ENV
else
echo "Branch is NOT in expected prefixes"
echo "unexpect=true" >> $GITHUB_ENV
fi
- name: Publish To Repo
if: (( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-push == '2')) || inputs.force-push == '1') && false # do not push to any repo
if: (( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !( inputs.force-release == '2' )) || inputs.force-push == '1') && false # do not push to any repo
continue-on-error: true
run: ./gradlew --refresh-dependencies generateDevelopmentBundle publish -PpublishDevBundle=true
env:
@@ -93,7 +104,7 @@ jobs:
PRIVATE_MAVEN_REPO_USERNAME: ${{ secrets.PRIVATE_MAVEN_REPO_USERNAME }}
- name: Create Release - Pre Process
if: ( github.event_name != 'pull_request' && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
if: ( github.event_name != 'pull_request' && !( env.unexpect == 'true' ) && env.flag_release == 'true' && env.release_exists != 'true' && !(inputs.force-release == '2')) || inputs.force-release == '1'
run: |
if [ ${{ inputs.comments }} == "" ]; then
echo "No comments provided"
+1 -1
View File
@@ -4,7 +4,7 @@ mcVersion=1.21.8
release=2
# 0 for skip release, 1 for pre-release, 2 for release
luminolRef=fc15c32debe0d87631bf5ecf69de4cfeba119a6c
luminolRef=ae1af655f57cd8666c2ae913fa53d3606019bf7b
org.gradle.configuration-cache=true
org.gradle.caching=true
@@ -5,10 +5,10 @@ Subject: [PATCH] Rebrand to Lophine
diff --git a/src/main/java/me/earthme/luminol/config/ConfigManager.java b/src/main/java/me/earthme/luminol/config/ConfigManager.java
index a5208f5426ea2e5d8f50c51fe17718ea1d63eef5..c80c578f1a3786bd7413c9a7af8ae125fe7975bb 100644
index 0bebc2cc87fb9c1c526e4de4f3bc157552307a72..cb1657939b86c039fcfe6403d3f202c2c5879e88 100644
--- a/src/main/java/me/earthme/luminol/config/ConfigManager.java
+++ b/src/main/java/me/earthme/luminol/config/ConfigManager.java
@@ -21,6 +21,7 @@ public class ConfigManager {
@@ -23,6 +23,7 @@ public class ConfigManager {
public static void initConfigs() {
configfiles.put("luminol", ConfigsInstance.of("luminol", "me.earthme.luminol.config.modules"));
@@ -18,10 +18,10 @@ index 6868b915bf3deb85783a638d4441a15fea6da2dc..70740381c6501c1a518c52b24381edd1
double rangeY = level.paperConfig().entities.trackingRangeY.get(this.entity, -1);
if (rangeY != -1) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index ea177b8ad7ebb25e3e2967c8ff3d36dc3dda6a1d..861684a36e3277c31842f30c82ffd9d85e2fe3f8 100644
index 38092dcc3dedc6c855e5598126be47f892223547..a8b6e89035579557b59a20ddbe9b32943e6b7164 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -146,7 +146,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
@@ -147,7 +147,7 @@ import net.minecraft.world.waypoints.WaypointTransmitter;
import org.jetbrains.annotations.Contract;
import org.slf4j.Logger;
@@ -30,7 +30,7 @@ index ea177b8ad7ebb25e3e2967c8ff3d36dc3dda6a1d..861684a36e3277c31842f30c82ffd9d8
// CraftBukkit start
private static final int CURRENT_LEVEL = 2;
public boolean preserveMotion = true; // Paper - Fix Entity Teleportation and cancel velocity if teleported; keep initial motion on first snapTo
@@ -6462,4 +6462,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -6463,4 +6463,46 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
// Paper end - Expose entity id counter
public boolean shouldTickHot() { return this.tickCount > 20 * 10 && this.isAlive(); } // KioCG
@@ -8,7 +8,7 @@ As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 985ddea9d74a37f58f32a27375f6f7e6af0f2192..9796c449f924b8fd9c0dd6bb02cf196641e495ed 100644
index 923aca94520f456a13d4e4eb23e1499b3dbc920f..0ee9e51c5abfd9269bcf0bb29c4b8394b27af02a 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2901,7 +2901,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -23,7 +23,7 @@ index d0d90a25a10bbecfffceee1992af88c60d14fd87..187e48e78e69c80b25710f193813335e
+ // Leaves end - servux
}
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index 9796c449f924b8fd9c0dd6bb02cf196641e495ed..4f1976c47a087bf4f36687124ef29ca7b664f682 100644
index 0ee9e51c5abfd9269bcf0bb29c4b8394b27af02a..d1a799199a68771ae3130a30a59625587c11b0b0 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -2368,6 +2368,7 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
@@ -539,10 +539,10 @@ index 52fd730998535ea071bfc99b7cc2c254b9b656d7..0abf6f0265fcb916f2c2c76fb1313bd1
for (WaypointTransmitter waypointTransmitter : this.waypoints) {
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 861684a36e3277c31842f30c82ffd9d85e2fe3f8..da1b004c1f66437534f3180b6d3f3a054b7c6945 100644
index a8b6e89035579557b59a20ddbe9b32943e6b7164..477241699752567df7695d33fa629fb1d5109e0a 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1224,7 +1224,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1225,7 +1225,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
BlockPos onPosLegacy = this.getOnPosLegacy();
BlockState blockState = this.level().getBlockState(onPosLegacy);
@@ -551,7 +551,7 @@ index 861684a36e3277c31842f30c82ffd9d85e2fe3f8..da1b004c1f66437534f3180b6d3f3a05
this.checkFallDamage(vec3.y, this.onGround(), blockState, onPosLegacy);
}
@@ -1538,7 +1538,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
@@ -1539,7 +1539,7 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
}
// Paper start - optimise collisions
@@ -0,0 +1,217 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 15 Nov 2025 01:06:20 +0800
Subject: [PATCH] Leaves: Catch update suppression crash
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/network/protocol/PacketUtils.java b/net/minecraft/network/protocol/PacketUtils.java
index 7280ca2250ade4166a1a883b205bbc89f4e00d1a..06268ac3420fc03a798a20bb617ba89a032df527 100644
--- a/net/minecraft/network/protocol/PacketUtils.java
+++ b/net/minecraft/network/protocol/PacketUtils.java
@@ -30,7 +30,20 @@ public class PacketUtils {
final int packetTimerId = profiler.getOrCreateTimerAndStart(() -> "Packet Handler: ".concat(io.papermc.paper.util.ObfHelper.INSTANCE.deobfClassName(packet.getClass().getName()))); try { // Folia - profiler
packet.handle(processor);
} finally { profiler.stopTimer(packetTimerId); } // Folia - profiler
+ // Leaves start - update suppression crash fix
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
} catch (Exception var4) {
+ if (var4.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ if (processor instanceof net.minecraft.server.network.ServerGamePacketListenerImpl gamePacketListener) {
+ exception.providePlayer(gamePacketListener.player);
+ }
+ exception.consume();
+ }
+ // Leaves end - update suppression crash fix
if (var4 instanceof ReportedException reportedException && reportedException.getCause() instanceof OutOfMemoryError) {
throw makeReportedException(var4, packet, processor);
}
diff --git a/net/minecraft/server/MinecraftServer.java b/net/minecraft/server/MinecraftServer.java
index 3c94631f468f4ee1b46de9981c17171e5901d745..f7a2a19c0832ca90536d09de23f4ec9a7d4a1521 100644
--- a/net/minecraft/server/MinecraftServer.java
+++ b/net/minecraft/server/MinecraftServer.java
@@ -1878,8 +1878,17 @@ public abstract class MinecraftServer extends ReentrantBlockableEventLoop<TickTa
try {
profiler.startTimer(serverLevel.tickTimerId); try { // Folia - profiler
serverLevel.tick(hasTimeLeft, region); // Folia - region threading
+ // Leaves start - update suppression crash fix
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(serverLevel);
+ exception.consume();
} finally { profiler.stopTimer(serverLevel.tickTimerId); } // Folia - profiler
} catch (Throwable var7) {
+ if (var7.getCause() instanceof org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(serverLevel);
+ exception.consume();
+ }
+ // Leaves end - update suppression crash fix
CrashReport crashReport = CrashReport.forThrowable(var7, "Exception ticking world");
serverLevel.fillReportDetails(crashReport);
throw new ReportedException(crashReport);
diff --git a/net/minecraft/server/level/ServerLevel.java b/net/minecraft/server/level/ServerLevel.java
index a4ee2bcdb31f889c7edbbc422636782c0d5d0af6..42bf4f0430a232a10cffb47d0d33f586afdc2a4d 100644
--- a/net/minecraft/server/level/ServerLevel.java
+++ b/net/minecraft/server/level/ServerLevel.java
@@ -840,7 +840,20 @@ public class ServerLevel extends Level implements ServerEntityGetter, WorldGenLe
// Kaiiju end
profilerFiller.push("tick");
- this.guardEntityTick(this::tickNonPassenger, entity);
+ // Lophine start - update suppression crash fix
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ try {
+ this.tickNonPassenger(entity); // Lophine changed
+ // Leaves start - update suppression crash fix - for dragon dupe
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideLevel(this);
+ exception.consume();
+ // Leaves end - update suppression crash fix - for dragon dupe
+ }
+ } else {
+ this.guardEntityTick(this::tickNonPassenger, entity);
+ }
+ // Lophine end - update suppression crash fix
profilerFiller.pop();
}
}
diff --git a/net/minecraft/server/level/ServerPlayer.java b/net/minecraft/server/level/ServerPlayer.java
index afd607df83fda3de6f53f55ad305c8f69fe6ddb6..e2f4b35c88c64a68cf7ef9fadf977e7b99e17c6e 100644
--- a/net/minecraft/server/level/ServerPlayer.java
+++ b/net/minecraft/server/level/ServerPlayer.java
@@ -1123,6 +1123,12 @@ public class ServerPlayer extends Player implements ca.spottedleaf.moonrise.patc
((org.bukkit.craftbukkit.CraftWorldBorder) this.getBukkitEntity().getWorldBorder()).getHandle().tick();
}
// CraftBukkit end
+ // Leaves start - update suppression crash fix
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.providePlayer(this);
+ exception.provideLevel(this.level());
+ exception.consume();
+ // Leaves start - update suppression crash fix
} catch (Throwable var4) {
CrashReport crashReport = CrashReport.forThrowable(var4, "Ticking player");
CrashReportCategory crashReportCategory = crashReport.addCategory("Player being ticked");
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
index 477241699752567df7695d33fa629fb1d5109e0a..f63252c580c313ccf89304866cfc6503f4b26052 100644
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
@@ -1403,9 +1403,19 @@ public abstract class Entity implements SyncedDataHolder, Nameable, EntityAccess
this.walkingStepSound(pos, state);
}
+ // Leaves start - update suppression crash fix
if (broadcastGameEvent) {
- this.level().gameEvent(GameEvent.STEP, this.position(), GameEvent.Context.of(this, state));
+ try {
+ this.level().gameEvent(net.minecraft.world.level.gameevent.GameEvent.STEP, this.position(), net.minecraft.world.level.gameevent.GameEvent.Context.of(this, state));
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException exception) {
+ exception.provideBlock(level, pos, state.getBlock());
+ if (this instanceof net.minecraft.server.level.ServerPlayer player) {
+ exception.providePlayer(player);
+ }
+ exception.consume();
+ }
}
+ // Leaves end - update suppression crash fix
return true;
} else {
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 49bac7af90b0a7c490141be6357563447783c6ca..a26cd86aedcaf7ab606f8543e08360cbe9f2d1e6 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -183,7 +183,17 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
@Override
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ // Leaves start - update suppression crash fix
+ try {
+ return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ } catch (ClassCastException ex) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
+ } else {
+ throw ex;
+ }
+ }
+ // Leaves end - update suppression crash fix
}
public static Block getBlockByColor(@Nullable DyeColor color) {
diff --git a/net/minecraft/world/level/block/state/StateHolder.java b/net/minecraft/world/level/block/state/StateHolder.java
index 9b9842462b210b0407279ee8a8e9ccecf3ead005..1057f3bd32ff4c8f93f09251341c243915593e4d 100644
--- a/net/minecraft/world/level/block/state/StateHolder.java
+++ b/net/minecraft/world/level/block/state/StateHolder.java
@@ -104,7 +104,16 @@ public abstract class StateHolder<O, S> implements ca.spottedleaf.moonrise.patch
if (ret != null) {
return ret;
}
- throw new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ // Leaves start - update suppression crash fix
+ IllegalArgumentException iae = new IllegalArgumentException("Cannot get property " + property + " as it does not exist in " + this.owner);
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ org.leavesmc.leaves.util.UpdateSuppressionException exception = new org.leavesmc.leaves.util.UpdateSuppressionException(null, null, null, null, iae);
+ if (exception.getStackTrace()[1].getClassName().startsWith("net.minecraft")) {
+ throw exception;
+ }
+ }
+ throw iae;
+ // Leaves end - update suppression crash fix
// Paper end - optimise blockstate property access
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index a536dc4e09b22b69bcdf59871a9cccfcf8129395..a557045888b153bb046a25d276d811b9146a7874 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -378,7 +378,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
if (blockState == state) {
return null;
} else {
- Block block = state.getBlock();
+ Block block = state.getBlock(); try { // Leaves start - update suppression crash fix
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING).update(i, y, i2, state);
this.heightmaps.get(Heightmap.Types.MOTION_BLOCKING_NO_LEAVES).update(i, y, i2, state);
this.heightmaps.get(Heightmap.Types.OCEAN_FLOOR).update(i, y, i2, state);
@@ -450,6 +450,7 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
this.markUnsaved();
return blockState;
}
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) { e.provideBlock(level, pos, block); throw e; } // Leaves - update suppression crash fix
}
}
}
diff --git a/net/minecraft/world/level/redstone/NeighborUpdater.java b/net/minecraft/world/level/redstone/NeighborUpdater.java
index 714e291b17856aacdac7db992fc18e6ae662f659..01285691a2e0bf72b94969e9045f7ab42a9161bf 100644
--- a/net/minecraft/world/level/redstone/NeighborUpdater.java
+++ b/net/minecraft/world/level/redstone/NeighborUpdater.java
@@ -63,9 +63,22 @@ public interface NeighborUpdater {
} finally { if (levelChunk != null) levelChunk.getChunkHot().stopTickingAndCount(); } // KioCG
// Spigot start
} catch (StackOverflowError ex) {
+ // Leaves start - update suppression crash fix
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, ex);
+ }
level.lastPhysicsProblem = pos.immutable();
// Spigot end
} catch (Throwable var9) {
+ if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
+ if (var9 instanceof org.leavesmc.leaves.util.UpdateSuppressionException ue) {
+ ue.provideBlock(level, pos, neighborBlock);
+ throw ue;
+ } else {
+ throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, level, neighborBlock, null, var9);
+ }
+ }
+ // Leaves end - update suppression crash fix
CrashReport crashReport = CrashReport.forThrowable(var9, "Exception while updating neighbours");
CrashReportCategory crashReportCategory = crashReport.addCategory("Block being updated");
crashReportCategory.setDetail(
@@ -0,0 +1,24 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Bacteriawa <A3167717663@hotmail.com>
Date: Sat, 15 Nov 2025 01:12:39 +0800
Subject: [PATCH] Leaves: CCE update suppression
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index a26cd86aedcaf7ab606f8543e08360cbe9f2d1e6..27ccce4b4d8b4cb8be48bfe5d55366abe4ea3a38 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -185,7 +185,9 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
protected int getAnalogOutputSignal(BlockState blockState, Level level, BlockPos pos) {
// Leaves start - update suppression crash fix
try {
- return AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.cce ?
+ AbstractContainerMenu.getRedstoneSignalFromContainer((net.minecraft.world.Container) level.getBlockEntity(pos)) : // Leaves - make cce happy(?)
+ AbstractContainerMenu.getRedstoneSignalFromBlockEntity(level.getBlockEntity(pos));
} catch (ClassCastException ex) {
if (fun.bm.lophine.config.modules.fixes.UpdateSuppressionCrashFixConfig.enabled) {
throw new org.leavesmc.leaves.util.UpdateSuppressionException(pos, null, this, null, ex);
@@ -0,0 +1,55 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: violetc <58360096+s-yh-china@users.noreply.github.com>
Date: Wed, 14 Jun 2023 12:07:07 +0800
Subject: [PATCH] Leaves: Redstone ignore upwards update
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/level/block/ComparatorBlock.java b/net/minecraft/world/level/block/ComparatorBlock.java
index afecf6bb6152b4d9dfee4cd8c5b1d798cbf723b3..a5bbe83b079276a3ab497e8a725713721db83aa1 100644
--- a/net/minecraft/world/level/block/ComparatorBlock.java
+++ b/net/minecraft/world/level/block/ComparatorBlock.java
@@ -58,6 +58,7 @@ public class ComparatorBlock extends DiodeBlock implements EntityBlock {
BlockState neighborState,
RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
return direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)
? Blocks.AIR.defaultBlockState()
: super.updateShape(state, level, scheduledTickAccess, pos, direction, neighborPos, neighborState, random);
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 4b37335e91a51b9a58ce0bce94b61ab5afbc6486..555a00e402da3d9126925135d030b7bccd8e5327 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -179,7 +179,7 @@ public class RedStoneWireBlock extends Block {
RandomSource random
) {
if (direction == Direction.DOWN) {
- return !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state;
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate ? state : !this.canSurviveOn(level, neighborPos, neighborState) ? Blocks.AIR.defaultBlockState() : state; // Leaves - behavior to 1.19
} else if (direction == Direction.UP) {
return this.getConnectionState(level, state, pos);
} else {
@@ -239,7 +239,7 @@ public class RedStoneWireBlock extends Block {
BlockPos blockPos = pos.relative(direction);
BlockState blockState = level.getBlockState(blockPos);
if (nonNormalCubeAbove) {
- boolean flag = blockState.getBlock() instanceof TrapDoorBlock || this.canSurviveOn(level, blockPos, blockState);
+ boolean flag = (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && blockState.getBlock() instanceof TrapDoorBlock) || this.canSurviveOn(level, blockPos, blockState); // Leaves - behavior to 1.19
if (flag && shouldConnectTo(level.getBlockState(blockPos.above()))) {
if (blockState.isFaceSturdy(level, blockPos, direction.getOpposite())) {
return RedstoneSide.UP;
diff --git a/net/minecraft/world/level/block/RepeaterBlock.java b/net/minecraft/world/level/block/RepeaterBlock.java
index 1d45564253258eebdf10470dd7eefa644a4151ae..4b8a0f7353984d8997ab3b702227ae8d46863d7e 100644
--- a/net/minecraft/world/level/block/RepeaterBlock.java
+++ b/net/minecraft/world/level/block/RepeaterBlock.java
@@ -68,6 +68,7 @@ public class RepeaterBlock extends DiodeBlock {
BlockState neighborState,
RandomSource random
) {
+ if (fun.bm.lophine.config.modules.experiment.RedStoneConfig.redstoneIgnoreUpwardsUpdate && direction == Direction.DOWN) return state; // Leaves - behavior to 1.20.1
if (direction == Direction.DOWN && !this.canSurviveOn(level, neighborPos, neighborState)) {
return Blocks.AIR.defaultBlockState();
} else {
@@ -0,0 +1,19 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Mon, 17 Nov 2025 18:41:08 +0800
Subject: [PATCH] Instant Block Updater
diff --git a/io/papermc/paper/threadedregions/RegionizedWorldData.java b/io/papermc/paper/threadedregions/RegionizedWorldData.java
index d0de3b22f6cef6eb213b7ff688a514a67f84fbcf..3b39b8f7ccb278cf910e3cc4e00da29790465a81 100644
--- a/io/papermc/paper/threadedregions/RegionizedWorldData.java
+++ b/io/papermc/paper/threadedregions/RegionizedWorldData.java
@@ -524,7 +524,7 @@ public final class RegionizedWorldData {
this.world = world;
this.blockLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, true);
this.fluidLevelTicks = new LevelTicks<>(world::isPositionTickingWithEntitiesLoaded, world, false);
- this.neighborUpdater = new CollectingNeighborUpdater(world, world.neighbourUpdateMax);
+ this.neighborUpdater = fun.bm.lophine.config.modules.experiment.RedStoneConfig.instantBlockUpdater ? new net.minecraft.world.level.redstone.InstantNeighborUpdater(world) : new CollectingNeighborUpdater(world, world.neighbourUpdateMax); // Lophine - Instant Block Updater
this.nearbyPlayers = new NearbyPlayers(world);
this.wireHandler = new alternate.current.wire.WireHandler(world);
this.turbo = new io.papermc.paper.redstone.RedstoneWireTurbo((RedStoneWireBlock)Blocks.REDSTONE_WIRE);
@@ -0,0 +1,49 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:24:32 +0800
Subject: [PATCH] Revert TrapDoorBlock changes form paperMC
diff --git a/net/minecraft/world/level/block/TrapDoorBlock.java b/net/minecraft/world/level/block/TrapDoorBlock.java
index a2140d22dc58aa2df1afbeb5170d04fd65739d55..ea79c471c03b6908710d5943f2ff378eaba4099e 100644
--- a/net/minecraft/world/level/block/TrapDoorBlock.java
+++ b/net/minecraft/world/level/block/TrapDoorBlock.java
@@ -128,37 +128,7 @@ public class TrapDoorBlock extends HorizontalDirectionalBlock implements SimpleW
if (!level.isClientSide) {
boolean hasNeighborSignal = level.hasNeighborSignal(pos);
if (hasNeighborSignal != state.getValue(POWERED)) {
- // CraftBukkit start
- org.bukkit.block.Block bblock = org.bukkit.craftbukkit.block.CraftBlock.at(level, pos);
- int power = bblock.getBlockPower();
- int oldPower = state.getValue(TrapDoorBlock.OPEN) ? 15 : 0;
-
- if (oldPower == 0 ^ power == 0 || neighborBlock.defaultBlockState().isSignalSource()) {
- org.bukkit.event.block.BlockRedstoneEvent eventRedstone = new org.bukkit.event.block.BlockRedstoneEvent(bblock, oldPower, power);
- level.getCraftServer().getPluginManager().callEvent(eventRedstone);
- hasNeighborSignal = eventRedstone.getNewCurrent() > 0;
- }
- // CraftBukkit end
- // Paper start - break redstone on trapdoors early
- boolean open = state.getValue(TrapDoorBlock.OPEN) != hasNeighborSignal;
- // note: this must run before any state for this block/its neighbours are written to the world
- // we allow the redstone event to fire so that plugins can block
- if (hasNeighborSignal && open) { // if we are now powered and it caused the trap door to open
- // in this case, first check for the redstone on top first
- BlockPos abovePos = pos.above();
- BlockState above = level.getBlockState(abovePos);
- if (above.getBlock() instanceof RedStoneWireBlock) {
- level.setBlock(abovePos, Blocks.AIR.defaultBlockState(), Block.UPDATE_CLIENTS | Block.UPDATE_NEIGHBORS);
- Block.popResource(level, abovePos, new net.minecraft.world.item.ItemStack(net.minecraft.world.item.Items.REDSTONE));
- // now check that this didn't change our state
- if (level.getBlockState(pos) != state) {
- // our state was changed, so we cannot propagate this update
- return;
- }
- }
- }
- if (open) {
- // Paper end - break redstone on trapdoors early
+ if (state.getValue(OPEN) != hasNeighborSignal) {
state = state.setValue(OPEN, hasNeighborSignal);
this.playSound(null, level, pos, hasNeighborSignal);
}
@@ -0,0 +1,42 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 00:35:13 +0800
Subject: [PATCH] Leaves: Prevent loss of item drops due to update suppression
when breaking blocks
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves/blob/ea91106ae57fc4cc14e2e0225009cf9919072f7f/leaves-server/minecraft-patches/features/0090-Servux-Protocol.patch)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/server/level/ServerPlayerGameMode.java b/net/minecraft/server/level/ServerPlayerGameMode.java
index ee7bdc3adbeb04cf6ca630282f31a21e52bdb215..58f6c3e83c80b4b419ba22da81a7880be5b5d551 100644
--- a/net/minecraft/server/level/ServerPlayerGameMode.java
+++ b/net/minecraft/server/level/ServerPlayerGameMode.java
@@ -369,7 +369,18 @@ public class ServerPlayerGameMode {
this.level.getCurrentWorldData().captureDrops = new java.util.ArrayList<>(); // Folia - region threading
// CraftBukkit end
BlockState blockState1 = block.playerWillDestroy(this.level, pos, blockState, this.player);
- boolean flag = this.level.removeBlock(pos, false);
+ // Leaves start - Prevent loss of item drops due to update suppression when breaking blocks
+ boolean flag;
+ org.leavesmc.leaves.util.UpdateSuppressionException ex = null;
+ try {
+ flag = this.level.removeBlock(pos, false);
+ } catch (org.leavesmc.leaves.util.UpdateSuppressionException e) {
+ ex = e;
+ ex.provideBlock(level, pos, block);
+ ex.providePlayer(this.player);
+ flag = false;
+ }
+ // Leaves end - Prevent loss of item drops due to update suppression when breaking blocks
if (flag) {
block.destroy(this.level, pos, blockState1);
}
@@ -397,6 +408,7 @@ public class ServerPlayerGameMode {
if (event.isDropItems()) {
org.bukkit.craftbukkit.event.CraftEventFactory.handleBlockDropItemEvent(bblock, state, this.player, itemsToDrop); // Paper - capture all item additions to the world
}
+ if (ex != null) throw ex; // Leaves - Prevent loss of item drops due to update suppression when breaking blocks
// Drop event experience
if (flag) {
@@ -0,0 +1,807 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 23:11:26 +0800
Subject: [PATCH] Leaves: Old Block remove behaviour
Co-authored by: violetc <58360096+s-yh-china@users.noreply.github.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/Containers.java b/net/minecraft/world/Containers.java
index da10ca5ef12be1a834adda9243c082dadde24ec0..f682930f765d04f0a278b0648c2773ab5d4d740e 100644
--- a/net/minecraft/world/Containers.java
+++ b/net/minecraft/world/Containers.java
@@ -51,4 +51,15 @@ public class Containers {
public static void updateNeighboursAfterDestroy(BlockState state, Level level, BlockPos pos) {
level.updateNeighbourForOutputSignal(pos, state.getBlock());
}
+
+ // Leaves start - behaviour 1.21.1-
+ public static void dropContentsOnDestroy(BlockState state, BlockState newState, Level level, BlockPos pos) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof Container container) {
+ dropContents(level, pos, container);
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
}
diff --git a/net/minecraft/world/level/block/AbstractFurnaceBlock.java b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
index d52eeff0d564a24bddb873750c81e3fe999f16f0..aa2597d825f93b0b0623ab7fae29e45de3f3ebcc 100644
--- a/net/minecraft/world/level/block/AbstractFurnaceBlock.java
+++ b/net/minecraft/world/level/block/AbstractFurnaceBlock.java
@@ -51,6 +51,26 @@ public abstract class AbstractFurnaceBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getHorizontalDirection().getOpposite());
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof AbstractFurnaceBlockEntity) {
+ if (level instanceof ServerLevel) {
+ Containers.dropContents(level, pos, (AbstractFurnaceBlockEntity)blockEntity);
+ ((AbstractFurnaceBlockEntity)blockEntity).getRecipesToAwardAndPopExperience((ServerLevel)level, net.minecraft.world.phys.Vec3.atCenterOf(pos));
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ level.updateNeighbourForOutputSignal(pos, this);
+ } else {
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BarrelBlock.java b/net/minecraft/world/level/block/BarrelBlock.java
index f7820265f10b78674acd13e6204b9212fd27b038..700bd0f6a4f4fd6cd85b3e666fff1b3fd0a96b8e 100644
--- a/net/minecraft/world/level/block/BarrelBlock.java
+++ b/net/minecraft/world/level/block/BarrelBlock.java
@@ -49,6 +49,14 @@ public class BarrelBlock extends BaseEntityBlock {
return InteractionResult.SUCCESS;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/BasePressurePlateBlock.java b/net/minecraft/world/level/block/BasePressurePlateBlock.java
index 42ee3f32fe44c1f0680c994a69201f7bd7792673..19214c236bca4e454e3bbe7dc50e00b66398c119 100644
--- a/net/minecraft/world/level/block/BasePressurePlateBlock.java
+++ b/net/minecraft/world/level/block/BasePressurePlateBlock.java
@@ -125,6 +125,19 @@ public abstract class BasePressurePlateBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (this.getSignalForState(state) > 0) {
+ this.updateNeighbours(level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && this.getSignalForState(state) > 0) {
diff --git a/net/minecraft/world/level/block/BaseRailBlock.java b/net/minecraft/world/level/block/BaseRailBlock.java
index 5f99e18244501ed2d85be77b71f48cc93058cdb7..6bf50d9c3921b15f40b4fba273abeb4c2e0f30b3 100644
--- a/net/minecraft/world/level/block/BaseRailBlock.java
+++ b/net/minecraft/world/level/block/BaseRailBlock.java
@@ -121,6 +121,23 @@ public abstract class BaseRailBlock extends Block implements SimpleWaterloggedBl
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ if (state.getValue(this.getShapeProperty()).isSlope()) {
+ level.updateNeighborsAt(pos.above(), this);
+ }
+
+ if (this.isStraight) {
+ level.updateNeighborsAt(pos, this);
+ level.updateNeighborsAt(pos.below(), this);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/BrewingStandBlock.java b/net/minecraft/world/level/block/BrewingStandBlock.java
index f563f8ea63e67f808802baa4c6a700e803c045a0..0cc4479d9d3f6aea280c9f88997d141dc24917a9 100644
--- a/net/minecraft/world/level/block/BrewingStandBlock.java
+++ b/net/minecraft/world/level/block/BrewingStandBlock.java
@@ -78,6 +78,14 @@ public class BrewingStandBlock extends BaseEntityBlock {
level.addParticle(ParticleTypes.SMOKE, d, d1, d2, 0.0, 0.0, 0.0);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ButtonBlock.java b/net/minecraft/world/level/block/ButtonBlock.java
index 66c589bc633d32ebf36b1ab55ba6250ca2ddd6f6..f96d3c7b7ec15973aca3aabe056608fd5efb856b 100644
--- a/net/minecraft/world/level/block/ButtonBlock.java
+++ b/net/minecraft/world/level/block/ButtonBlock.java
@@ -132,6 +132,19 @@ public class ButtonBlock extends FaceAttachedHorizontalDirectionalBlock {
return isOn ? this.type.buttonClickOn() : this.type.buttonClickOff();
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/CampfireBlock.java b/net/minecraft/world/level/block/CampfireBlock.java
index 028e2ad8bcb23b3f9f80a5ec551204bb2d7db1ae..c9e2becc0644de707e0bd251318813c50fc82be2 100644
--- a/net/minecraft/world/level/block/CampfireBlock.java
+++ b/net/minecraft/world/level/block/CampfireBlock.java
@@ -105,6 +105,20 @@ public class CampfireBlock extends BaseEntityBlock implements SimpleWaterloggedB
return InteractionResult.TRY_WITH_EMPTY_HAND;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof CampfireBlockEntity) {
+ net.minecraft.world.Containers.dropContents(level, pos, ((CampfireBlockEntity)blockEntity).getItems());
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void entityInside(BlockState state, Level level, BlockPos pos, Entity entity, InsideBlockEffectApplier effectApplier) {
if (!new io.papermc.paper.event.entity.EntityInsideBlockEvent(entity.getBukkitEntity(), org.bukkit.craftbukkit.block.CraftBlock.at(level, pos)).callEvent()) { return; } // Paper - Add EntityInsideBlockEvent
diff --git a/net/minecraft/world/level/block/ChestBlock.java b/net/minecraft/world/level/block/ChestBlock.java
index c4937d1b482e2ec60961bda62ad6cc155f0ce8f7..818b1a5df0e9a0566210e4b3512ad856515e385f 100644
--- a/net/minecraft/world/level/block/ChestBlock.java
+++ b/net/minecraft/world/level/block/ChestBlock.java
@@ -244,6 +244,14 @@ public class ChestBlock extends AbstractChestBlock<ChestBlockEntity> implements
return blockState.is(this) && blockState.getValue(TYPE) == ChestType.SINGLE ? blockState.getValue(FACING) : null;
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
index eb315a50a83dc7230d7ad66f4daeb0d632679941..7bccf15310f6851875bfd77d4c66f4ce863b65e1 100644
--- a/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
+++ b/net/minecraft/world/level/block/ChiseledBookShelfBlock.java
@@ -180,6 +180,27 @@ public class ChiseledBookShelfBlock extends BaseEntityBlock {
SLOT_OCCUPIED_PROPERTIES.forEach(property -> builder.add(property));
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof ChiseledBookShelfBlockEntity chiseledBookShelfBlockEntity && !chiseledBookShelfBlockEntity.isEmpty()) {
+ for (int i = 0; i < 6; i++) {
+ ItemStack item = chiseledBookShelfBlockEntity.getItem(i);
+ if (!item.isEmpty()) {
+ Containers.dropItemStack(level, pos.getX(), pos.getY(), pos.getZ(), item);
+ }
+ }
+
+ chiseledBookShelfBlockEntity.clearContent();
+ level.updateNeighbourForOutputSignal(pos, this);
+ }
+
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CrafterBlock.java b/net/minecraft/world/level/block/CrafterBlock.java
index caf31218a1aff84367da126ee1dc46b8c8a1e5d1..59272e7223aff61d44c86776091ca74891839a45 100644
--- a/net/minecraft/world/level/block/CrafterBlock.java
+++ b/net/minecraft/world/level/block/CrafterBlock.java
@@ -129,6 +129,14 @@ public class CrafterBlock extends BaseEntityBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/CreakingHeartBlock.java b/net/minecraft/world/level/block/CreakingHeartBlock.java
index 73885449a3316face50292756de2a3f298d3d111..333e18e4ead0bb6ef9681ce27ec156f79821af7c 100644
--- a/net/minecraft/world/level/block/CreakingHeartBlock.java
+++ b/net/minecraft/world/level/block/CreakingHeartBlock.java
@@ -152,6 +152,16 @@ public class CreakingHeartBlock extends BaseEntityBlock {
builder.add(AXIS, STATE, NATURAL);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (level.getBlockEntity(pos) instanceof CreakingHeartBlockEntity creakingHeartBlockEntity) {
+ creakingHeartBlockEntity.removeProtector(null);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DecoratedPotBlock.java b/net/minecraft/world/level/block/DecoratedPotBlock.java
index f1570f1f4f7e43aacbcffef8bcf8ef27d46899da..6afd1c618112234ce4940105582a4399e20ab34c 100644
--- a/net/minecraft/world/level/block/DecoratedPotBlock.java
+++ b/net/minecraft/world/level/block/DecoratedPotBlock.java
@@ -165,6 +165,14 @@ public class DecoratedPotBlock extends BaseEntityBlock implements SimpleWaterlog
return new DecoratedPotBlockEntity(pos, state);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/DiodeBlock.java b/net/minecraft/world/level/block/DiodeBlock.java
index 0ab376b4207b695e92c324b8a5f9818d3f4accde..bcceb8f17294fb9f275ab6b3a28c75cb423394f2 100644
--- a/net/minecraft/world/level/block/DiodeBlock.java
+++ b/net/minecraft/world/level/block/DiodeBlock.java
@@ -176,6 +176,16 @@ public abstract class DiodeBlock extends HorizontalDirectionalBlock {
if (me.earthme.luminol.config.modules.optimizations.LeavesSleepingBlockEntityConfig.enabled && this instanceof ComparatorBlock && !oldState.is(Blocks.COMPARATOR)) org.leavesmc.leaves.lithium.common.block.entity.inventory_comparator_tracking.ComparatorTracking.notifyNearbyBlockEntitiesAboutNewComparator(level, pos); // Leaves - Lithium Sleeping Block Entity
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ this.updateNeighborsInFront(level, pos, state);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/DispenserBlock.java b/net/minecraft/world/level/block/DispenserBlock.java
index 7ff6255fcd50344cd6ac7f8a67d61fd59c85e413..7a23d27ce76ae6b90d01c4dc7af416bb6b6516ea 100644
--- a/net/minecraft/world/level/block/DispenserBlock.java
+++ b/net/minecraft/world/level/block/DispenserBlock.java
@@ -147,6 +147,14 @@ public class DispenserBlock extends BaseEntityBlock {
return this.defaultBlockState().setValue(FACING, context.getNearestLookingDirection().getOpposite());
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/HopperBlock.java b/net/minecraft/world/level/block/HopperBlock.java
index 912d1ba98809b4469e1468e4855bb1bc91bb4540..0f2b344b385b7726c3c23b68da8a2329180fe034 100644
--- a/net/minecraft/world/level/block/HopperBlock.java
+++ b/net/minecraft/world/level/block/HopperBlock.java
@@ -137,6 +137,14 @@ public class HopperBlock extends BaseEntityBlock implements org.leavesmc.leaves.
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ Containers.dropContentsOnDestroy(state, newState, level, pos);
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/JukeboxBlock.java b/net/minecraft/world/level/block/JukeboxBlock.java
index 56cf6528f0cd9b8528490d7cee9a1f0e54108ef9..955854e5b3a18b8f1441145554a97c5454a65d12 100644
--- a/net/minecraft/world/level/block/JukeboxBlock.java
+++ b/net/minecraft/world/level/block/JukeboxBlock.java
@@ -73,6 +73,19 @@ public class JukeboxBlock extends BaseEntityBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (level.getBlockEntity(pos) instanceof JukeboxBlockEntity jukeboxBlockEntity) {
+ jukeboxBlockEntity.popOutTheItem();
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/LecternBlock.java b/net/minecraft/world/level/block/LecternBlock.java
index 5a9b601b7bf7e80b04ebd8f5c8b7d121031132c7..b714d3c7649384a8fdbe0a713e2193e241c80618 100644
--- a/net/minecraft/world/level/block/LecternBlock.java
+++ b/net/minecraft/world/level/block/LecternBlock.java
@@ -197,6 +197,36 @@ public class LecternBlock extends BaseEntityBlock {
changePowered(level, pos, state, false);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(HAS_BOOK)) {
+ this.popBook(state, level, pos);
+ }
+
+ if (state.getValue(POWERED)) {
+ updateBelow(level, pos, state);
+ }
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+
+ private void popBook(BlockState state, Level level, BlockPos pos) {
+ if (level.getBlockEntity(pos) instanceof LecternBlockEntity lecternBlockEntity) { // CraftBukkit - don't validate, type may be changed already // Leaves - the method with validate arg already removed by paper...
+ Direction direction = state.getValue(FACING);
+ ItemStack itemStack = lecternBlockEntity.getBook().copy();
+ if (itemStack.isEmpty()) return; // CraftBukkit - SPIGOT-5500
+ float f = 0.25F * direction.getStepX();
+ float f1 = 0.25F * direction.getStepZ();
+ net.minecraft.world.entity.item.ItemEntity itemEntity = new net.minecraft.world.entity.item.ItemEntity(level, pos.getX() + 0.5 + f, pos.getY() + 1, pos.getZ() + 0.5 + f1, itemStack);
+ itemEntity.setDefaultPickUpDelay();
+ level.addFreshEntity(itemEntity);
+ lecternBlockEntity.clearContent();
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LeverBlock.java b/net/minecraft/world/level/block/LeverBlock.java
index 76f2a29f37187344324d68941307d58e6343b6ae..3645ca9589aa1a74134180c9918a6f67bc64ce7a 100644
--- a/net/minecraft/world/level/block/LeverBlock.java
+++ b/net/minecraft/world/level/block/LeverBlock.java
@@ -125,6 +125,19 @@ public class LeverBlock extends FaceAttachedHorizontalDirectionalBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston && state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/LightningRodBlock.java b/net/minecraft/world/level/block/LightningRodBlock.java
index d702d234111c2a34585f3532b5bb4bdb1501b82a..d9bedb99590a860a7ebb1d68861dc175ca3f4a2b 100644
--- a/net/minecraft/world/level/block/LightningRodBlock.java
+++ b/net/minecraft/world/level/block/LightningRodBlock.java
@@ -120,6 +120,18 @@ public class LightningRodBlock extends RodBlock implements SimpleWaterloggedBloc
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(POWERED)) {
+ this.updateNeighbours(state, level, pos);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED)) {
diff --git a/net/minecraft/world/level/block/ObserverBlock.java b/net/minecraft/world/level/block/ObserverBlock.java
index bd2aa00ce8b78c16f6107064dd00bfbb072df0df..6db3a21bcc37ae79f82b19ee0a851f539d4a654d 100644
--- a/net/minecraft/world/level/block/ObserverBlock.java
+++ b/net/minecraft/world/level/block/ObserverBlock.java
@@ -127,6 +127,17 @@ public class ObserverBlock extends DirectionalBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
+ this.updateNeighborsInFront(level, pos, state.setValue(POWERED, Boolean.FALSE));
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (state.getValue(POWERED) && level.getBlockTicks().hasScheduledTick(pos, this)) {
diff --git a/net/minecraft/world/level/block/RedStoneWireBlock.java b/net/minecraft/world/level/block/RedStoneWireBlock.java
index 555a00e402da3d9126925135d030b7bccd8e5327..20cec51bcead34f95ed6195a7762cea7ce280914 100644
--- a/net/minecraft/world/level/block/RedStoneWireBlock.java
+++ b/net/minecraft/world/level/block/RedStoneWireBlock.java
@@ -369,6 +369,27 @@ public class RedStoneWireBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ for (Direction direction : Direction.values()) {
+ level.updateNeighborsAt(pos.relative(direction), this);
+ }
+
+ // Paper start - optimize redstone - replace call to updatePowerStrength
+ if (level.paperConfig().misc.redstoneImplementation == io.papermc.paper.configuration.WorldConfiguration.Misc.RedstoneImplementation.ALTERNATE_CURRENT) {
+ level.getWireHandler().onWireRemoved(pos, state); // Alternate Current
+ } else {
+ this.updateSurroundingRedstone(level, pos, state, null, false); // Vanilla/Eigencraft
+ }
+ // Paper end - optimize redstone
+ this.updateNeighborsOfNeighboringWires(level, pos);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/RedstoneTorchBlock.java b/net/minecraft/world/level/block/RedstoneTorchBlock.java
index df4f1b18deb8bb4a04e740bbbeb6a89cb1ff8e71..7f165a4e2935cf4638b14379a0d1aca1b65ef84a 100644
--- a/net/minecraft/world/level/block/RedstoneTorchBlock.java
+++ b/net/minecraft/world/level/block/RedstoneTorchBlock.java
@@ -53,6 +53,15 @@ public class RedstoneTorchBlock extends BaseTorchBlock {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving) {
+ this.notifyNeighbors(level, pos, state);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/SculkSensorBlock.java b/net/minecraft/world/level/block/SculkSensorBlock.java
index f0101e88140f480c1a94f899744991f78c9e3756..fa9cb4c40a41eea7fd63a4513d0b0f39067de9ba 100644
--- a/net/minecraft/world/level/block/SculkSensorBlock.java
+++ b/net/minecraft/world/level/block/SculkSensorBlock.java
@@ -129,6 +129,18 @@ public class SculkSensorBlock extends BaseEntityBlock implements SimpleWaterlogg
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (!state.is(newState.getBlock())) {
+ if (getPhase(state) == SculkSensorPhase.ACTIVE) {
+ updateNeighbours(level, pos, state);
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (getPhase(state) == SculkSensorPhase.ACTIVE) {
diff --git a/net/minecraft/world/level/block/SculkShriekerBlock.java b/net/minecraft/world/level/block/SculkShriekerBlock.java
index 757f8453e147875ab9f14d9726bb734ef27447c9..d0558d0e33f3d6e25af2dd71650d723e8997dae6 100644
--- a/net/minecraft/world/level/block/SculkShriekerBlock.java
+++ b/net/minecraft/world/level/block/SculkShriekerBlock.java
@@ -68,6 +68,16 @@ public class SculkShriekerBlock extends BaseEntityBlock implements SimpleWaterlo
super.stepOn(level, pos, state, entity);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ if (level instanceof ServerLevel serverLevel && state.getValue(SHRIEKING) && !state.is(newState.getBlock())) {
+ serverLevel.getBlockEntity(pos, BlockEntityType.SCULK_SHRIEKER).ifPresent(sculkShrieker -> sculkShrieker.tryRespond(serverLevel));
+ }
+ super.onRemove(state, level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void tick(BlockState state, ServerLevel level, BlockPos pos, RandomSource random) {
if (state.getValue(SHRIEKING)) {
diff --git a/net/minecraft/world/level/block/ShulkerBoxBlock.java b/net/minecraft/world/level/block/ShulkerBoxBlock.java
index 27ccce4b4d8b4cb8be48bfe5d55366abe4ea3a38..2e6d462fb27ad1e538164934417ce07cc0e603c2 100644
--- a/net/minecraft/world/level/block/ShulkerBoxBlock.java
+++ b/net/minecraft/world/level/block/ShulkerBoxBlock.java
@@ -152,6 +152,19 @@ public class ShulkerBoxBlock extends BaseEntityBlock {
// Paper end - re-set loot table if it was cleared
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof ShulkerBoxBlockEntity) {
+ level.updateNeighbourForOutputSignal(pos, state.getBlock());
+ }
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
Containers.updateNeighboursAfterDestroy(state, level, pos);
diff --git a/net/minecraft/world/level/block/TripWireBlock.java b/net/minecraft/world/level/block/TripWireBlock.java
index c8f793d1cdeef7e3e0d5fceb45a4507d542e4b33..27f382f6c663b2954a6fb966ece05ba021fcd6b1 100644
--- a/net/minecraft/world/level/block/TripWireBlock.java
+++ b/net/minecraft/world/level/block/TripWireBlock.java
@@ -108,6 +108,16 @@ public class TripWireBlock extends Block {
}
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
+ if (!isMoving && !state.is(newState.getBlock())) {
+ this.updateSource(level, pos, state.setValue(POWERED, Boolean.TRUE));
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (io.papermc.paper.configuration.GlobalConfiguration.get().blockUpdates.disableTripwireUpdates) return; // Paper - prevent adjacent tripwires from updating
diff --git a/net/minecraft/world/level/block/TripWireHookBlock.java b/net/minecraft/world/level/block/TripWireHookBlock.java
index 3f412b08e7d40d577efb7be291dd14826ba21f0e..30c65a0906646fc12cd842336ec4f3e2aaf31717 100644
--- a/net/minecraft/world/level/block/TripWireHookBlock.java
+++ b/net/minecraft/world/level/block/TripWireHookBlock.java
@@ -245,6 +245,25 @@ public class TripWireHookBlock extends Block {
level.updateNeighborsAt(pos.relative(opposite), block, orientation);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!isMoving && !state.is(newState.getBlock())) {
+ boolean attachedValue = state.getValue(ATTACHED);
+ boolean poweredValue = state.getValue(POWERED);
+ if (attachedValue || poweredValue) {
+ calculateState(level, pos, state, true, false, -1, null);
+ }
+
+ if (poweredValue) {
+ notifyNeighbors(this, level, pos, state.getValue(FACING));
+ }
+
+ super.onRemove(state, level, pos, newState, isMoving);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
if (!movedByPiston) {
diff --git a/net/minecraft/world/level/block/entity/BlockEntityType.java b/net/minecraft/world/level/block/entity/BlockEntityType.java
index 7b8631abf8adcdb889d412b30eca10faf044032a..13134dfe9f548b87fd6be4683bf3386c522aba6a 100644
--- a/net/minecraft/world/level/block/entity/BlockEntityType.java
+++ b/net/minecraft/world/level/block/entity/BlockEntityType.java
@@ -267,7 +267,7 @@ public class BlockEntityType<T extends BlockEntity> {
}
public boolean isValid(BlockState state) {
- return this.validBlocks.contains(state.getBlock());
+ return fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour || this.validBlocks.contains(state.getBlock()); // Leaves - behaviour 1.21.1-
}
@Deprecated
diff --git a/net/minecraft/world/level/block/piston/MovingPistonBlock.java b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
index 05bbc2e59384702439548a988e128a85f1adbe82..af516d5b6bd31de2c6a388ec8001126e2a351cf3 100644
--- a/net/minecraft/world/level/block/piston/MovingPistonBlock.java
+++ b/net/minecraft/world/level/block/piston/MovingPistonBlock.java
@@ -67,6 +67,18 @@ public class MovingPistonBlock extends BaseEntityBlock {
return createTickerHelper(blockEntityType, BlockEntityType.PISTON, PistonMovingBlockEntity::tick);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ BlockEntity blockEntity = level.getBlockEntity(pos);
+ if (blockEntity instanceof PistonMovingBlockEntity) {
+ ((PistonMovingBlockEntity)blockEntity).finalTick();
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
public void destroy(LevelAccessor level, BlockPos pos, BlockState state) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/piston/PistonHeadBlock.java b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
index 6c789e56f21f01252c21786cfeb48d88485b5636..e24a61a4e2dac0159d52f07c93ddf860f4bfb8f7 100644
--- a/net/minecraft/world/level/block/piston/PistonHeadBlock.java
+++ b/net/minecraft/world/level/block/piston/PistonHeadBlock.java
@@ -78,6 +78,19 @@ public class PistonHeadBlock extends DirectionalBlock {
return super.playerWillDestroy(level, pos, state, player);
}
+ // Leaves start - behaviour 1.21.1-
+ @Override
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean isMoving) {
+ if (!state.is(newState.getBlock())) {
+ super.onRemove(state, level, pos, newState, isMoving);
+ BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
+ if (this.isFittingBase(state, level.getBlockState(blockPos))) {
+ level.destroyBlock(blockPos, true);
+ }
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
@Override
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
BlockPos blockPos = pos.relative(state.getValue(FACING).getOpposite());
diff --git a/net/minecraft/world/level/block/state/BlockBehaviour.java b/net/minecraft/world/level/block/state/BlockBehaviour.java
index e9749b66239d7562ecf22002bfbaa95df197050f..6e3841ed012eee16dcaa61f70edfc1d870374a56 100644
--- a/net/minecraft/world/level/block/state/BlockBehaviour.java
+++ b/net/minecraft/world/level/block/state/BlockBehaviour.java
@@ -172,6 +172,15 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
org.spigotmc.AsyncCatcher.catchOp("block onPlace"); // Spigot
}
+ // Leaves start - behaviour 1.21.1-
+ protected void onRemove(BlockState state, Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ org.spigotmc.AsyncCatcher.catchOp("block remove"); // Spigot
+ if (state.hasBlockEntity() && !state.is(newState.getBlock())) {
+ level.removeBlockEntity(pos);
+ }
+ }
+ // Leaves end - behaviour 1.21.1-
+
protected void affectNeighborsAfterRemoval(BlockState state, ServerLevel level, BlockPos pos, boolean movedByPiston) {
}
@@ -868,6 +877,12 @@ public abstract class BlockBehaviour implements FeatureElement, org.leavesmc.lea
// CraftBukkit end
}
+ // Leaves start - behaviour 1.21.1-
+ public void onRemove(Level level, BlockPos pos, BlockState newState, boolean movedByPiston) {
+ this.getBlock().onRemove(this.asState(), level, pos, newState, movedByPiston);
+ }
+ // Leaves end - behaviour 1.21.1-
+
public void affectNeighborsAfterRemoval(ServerLevel level, BlockPos pos, boolean movedByPiston) {
this.getBlock().affectNeighborsAfterRemoval(this.asState(), level, pos, movedByPiston);
}
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index a557045888b153bb046a25d276d811b9146a7874..568427a952a24012c17f64f62b6545a9d89c8c8a 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -401,20 +401,26 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
boolean flag = !blockState.is(block);
boolean flag1 = (flags & 64) != 0;
boolean flag2 = (flags & 256) == 0;
- if (flag && blockState.hasBlockEntity()) {
- if (!this.level.isClientSide && flag2) {
- BlockEntity blockEntity = this.level.getBlockEntity(pos);
- if (blockEntity != null) {
- blockEntity.preRemoveSideEffects(pos, blockState);
+ // Leaves start - behaviour 1.21.1-
+ if (!fun.bm.lophine.config.modules.experiment.RedStoneConfig.oldBlockRemoveBehaviour) {
+ if (flag && blockState.hasBlockEntity()) {
+ if (!this.level.isClientSide && flag2) {
+ BlockEntity blockEntity = this.level.getBlockEntity(pos);
+ if (blockEntity != null) {
+ blockEntity.preRemoveSideEffects(pos, blockState);
+ }
}
- }
- this.removeBlockEntity(pos);
- }
+ this.removeBlockEntity(pos);
+ }
- if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) {
- blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ if ((flag || block instanceof BaseRailBlock) && this.level instanceof ServerLevel serverLevel && ((flags & 1) != 0 || flag1)) {
+ blockState.affectNeighborsAfterRemoval(serverLevel, pos, flag1);
+ }
+ } else {
+ blockState.onRemove(this.level, pos, state, flag1);
}
+ // Leaves end - behaviour 1.21.1-
if (!section.getBlockState(i, i1, i2).is(block)) {
return null;
@@ -0,0 +1,70 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Tue, 18 Nov 2025 23:26:27 +0800
Subject: [PATCH] Leaves: Do not reset placed block on exception & Do not
prevent block entity and entity crash at LevelChunk
Co-authored by: MC_XiaoHei <xiaohei.xor7@outlook.com>
As a part of : Leaves (https://github.com/LeavesMC/Leaves)
Licensed under: GPL-3.0 (https://www.gnu.org/licenses/gpl-3.0.html)
diff --git a/net/minecraft/world/item/BlockItem.java b/net/minecraft/world/item/BlockItem.java
index 8f112f382190d606a87f38da8bcdf8dd5f31d1c5..f27915e43df8e627000cda1cb213a95300c98038 100644
--- a/net/minecraft/world/item/BlockItem.java
+++ b/net/minecraft/world/item/BlockItem.java
@@ -77,20 +77,22 @@ public class BlockItem extends Item {
BlockState blockState = level.getBlockState(clickedPos);
if (blockState.is(placementState.getBlock())) {
blockState = this.updateBlockStateFromTag(clickedPos, level, itemInHand, blockState);
+ // Leaves start - we do not need this
// Paper start - Reset placed block on exception
- try {
+ // try {
this.updateCustomBlockEntityTag(clickedPos, level, player, itemInHand, blockState);
updateBlockEntityComponents(level, clickedPos, itemInHand);
- } catch (Exception ex) {
- ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
- if (player instanceof ServerPlayer serverPlayer) {
- org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
- serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
- return InteractionResult.FAIL;
- }
- throw ex; // Rethrow exception if not placed by a player
- }
+ // } catch (Exception ex) {
+ // ((org.bukkit.craftbukkit.block.CraftBlockState) oldBukkitState).revertPlace();
+ // if (player instanceof ServerPlayer serverPlayer) {
+ // org.apache.logging.log4j.LogManager.getLogger().error("Player {} tried placing invalid block", player.getScoreboardName(), ex);
+ // serverPlayer.getBukkitEntity().kickPlayer("Packet processing error");
+ // return InteractionResult.FAIL;
+ // }
+ // throw ex; // Rethrow exception if not placed by a player
+ // }
// Paper end - Reset placed block on exception
+ // Leaves end - we dot not need this
blockState.getBlock().setPlacedBy(level, clickedPos, blockState, player, itemInHand);
// CraftBukkit start
if (bukkitState != null) {
diff --git a/net/minecraft/world/level/chunk/LevelChunk.java b/net/minecraft/world/level/chunk/LevelChunk.java
index 568427a952a24012c17f64f62b6545a9d89c8c8a..49a740bf17b2bed8010e347747b170b69ac26929 100644
--- a/net/minecraft/world/level/chunk/LevelChunk.java
+++ b/net/minecraft/world/level/chunk/LevelChunk.java
@@ -971,12 +971,14 @@ public class LevelChunk extends ChunkAccess implements ca.spottedleaf.moonrise.p
profilerFiller.pop();
} catch (Throwable var5) {
+ // Leaves start - do not prevent here
// Paper start - Prevent block entity and entity crashes
- final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
- net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
- net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
- LevelChunk.this.removeBlockEntity(this.getPos());
+ // final String msg = String.format("BlockEntity threw exception at %s:%s,%s,%s", LevelChunk.this.getLevel().getWorld().getName(), this.getPos().getX(), this.getPos().getY(), this.getPos().getZ());
+ // net.minecraft.server.MinecraftServer.LOGGER.error(msg, var5);
+ // net.minecraft.world.level.chunk.LevelChunk.this.level.getCraftServer().getPluginManager().callEvent(new com.destroystokyo.paper.event.server.ServerExceptionEvent(new com.destroystokyo.paper.exception.ServerInternalException(msg, var5))); // Paper - ServerExceptionEvent
+ // LevelChunk.this.removeBlockEntity(this.getPos());
// Paper end - Prevent block entity and entity crashes
+ // Leaves end - do not prevent here
}
}
}
@@ -0,0 +1,101 @@
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: Helvetica Volubi <suisuroru@blue-millennium.fun>
Date: Sat, 22 Nov 2025 01:43:26 +0800
Subject: [PATCH] add cancel task by task id in FoliaGlobalRegionScheduler
diff --git a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
index d306f911757a4d556c82c0070d4837db87afc497..7c9d3e4c399b2ea246a76b4550ba12e45e75078e 100644
--- a/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
+++ b/src/main/java/io/papermc/paper/threadedregions/scheduler/FoliaGlobalRegionScheduler.java
@@ -17,6 +17,8 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private long tickCount = 0L;
private final Object stateLock = new Object();
private final Long2ObjectOpenHashMap<List<GlobalScheduledTask>> tasksByDeadline = new Long2ObjectOpenHashMap<>();
+ private int lastTaskId = 1; // Lophine - add task id
+ private final Object stateLockForTaskId = new Object(); // Lophine - add task id
public void tick() {
final List<GlobalScheduledTask> run;
@@ -65,7 +67,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, -1, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, delayTicks);
@@ -92,7 +94,7 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
throw new IllegalPluginAccessException("Plugin attempted to register task while disabled");
}
- final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task);
+ final GlobalScheduledTask ret = new GlobalScheduledTask(plugin, periodTicks, task, this.getNextTaskId()); // Lophine - add task id
this.scheduleInternal(ret, initialDelayTicks);
@@ -134,7 +136,33 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
- private final class GlobalScheduledTask implements ScheduledTask, Runnable {
+ // Lophine start - add cancel task by task id
+ public void cancelTask(final int taskId) {
+ synchronized (this.stateLock) {
+ for (final List<GlobalScheduledTask> tasks : this.tasksByDeadline.values()) {
+ for (final GlobalScheduledTask task : tasks) {
+ if (task.getTaskId() == taskId) {
+ task.cancel();
+ return;
+ }
+ }
+ }
+ }
+ }
+
+ private int getNextTaskId() {
+ synchronized (this.stateLockForTaskId) {
+ if (this.lastTaskId == Integer.MAX_VALUE) {
+ this.lastTaskId = 1;
+ } else {
+ ++this.lastTaskId;
+ }
+ }
+ return this.lastTaskId;
+ }
+ // Lophine end - add cancel task by task id
+
+ public final class GlobalScheduledTask implements ScheduledTask, Runnable { // Lophine - private -> public
private static final int STATE_IDLE = 0;
private static final int STATE_EXECUTING = 1;
@@ -146,13 +174,15 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
private final long repeatDelay; // in ticks
private Consumer<ScheduledTask> run;
private volatile int state;
+ private int taskId; // Lophine - add task id
private static final VarHandle STATE_HANDLE = ConcurrentUtil.getVarHandle(GlobalScheduledTask.class, "state", int.class);
- private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run) {
+ private GlobalScheduledTask(final Plugin plugin, final long repeatDelay, final Consumer<ScheduledTask> run, int taskId) { // Lophine - add task id
this.plugin = plugin;
this.repeatDelay = repeatDelay;
this.run = run;
+ this.taskId = taskId; // Lophine - add task id
}
private final int getStateVolatile() {
@@ -263,5 +293,11 @@ public class FoliaGlobalRegionScheduler implements GlobalRegionScheduler {
}
}
}
+
+ // Lophine start - add task id
+ public int getTaskId() {
+ return taskId;
+ }
+ // Lophine end - add task id
}
}
@@ -0,0 +1,8 @@
package fun.bm.lophine;
import com.mojang.logging.LogUtils;
import org.slf4j.Logger;
public class LophineLogger {
public static final Logger LOGGER = LogUtils.getClassLogger(); // only provided for some Logger can not be initialized
}
@@ -0,0 +1,34 @@
package fun.bm.lophine.config.modules.experiment;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.config.flags.HotReloadUnsupported;
import me.earthme.luminol.config.flags.TransformedConfig;
import me.earthme.luminol.enums.EnumConfigCategory;
/*
* This is a config module for redstone in experimental level
* If we think configs from here is stable for future, we will move them to function module directory
*/
@ConfigClassInfo(category = EnumConfigCategory.EXPERIMENT, name = "redstone")
public class RedStoneConfig implements IConfigModule {
@TransformedConfig(name = "enabled", directory = {"experiment", "redstone-ignore-upwards-update"})
@ConfigInfo(name = "redstone-ignore-upwards-update", comments = """
Should the pre-1.20 mechanism be reintroduced:
Redstone dust does not connect to adjacent redstone dust on trapdoors that are open
Pre-1.20.2 mechanism: Redstone dust, redstone repeaters, and redstone comparators do not check for attachment when receiving status updates from below""")
public static boolean redstoneIgnoreUpwardsUpdate = false;
@TransformedConfig(name = "enabled", directory = {"experiment", "cce-update-suppression"})
@ConfigInfo(name = "cce-update-suppression", comments = """
Is it permissible to use ClassCastException for update suppression?""")
public static boolean cce = false;
@HotReloadUnsupported
@ConfigInfo(name = "instant-block-updater")
public static boolean instantBlockUpdater = false;
@ConfigInfo(name = "old-block-remove-behaviour")
public static boolean oldBlockRemoveBehaviour = false;
}
@@ -0,0 +1,13 @@
package fun.bm.lophine.config.modules.fixes;
import me.earthme.luminol.config.IConfigModule;
import me.earthme.luminol.config.flags.ConfigClassInfo;
import me.earthme.luminol.config.flags.ConfigInfo;
import me.earthme.luminol.enums.EnumConfigCategory;
@ConfigClassInfo(category = EnumConfigCategory.FIXES, name = "update-suppression-crash-fix")
public class UpdateSuppressionCrashFixConfig implements IConfigModule {
@ConfigInfo(name = "enabled", comments = """
Should crash caused by update suppression be prevented?""")
public static boolean enabled = true;
}
@@ -0,0 +1,4 @@
package org.leavesmc.leaves;
public class LeavesConfig {
}
@@ -25,6 +25,7 @@ import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.FakeplayerConfig;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.RegionizedServer;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.kyori.adventure.text.format.NamedTextColor;
import net.kyori.adventure.text.format.Style;
import net.minecraft.nbt.CompoundTag;
@@ -238,7 +239,7 @@ public class BotList {
}
if (bot.removeTaskId != -1) {
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
bot.removeTaskId = -1;
}
@@ -473,7 +473,7 @@ public class ServerBot extends ServerPlayer {
playerConnection.send(this.getAddEntityPacket(entityTracker.serverEntity));
if (login) {
Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f))), 10);
} else {
playerConnection.send(new ClientboundRotateHeadPacket(this, (byte) ((getYRot() * 256f) / 360f)));
}
@@ -499,7 +499,7 @@ public class ServerBot extends ServerPlayer {
Component defaultMessage = this.getCombatTracker().getDeathMessage();
BotDeathEvent event = new BotDeathEvent(this.getBukkitEntity(), PaperAdventure.asAdventure(defaultMessage), flag);
this.getServer().server.getPluginManager().callEvent(event);
MinecraftServer.getServer().server.getPluginManager().callEvent(event);
if (event.isCancelled()) {
if (this.getHealth() <= 0) {
@@ -20,6 +20,7 @@ package org.leavesmc.leaves.command.bot.subcommands;
import com.mojang.brigadier.arguments.StringArgumentType;
import com.mojang.brigadier.exceptions.CommandSyntaxException;
import io.papermc.paper.adventure.PaperAdventure;
import io.papermc.paper.threadedregions.scheduler.FoliaGlobalRegionScheduler;
import net.minecraft.world.entity.LivingEntity;
import org.bukkit.Bukkit;
import org.bukkit.command.CommandSender;
@@ -102,12 +103,12 @@ public class RemoveCommand extends BotSubcommand {
boolean isReschedule = bot.removeTaskId != -1;
if (isReschedule) {
Bukkit.getScheduler().cancelTask(bot.removeTaskId);
((FoliaGlobalRegionScheduler) Bukkit.getGlobalRegionScheduler()).cancelTask(bot.removeTaskId);
}
bot.removeTaskId = Bukkit.getScheduler().runTaskLater(MinecraftInternalPlugin.INSTANCE, () -> {
bot.removeTaskId = ((FoliaGlobalRegionScheduler.GlobalScheduledTask) Bukkit.getGlobalRegionScheduler().runDelayed(MinecraftInternalPlugin.INSTANCE, (unused) -> {
bot.removeTaskId = -1;
removeBot(bot, sender);
}, removeTimeSeconds * 20L).getTaskId();
}, removeTimeSeconds * 20L)).getTaskId();
sender.sendMessage(join(spaces(),
text("Bot", GRAY),
@@ -17,6 +17,7 @@
package org.leavesmc.leaves.protocol.servux;
import ca.spottedleaf.moonrise.common.util.TickThread;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.config.modules.function.protocol.ServuxProtocolConfig;
import io.netty.buffer.Unpooled;
@@ -31,6 +32,7 @@ import net.minecraft.util.RandomSource;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.level.block.entity.BlockEntity;
import net.minecraft.world.phys.Vec3;
import org.leavesmc.leaves.protocol.core.LeavesCustomPayload;
import org.leavesmc.leaves.protocol.core.LeavesProtocol;
import org.leavesmc.leaves.protocol.core.ProtocolHandler;
@@ -104,6 +106,7 @@ public class ServuxEntityDataProtocol implements LeavesProtocol {
public static void onBlockEntityRequest(ServerPlayer player, BlockPos pos) {
player.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
if (!TickThread.isTickThreadFor(nmsEntity.level(), pos)) return;
BlockEntity be = nmsEntity.level().getBlockEntity(pos);
CompoundTag nbt = be != null ? be.saveWithFullMetadata(nmsEntity.registryAccess()) : new CompoundTag();
@@ -115,7 +118,9 @@ public class ServuxEntityDataProtocol implements LeavesProtocol {
}
public static void onEntityRequest(ServerPlayer player, int entityId) {
final Vec3 pos = player.position();
player.getBukkitEntity().taskScheduler.schedule((LivingEntity nmsEntity) -> {
if (!TickThread.isTickThreadFor(nmsEntity.level(), pos)) return;
Entity entity = nmsEntity.level().getEntity(entityId);
CompoundTag nbt = TagUtil.saveEntityWithoutId(entity);
@@ -103,7 +103,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
final ChunkPos pos = chunk.getPos();
if (chunkHasStructureReferences(pos.x, pos.z, chunk.getLevel())) {
final Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new HashMap<>());
final Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new ConcurrentHashMap<>());
map.computeIfAbsent(pos, (p) -> new Timeout(tickCounter - ServuxProtocolConfig.maxDelay));
}
}
@@ -304,7 +304,7 @@ public class ServuxStructuresProtocol implements LeavesProtocol {
}
public static void addOrRefreshTimeouts(final UUID uuid, final Map<Structure, LongSet> references, final long tickCounter) {
Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new HashMap<>());
Map<ChunkPos, Timeout> map = timeouts.computeIfAbsent(uuid, (u) -> new ConcurrentHashMap<>());
for (LongSet chunks : references.values()) {
for (Long chunkPosLong : chunks) {
@@ -17,7 +17,7 @@
package org.leavesmc.leaves.util;
import com.mojang.logging.LogUtils;
import fun.bm.lophine.LophineLogger;
import net.minecraft.core.BlockPos;
import net.minecraft.server.level.ServerPlayer;
import net.minecraft.world.level.Level;
@@ -30,7 +30,6 @@ import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.leavesmc.leaves.bot.ServerBot;
import org.leavesmc.leaves.event.player.UpdateSuppressionEvent;
import org.slf4j.Logger;
import java.util.ArrayList;
import java.util.List;
@@ -41,7 +40,6 @@ public class UpdateSuppressionException extends RuntimeException {
private @Nullable Block source;
private @Nullable ServerPlayer player;
private final @NotNull Throwable throwable;
private static final Logger LOGGER = LogUtils.getLogger();
public UpdateSuppressionException(
@Nullable BlockPos pos,
@@ -87,7 +85,7 @@ public class UpdateSuppressionException extends RuntimeException {
public void consume() {
submitEvent();
LOGGER.info(getMessage());
LophineLogger.LOGGER.info(getMessage());
}
private void submitEvent() {