From edb9d18aed46e0e9db831fdac4d58be1d4827841 Mon Sep 17 00:00:00 2001 From: kashike Date: Wed, 15 Aug 2018 01:26:51 -0700 Subject: [PATCH 1/4] Allow disabling armour stand ticking --- ...Allow-disabling-armour-stand-ticking.patch | 35 +++++++++ ...Allow-disabling-armour-stand-ticking.patch | 73 +++++++++++++++++++ 2 files changed, 108 insertions(+) create mode 100644 Spigot-API-Patches/0128-Allow-disabling-armour-stand-ticking.patch create mode 100644 Spigot-Server-Patches/0352-Allow-disabling-armour-stand-ticking.patch diff --git a/Spigot-API-Patches/0128-Allow-disabling-armour-stand-ticking.patch b/Spigot-API-Patches/0128-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 000000000..71a6b707b --- /dev/null +++ b/Spigot-API-Patches/0128-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,35 @@ +From 800083976a454caf39f0a2019df51e3af314b022 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:03 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/org/bukkit/entity/ArmorStand.java b/src/main/java/org/bukkit/entity/ArmorStand.java +index 099da6ce..859f166f 100644 +--- a/src/main/java/org/bukkit/entity/ArmorStand.java ++++ b/src/main/java/org/bukkit/entity/ArmorStand.java +@@ -275,5 +275,21 @@ public interface ArmorStand extends LivingEntity { + * @param move {@code true} if this armour stand can move, {@code false} otherwise + */ + void setCanMove(boolean move); ++ ++ /** ++ * Tests if this armor stand can tick. ++ * ++ *

The default value is defined in {@code paper.yml}.

++ * ++ * @return {@code true} if this armour stand can tick, {@code false} otherwise ++ */ ++ boolean canTick(); ++ ++ /** ++ * Sets if this armor stand can tick. ++ * ++ * @param tick {@code true} if this armour stand can tick, {@code false} otherwise ++ */ ++ void setCanTick(final boolean tick); + // Paper end + } +-- +2.18.0 + diff --git a/Spigot-Server-Patches/0352-Allow-disabling-armour-stand-ticking.patch b/Spigot-Server-Patches/0352-Allow-disabling-armour-stand-ticking.patch new file mode 100644 index 000000000..8a0339565 --- /dev/null +++ b/Spigot-Server-Patches/0352-Allow-disabling-armour-stand-ticking.patch @@ -0,0 +1,73 @@ +From 8e587147671ae4291c03ddbec1a4687639db87e9 Mon Sep 17 00:00:00 2001 +From: kashike +Date: Wed, 15 Aug 2018 01:26:09 -0700 +Subject: [PATCH] Allow disabling armour stand ticking + + +diff --git a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +index c3bd82692..ed1475351 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperWorldConfig.java +@@ -584,4 +584,10 @@ public class PaperWorldConfig { + break; + } + } ++ ++ public boolean armorStandTick = true; ++ private void armorStandTick() { ++ this.armorStandTick = this.getBoolean("armor-stands-tick", this.armorStandTick); ++ log("ArmorStand ticking is " + (this.armorStandTick ? "enabled" : "disabled") + " by default"); ++ } + } +diff --git a/src/main/java/net/minecraft/server/EntityArmorStand.java b/src/main/java/net/minecraft/server/EntityArmorStand.java +index df0d66ad0..dca497072 100644 +--- a/src/main/java/net/minecraft/server/EntityArmorStand.java ++++ b/src/main/java/net/minecraft/server/EntityArmorStand.java +@@ -51,6 +51,7 @@ public class EntityArmorStand extends EntityLiving { + public Vector3f leftLegPose; + public Vector3f rightLegPose; + public boolean canMove = true; // Paper ++ public boolean canTick = true; // Paper - armour stand ticking + + public EntityArmorStand(World world) { + super(world); +@@ -64,6 +65,7 @@ public class EntityArmorStand extends EntityLiving { + this.rightLegPose = EntityArmorStand.bw; + this.noclip = this.isNoGravity(); + this.setSize(0.5F, 1.975F); ++ if (world != null) this.canTick = world.paperConfig.armorStandTick; // Paper - armour stand ticking + } + + public EntityArmorStand(World world, double d0, double d1, double d2) { +@@ -568,6 +570,7 @@ public class EntityArmorStand extends EntityLiving { + } + + public void B_() { ++ if (!this.canTick) return;// Paper + super.B_(); + Vector3f vector3f = (Vector3f) this.datawatcher.get(EntityArmorStand.b); + +diff --git a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +index 8a06cb165..91b7bc2ed 100644 +--- a/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java ++++ b/src/main/java/org/bukkit/craftbukkit/entity/CraftArmorStand.java +@@ -221,4 +221,16 @@ public class CraftArmorStand extends CraftLivingEntity implements ArmorStand { + public void setCanMove(boolean move) { + getHandle().canMove = move; + } ++ ++ // Paper start ++ @Override ++ public boolean canTick() { ++ return this.getHandle().canTick; ++ } ++ ++ @Override ++ public void setCanTick(final boolean tick) { ++ this.getHandle().canTick = tick; ++ } ++ // Paper end + } +-- +2.18.0 + From dc428860cf1ef8df4df5b53b97ea61f551f50b11 Mon Sep 17 00:00:00 2001 From: Aikar Date: Sun, 12 Aug 2018 13:27:23 -0400 Subject: [PATCH 2/4] Improve Watchdog Early Warning Feature - Closes #1319 1) Don't kick in until server has started (the full crash will still kick in before full start) 2) Delay reporting until 10 seconds, then print every 5 3) Make the intervals configurable 4) Make it able to be disabled by setting every interval to <= 0 --- ...Add-5-second-short-dumps-to-watchdog.patch | 87 --------- ...dd-Early-Warning-Feature-to-WatchDog.patch | 166 ++++++++++++++++++ 2 files changed, 166 insertions(+), 87 deletions(-) delete mode 100644 Spigot-Server-Patches/0349-Add-5-second-short-dumps-to-watchdog.patch create mode 100644 Spigot-Server-Patches/0349-Add-Early-Warning-Feature-to-WatchDog.patch diff --git a/Spigot-Server-Patches/0349-Add-5-second-short-dumps-to-watchdog.patch b/Spigot-Server-Patches/0349-Add-5-second-short-dumps-to-watchdog.patch deleted file mode 100644 index 63dfe16f0..000000000 --- a/Spigot-Server-Patches/0349-Add-5-second-short-dumps-to-watchdog.patch +++ /dev/null @@ -1,87 +0,0 @@ -From a30613e82fe3e0e0759e03c7d6b4b69d60e005f0 Mon Sep 17 00:00:00 2001 -From: miclebrick -Date: Wed, 8 Aug 2018 15:30:52 -0400 -Subject: [PATCH] Add 5 second short dumps to watchdog - - -diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java -index 57a4748a3..815c3e664 100644 ---- a/src/main/java/org/spigotmc/WatchdogThread.java -+++ b/src/main/java/org/spigotmc/WatchdogThread.java -@@ -13,8 +13,10 @@ public class WatchdogThread extends Thread - - private static WatchdogThread instance; - private final long timeoutTime; -+ private final long shortTimeout; // Paper - Timeout time for just printing a dump but not restarting - private final boolean restart; - private volatile long lastTick; -+ private long lastShortDump; // Paper - Keep track of short dump times to avoid spamming console with short dumps - private volatile boolean stopping; - - private WatchdogThread(long timeoutTime, boolean restart) -@@ -22,6 +24,7 @@ public class WatchdogThread extends Thread - super( "Paper Watchdog Thread" ); - this.timeoutTime = timeoutTime; - this.restart = restart; -+ shortTimeout = Math.min(5000, timeoutTime); // Paper - Make short timeout the lower of 5 seconds, and timeout time - } - - public static void doStart(int timeoutTime, boolean restart) -@@ -52,9 +55,19 @@ public class WatchdogThread extends Thread - while ( !stopping ) - { - // -- if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable -+ long currentTime = System.currentTimeMillis(); // Paper - do we REALLY need to call this method multiple times? -+ if ( lastTick != 0 && currentTime > lastTick + shortTimeout && !Boolean.getBoolean("disable.watchdog") ) // Paper - Add property to disable and short timeout - { -+ // Paper start -+ boolean isLongTimeout = currentTime > lastTick + timeoutTime; -+ // Don't spam short dumps -+ if ( !isLongTimeout && currentTime < lastShortDump + shortTimeout ) continue; -+ lastShortDump = currentTime; -+ // Paper end - Logger log = Bukkit.getServer().getLogger(); -+ // Paper start - Different message when it's a short timeout -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "The server has stopped responding!" ); - log.log( Level.SEVERE, "Please report this to https://github.com/PaperMC/Paper/issues" ); - log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); -@@ -79,11 +92,19 @@ public class WatchdogThread extends Thread - } - } - // Paper end -+ } else -+ { -+ log.log( Level.SEVERE, "The server has not responded for " + shortTimeout / 1000 + " seconds! Creating thread dump"); -+ } -+ // Paper end - Different message for short timeout - log.log( Level.SEVERE, "------------------------------" ); - log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); - dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); - log.log( Level.SEVERE, "------------------------------" ); - // -+ // Paper start - Only print full dump on long timeouts -+ if ( isLongTimeout ) -+ { - log.log( Level.SEVERE, "Entire Thread Dump:" ); - ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); - for ( ThreadInfo thread : threads ) -@@ -97,11 +118,12 @@ public class WatchdogThread extends Thread - RestartCommand.restart(); - } - break; -+ } // Paper end - } - - try - { -- sleep( 10000 ); -+ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout - } catch ( InterruptedException ex ) - { - interrupt(); --- -2.18.0 - diff --git a/Spigot-Server-Patches/0349-Add-Early-Warning-Feature-to-WatchDog.patch b/Spigot-Server-Patches/0349-Add-Early-Warning-Feature-to-WatchDog.patch new file mode 100644 index 000000000..ab9f66b46 --- /dev/null +++ b/Spigot-Server-Patches/0349-Add-Early-Warning-Feature-to-WatchDog.patch @@ -0,0 +1,166 @@ +From 572418116aca425b6283f25eb1aaefafac1381fd Mon Sep 17 00:00:00 2001 +From: miclebrick +Date: Wed, 8 Aug 2018 15:30:52 -0400 +Subject: [PATCH] Add Early Warning Feature to WatchDog + +Detect when the server has been hung for a long duration, and start printing +thread dumps at an interval until the point of crash. + +This will help diagnose what was going on in that time before the crash. + +diff --git a/src/main/java/com/destroystokyo/paper/PaperConfig.java b/src/main/java/com/destroystokyo/paper/PaperConfig.java +index a5ff014e33..332e90f86b 100644 +--- a/src/main/java/com/destroystokyo/paper/PaperConfig.java ++++ b/src/main/java/com/destroystokyo/paper/PaperConfig.java +@@ -23,6 +23,8 @@ import org.bukkit.configuration.InvalidConfigurationException; + import org.bukkit.configuration.file.YamlConfiguration; + import co.aikar.timings.Timings; + import co.aikar.timings.TimingsManager; ++import org.spigotmc.SpigotConfig; ++import org.spigotmc.WatchdogThread; + + public class PaperConfig { + +@@ -304,6 +306,14 @@ public class PaperConfig { + } + } + ++ public static int watchdogPrintEarlyWarningEvery = 5000; ++ public static int watchdogPrintEarlyWarningDelay = 10000; ++ private static void watchdogEarlyWarning() { ++ watchdogPrintEarlyWarningEvery = getInt("settings.watchdog.early-warning-every", 5000); ++ watchdogPrintEarlyWarningDelay = getInt("settings.watchdog.early-warning-delay", 10000); ++ WatchdogThread.doStart(SpigotConfig.timeoutTime, SpigotConfig.restartOnCrash ); ++ } ++ + public static int tabSpamIncrement = 10; + public static int tabSpamLimit = 500; + private static void tabSpamLimiters() { +diff --git a/src/main/java/net/minecraft/server/MinecraftServer.java b/src/main/java/net/minecraft/server/MinecraftServer.java +index 0399a48e19..e0546e3dd2 100644 +--- a/src/main/java/net/minecraft/server/MinecraftServer.java ++++ b/src/main/java/net/minecraft/server/MinecraftServer.java +@@ -622,6 +622,7 @@ public abstract class MinecraftServer implements ICommandListener, Runnable, IAs + this.a(this.q); + + // Spigot start ++ org.spigotmc.WatchdogThread.hasStarted = true; + Arrays.fill( recentTps, 20 ); + long start = System.nanoTime(), lastTick = start - TICK_TIME, catchupTime = 0, curTime, wait, tickSection = start; // Paper - Further improve server tick loop + while (this.isRunning) { +diff --git a/src/main/java/org/spigotmc/SpigotConfig.java b/src/main/java/org/spigotmc/SpigotConfig.java +index 4f9fd4bc60..2cdd9aaf81 100644 +--- a/src/main/java/org/spigotmc/SpigotConfig.java ++++ b/src/main/java/org/spigotmc/SpigotConfig.java +@@ -223,7 +223,7 @@ public class SpigotConfig + restartScript = getString( "settings.restart-script", restartScript ); + restartMessage = transform( getString( "messages.restart", "Server is restarting" ) ); + commands.put( "restart", new RestartCommand( "restart" ) ); +- WatchdogThread.doStart( timeoutTime, restartOnCrash ); ++ //WatchdogThread.doStart( timeoutTime, restartOnCrash ); // Paper - moved to PaperConfig + } + + public static boolean bungee; +diff --git a/src/main/java/org/spigotmc/WatchdogThread.java b/src/main/java/org/spigotmc/WatchdogThread.java +index 57a4748a30..28a9e2b96f 100644 +--- a/src/main/java/org/spigotmc/WatchdogThread.java ++++ b/src/main/java/org/spigotmc/WatchdogThread.java +@@ -5,6 +5,7 @@ import java.lang.management.MonitorInfo; + import java.lang.management.ThreadInfo; + import java.util.logging.Level; + import java.util.logging.Logger; ++import com.destroystokyo.paper.PaperConfig; + import net.minecraft.server.MinecraftServer; + import org.bukkit.Bukkit; + +@@ -13,6 +14,10 @@ public class WatchdogThread extends Thread + + private static WatchdogThread instance; + private final long timeoutTime; ++ private final long earlyWarningEvery; // Paper - Timeout time for just printing a dump but not restarting ++ private final long earlyWarningDelay; // Paper ++ public static volatile boolean hasStarted; // Paper ++ private long lastEarlyWarning; // Paper - Keep track of short dump times to avoid spamming console with short dumps + private final boolean restart; + private volatile long lastTick; + private volatile boolean stopping; +@@ -22,6 +27,8 @@ public class WatchdogThread extends Thread + super( "Paper Watchdog Thread" ); + this.timeoutTime = timeoutTime; + this.restart = restart; ++ earlyWarningEvery = Math.min(PaperConfig.watchdogPrintEarlyWarningEvery, timeoutTime); // Paper ++ earlyWarningDelay = Math.min(PaperConfig.watchdogPrintEarlyWarningDelay, timeoutTime); // Paper + } + + public static void doStart(int timeoutTime, boolean restart) +@@ -52,9 +59,19 @@ public class WatchdogThread extends Thread + while ( !stopping ) + { + // +- if ( lastTick != 0 && System.currentTimeMillis() > lastTick + timeoutTime && !Boolean.getBoolean("disable.watchdog")) // Paper - Add property to disable ++ long currentTime = System.currentTimeMillis(); // Paper - do we REALLY need to call this method multiple times? ++ if ( lastTick != 0 && currentTime > lastTick + earlyWarningEvery && !Boolean.getBoolean("disable.watchdog") ) // Paper - Add property to disable and short timeout + { ++ // Paper start ++ boolean isLongTimeout = currentTime > lastTick + timeoutTime; ++ // Don't spam early warning dumps ++ if ( !isLongTimeout && (earlyWarningEvery <= 0 || !hasStarted || currentTime < lastEarlyWarning + earlyWarningEvery || currentTime < lastTick + earlyWarningDelay)) continue; ++ lastEarlyWarning = currentTime; ++ // Paper end + Logger log = Bukkit.getServer().getLogger(); ++ // Paper start - Different message when it's a short timeout ++ if ( isLongTimeout ) ++ { + log.log( Level.SEVERE, "The server has stopped responding!" ); + log.log( Level.SEVERE, "Please report this to https://github.com/PaperMC/Paper/issues" ); + log.log( Level.SEVERE, "Be sure to include ALL relevant console errors and Minecraft crash reports" ); +@@ -79,29 +96,45 @@ public class WatchdogThread extends Thread + } + } + // Paper end ++ } else ++ { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ log.log(Level.SEVERE, "The server has not responded for " + (currentTime - lastTick) / 1000 + " seconds! Creating thread dump"); ++ } ++ // Paper end - Different message for short timeout + log.log( Level.SEVERE, "------------------------------" ); + log.log( Level.SEVERE, "Server thread dump (Look for plugins here before reporting to Paper!):" ); + dumpThread( ManagementFactory.getThreadMXBean().getThreadInfo( MinecraftServer.getServer().primaryThread.getId(), Integer.MAX_VALUE ), log ); + log.log( Level.SEVERE, "------------------------------" ); + // ++ // Paper start - Only print full dump on long timeouts ++ if ( isLongTimeout ) ++ { + log.log( Level.SEVERE, "Entire Thread Dump:" ); + ThreadInfo[] threads = ManagementFactory.getThreadMXBean().dumpAllThreads( true, true ); + for ( ThreadInfo thread : threads ) + { + dumpThread( thread, log ); + } ++ } else { ++ log.log(Level.SEVERE, "--- DO NOT REPORT THIS TO PAPER - THIS IS NOT A BUG OR A CRASH ---"); ++ } ++ ++ + log.log( Level.SEVERE, "------------------------------" ); + + if ( restart ) + { + RestartCommand.restart(); + } ++ if (isLongTimeout) { + break; ++ } // Paper end + } + + try + { +- sleep( 10000 ); ++ sleep( 1000 ); // Paper - Reduce check time to every second instead of every ten seconds, more consistent and allows for short timeout + } catch ( InterruptedException ex ) + { + interrupt(); +-- +2.18.0 + From 0645364ee5ae64571844eb828eed0da069355fff Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 16 Aug 2018 17:46:38 -0400 Subject: [PATCH 3/4] Ensure chunks are always loaded on hard position sets Player Movement, Entity Creation and Teleportation move entities with a very "You are here, no debate" change, making the server register them as there, regardless if that chunk was loaded or not. It appears possible that with hack clients and lag, a player may be able to move fast enough to move into an unloaded chunk and get into a buggy state. To prevent this, we will ensure a chunk is always loaded, guaranteeing that the entity will be properly registered into its new home comfortably. Closes #1316 --- ...e-always-loaded-on-hard-position-set.patch | 33 +++++++++++++++++++ 1 file changed, 33 insertions(+) create mode 100644 Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch diff --git a/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch b/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch new file mode 100644 index 000000000..291b78e8d --- /dev/null +++ b/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch @@ -0,0 +1,33 @@ +From 88e7c7af098c7a40518c05dbba690e037cb306d8 Mon Sep 17 00:00:00 2001 +From: Aikar +Date: Thu, 16 Aug 2018 17:36:41 -0400 +Subject: [PATCH] Ensure chunks are always loaded on hard position sets + +Player Movement, Entity Creation and Teleportation move +entities with a very "You are here, no debate" change, making +the server register them as there, regardless if that chunk was +loaded or not. + +It appears possible that with hack clients and lag, a player +may be able to move fast enough to move into an unloaded +chunk and get into a buggy state. + +To prevent this, we will ensure a chunk is always loaded, +guaranteeing that the entity will be properly registered +into its new home comfortably. + +diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java +index 9b5f7fcf72..3c279d3fe8 100644 +--- a/src/main/java/net/minecraft/server/Entity.java ++++ b/src/main/java/net/minecraft/server/Entity.java +@@ -1309,6 +1309,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper + this.lastYaw -= 360.0F; + } + ++ world.getChunkAt((int) Math.floor(this.locX), (int) Math.floor(this.locZ)); // Paper - ensure chunk is always loaded + this.setPosition(this.locX, this.locY, this.locZ); + this.setYawPitch(f, f1); + } +-- +2.18.0 + From 6e2711d666533234703cb1ab36d3f834c7c3f05a Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 16 Aug 2018 17:52:24 -0400 Subject: [PATCH 4/4] Fix bug in last patch --- ...sure-chunks-are-always-loaded-on-hard-position-set.patch | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch b/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch index 291b78e8d..dd505a953 100644 --- a/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch +++ b/Spigot-Server-Patches/0353-Ensure-chunks-are-always-loaded-on-hard-position-set.patch @@ -1,4 +1,4 @@ -From 88e7c7af098c7a40518c05dbba690e037cb306d8 Mon Sep 17 00:00:00 2001 +From ee5f7b1451005f94292b283fa1bc9e21cacb05c2 Mon Sep 17 00:00:00 2001 From: Aikar Date: Thu, 16 Aug 2018 17:36:41 -0400 Subject: [PATCH] Ensure chunks are always loaded on hard position sets @@ -17,14 +17,14 @@ guaranteeing that the entity will be properly registered into its new home comfortably. diff --git a/src/main/java/net/minecraft/server/Entity.java b/src/main/java/net/minecraft/server/Entity.java -index 9b5f7fcf72..3c279d3fe8 100644 +index 9b5f7fcf72..48c9fbd9b3 100644 --- a/src/main/java/net/minecraft/server/Entity.java +++ b/src/main/java/net/minecraft/server/Entity.java @@ -1309,6 +1309,7 @@ public abstract class Entity implements ICommandListener, KeyedObject { // Paper this.lastYaw -= 360.0F; } -+ world.getChunkAt((int) Math.floor(this.locX), (int) Math.floor(this.locZ)); // Paper - ensure chunk is always loaded ++ world.getChunkAt((int) Math.floor(this.locX) >> 4, (int) Math.floor(this.locZ) >> 4); // Paper - ensure chunk is always loaded this.setPosition(this.locX, this.locY, this.locZ); this.setYawPitch(f, f1); }