Files

89 lines
6.1 KiB
Diff
Raw Permalink Normal View History

2026-07-09 00:03:09 +08:00
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
From: MrHua269 <mrhua269@gmail.com>
Date: Wed, 8 Jul 2026 21:34:46 +0800
Subject: [PATCH] Fix high velocity moving issue
On folia, entity usually cannot move out of the tickregion, but sometimes it actually does(like some end pearl gun that can shoot an end pearl to the block faraway than 10000 blocks even more). To fix this, we added a temporary fix which teleport these entities to the destination instead running its move logics so that we could ensure anything is under control.But one thing need to consider is that teleportAsync is actually calling halfway of the entity tick and there is still something running when teleportAsync called, which is actually modified the entity in another thread, so there is still need an improvement
Reference from : https://github.com/KaiijuMC/Kaiiju/blob/ver/1.20.1/patches/server/0040-Teleport-async-if-we-cannot-move-entity-off-main.patch
diff --git a/net/minecraft/world/entity/Entity.java b/net/minecraft/world/entity/Entity.java
2026-08-15 16:14:13 +08:00
index dee189bea3e90fd5dd503a2fe6b8a5c986589c62..6715a4c8078fe49c929f24d87df76bef04e5b43a 100644
2026-07-09 00:03:09 +08:00
--- a/net/minecraft/world/entity/Entity.java
+++ b/net/minecraft/world/entity/Entity.java
2026-08-15 16:14:13 +08:00
@@ -1165,6 +1165,20 @@ public abstract class Entity
2026-07-09 00:03:09 +08:00
this.moveStartZ = this.getZ();
this.moveVector = delta;
}
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Fix high velocity moving issue
2026-07-09 00:03:09 +08:00
+ // Filter the threads as it may be called by the chunk system worker thread
2026-07-14 12:22:17 +08:00
+ if (io.nanachiyo0721.shiroha.config.modules.fixes.FoliaEntityMovingFixConfig.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()){
2026-07-09 00:03:09 +08:00
+ var finalPosition = delta.add(this.position);
+ // not NaN (Prevent incorrect checks under NaN minecarts)
+ if (!Double.isNaN(finalPosition.x) && !Double.isNaN(finalPosition.y) && !Double.isNaN(finalPosition.z)) {
+ // kill tick passively if it's moving out of region and we'll catch this exception
2026-08-14 01:49:37 +08:00
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, finalPosition)) {
2026-07-14 12:22:17 +08:00
+ throw new io.nanachiyo0721.shiroha.utils.entity.EntityMoveOutOfRegionException(this, delta, moverType);
2026-07-09 00:03:09 +08:00
+ }
+ }
+ }
2026-08-14 01:49:37 +08:00
+ // Guard delta too large at the initial input
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
try {
// Paper end - detailed watchdog information
if (this.noPhysics) {
2026-08-15 16:14:13 +08:00
@@ -1203,6 +1217,23 @@ public abstract class Entity
2026-08-14 01:49:37 +08:00
}
// Paper end
+ // Shiroha start - Fix high velocity moving issue
+ // Filter the threads as it may be called by the chunk system worker thread
+ if (io.nanachiyo0721.shiroha.config.modules.fixes.FoliaEntityMovingFixConfig.enabled && ca.spottedleaf.moonrise.common.util.TickThread.isTickThread()){
+ var finalPosition = delta.add(this.position);
+ // not NaN (Prevent incorrect checks under NaN minecarts)
+ if (!Double.isNaN(finalPosition.x) && !Double.isNaN(finalPosition.y) && !Double.isNaN(finalPosition.z)) {
+ // kill tick passively if it's moving out of region and we'll catch this exception
+ if (!ca.spottedleaf.moonrise.common.util.TickThread.isTickThreadFor(this.level, finalPosition)) {
+ throw new io.nanachiyo0721.shiroha.utils.entity.EntityMoveOutOfRegionException(this, delta, moverType);
+ }
+ }
+ }
+ // Guard against delta too large when it was processed above
+ // note: following method call "maybeBackOffFromEdge" have indirect access to world data, so gurad is needed.
+ // We ignore to check the final delta movemnt after calling "colliding" as it's clamped at least unless the AABB of the entity is
+ // in a large scale, but it's never allowed and reasonable to have
+ // Shiroha end
delta = this.maybeBackOffFromEdge(delta, moverType);
Vec3 movement = this.collide(delta);
double movementLength = movement.lengthSqr();
2026-07-09 00:03:09 +08:00
diff --git a/net/minecraft/world/level/Level.java b/net/minecraft/world/level/Level.java
2026-07-14 15:09:17 +08:00
index a0eb1f608a99301e0197ab1d1a6fbbb0a0be4ce0..21b3fcba9e80082ad33a4331f27758cffef163f8 100644
2026-07-09 00:03:09 +08:00
--- a/net/minecraft/world/level/Level.java
+++ b/net/minecraft/world/level/Level.java
@@ -1571,6 +1571,25 @@ public abstract class Level implements LevelAccessor, AutoCloseable, ca.spottedl
public <T extends Entity> void guardEntityTick(final Consumer<T> tick, final T entity) {
try {
tick.accept(entity);
2026-07-14 12:22:17 +08:00
+ } catch (io.nanachiyo0721.shiroha.utils.entity.EntityMoveOutOfRegionException moveOutOfRegionException) { // Shiroha - Fix high velocity moving issue
2026-07-14 11:32:51 +08:00
+ // Shiroha start - Fix high velocity moving issue
2026-07-09 00:03:09 +08:00
+ final Entity ent = moveOutOfRegionException.getEntity();
+ var currPosition = ent.position();
+ var toPosition = moveOutOfRegionException.getMovement().add(currPosition);
+
2026-07-14 12:22:17 +08:00
+ if (io.nanachiyo0721.shiroha.config.modules.fixes.FoliaEntityMovingFixConfig.warnOnDetected) {
2026-07-09 00:03:09 +08:00
+ MinecraftServer.LOGGER.warn("Entity {} with entityId {} has tried moving to another region!",ent, ent.getId());
+ }
+
+ ent.getBukkitEntity().taskScheduler.scheduleOrExecute(entityFresh -> entityFresh.teleportAsync(
+ (ServerLevel) entityFresh.level(),
+ toPosition,
+ entityFresh.getYRot(), entityFresh.getXRot(),
+ entityFresh.getDeltaMovement(), org.bukkit.event.player.PlayerTeleportEvent.TeleportCause.UNKNOWN,
+ Entity.TELEPORT_FLAG_LOAD_CHUNK | Entity.TELEPORT_FLAG_TELEPORT_PASSENGERS,
+ null
+ ));
2026-07-14 11:32:51 +08:00
+ // Shiroha end
2026-07-09 00:03:09 +08:00
} catch (Throwable t) {
// Paper start - Prevent block entity and entity crashes
final String msg = String.format("Entity threw exception at %s:%s,%s,%s", io.papermc.paper.util.MCUtil.getLevelName(entity.level()), entity.getX(), entity.getY(), entity.getZ());