diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java new file mode 100755 index 00000000..8d4a4f7d --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java @@ -0,0 +1,91 @@ +package me.xginko.aef.modules.combat; + +import com.cryptomorin.xseries.XEntityType; +import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import me.xginko.aef.modules.AEFModule; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.time.Duration; +import java.util.UUID; + +public class PortalGodMode extends AEFModule implements Listener { + + private final Cache playersWaitingForPortalTeleport; + private final long delayTicks; + + public PortalGodMode() { + super("combat.portal-god-mode-patch"); + config.addComment(configPath + ".enable", """ + Patches an exploit that allows players to stand in portals and not take\s + damage indefinitely by just never sending a TeleportAccept packet to the\s + server.\s + A similar method is used for the chorus tp exploit, which is not covered\s + by this module."""); + this.delayTicks = config.getInt(".destroy-portal-delay-ticks", 100, """ + If the player stays inside the nether portal for this time without teleporting,\s + the portal will be broken."""); + this.playersWaitingForPortalTeleport = Caffeine.newBuilder() + .expireAfterWrite(Duration.ofMillis((delayTicks * 50L) + 1000L)).build(); + } + + @Override + public void enable() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", false); + } + + @Override + public void disable() { + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onEntityPortalEnter(EntityPortalEnterEvent event) { + if (event.getEntityType() != XEntityType.PLAYER.get()) return; + + if (playersWaitingForPortalTeleport.getIfPresent(event.getEntity().getUniqueId()) != null) return; + + playersWaitingForPortalTeleport.put(event.getEntity().getUniqueId(), + plugin.getServer().getRegionScheduler().runDelayed(plugin, event.getLocation(), breakPortal -> { + event.getLocation().getBlock().setType(XMaterial.AIR.parseMaterial(), true); + playersWaitingForPortalTeleport.invalidate(event.getEntity().getUniqueId()); + }, delayTicks)); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerTeleport(PlayerTeleportEvent event) { + if (event.getCause() != PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) return; + + @Nullable ScheduledTask breakPortalTask = playersWaitingForPortalTeleport.getIfPresent(event.getPlayer().getUniqueId()); + + if (breakPortalTask != null) { + breakPortalTask.cancel(); + playersWaitingForPortalTeleport.invalidate(event.getPlayer().getUniqueId()); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onPlayerMove(PlayerMoveEvent event) { + @Nullable ScheduledTask breakPortalTask = playersWaitingForPortalTeleport.getIfPresent(event.getPlayer().getUniqueId()); + if (breakPortalTask == null) return; + + if (event.getTo().getBlock().getType() != XMaterial.NETHER_PORTAL.parseMaterial()) { + breakPortalTask.cancel(); + playersWaitingForPortalTeleport.invalidate(event.getPlayer().getUniqueId()); + } + } +} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/SignLag.java b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/SignLag.java index a3b2aad8..8d77c00e 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/SignLag.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/xginko/aef/modules/packets/SignLag.java @@ -4,7 +4,6 @@ import com.github.retrooper.packetevents.event.PacketReceiveEvent; import com.github.retrooper.packetevents.protocol.packettype.PacketType; import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientUpdateSign; -import me.xginko.aef.AnarchyExploitFixes; import me.xginko.aef.utils.models.ExpiringSet; import java.time.Duration; @@ -35,7 +34,7 @@ public SignLag() { @Override public boolean shouldEnable() { - return AnarchyExploitFixes.config().getBoolean(configPath + ".enable", true); + return config.getBoolean(configPath + ".enable", true); } @Override diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java new file mode 100755 index 00000000..854bd687 --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/xginko/aef/modules/combat/PortalGodMode.java @@ -0,0 +1,91 @@ +package me.xginko.aef.modules.combat; + +import com.cryptomorin.xseries.XEntityType; +import com.cryptomorin.xseries.XMaterial; +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import me.xginko.aef.modules.AEFModule; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.HandlerList; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityPortalEnterEvent; +import org.bukkit.event.player.PlayerMoveEvent; +import org.bukkit.event.player.PlayerTeleportEvent; +import org.bukkit.scheduler.BukkitTask; +import org.checkerframework.checker.nullness.qual.Nullable; + +import java.time.Duration; +import java.util.UUID; + +public class PortalGodMode extends AEFModule implements Listener { + + private final Cache playersWaitingForPortalTeleport; + private final long delayTicks; + + public PortalGodMode() { + super("combat.portal-god-mode-patch"); + config.addComment(configPath + ".enable", + "Patches an exploit that allows players to stand in portals and not take \n" + + "damage indefinitely by just never sending a TeleportAccept packet to the \n" + + "server. \n" + + "A similar method is used for the chorus tp exploit, which is not covered \n" + + "by this module."); + this.delayTicks = config.getInt(".destroy-portal-delay-ticks", 100, + "If the player stays inside the nether portal for this time without teleporting, \n" + + "the portal will be broken."); + this.playersWaitingForPortalTeleport = Caffeine.newBuilder() + .expireAfterWrite(Duration.ofMillis((delayTicks * 50L) + 1000L)).build(); + } + + @Override + public void enable() { + plugin.getServer().getPluginManager().registerEvents(this, plugin); + } + + @Override + public boolean shouldEnable() { + return config.getBoolean(configPath + ".enable", false); + } + + @Override + public void disable() { + HandlerList.unregisterAll(this); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onEntityPortalEnter(EntityPortalEnterEvent event) { + if (event.getEntityType() != XEntityType.PLAYER.get()) return; + + if (playersWaitingForPortalTeleport.getIfPresent(event.getEntity().getUniqueId()) != null) return; + + playersWaitingForPortalTeleport.put(event.getEntity().getUniqueId(), + plugin.getServer().getScheduler().runTaskLater(plugin, () -> { + event.getLocation().getBlock().setType(XMaterial.AIR.parseMaterial(), true); + playersWaitingForPortalTeleport.invalidate(event.getEntity().getUniqueId()); + }, delayTicks)); + } + + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) + private void onPlayerTeleport(PlayerTeleportEvent event) { + if (event.getCause() != PlayerTeleportEvent.TeleportCause.NETHER_PORTAL) return; + + @Nullable BukkitTask breakPortalTask = playersWaitingForPortalTeleport.getIfPresent(event.getPlayer().getUniqueId()); + + if (breakPortalTask != null) { + breakPortalTask.cancel(); + playersWaitingForPortalTeleport.invalidate(event.getPlayer().getUniqueId()); + } + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onPlayerMove(PlayerMoveEvent event) { + @Nullable BukkitTask breakPortalTask = playersWaitingForPortalTeleport.getIfPresent(event.getPlayer().getUniqueId()); + if (breakPortalTask == null) return; + + if (event.getTo().getBlock().getType() != XMaterial.NETHER_PORTAL.parseMaterial()) { + breakPortalTask.cancel(); + playersWaitingForPortalTeleport.invalidate(event.getPlayer().getUniqueId()); + } + } +}