diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java index 6f34d9329..f3c645884 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java @@ -9,6 +9,7 @@ import me.moomoo.anarchyexploitfixes.modules.combat.*; import me.moomoo.anarchyexploitfixes.modules.dupepreventions.*; import me.moomoo.anarchyexploitfixes.modules.elytra.*; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RemoveSpecificItemNames; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RevertOverstacked; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RevertUnbreakables; diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java index 1d1bba529..ddf93454c 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import net.kyori.adventure.text.Component; diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java index 9ad5f36bf..40756d4f0 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import net.kyori.adventure.text.Component; diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java deleted file mode 100755 index 135f7ad32..000000000 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java +++ /dev/null @@ -1,169 +0,0 @@ -package me.moomoo.anarchyexploitfixes.modules.elytra; - -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; -import io.papermc.paper.threadedregions.scheduler.ScheduledTask; -import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; -import me.moomoo.anarchyexploitfixes.config.Config; -import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; -import me.moomoo.anarchyexploitfixes.utils.LocationUtil; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -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.EntityToggleGlideEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.util.NumberConversions; - -import java.time.Duration; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -public class ElytraHelper implements AnarchyExploitFixesModule, Listener { - private static ElytraHelper instance; - private final AnarchyExploitFixes plugin; - private final Set PLAYERS_GLIDING; - private final Set PLAYERS_NEAR_NEW_CHUNKS; - private final Cache PLAYER_SPEEDS_INTERVAL; - private final Cache LAST_GLIDE_POS; - private ScheduledTask CHECK_SCHEDULER; - public static final double SPEED_TOLERANCE = 0.02; - private final int checkIntervalTicks; - private final boolean doIntervalCheck; - - public ElytraHelper() { - instance = this; - this.plugin = AnarchyExploitFixes.getInstance(); - this.PLAYERS_GLIDING = new HashSet<>(); - this.PLAYERS_NEAR_NEW_CHUNKS = new HashSet<>(plugin.getServer().getOnlinePlayers().size()); - Config config = AnarchyExploitFixes.getConfiguration(); - this.doIntervalCheck = config.getBoolean("elytra.patch-generic-speedhacks.enable", true, - "Patches speed-limit bypass using generic speedhacks (Timer) by additionally checking player position every x ticks"); - final int tickInterval = config.getInt("elytra.patch-generic-speedhacks.check-interval-in-ticks", 10, - "Lower value means more accuracy but also more overhead."); - this.checkIntervalTicks = Math.max(tickInterval, 1); - final Duration cacheTime = Duration.ofMillis(Math.max(1000, (tickInterval * 50L) + 100L)); - this.PLAYER_SPEEDS_INTERVAL = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); - this.LAST_GLIDE_POS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); - } - - public static ElytraHelper getInstance() { - return instance; - } - - @Override - public String name() { - return "elytra-helper"; - } - - @Override - public String category() { - return "elytra"; - } - - @Override - public void enable() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - if (!doIntervalCheck) return; - CHECK_SCHEDULER = plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, scheduleChecks -> { - for (Player player : plugin.getServer().getOnlinePlayers()) { - player.getScheduler().run(plugin, checkFlight -> { - if (this.isGliding(player)) { - Location currentLocation = player.getLocation().clone(); - Location lastLocation = LAST_GLIDE_POS.getIfPresent(player.getUniqueId()); - if (lastLocation != null) PLAYER_SPEEDS_INTERVAL.put(player.getUniqueId(), - LocationUtil.getRelDistance3D(lastLocation, currentLocation) / checkIntervalTicks); - LAST_GLIDE_POS.put(player.getUniqueId(), currentLocation); - } - }, null); - } - }, checkIntervalTicks, checkIntervalTicks); - } - - @Override - public boolean shouldEnable() { - Config config = AnarchyExploitFixes.getConfiguration(); - return config.elytra_enable_at_spawn || config.elytra_enable_global || config.elytra_enable_netherceiling; - } - - @Override - public void disable() { - HandlerList.unregisterAll(this); - if (CHECK_SCHEDULER != null) CHECK_SCHEDULER.cancel(); - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onGlideToggle(EntityToggleGlideEvent event) { - if (event.getEntityType() != EntityType.PLAYER) return; - - if (event.isGliding()) { - PLAYERS_GLIDING.add(event.getEntity().getUniqueId()); - } else { - PLAYERS_GLIDING.remove(event.getEntity().getUniqueId()); - } - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onJoin(PlayerQuitEvent event) { - PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onJoin(PlayerJoinEvent event) { - if (event.getPlayer().isGliding()) { - PLAYERS_GLIDING.add(event.getPlayer().getUniqueId()); - } else { - PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); - } - } - - private double getChunkDistance(Chunk chunk, Location location) { - return Math.sqrt( - NumberConversions.square(chunk.getX() - location.getBlockX() >> 4) + - NumberConversions.square(chunk.getZ() - location.getBlockZ() >> 4) - ); - } - - @EventHandler(priority = EventPriority.LOW) - private void onChunkLoad(ChunkLoadEvent event) { - for (Player player : event.getWorld().getPlayers()) { - if (this.getChunkDistance(event.getChunk(), player.getLocation().clone()) < player.getViewDistance()) { - if (event.isNewChunk()) { - PLAYERS_NEAR_NEW_CHUNKS.add(player.getUniqueId()); - } else { - PLAYERS_NEAR_NEW_CHUNKS.remove(player.getUniqueId()); - } - } - } - } - - public Location getFrom(PlayerMoveEvent event) { - final Location lastGlidePos = LAST_GLIDE_POS.getIfPresent(event.getPlayer().getUniqueId()); - return lastGlidePos != null ? lastGlidePos : event.getFrom(); - } - - public double getBlocksPerTick(PlayerMoveEvent event) { - double eventSpeed = LocationUtil.getRelDistance3D(event.getTo(), event.getFrom()); - if (doIntervalCheck) { - Double speedInterval = PLAYER_SPEEDS_INTERVAL.getIfPresent(event.getPlayer().getUniqueId()); - if (speedInterval != null) return Math.max(speedInterval, eventSpeed); - } - return eventSpeed; - } - - public boolean isInNewChunks(UUID playerUniqueId) { - return PLAYERS_NEAR_NEW_CHUNKS.contains(playerUniqueId); - } - - public boolean isGliding(Player player) { - return PLAYERS_GLIDING.contains(player.getUniqueId()) || player.isGliding(); - } -} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java index 96c6c29a5..ec053c457 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import net.kyori.adventure.text.Component; diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java new file mode 100644 index 000000000..cb4232fef --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java @@ -0,0 +1,45 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.util.NumberConversions; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class ChunkListener extends ElytraHelper implements Listener { + + public final Set PLAYERS_NEAR_NEW_CHUNKS; + + public ChunkListener() { + this.PLAYERS_NEAR_NEW_CHUNKS = new HashSet<>(); + } + + @EventHandler(priority = EventPriority.LOWEST) + private void onChunkLoad(ChunkLoadEvent event) { + for (Player player : event.getWorld().getPlayers()) { + if (this.getChunkDistanceSquared(event.getChunk(), player.getLocation().clone()) < NumberConversions.square(player.getViewDistance())) { + if (event.isNewChunk()) { + this.PLAYERS_NEAR_NEW_CHUNKS.add(player.getUniqueId()); + } else { + this.PLAYERS_NEAR_NEW_CHUNKS.remove(player.getUniqueId()); + } + } + } + } + + /** + * Since the distance here is only used to see whether a chunk is loaded roughly within the player's view distance, + * we can resort to comparing squared distances. + * This saves cpu usage as we don't have to use {@link Math#sqrt(double)} to get the accurate distance in chunks. + */ + private double getChunkDistanceSquared(Chunk chunk, Location location) { + return NumberConversions.square(chunk.getX() - location.getBlockX() >> 4) + NumberConversions.square(chunk.getZ() - location.getBlockZ() >> 4); + } +} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java new file mode 100755 index 000000000..7ee97731f --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java @@ -0,0 +1,86 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.config.Config; +import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.utils.LocationUtil; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.HandlerList; +import org.bukkit.event.player.PlayerMoveEvent; + +import java.util.UUID; + +public class ElytraHelper implements AnarchyExploitFixesModule { + private static ElytraHelper instance; + public static final double SPEED_TOLERANCE = 0.02; + + protected final AnarchyExploitFixes plugin; + private GlideListener glideListener; + private ChunkListener chunkListener; + private IntervalCheck intervalCheck; + + public ElytraHelper() { + instance = this; + this.plugin = AnarchyExploitFixes.getInstance(); + } + + public static ElytraHelper getInstance() { + return instance; + } + + @Override + public String name() { + return "elytra-helper"; + } + + @Override + public String category() { + return "elytra"; + } + + @Override + public void enable() { + glideListener = new GlideListener(); + plugin.getServer().getPluginManager().registerEvents(glideListener, plugin); + chunkListener = new ChunkListener(); + plugin.getServer().getPluginManager().registerEvents(chunkListener, plugin); + intervalCheck = new IntervalCheck(); + intervalCheck.startIfEnabled(); + } + + @Override + public boolean shouldEnable() { + Config config = AnarchyExploitFixes.getConfiguration(); + return config.elytra_enable_at_spawn || config.elytra_enable_global || config.elytra_enable_netherceiling; + } + + @Override + public void disable() { + HandlerList.unregisterAll(glideListener); + HandlerList.unregisterAll(chunkListener); + intervalCheck.stopIfEnabled(); + } + + public Location getFrom(PlayerMoveEvent event) { + final Location lastGlidePos = intervalCheck.LAST_GLIDE_POS.getIfPresent(event.getPlayer().getUniqueId()); + return lastGlidePos != null ? lastGlidePos : event.getFrom(); + } + + public double getBlocksPerTick(PlayerMoveEvent event) { + double eventSpeed = LocationUtil.getRelDistance3D(event.getTo(), event.getFrom()); + if (intervalCheck.isEnabled) { + Double speedInterval = intervalCheck.PLAYER_SPEEDS.getIfPresent(event.getPlayer().getUniqueId()); + if (speedInterval != null) return Math.max(speedInterval, eventSpeed); + } + return eventSpeed; + } + + public boolean isInNewChunks(UUID playerUniqueId) { + return chunkListener.PLAYERS_NEAR_NEW_CHUNKS.contains(playerUniqueId); + } + + public boolean isGliding(Player player) { + return glideListener.PLAYERS_GLIDING.contains(player.getUniqueId()) || player.isGliding(); + } +} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java new file mode 100644 index 000000000..8ecaf5aa4 --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java @@ -0,0 +1,54 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityToggleGlideEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class GlideListener extends ElytraHelper implements Listener { + + public final Set PLAYERS_GLIDING; + + public GlideListener() { + this.PLAYERS_GLIDING = Bukkit.getOnlinePlayers().stream() + .filter(LivingEntity::isGliding) + .map(Player::getUniqueId) + .collect(Collectors.toCollection(HashSet::new)); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onGlideToggle(EntityToggleGlideEvent event) { + if (event.getEntityType() == EntityType.PLAYER) { + if (event.isGliding()) { + this.PLAYERS_GLIDING.add(event.getEntity().getUniqueId()); + } else { + this.PLAYERS_GLIDING.remove(event.getEntity().getUniqueId()); + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onQuit(PlayerQuitEvent event) { + this.PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onJoin(PlayerJoinEvent event) { + if (event.getPlayer().isGliding()) { + this.PLAYERS_GLIDING.add(event.getPlayer().getUniqueId()); + } else { + this.PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); + } + } +} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java new file mode 100644 index 000000000..e93642266 --- /dev/null +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java @@ -0,0 +1,57 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import io.papermc.paper.threadedregions.scheduler.ScheduledTask; +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.config.Config; +import me.moomoo.anarchyexploitfixes.utils.LocationUtil; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.time.Duration; +import java.util.UUID; + +public class IntervalCheck extends ElytraHelper { + + public ScheduledTask scheduledTask; + public final Cache PLAYER_SPEEDS; + public final Cache LAST_GLIDE_POS; + private final int checkIntervalTicks; + public final boolean isEnabled; + + public IntervalCheck() { + Config config = AnarchyExploitFixes.getConfiguration(); + this.isEnabled = config.getBoolean("elytra.patch-generic-speedhacks.enable", true, + "Patches speed-limit bypass using generic speedhacks (Timer) by additionally checking player position every x ticks"); + final int tickInterval = config.getInt("elytra.patch-generic-speedhacks.check-interval-in-ticks", 10, + "Lower value means more accuracy but also more overhead."); + this.checkIntervalTicks = Math.max(tickInterval, 1); + final Duration cacheTime = Duration.ofMillis(Math.max(1000, (tickInterval * 50L) + 100L)); + this.PLAYER_SPEEDS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); + this.LAST_GLIDE_POS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); + } + + public void startIfEnabled() { + if (isEnabled) this.scheduledTask = super.plugin.getServer().getGlobalRegionScheduler().runAtFixedRate(plugin, + scheduleChecks -> this.run(), checkIntervalTicks, checkIntervalTicks); + } + + public void stopIfEnabled() { + if (scheduledTask != null) scheduledTask.cancel(); + } + + private void run() { + for (Player player : super.plugin.getServer().getOnlinePlayers()) { + player.getScheduler().run(plugin, checkFlight -> { + if (super.isGliding(player)) { + Location currentLocation = player.getLocation().clone(); + Location lastLocation = this.LAST_GLIDE_POS.getIfPresent(player.getUniqueId()); + if (lastLocation != null) this.PLAYER_SPEEDS.put(player.getUniqueId(), + LocationUtil.getRelDistance3D(lastLocation, currentLocation) / checkIntervalTicks); + this.LAST_GLIDE_POS.put(player.getUniqueId(), currentLocation); + } + }, null); + } + } +} diff --git a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java index 45485e76a..971bedd3d 100755 --- a/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java +++ b/AnarchyExploitFixesFolia/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java @@ -27,7 +27,7 @@ public void onPacketReceiving(PacketEvent event) { try { final int button = this.getButton(packet); - if (button < 0 || button > 9 && button != 40) { + if (button < 0 || button > 9 && button != 40 && button != 99) { event.setCancelled(true); return; } diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java index fcab6a3f3..6afab1a05 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/AnarchyExploitFixesModule.java @@ -9,6 +9,7 @@ import me.moomoo.anarchyexploitfixes.modules.combat.*; import me.moomoo.anarchyexploitfixes.modules.dupepreventions.*; import me.moomoo.anarchyexploitfixes.modules.elytra.*; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RemoveSpecificItemNames; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RevertOverstacked; import me.moomoo.anarchyexploitfixes.modules.illegals.items.RevertUnbreakables; @@ -45,6 +46,7 @@ import me.moomoo.anarchyexploitfixes.modules.preventions.withers.*; import me.moomoo.anarchyexploitfixes.modules.protocollib.boatfly.AntiBoatFlyModule; import me.moomoo.anarchyexploitfixes.modules.protocollib.craftrecipe.CraftRecipeCooldownModule; +import me.moomoo.anarchyexploitfixes.modules.protocollib.lecterncrash.AntiLecternCrash; import me.moomoo.anarchyexploitfixes.modules.protocollib.nocom.NoComModule; import me.moomoo.anarchyexploitfixes.modules.protocollib.windowclick.AntiWindowClickCrash; import org.bukkit.event.HandlerList; @@ -225,6 +227,7 @@ static void reloadModules() { modules.add(new AntiBoatFlyModule()); modules.add(new CraftRecipeCooldownModule()); modules.add(new AntiWindowClickCrash()); + modules.add(new AntiLecternCrash()); if (!AnarchyExploitFixes.getConfiguration().protocolLib_IsDisabled && !protocolLibIsInstalled) { AnarchyExploitFixes.getLog().severe("Could not find ProtocolLib. Many gamebreaking exploits cannot be patched without it."); diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java index 95b35367e..d2bfebb6f 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraAtSpawn.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import org.bukkit.Location; diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java index e15b369bf..6d71a3fc6 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraGlobal.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import org.bukkit.Location; diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java deleted file mode 100755 index 886ad834b..000000000 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraHelper.java +++ /dev/null @@ -1,160 +0,0 @@ -package me.moomoo.anarchyexploitfixes.modules.elytra; - -import com.github.benmanes.caffeine.cache.Cache; -import com.github.benmanes.caffeine.cache.Caffeine; -import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; -import me.moomoo.anarchyexploitfixes.config.Config; -import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; -import me.moomoo.anarchyexploitfixes.utils.LocationUtil; -import org.bukkit.Chunk; -import org.bukkit.Location; -import org.bukkit.entity.EntityType; -import org.bukkit.entity.Player; -import org.bukkit.event.EventHandler; -import org.bukkit.event.EventPriority; -import org.bukkit.event.Listener; -import org.bukkit.event.entity.EntityToggleGlideEvent; -import org.bukkit.event.player.PlayerJoinEvent; -import org.bukkit.event.player.PlayerMoveEvent; -import org.bukkit.event.player.PlayerQuitEvent; -import org.bukkit.event.world.ChunkLoadEvent; -import org.bukkit.util.NumberConversions; - -import java.time.Duration; -import java.util.HashSet; -import java.util.Set; -import java.util.UUID; - -public class ElytraHelper implements AnarchyExploitFixesModule, Listener, Runnable { - private static ElytraHelper instance; - private final AnarchyExploitFixes plugin; - private final Set PLAYERS_GLIDING; - private final Set PLAYERS_NEAR_NEW_CHUNKS; - private final Cache PLAYER_SPEEDS_INTERVAL; - private final Cache LAST_GLIDE_POS; - public static final double SPEED_TOLERANCE = 0.02; - private final int checkIntervalTicks; - private final boolean doIntervalCheck; - - public ElytraHelper() { - instance = this; - this.plugin = AnarchyExploitFixes.getInstance(); - this.PLAYERS_GLIDING = new HashSet<>(); - this.PLAYERS_NEAR_NEW_CHUNKS = new HashSet<>(plugin.getServer().getOnlinePlayers().size()); - Config config = AnarchyExploitFixes.getConfiguration(); - this.doIntervalCheck = config.getBoolean("elytra.patch-generic-speedhacks.enable", true, - "Patches speed-limit bypass using generic speedhacks (Timer) by additionally checking player position every x ticks"); - final int tickInterval = config.getInt("elytra.patch-generic-speedhacks.check-interval-in-ticks", 10, - "Lower value means more accuracy but also more overhead."); - this.checkIntervalTicks = Math.max(tickInterval, 1); - final Duration cacheTime = Duration.ofMillis(Math.max(1000, (tickInterval * 50L) + 100L)); - this.PLAYER_SPEEDS_INTERVAL = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); - this.LAST_GLIDE_POS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); - } - - public static ElytraHelper getInstance() { - return instance; - } - - @Override - public String name() { - return "elytra-helper"; - } - - @Override - public String category() { - return "elytra"; - } - - @Override - public void enable() { - plugin.getServer().getPluginManager().registerEvents(this, plugin); - if (doIntervalCheck) plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, checkIntervalTicks, checkIntervalTicks); - } - - @Override - public boolean shouldEnable() { - Config config = AnarchyExploitFixes.getConfiguration(); - return config.elytra_enable_at_spawn || config.elytra_enable_global || config.elytra_enable_netherceiling; - } - - @Override - public void run() { - for (Player player : plugin.getServer().getOnlinePlayers()) { - if (this.isGliding(player)) { - Location currentLocation = player.getLocation().clone(); - Location lastLocation = LAST_GLIDE_POS.getIfPresent(player.getUniqueId()); - if (lastLocation != null) PLAYER_SPEEDS_INTERVAL.put(player.getUniqueId(), - LocationUtil.getRelDistance3D(lastLocation, currentLocation) / checkIntervalTicks); - LAST_GLIDE_POS.put(player.getUniqueId(), currentLocation); - } - } - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onGlideToggle(EntityToggleGlideEvent event) { - if (event.getEntityType() != EntityType.PLAYER) return; - - if (event.isGliding()) { - PLAYERS_GLIDING.add(event.getEntity().getUniqueId()); - } else { - PLAYERS_GLIDING.remove(event.getEntity().getUniqueId()); - } - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onJoin(PlayerQuitEvent event) { - PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); - } - - @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - private void onJoin(PlayerJoinEvent event) { - if (event.getPlayer().isGliding()) { - PLAYERS_GLIDING.add(event.getPlayer().getUniqueId()); - } else { - PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); - } - } - - private double getChunkDistance(Chunk chunk, Location location) { - return Math.sqrt( - NumberConversions.square(chunk.getX() - location.getBlockX() >> 4) + - NumberConversions.square(chunk.getZ() - location.getBlockZ() >> 4) - ); - } - - @EventHandler(priority = EventPriority.LOW) - private void onChunkLoad(ChunkLoadEvent event) { - for (Player player : event.getWorld().getPlayers()) { - if (this.getChunkDistance(event.getChunk(), player.getLocation().clone()) < player.getViewDistance()) { - if (event.isNewChunk()) { - PLAYERS_NEAR_NEW_CHUNKS.add(player.getUniqueId()); - } else { - PLAYERS_NEAR_NEW_CHUNKS.remove(player.getUniqueId()); - } - } - } - } - - public Location getFrom(PlayerMoveEvent event) { - final Location lastGlidePos = LAST_GLIDE_POS.getIfPresent(event.getPlayer().getUniqueId()); - return lastGlidePos != null ? lastGlidePos : event.getFrom(); - } - - public double getBlocksPerTick(PlayerMoveEvent event) { - double eventSpeed = LocationUtil.getRelDistance3D(event.getFrom(), event.getTo()); - if (doIntervalCheck) { - Double speedInterval = PLAYER_SPEEDS_INTERVAL.getIfPresent(event.getPlayer().getUniqueId()); - if (speedInterval != null) return Math.max(speedInterval, eventSpeed); - } - return eventSpeed; - } - - public boolean isInNewChunks(UUID playerUniqueId) { - return PLAYERS_NEAR_NEW_CHUNKS.contains(playerUniqueId); - } - - public boolean isGliding(Player player) { - return PLAYERS_GLIDING.contains(player.getUniqueId()) || player.isGliding(); - } -} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java index ef24f54d2..36092207f 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/ElytraOnCeiling.java @@ -4,6 +4,7 @@ import me.moomoo.anarchyexploitfixes.config.Config; import me.moomoo.anarchyexploitfixes.config.LanguageCache; import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.modules.elytra.helper.ElytraHelper; import me.moomoo.anarchyexploitfixes.utils.LocationUtil; import me.moomoo.anarchyexploitfixes.utils.MaterialUtil; import org.bukkit.Location; diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java new file mode 100644 index 000000000..cb4232fef --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ChunkListener.java @@ -0,0 +1,45 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import org.bukkit.Chunk; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.world.ChunkLoadEvent; +import org.bukkit.util.NumberConversions; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; + +public class ChunkListener extends ElytraHelper implements Listener { + + public final Set PLAYERS_NEAR_NEW_CHUNKS; + + public ChunkListener() { + this.PLAYERS_NEAR_NEW_CHUNKS = new HashSet<>(); + } + + @EventHandler(priority = EventPriority.LOWEST) + private void onChunkLoad(ChunkLoadEvent event) { + for (Player player : event.getWorld().getPlayers()) { + if (this.getChunkDistanceSquared(event.getChunk(), player.getLocation().clone()) < NumberConversions.square(player.getViewDistance())) { + if (event.isNewChunk()) { + this.PLAYERS_NEAR_NEW_CHUNKS.add(player.getUniqueId()); + } else { + this.PLAYERS_NEAR_NEW_CHUNKS.remove(player.getUniqueId()); + } + } + } + } + + /** + * Since the distance here is only used to see whether a chunk is loaded roughly within the player's view distance, + * we can resort to comparing squared distances. + * This saves cpu usage as we don't have to use {@link Math#sqrt(double)} to get the accurate distance in chunks. + */ + private double getChunkDistanceSquared(Chunk chunk, Location location) { + return NumberConversions.square(chunk.getX() - location.getBlockX() >> 4) + NumberConversions.square(chunk.getZ() - location.getBlockZ() >> 4); + } +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java new file mode 100755 index 000000000..db9017a9e --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/ElytraHelper.java @@ -0,0 +1,78 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.config.Config; +import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.utils.LocationUtil; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.event.player.PlayerMoveEvent; + +import java.util.UUID; + +public class ElytraHelper implements AnarchyExploitFixesModule { + private static ElytraHelper instance; + public static final double SPEED_TOLERANCE = 0.02; + + protected final AnarchyExploitFixes plugin; + private GlideListener glideListener; + private ChunkListener chunkListener; + private IntervalCheck intervalCheck; + + public ElytraHelper() { + instance = this; + this.plugin = AnarchyExploitFixes.getInstance(); + } + + public static ElytraHelper getInstance() { + return instance; + } + + @Override + public String name() { + return "elytra-helper"; + } + + @Override + public String category() { + return "elytra"; + } + + @Override + public void enable() { + this.glideListener = new GlideListener(); + plugin.getServer().getPluginManager().registerEvents(glideListener, plugin); + this.chunkListener = new ChunkListener(); + plugin.getServer().getPluginManager().registerEvents(chunkListener, plugin); + this.intervalCheck = new IntervalCheck(); + intervalCheck.startIfEnabled(); + } + + @Override + public boolean shouldEnable() { + Config config = AnarchyExploitFixes.getConfiguration(); + return config.elytra_enable_at_spawn || config.elytra_enable_global || config.elytra_enable_netherceiling; + } + + public Location getFrom(PlayerMoveEvent event) { + final Location lastGlidePos = intervalCheck.LAST_GLIDE_POS.getIfPresent(event.getPlayer().getUniqueId()); + return lastGlidePos != null ? lastGlidePos : event.getFrom(); + } + + public double getBlocksPerTick(PlayerMoveEvent event) { + double eventSpeed = LocationUtil.getRelDistance3D(event.getTo(), event.getFrom()); + if (intervalCheck.isEnabled) { + Double speedInterval = intervalCheck.PLAYER_SPEEDS.getIfPresent(event.getPlayer().getUniqueId()); + if (speedInterval != null) return Math.max(speedInterval, eventSpeed); + } + return eventSpeed; + } + + public boolean isInNewChunks(UUID playerUniqueId) { + return chunkListener.PLAYERS_NEAR_NEW_CHUNKS.contains(playerUniqueId); + } + + public boolean isGliding(Player player) { + return glideListener.PLAYERS_GLIDING.contains(player.getUniqueId()) || player.isGliding(); + } +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java new file mode 100644 index 000000000..8ecaf5aa4 --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/GlideListener.java @@ -0,0 +1,54 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import org.bukkit.Bukkit; +import org.bukkit.entity.EntityType; +import org.bukkit.entity.LivingEntity; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.entity.EntityToggleGlideEvent; +import org.bukkit.event.player.PlayerJoinEvent; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.HashSet; +import java.util.Set; +import java.util.UUID; +import java.util.stream.Collectors; + +public class GlideListener extends ElytraHelper implements Listener { + + public final Set PLAYERS_GLIDING; + + public GlideListener() { + this.PLAYERS_GLIDING = Bukkit.getOnlinePlayers().stream() + .filter(LivingEntity::isGliding) + .map(Player::getUniqueId) + .collect(Collectors.toCollection(HashSet::new)); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onGlideToggle(EntityToggleGlideEvent event) { + if (event.getEntityType() == EntityType.PLAYER) { + if (event.isGliding()) { + this.PLAYERS_GLIDING.add(event.getEntity().getUniqueId()); + } else { + this.PLAYERS_GLIDING.remove(event.getEntity().getUniqueId()); + } + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onQuit(PlayerQuitEvent event) { + this.PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onJoin(PlayerJoinEvent event) { + if (event.getPlayer().isGliding()) { + this.PLAYERS_GLIDING.add(event.getPlayer().getUniqueId()); + } else { + this.PLAYERS_GLIDING.remove(event.getPlayer().getUniqueId()); + } + } +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java new file mode 100644 index 000000000..40f0e8840 --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/elytra/helper/IntervalCheck.java @@ -0,0 +1,49 @@ +package me.moomoo.anarchyexploitfixes.modules.elytra.helper; + +import com.github.benmanes.caffeine.cache.Cache; +import com.github.benmanes.caffeine.cache.Caffeine; +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.config.Config; +import me.moomoo.anarchyexploitfixes.utils.LocationUtil; +import org.bukkit.Location; +import org.bukkit.entity.Player; + +import java.time.Duration; +import java.util.UUID; + +public class IntervalCheck extends ElytraHelper implements Runnable { + + public final Cache PLAYER_SPEEDS; + public final Cache LAST_GLIDE_POS; + private final int checkIntervalTicks; + public final boolean isEnabled; + + public IntervalCheck() { + Config config = AnarchyExploitFixes.getConfiguration(); + this.isEnabled = config.getBoolean("elytra.patch-generic-speedhacks.enable", true, + "Patches speed-limit bypass using generic speedhacks (Timer) by additionally checking player position every x ticks"); + final int tickInterval = config.getInt("elytra.patch-generic-speedhacks.check-interval-in-ticks", 10, + "Lower value means more accuracy but also more overhead."); + this.checkIntervalTicks = Math.max(tickInterval, 1); + final Duration cacheTime = Duration.ofMillis(Math.max(1000, (tickInterval * 50L) + 100L)); + this.PLAYER_SPEEDS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); + this.LAST_GLIDE_POS = Caffeine.newBuilder().expireAfterWrite(cacheTime).build(); + } + + public void startIfEnabled() { + if (isEnabled) super.plugin.getServer().getScheduler().scheduleSyncRepeatingTask(plugin, this, checkIntervalTicks, checkIntervalTicks); + } + + @Override + public void run() { + for (Player player : super.plugin.getServer().getOnlinePlayers()) { + if (this.isGliding(player)) { + Location currentLocation = player.getLocation().clone(); + Location lastLocation = LAST_GLIDE_POS.getIfPresent(player.getUniqueId()); + if (lastLocation != null) PLAYER_SPEEDS.put(player.getUniqueId(), + LocationUtil.getRelDistance3D(lastLocation, currentLocation) / checkIntervalTicks); + LAST_GLIDE_POS.put(player.getUniqueId(), currentLocation); + } + } + } +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/AntiLecternCrash.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/AntiLecternCrash.java new file mode 100755 index 000000000..d705a9dbb --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/AntiLecternCrash.java @@ -0,0 +1,56 @@ +package me.moomoo.anarchyexploitfixes.modules.protocollib.lecterncrash; + +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.modules.AnarchyExploitFixesModule; +import me.moomoo.anarchyexploitfixes.utils.LogUtil; +import org.bukkit.event.inventory.InventoryType; + +import java.util.logging.Level; + +public class AntiLecternCrash implements AnarchyExploitFixesModule { + + public InventoryType LECTERN; + + public AntiLecternCrash() { + AnarchyExploitFixes.getConfiguration().addComment("patches.lectern-crash-patch.enable", + "Patches crash method by sending a QUICK_MOVE packet while lectern inventory is open."); + try { + this.LECTERN = InventoryType.valueOf("LECTERN"); + } catch (IllegalArgumentException e) { + this.LECTERN = null; + } + } + + @Override + public String name() { + return "lectern-crash-patch"; + } + + @Override + public String category() { + return "patches"; + } + + @Override + public void enable() { + new LecternClickListener(LECTERN).register(); + } + + @Override + public boolean shouldEnable() { + if (AnarchyExploitFixes.getConfiguration().getBoolean("patches.lectern-crash-patch.enable", true)) { + if (this.LECTERN == null) + return false; // Can't enable if there are no lectern inventories in the game + if (AnarchyExploitFixes.getConfiguration().protocolLib_IsDisabled) { + LogUtil.moduleLog(Level.WARNING, name(), "Not patching exploit because you disabled ProtocolLib in config!"); + return false; + } + if (!AnarchyExploitFixes.isProtocolLibInstalled()) { + LogUtil.moduleLog(Level.SEVERE, name(), "Unable to patch exploit because ProtocolLib is not installed!"); + return false; + } + return true; + } + return false; + } +} diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/LecternClickListener.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/LecternClickListener.java new file mode 100755 index 000000000..e699d4e3c --- /dev/null +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/lecterncrash/LecternClickListener.java @@ -0,0 +1,96 @@ +package me.moomoo.anarchyexploitfixes.modules.protocollib.lecterncrash; + +import com.comphenix.protocol.PacketType; +import com.comphenix.protocol.ProtocolLibrary; +import com.comphenix.protocol.events.*; +import me.moomoo.anarchyexploitfixes.AnarchyExploitFixes; +import me.moomoo.anarchyexploitfixes.utils.LogUtil; +import org.bukkit.entity.Player; +import org.bukkit.event.EventHandler; +import org.bukkit.event.EventPriority; +import org.bukkit.event.Listener; +import org.bukkit.event.inventory.InventoryCloseEvent; +import org.bukkit.event.inventory.InventoryOpenEvent; +import org.bukkit.event.inventory.InventoryType; +import org.bukkit.event.player.PlayerQuitEvent; + +import java.util.Collections; +import java.util.HashMap; +import java.util.Map; +import java.util.UUID; +import java.util.logging.Level; + +public class LecternClickListener extends PacketAdapter implements Listener { + + private final InventoryType LECTERN; + private final Map openInventoryTypes; + private final int index_slot, index_button, index_clickType; + + public LecternClickListener(InventoryType LECTERN) { + super(AnarchyExploitFixes.getInstance(), ListenerPriority.HIGHEST, Collections.singletonList(PacketType.Play.Client.WINDOW_CLICK), ListenerOptions.SYNC); + this.openInventoryTypes = new HashMap<>(); + this.index_slot = AnarchyExploitFixes.getMCVersion() > 12 ? 2 : 1; // This needs cross version mapping urgently + this.index_button = AnarchyExploitFixes.getMCVersion() > 12 ? 3 : 2; + this.index_clickType = AnarchyExploitFixes.getMCVersion() > 12 ? 4 : 5; + this.LECTERN = LECTERN; + } + + protected void register() { + ProtocolLibrary.getProtocolManager().addPacketListener(this); + getPlugin().getServer().getPluginManager().registerEvents(this, getPlugin()); + } + + @Override + public void onPacketReceiving(PacketEvent event) { + final PacketContainer packet = event.getPacket(); + try { + if (this.getClickType(packet) != InventoryClickType.QUICK_MOVE) return; + + Player player = event.getPlayer(); + if (player == null) return; + + if ( + this.openInventoryTypes.containsKey(player.getUniqueId()) + && this.openInventoryTypes.get(player.getUniqueId()) == LECTERN + ) { + event.setCancelled(true); + } + } catch (Exception e) { + LogUtil.moduleLog(Level.WARNING, "lectern-crash-patch", + "Error reading ClickSlotC2SPacket - " + e.getLocalizedMessage() + "\n" + + "This might be due to version incompatibilities.\n" + + "Packet in question: " + packet.toString()); + } + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onInventoryOpen(InventoryOpenEvent event) { + this.openInventoryTypes.put(event.getPlayer().getUniqueId(), event.getView().getType()); + } + + @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) + private void onInventoryClose(InventoryCloseEvent event) { + this.openInventoryTypes.remove(event.getPlayer().getUniqueId()); + } + + @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) + private void onPlayerQuit(PlayerQuitEvent event) { + this.openInventoryTypes.remove(event.getPlayer().getUniqueId()); + } + + private int getSlot(PacketContainer packet) { + return packet.getIntegers().read(index_slot); + } + + private int getButton(PacketContainer packet) { + return packet.getIntegers().read(index_button); + } + + private enum InventoryClickType { + PICKUP, QUICK_MOVE, SWAP, CLONE, THROW, QUICK_CRAFT, PICKUP_ALL + } + + private InventoryClickType getClickType(PacketContainer packet) { + return packet.getEnumModifier(InventoryClickType.class, index_clickType).read(0); + } +} \ No newline at end of file diff --git a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java index ba2223ae2..fa5bb08d9 100755 --- a/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java +++ b/AnarchyExploitFixesLegacy/src/main/java/me/moomoo/anarchyexploitfixes/modules/protocollib/windowclick/WindowClickListener.java @@ -17,7 +17,7 @@ public class WindowClickListener extends PacketAdapter { public WindowClickListener() { super(AnarchyExploitFixes.getInstance(), ListenerPriority.HIGHEST, PacketType.Play.Client.WINDOW_CLICK); - this.index_slot = AnarchyExploitFixes.getMCVersion() > 12 ? 2 : 1; + this.index_slot = AnarchyExploitFixes.getMCVersion() > 12 ? 2 : 1; // This needs cross version mapping urgently this.index_button = AnarchyExploitFixes.getMCVersion() > 12 ? 3 : 2; this.index_clickType = AnarchyExploitFixes.getMCVersion() > 12 ? 4 : 5; } @@ -32,7 +32,7 @@ public void onPacketReceiving(PacketEvent event) { try { final int button = this.getButton(packet); - if (button < 0 || button > 9 && button != 40) { + if (button < 0 || button > 9 && button != 40 && button != 99) { event.setCancelled(true); return; } @@ -53,8 +53,10 @@ public void onPacketReceiving(PacketEvent event) { case SWAP: case PICKUP_ALL: event.setCancelled(true); + return; case THROW: event.setCancelled(slot == -1); + return; case QUICK_MOVE: event.setCancelled(slot == -999); }