diff --git a/build.gradle.kts b/build.gradle.kts index b77fa28..b91ec5a 100644 --- a/build.gradle.kts +++ b/build.gradle.kts @@ -4,6 +4,8 @@ plugins { idea eclipse + + id("com.github.johnrengelman.shadow") version "7.1.0" } repositories { @@ -20,6 +22,10 @@ repositories { name = "PaperMC" url = uri("https://repo.papermc.io/repository/maven-public/") } + maven { + name = "PacketEvents" + url = uri("https://repo.codemc.io/repository/maven-releases/") + } maven { name = "ProtocolLib" url = uri("https://repo.dmulloy2.net/nexus/repository/public/") @@ -52,6 +58,7 @@ dependencies { compileOnly("fr.minuskube.inv:smart-invs:1.2.7") //compileOnly("com.github.CraftingStore.MinecraftPlugin:core:master-e366d322f8-1") compileOnly("com.github.brcdev-minecraft:shopgui-api:3.0.0") + implementation("com.github.retrooper:packetevents-spigot:2.4.0") } the().toolchain { @@ -66,10 +73,23 @@ tasks.compileJava.configure { options.release.set(8) } -version = "2.9.12-SNAPSHOT-01" +version = "2.10.0-SNAPSHOT-01" tasks.named("processResources") { filesMatching("plugin.yml") { expand("version" to project.version) } } + +// ShadowJar configuration +tasks.shadowJar { + // Optionally, relocate the PacketEvents package to avoid conflicts + relocate("com.github.retrooper.packetevents", "me.dniym.packetevents.api") + relocate("io.github.retrooper.packetevents", "me.dniym.packetevents.impl") + minimize() +} + +// Build the ShadowJar +tasks.build { + dependsOn(tasks.shadowJar) +} diff --git a/src/main/java/main/java/me/dniym/IllegalStack.java b/src/main/java/main/java/me/dniym/IllegalStack.java index 1d51ddf..16802a4 100644 --- a/src/main/java/main/java/me/dniym/IllegalStack.java +++ b/src/main/java/main/java/me/dniym/IllegalStack.java @@ -1,16 +1,20 @@ package main.java.me.dniym; +import com.github.retrooper.packetevents.PacketEvents; +import com.github.retrooper.packetevents.PacketEventsAPI; +import io.github.retrooper.packetevents.factory.spigot.SpigotPacketEventsBuilder; import main.java.me.dniym.commands.IllegalStackCommand; import main.java.me.dniym.enums.Msg; import main.java.me.dniym.enums.Protections; import main.java.me.dniym.enums.ServerVersion; +import main.java.me.dniym.listeners.CreativeInvPacketListeners; import main.java.me.dniym.listeners.Listener113; import main.java.me.dniym.listeners.Listener114; import main.java.me.dniym.listeners.Listener116; import main.java.me.dniym.listeners.ProtectionListener; +import main.java.me.dniym.listeners.UseEntityPacketListener; import main.java.me.dniym.listeners.fListener; import main.java.me.dniym.listeners.mcMMOListener; -import main.java.me.dniym.listeners.pLisbListener; import main.java.me.dniym.timers.fTimer; import main.java.me.dniym.timers.sTimer; import main.java.me.dniym.timers.syncTimer; @@ -23,6 +27,7 @@ import org.bukkit.configuration.InvalidConfigurationException; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; +import org.bukkit.event.HandlerList; import org.bukkit.inventory.Inventory; import org.bukkit.inventory.ItemStack; import org.bukkit.inventory.meta.ItemMeta; @@ -112,6 +117,16 @@ public static void setCMI(boolean cMI) { CMI = cMI; } + @Override + public void onLoad() { + // Load PacketEventsAPI + PacketEvents.setAPI(SpigotPacketEventsBuilder.build(this)); + PacketEvents.getAPI().getSettings() + .checkForUpdates(false) + .debug(false); + PacketEvents.getAPI().load(); + } + public static void ReloadConfig(Boolean wasCommand) { if (!wasCommand) { IllegalStack.getPlugin().writeConfig(); @@ -432,6 +447,13 @@ public static boolean hasStorage() { @Override public void onEnable() { + // Register PacketEvents listeners + LOGGER.info("Registering PacketEvents listeners..."); + PacketEvents.getAPI().getEventManager().registerListeners(new CreativeInvPacketListeners(this)); + PacketEvents.getAPI().getEventManager().registerListeners(new UseEntityPacketListener(this)); + PacketEventsAPI packetEventsAPI = PacketEvents.getAPI(); + packetEventsAPI.init(); + LOGGER.info("PacketEvents API {} has been initialized!", PacketEvents.getAPI().getVersion()); // new EntityRegistry(this); this.setPlugin(this); @@ -542,25 +564,6 @@ public void onEnable() { } } - if (this - .getServer() - .getPluginManager() - .getPlugin("ProtocolLib") != null && Protections.BlockBadItemsFromCreativeTab.isEnabled()) { - LOGGER.info( - "ProtocolLib was detected, creative inventory exploit detection enabled. NOTE* This protection ONLY needs to be turned on if you have regular (non op) players with access to /gmc"); - new pLisbListener(this); - } - - if (this.getServer().getPluginManager().getPlugin("ProtocolLib") == null && Protections.DisableChestsOnMobs.isEnabled()) { - - LOGGER.warn( - "ProtocolLib NOT FOUND!!!! and DisableChestsOnMobs protection is turned on.. It may still be possible for players to dupe using horses/donkeys on your server using a hacked client. It is highly recommended that you install ProtocolLib for optimal protection!"); - - } else if (Protections.DisableChestsOnMobs.isEnabled()) { - new pLisbListener(this); - setHasProtocolLib(true); - } - this.getServer().getPluginManager().registerEvents(new fListener(this), this); if (!fListener.is18()) { @@ -1033,13 +1036,26 @@ public static boolean isDisable() { @Override public void onDisable() { + // Signal plugin is now disabled disable = true; + + // Terminate PacketEvents + PacketEvents.getAPI().getEventManager().unregisterAllListeners(); + PacketEvents.getAPI().terminate(); + LOGGER.info("PacketEvents has been terminated successfully!"); + + // Unregister listeners + HandlerList.unregisterAll(this); + LOGGER.info("Listeners have unregistered successfully!"); + + // Cancel all tasks if (hasAsyncScheduler) { getServer().getAsyncScheduler().cancelTasks(this); } else if (!isFoliaServer()){ Bukkit.getScheduler().cancelTasks(this); } + // Save configuration writeConfig(); } diff --git a/src/main/java/main/java/me/dniym/enums/Protections.java b/src/main/java/main/java/me/dniym/enums/Protections.java index 1efdf4c..336c86a 100644 --- a/src/main/java/main/java/me/dniym/enums/Protections.java +++ b/src/main/java/main/java/me/dniym/enums/Protections.java @@ -1676,8 +1676,7 @@ World getWorldFromObj(Object obj) { public boolean isDisabledInWorld(World wld) { return Protections.DisableInWorlds.isWhitelisted(wld.getName()); } - - @Deprecated + public boolean isEnabled() { if (this.getVersion().isEmpty()) //child node return this.enabled; diff --git a/src/main/java/main/java/me/dniym/listeners/CreativeInvPacketListeners.java b/src/main/java/main/java/me/dniym/listeners/CreativeInvPacketListeners.java new file mode 100644 index 0000000..5ae3de2 --- /dev/null +++ b/src/main/java/main/java/me/dniym/listeners/CreativeInvPacketListeners.java @@ -0,0 +1,73 @@ +package main.java.me.dniym.listeners; + +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.player.User; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientCreativeInventoryAction; +import io.github.retrooper.packetevents.util.SpigotConversionUtil; +import main.java.me.dniym.IllegalStack; +import main.java.me.dniym.enums.Msg; +import main.java.me.dniym.enums.Protections; +import main.java.me.dniym.utils.Scheduler; +import org.apache.logging.log4j.LogManager; +import org.apache.logging.log4j.Logger; +import org.bukkit.Material; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.UUID; + +public class CreativeInvPacketListeners extends PacketListenerAbstract { + + private final IllegalStack plugin; + + private static final Logger LOGGER = LogManager.getLogger("IllegalStack/" + CreativeInvPacketListeners.class.getSimpleName()); + + public CreativeInvPacketListeners(IllegalStack plugin) { + super(PacketListenerPriority.LOW); + this.plugin = plugin; + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + + if (event.getPacketType() != PacketType.Play.Client.CREATIVE_INVENTORY_ACTION) { + return; + } + + if (!Protections.BlockBadItemsFromCreativeTab.isEnabled()) { + return; + } + + User user = event.getUser(); + UUID uuid = user.getUUID(); + Player player = plugin.getServer().getPlayer(uuid); + + if (player == null) { + return; + } + + if (player.isOp() || player.hasPermission("illegalstack.admin")) { + return; + } + + WrapperPlayClientCreativeInventoryAction packetWrapper = new WrapperPlayClientCreativeInventoryAction(event); + + try { + com.github.retrooper.packetevents.protocol.item.ItemStack wrapperItemStack = packetWrapper.getItemStack(); + ItemStack stack = SpigotConversionUtil.toBukkitItemStack(wrapperItemStack); + if (stack != null && stack.hasItemMeta()) { + stack = new ItemStack(Material.AIR); + Scheduler.runTaskLater(plugin, player::updateInventory, 5L, player); + event.setCancelled(true); + Msg.StaffMsgCreativeBlock.getValue(player.getName()); + } + } catch (IndexOutOfBoundsException ex) { + LOGGER.error( + "An error receiving a CREATIVE_INVENTORY_ACTION packet has occurred, you are probably using paper and have BlockBadItemsFromCreativeTab turned on. This setting is needed very rarely, and ONLY if you have regular non-op players with access to /gmc."); + } + } + +} diff --git a/src/main/java/main/java/me/dniym/listeners/UseEntityPacketListener.java b/src/main/java/main/java/me/dniym/listeners/UseEntityPacketListener.java new file mode 100644 index 0000000..f4bb98a --- /dev/null +++ b/src/main/java/main/java/me/dniym/listeners/UseEntityPacketListener.java @@ -0,0 +1,124 @@ +package main.java.me.dniym.listeners; + +import com.github.retrooper.packetevents.event.PacketListenerAbstract; +import com.github.retrooper.packetevents.event.PacketListenerPriority; +import com.github.retrooper.packetevents.event.PacketReceiveEvent; +import com.github.retrooper.packetevents.protocol.packettype.PacketType; +import com.github.retrooper.packetevents.protocol.player.User; +import com.github.retrooper.packetevents.wrapper.play.client.WrapperPlayClientInteractEntity; +import main.java.me.dniym.IllegalStack; +import main.java.me.dniym.enums.Msg; +import main.java.me.dniym.enums.Protections; +import main.java.me.dniym.timers.fTimer; +import main.java.me.dniym.utils.Scheduler; +import org.bukkit.Material; +import org.bukkit.World; +import org.bukkit.entity.ChestedHorse; +import org.bukkit.entity.Entity; +import org.bukkit.entity.Horse; +import org.bukkit.entity.Player; +import org.bukkit.inventory.ItemStack; + +import java.util.HashMap; +import java.util.UUID; + +public class UseEntityPacketListener extends PacketListenerAbstract { + + private final IllegalStack plugin; + private final HashMap messageDelay = new HashMap<>(); + + public UseEntityPacketListener(IllegalStack plugin) { + super(PacketListenerPriority.LOW); + this.plugin = plugin; + } + + @Override + public void onPacketReceive(PacketReceiveEvent event) { + + if (event.getPacketType() != PacketType.Play.Client.INTERACT_ENTITY) { + return; + } + + if (!IllegalStack.hasChestedAnimals()) { + return; + } + + if (!Protections.DisableChestsOnMobs.isEnabled()) { + return; + } + + User user = event.getUser(); + UUID uuid = user.getUUID(); + Player player = plugin.getServer().getPlayer(uuid); + + if (player == null) { + return; + } + + if (player.isOp() || player.hasPermission("illegalstack.admin")) { + return; + } + + WrapperPlayClientInteractEntity packetWrapper = new WrapperPlayClientInteractEntity(event); + + World world = player.getWorld(); + int entityId = packetWrapper.getEntityId(); + + if (entityId <= 0) { + return; + } + + Scheduler.runTask(plugin, () -> { + + Entity entity = world.getEntities().stream().filter(e -> e.getEntityId() == entityId).findFirst().orElse(null); + + Scheduler.runTaskLater(plugin, () -> { + + if (entity instanceof Horse && ((Horse) entity).isTamed()) { + ItemStack is = player.getInventory().getItemInMainHand(); + if (!fListener.is18() && (is == null || is.getType() != Material.CHEST)) { + is = player.getInventory().getItemInOffHand(); + } + if (is == null || is.getType() != Material.CHEST) { + return; + } + exploitMessage(player, entity); + event.setCancelled(true); + fTimer.getPunish().put(player, entity); + return; + } + + if (entity instanceof ChestedHorse && ((ChestedHorse) entity).isTamed()) { + ItemStack is = player.getInventory().getItemInMainHand(); + if (is == null || is.getType() != Material.CHEST) { + is = player.getInventory().getItemInOffHand(); + } + if (is == null || is.getType() != Material.CHEST) { + return; + } + exploitMessage(player, entity); + event.setCancelled(true); + + ((ChestedHorse) entity).setCarryingChest(true); + ((ChestedHorse) entity).setCarryingChest(false); + fTimer.getPunish().put(player, entity); + } + + }, 1, entity); + + }, player.getLocation()); + } + + private void exploitMessage(Player p, Entity ent) { + if (!messageDelay.containsKey(p.getUniqueId())) { + messageDelay.put(p.getUniqueId(), 0L); + } + + if (System.currentTimeMillis() > messageDelay.get(p.getUniqueId())) { + p.sendMessage(Msg.PlayerDisabledHorseChestMsg.getValue()); + fListener.getLog().append2(Msg.ChestPrevented.getValue(p, ent)); + messageDelay.put(p.getUniqueId(), System.currentTimeMillis() + 2000L); + } + } + +} diff --git a/src/main/java/main/java/me/dniym/listeners/fListener.java b/src/main/java/main/java/me/dniym/listeners/fListener.java index 9ad7706..adbef32 100644 --- a/src/main/java/main/java/me/dniym/listeners/fListener.java +++ b/src/main/java/main/java/me/dniym/listeners/fListener.java @@ -64,7 +64,6 @@ import org.bukkit.entity.TNTPrimed; import org.bukkit.entity.Tameable; import org.bukkit.entity.TraderLlama; -import org.bukkit.entity.Vehicle; import org.bukkit.entity.Vex; import org.bukkit.entity.Zombie; import org.bukkit.entity.minecart.HopperMinecart; @@ -85,6 +84,7 @@ import org.bukkit.event.entity.CreatureSpawnEvent; import org.bukkit.event.entity.EntityDeathEvent; import org.bukkit.event.entity.EntityExplodeEvent; +import org.bukkit.event.entity.EntityMountEvent; import org.bukkit.event.entity.EntityPortalEvent; import org.bukkit.event.entity.EntitySpawnEvent; import org.bukkit.event.entity.EntityTargetEvent; @@ -94,7 +94,6 @@ import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryOpenEvent; -import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.PrepareItemCraftEvent; import org.bukkit.event.player.PlayerBucketEmptyEvent; @@ -120,7 +119,6 @@ import org.bukkit.inventory.meta.BookMeta; import org.bukkit.inventory.meta.ItemMeta; import org.bukkit.util.Vector; -import org.spigotmc.event.entity.EntityMountEvent; import java.nio.charset.Charset; import java.util.ArrayList; diff --git a/src/main/java/main/java/me/dniym/listeners/pLisbListener.java b/src/main/java/main/java/me/dniym/listeners/pLisbListener.java index 635a650..fe0e8c6 100644 --- a/src/main/java/main/java/me/dniym/listeners/pLisbListener.java +++ b/src/main/java/main/java/me/dniym/listeners/pLisbListener.java @@ -18,10 +18,13 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.ApiStatus; import java.util.HashMap; import java.util.UUID; +@Deprecated +@ApiStatus.ScheduledForRemoval public class pLisbListener { private static final Logger LOGGER = LogManager.getLogger("IllegalStack/" + pLisbListener.class.getSimpleName()); diff --git a/src/main/java/main/java/me/dniym/utils/BookCrashExploitCheck.java b/src/main/java/main/java/me/dniym/utils/BookCrashExploitCheck.java index 87f07d3..a3e0f57 100644 --- a/src/main/java/main/java/me/dniym/utils/BookCrashExploitCheck.java +++ b/src/main/java/main/java/me/dniym/utils/BookCrashExploitCheck.java @@ -7,7 +7,10 @@ import org.bukkit.entity.Player; import org.bukkit.inventory.InventoryView; import org.bukkit.plugin.Plugin; +import org.jetbrains.annotations.ApiStatus; +@Deprecated +@ApiStatus.ScheduledForRemoval public class BookCrashExploitCheck extends PacketAdapter { public BookCrashExploitCheck(final Plugin plugin) { diff --git a/src/main/java/main/java/me/dniym/utils/PacketAttack.java b/src/main/java/main/java/me/dniym/utils/PacketAttack.java index bd26281..429f1c7 100644 --- a/src/main/java/main/java/me/dniym/utils/PacketAttack.java +++ b/src/main/java/main/java/me/dniym/utils/PacketAttack.java @@ -8,11 +8,14 @@ import main.java.me.dniym.listeners.fListener; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; +import org.jetbrains.annotations.ApiStatus; import java.util.HashMap; import java.util.HashSet; import java.util.UUID; +@Deprecated +@ApiStatus.ScheduledForRemoval public class PacketAttack { private static final Logger LOGGER = LogManager.getLogger("IllegalStack/" + PacketAttack.class.getSimpleName()); diff --git a/src/main/java/main/java/me/dniym/utils/SpigotMethods.java b/src/main/java/main/java/me/dniym/utils/SpigotMethods.java index 9f35fac..85ab6ee 100644 --- a/src/main/java/main/java/me/dniym/utils/SpigotMethods.java +++ b/src/main/java/main/java/me/dniym/utils/SpigotMethods.java @@ -11,6 +11,7 @@ import org.bukkit.entity.LivingEntity; +@SuppressWarnings("deprecation") public class SpigotMethods { public static BaseComponent makeParentText(Protections protections, String status, boolean children, int catId) { diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index aa74972..785a7ec 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -5,7 +5,23 @@ api-version: 1.13 folia-supported: true description: Closes some dupe bugs still present in vanilla minecraft. authors: [ dNiym, Loving11ish ] -softdepend: [Magic, Factions, NBTAPI, ProtocolLib, Slimefun, CraftingStore, DynamicShop, ClueScrolls, mcMMO, JetsMinions, SmartInvs, FactionsX] +softdepend: + - MagicFactions + - NBTAPI + - ProtocolLib + - ProtocolSupport + - ViaVersion + - ViaBackwards + - ViaRewind + - Geyser-Spigot + - Slimefun + - CraftingStore + - DynamicShop + - ClueScrolls + - mcMMO + - JetsMinions + - SmartInvs + - FactionsX loadbefore: [MythicDrops] website: https://www.spigotmc.org/resources/44411/ commands: