From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001 From: MrHua269 Date: Thu, 1 Feb 2024 09:51:45 +0000 Subject: [PATCH] Prevent teleportAsync calling during moving event being handled diff --git a/src/main/java/me/earthme/luminol/LuminolConfig.java b/src/main/java/me/earthme/luminol/LuminolConfig.java index 87f5c0fc3f92feecb167c3e28d86a67ba848cb61..0a1a8016f5e51163c2c375a9444d68d3d68544d1 100644 --- a/src/main/java/me/earthme/luminol/LuminolConfig.java +++ b/src/main/java/me/earthme/luminol/LuminolConfig.java @@ -46,6 +46,8 @@ public class LuminolConfig { public static boolean useVanillaRandomSource = false; public static boolean fixLargePosMoving = false; public static boolean warnOnLargeMovingDetected = true; + public static boolean preventTeleportAsyncDuringMovingEvent = false; + public static boolean throwOnPreventingTeleportAsync = true; public static RegionFileFormat regionFormatName = RegionFileFormat.ANVIL; public static int regionFormatLinearCompressionLevel = 1; @@ -199,6 +201,8 @@ public class LuminolConfig { useVanillaRandomSource = get("fixes.use_vanilla_random_source",useVanillaRandomSource,"RNG feature related"); fixLargePosMoving = get("fixes.fix_large_pos_moving", fixLargePosMoving,"Fix an entity moving issue on folia which is not fixed yet"); warnOnLargeMovingDetected = get("fixes.warn_on_large_pos_moving",warnOnLargeMovingDetected); + preventTeleportAsyncDuringMovingEvent = get("fixes.prevent_teleportasync_during_moving_event",preventTeleportAsyncDuringMovingEvent); + throwOnPreventingTeleportAsync = get("fixes.throw_on_preventing_async_teleport",throwOnPreventingTeleportAsync); regionFormatName = RegionFileFormat.fromString(get("save.region-format.format", regionFormatName.name())); if (regionFormatName.equals(RegionFileFormat.INVALID)) { diff --git a/src/main/java/net/minecraft/server/level/ServerPlayer.java b/src/main/java/net/minecraft/server/level/ServerPlayer.java index ea409d2a03c35990c6857c24305346a6ec7f4bf8..33d2205ba32dd1e11bba92e40d6a4125379b715f 100644 --- a/src/main/java/net/minecraft/server/level/ServerPlayer.java +++ b/src/main/java/net/minecraft/server/level/ServerPlayer.java @@ -326,6 +326,10 @@ public class ServerPlayer extends Player { public double lastEntitySpawnRadiusSquared = -1.0; // Paper end - optimise chunk tick iteration + //Luminol start - Prevent teleportAsync calling during moving event being handled + public boolean handlingMoveEvent = false; + //Luminol end + public ServerPlayer(MinecraftServer server, ServerLevel world, GameProfile profile, ClientInformation clientOptions) { super(world, world.getSharedSpawnPos(), world.getSharedSpawnAngle(), profile); this.chatVisibility = ChatVisiblity.FULL; diff --git a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java index 18745ee33843d668613fd9e7f15d6a79f118280f..9f7eedbac2cbccba4e4cf5e0059cf3a4248438f1 100644 --- a/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java +++ b/src/main/java/net/minecraft/server/network/ServerGamePacketListenerImpl.java @@ -688,7 +688,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (true) { // Spigot - don't skip any move events Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); + this.player.handlingMoveEvent = true; //Luminol - Prevent teleportAsync calling during moving event being handled this.cserver.getPluginManager().callEvent(event); + this.player.handlingMoveEvent = false; //Luminol - Prevent teleportAsync calling during moving event being handled // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { @@ -1592,7 +1594,9 @@ public class ServerGamePacketListenerImpl extends ServerCommonPacketListenerImpl if (from.getX() != Double.MAX_VALUE) { Location oldTo = to.clone(); PlayerMoveEvent event = new PlayerMoveEvent(player, from, to); + this.player.handlingMoveEvent = true; //Luminol - Prevent teleportAsync calling during moving event being handled this.cserver.getPluginManager().callEvent(event); + this.player.handlingMoveEvent = false; //Luminol - Prevent teleportAsync calling during moving event being handled // If the event is cancelled we move the player back to their old location. if (event.isCancelled()) { diff --git a/src/main/java/net/minecraft/world/entity/Entity.java b/src/main/java/net/minecraft/world/entity/Entity.java index e24b55dc96c2e3904e3c03d6bfa769aedf767b3b..1e5eb1277e1b4f2ba51fadbe2d882198ae940ae0 100644 --- a/src/main/java/net/minecraft/world/entity/Entity.java +++ b/src/main/java/net/minecraft/world/entity/Entity.java @@ -3950,6 +3950,18 @@ public abstract class Entity implements Nameable, EntityAccess, CommandSource { java.util.function.Consumer teleportComplete) { io.papermc.paper.util.TickThread.ensureTickThread(this, "Cannot teleport entity async"); + //Luminol start - Prevent teleportAsync calling during moving event being handled + if (this instanceof ServerPlayer player && LuminolConfig.preventTeleportAsyncDuringMovingEvent){ + if (player.handlingMoveEvent){ + if (LuminolConfig.throwOnPreventingTeleportAsync){ + throw new IllegalStateException("Player " + player.getScoreboardName() + " is trying to teleport to " + pos + " during move event handling!"); + } + MinecraftServer.LOGGER.warn("Player {} is trying to teleport to {} during move event handling!",player.getScoreboardName(),pos); + return false; + } + } + //Luminol end + if (!ServerLevel.isInSpawnableBounds(new BlockPos(io.papermc.paper.util.CoordinateUtils.getBlockX(pos), io.papermc.paper.util.CoordinateUtils.getBlockY(pos), io.papermc.paper.util.CoordinateUtils.getBlockZ(pos)))) { return false; } diff --git a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java index 44a6118d3bd67a95180f750c17967561946e2e87..d642f4d42ae7e73642929708a198294e4c5a24d4 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/AbstractMinecart.java @@ -5,6 +5,8 @@ import com.google.common.collect.ImmutableMap; import com.google.common.collect.Maps; import com.google.common.collect.UnmodifiableIterator; import com.mojang.datafixers.util.Pair; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.Map; @@ -20,6 +22,7 @@ import net.minecraft.nbt.NbtUtils; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.tags.BlockTags; import net.minecraft.util.Mth; import net.minecraft.world.damagesource.DamageSource; @@ -426,7 +429,21 @@ public abstract class AbstractMinecart extends Entity { this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); if (!from.equals(to)) { + //Luminol start - Prevent teleportAsync calling during moving event being handled + for (Entity passenger : this.getPassengers()) { + if (passenger instanceof ServerPlayer player){ + player.handlingMoveEvent = true; + } + } + //Luminol end this.level().getCraftServer().getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleMoveEvent(vehicle, from, to)); + //Luminol start - Prevent teleportAsync calling during moving event being handled + for (Entity passenger : this.getPassengers()) { + if (passenger instanceof ServerPlayer player){ + player.handlingMoveEvent = false; + } + } + //Luminol end } // CraftBukkit end if (this.getMinecartType() == AbstractMinecart.Type.RIDEABLE && this.getDeltaMovement().horizontalDistanceSqr() > 0.01D) { diff --git a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java index 5c07da62c82bc70138f6cb5007629d6974be69ac..c68c84af56053cbf7f0c7809a16b60749a4fdd05 100644 --- a/src/main/java/net/minecraft/world/entity/vehicle/Boat.java +++ b/src/main/java/net/minecraft/world/entity/vehicle/Boat.java @@ -2,6 +2,8 @@ package net.minecraft.world.entity.vehicle; import com.google.common.collect.Lists; import com.google.common.collect.UnmodifiableIterator; + +import java.util.ArrayList; import java.util.Iterator; import java.util.List; import java.util.function.IntFunction; @@ -16,6 +18,7 @@ import net.minecraft.network.protocol.game.ServerboundPaddleBoatPacket; import net.minecraft.network.syncher.EntityDataAccessor; import net.minecraft.network.syncher.EntityDataSerializers; import net.minecraft.network.syncher.SynchedEntityData; +import net.minecraft.server.level.ServerPlayer; import net.minecraft.sounds.SoundEvent; import net.minecraft.sounds.SoundEvents; import net.minecraft.tags.FluidTags; @@ -434,8 +437,22 @@ public class Boat extends Entity implements VariantHolder { server.getPluginManager().callEvent(new org.bukkit.event.vehicle.VehicleUpdateEvent(vehicle)); if (this.lastLocation != null && !this.lastLocation.equals(to)) { + //Luminol start - Prevent teleportAsync calling during moving event being handled + for (Entity passenger : this.getPassengers()) { + if (passenger instanceof ServerPlayer player){ + player.handlingMoveEvent = true; + } + } + //Luminol end VehicleMoveEvent event = new VehicleMoveEvent(vehicle, this.lastLocation, to); server.getPluginManager().callEvent(event); + //Luminol start - Prevent teleportAsync calling during moving event being handled + for (Entity passenger : this.getPassengers()) { + if (passenger instanceof ServerPlayer player){ + player.handlingMoveEvent = false; + } + } + //Luminol end } this.lastLocation = vehicle.getLocation(); // CraftBukkit end