From 06c714b363a18af2e8c6738070719eda112bd83c Mon Sep 17 00:00:00 2001 From: Zrips Date: Thu, 27 Jun 2024 16:41:47 +0300 Subject: [PATCH] Second pass for block protection Separation of block place and breaking when it comes to global timers --- libs/CMILib1.5.0.3.jar | Bin 842762 -> 843641 bytes src/main/java/com/gamingmesh/jobs/Jobs.java | 7 +- .../com/gamingmesh/jobs/commands/list/bp.java | 21 +- .../jobs/config/BlockProtectionManager.java | 25 +-- .../jobs/config/ExploitProtectionManager.java | 182 ++++++++++++++---- .../jobs/config/GeneralConfigManager.java | 24 ++- .../jobs/listeners/JobsListener.java | 26 ++- 7 files changed, 215 insertions(+), 70 deletions(-) diff --git a/libs/CMILib1.5.0.3.jar b/libs/CMILib1.5.0.3.jar index 223091999066f1eb505a67786abd2a14d4696de1..a4ab87907fbc30b823a4e0dc0594c22bcdb61d50 100644 GIT binary patch delta 17559 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 delta 16848 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%0DlK$syq(OcT z0{1mmNl85X#~w!?Hbp7+0ax<7{*qYX<|J%-5*f{gb^tX>;8~}=N|j>IUw;1onpLW3 zvvvV+_zc*{(OSjd^Y|}6E1Wn;A;S*+SSq~xf&Jb=I(-}5(hqSVGwlc+`+Nw+ZhDN( z0ju^AR~eWcp|e^c6<@WPxSDGWRVX@u6)&OCAuR?>rrjW6`m0!XPNJ+?1K4v;Nh`s_>HXTza z1tIZ**>3d^q;8?7PY4EkyX^3dF-RQoyJrljidFlE1U7~F;Rj=&Dd-Mpjstq8#$UR~ ze7*_Ll;md&4iz4jg2I4( zW$Py93zPwns?8u0bdwj&TYls|M|f%iJhADU&Ohl2ESzBeXV6*%0rn9Em{wN8o#1`X zAPEEo_AUhoD=Xzr5Ug progression = jPlayer.getJobProgression(); int numjobs = progression.size(); - if (!Jobs.getGCManager().useBlockProtectionBlockTracker && !Jobs.getExploitManager().isProtectionValidAddIfNotExists(jPlayer, info, block, true)) + CMIDebug.it(); + if (!Jobs.getGCManager().useBlockProtectionBlockTracker && !Jobs.getExploitManager().isProtectionValidAddIfNotExists(jPlayer, info, block, true)) { + CMIDebug.d(CMIDebug.getIT(), "ms"); return; + } + CMIDebug.d(CMIDebug.getIT(), "ms"); // no job if (numjobs == 0) { diff --git a/src/main/java/com/gamingmesh/jobs/commands/list/bp.java b/src/main/java/com/gamingmesh/jobs/commands/list/bp.java index aa9d83db..170abb2b 100644 --- a/src/main/java/com/gamingmesh/jobs/commands/list/bp.java +++ b/src/main/java/com/gamingmesh/jobs/commands/list/bp.java @@ -3,7 +3,6 @@ package com.gamingmesh.jobs.commands.list; import java.util.ArrayList; import java.util.List; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.block.Block; import org.bukkit.command.CommandSender; @@ -15,8 +14,10 @@ import com.gamingmesh.jobs.container.BlockProtection; import com.gamingmesh.jobs.container.DBAction; import com.gamingmesh.jobs.i18n.Language; +import net.Zrips.CMILib.Container.CMINumber; import net.Zrips.CMILib.Items.CMIMaterial; import net.Zrips.CMILib.Locale.LC; +import net.Zrips.CMILib.Logs.CMIDebug; import net.Zrips.CMILib.Messages.CMIMessages; import net.Zrips.CMILib.Version.Version; import net.Zrips.CMILib.Version.Schedulers.CMIScheduler; @@ -42,6 +43,19 @@ public class bp implements Cmd { final List changedBlocks = new ArrayList<>(); if (Jobs.getGCManager().useNewBlockProtection) { + +// if (Version.isTestServer()) { +// CMIDebug.d("Filling test blocks"); +// for (int x = 0; x < 16; x++) { +// for (int y = 72; y < 150; y++) { +// for (int z = 0; z < 16; z++) { +// Block block = loc.getChunk().getBlock(x, y, z); +// Jobs.getExploitManager().addProtection(block, CMINumber.random(1, 10)); +// } +// } +// } +// } + for (int x = -10; x < 10; x++) { for (int y = -10; y < 10; y++) { for (int z = -10; z < 10; z++) { @@ -58,10 +72,9 @@ public class bp implements Cmd { changedBlocks.add(l.getBlock()); if (Version.isCurrentEqualOrHigher(Version.v1_15_R1)) { - player.sendBlockChange(l, (time == -1 ? CMIMaterial.BLACK_STAINED_GLASS : CMIMaterial.WHITE_STAINED_GLASS) - .getMaterial().createBlockData()); + player.sendBlockChange(l, (time == -1 ? CMIMaterial.BLACK_STAINED_GLASS : CMIMaterial.WHITE_STAINED_GLASS).getMaterial().createBlockData()); } else { - if (time == -1) + if (time == -1) player.sendBlockChange(l, CMIMaterial.RED_STAINED_GLASS.getMaterial(), (byte) 15); else player.sendBlockChange(l, CMIMaterial.RED_STAINED_GLASS.getMaterial(), (byte) 0); diff --git a/src/main/java/com/gamingmesh/jobs/config/BlockProtectionManager.java b/src/main/java/com/gamingmesh/jobs/config/BlockProtectionManager.java index 43453e0f..a7a0a44d 100644 --- a/src/main/java/com/gamingmesh/jobs/config/BlockProtectionManager.java +++ b/src/main/java/com/gamingmesh/jobs/config/BlockProtectionManager.java @@ -222,19 +222,16 @@ public class BlockProtectionManager { return (int) Math.floor(x / 32D) + ":" + (int) Math.floor(z / 32D); } + @Deprecated public Integer getBlockDelayTime(Block block) { - Integer time = Jobs.getRestrictedBlockManager().restrictedBlocksTimer.get(CMIMaterial.get(block)); - if (time == null && Jobs.getGCManager().useGlobalTimer) { - time = Jobs.getGCManager().globalblocktimer; - } - return time; + return Jobs.getExploitManager().getBlockProtectionTime(block); } + @Deprecated public boolean isInBp(Block block) { return Jobs.getRestrictedBlockManager().restrictedBlocksTimer.containsKey(CMIMaterial.get(block)); } - - + public boolean isBpOk(JobsPlayer player, ActionInfo info, Block block, boolean inform) { if (block == null || !Jobs.getGCManager().useBlockProtection) return true; @@ -248,7 +245,7 @@ public class BlockProtectionManager { BlockProtection bp = getBp(block.getLocation()); if (bp != null) { long time = bp.getTime(); - Integer cd = getBlockDelayTime(block); + Integer cd = Jobs.getExploitManager().getBlockProtectionTime(info.getType(), block); if (time == -1L) { remove(block); @@ -271,18 +268,14 @@ public class BlockProtectionManager { add(block, cd); - if ((cd == null || cd == 0) && Jobs.getGCManager().useGlobalTimer) { - add(block, Jobs.getGCManager().globalblocktimer); - } + } else + add(block, Jobs.getExploitManager().getBlockProtectionTime(info.getType(), block)); - } else if (Jobs.getGCManager().useGlobalTimer) { - add(block, Jobs.getGCManager().globalblocktimer); - } } else if (info.getType() == ActionType.PLACE) { BlockProtection bp = getBp(block.getLocation()); if (bp != null) { Long time = bp.getTime(); - Integer cd = getBlockDelayTime(block); + Integer cd = Jobs.getExploitManager().getBlockProtectionTime(info.getType(), block); if (time != -1L) { if (time < System.currentTimeMillis() && bp.getAction() != DBAction.DELETE) { add(block, cd); @@ -307,7 +300,7 @@ public class BlockProtectionManager { } else add(block, cd); } else - add(block, getBlockDelayTime(block)); + add(block, Jobs.getExploitManager().getBlockProtectionTime(info.getType(), block)); } return true; diff --git a/src/main/java/com/gamingmesh/jobs/config/ExploitProtectionManager.java b/src/main/java/com/gamingmesh/jobs/config/ExploitProtectionManager.java index 0d08541c..7c183022 100644 --- a/src/main/java/com/gamingmesh/jobs/config/ExploitProtectionManager.java +++ b/src/main/java/com/gamingmesh/jobs/config/ExploitProtectionManager.java @@ -1,7 +1,13 @@ package com.gamingmesh.jobs.config; +import java.util.HashMap; +import java.util.Set; + +import org.bukkit.Chunk; import org.bukkit.Location; +import org.bukkit.NamespacedKey; import org.bukkit.block.Block; +import org.bukkit.util.Vector; import com.gamingmesh.jobs.Jobs; import com.gamingmesh.jobs.container.ActionInfo; @@ -15,12 +21,37 @@ import net.Zrips.CMILib.Container.CMIBlock; import net.Zrips.CMILib.Container.CMIBlock.Bisect; import net.Zrips.CMILib.Items.CMIMaterial; import net.Zrips.CMILib.Logs.CMIDebug; -import net.Zrips.CMILib.PersistentData.CMIBlockPersistentDataContainer; +import net.Zrips.CMILib.PersistentData.CMIChunkPersistentDataContainer; public class ExploitProtectionManager { private static final String NAMEGENERAL = "JobsExploitProtection"; - private static final String NAMEPAID = "JobsPaidProtection"; + private static final String NAMETIME = "Time"; + private static final String NAMEPAID = "Paid"; + + private HashMap> map = new HashMap<>(); + + private CMIChunkPersistentDataContainer getPDC(Block block) { + if (block == null) + return null; + return getPDC(block.getChunk()); + } + + private CMIChunkPersistentDataContainer getPDC(Chunk chunk) { + if (chunk == null) + return null; + HashMap world = map.computeIfAbsent(chunk.getWorld().getName(), x -> new HashMap<>()); + return world.computeIfAbsent(chunk.getX() + ":" + chunk.getZ(), x -> new CMIChunkPersistentDataContainer(NAMEGENERAL, chunk)); + } + + public void removePDC(Chunk chunk) { + if (!Jobs.getGCManager().useNewBlockProtection) + return; + HashMap world = map.get(chunk.getWorld().getName()); + if (world == null) + return; + world.remove(chunk.getX() + ":" + chunk.getZ()); + } public void addProtection(Block block, Integer cd) { @@ -50,8 +81,30 @@ public class ExploitProtectionManager { addProtection(block, cd != -1 ? System.currentTimeMillis() + (cd * 1000) : -1, paid); } - public ExploitProtection addProtection(Block block, Long protectedUntil, boolean paid) { + private String convertLoc(Location loc) { + return convertLoc(loc.toVector()); + } + private String convertLoc(Vector loc) { + return loc.getBlockX() + "." + loc.getBlockY() + "." + loc.getBlockZ(); + } + + private int shortenLong(long value) { + if (value == -1) + return -1; + return (int) (value / 1000) - 2147483647; + } + + private Long deconvertLong(Integer value) { + if (value == null) + return null; + if (value == -1) + return -1L; + return (value + 2147483647L) * 1000L; + } + + public ExploitProtection addProtection(Block block, Long protectedUntil, boolean paid) { +// CMIDebug.c("Adding protection ", block.getLocation().toVector()); if (!Jobs.getGCManager().useNewBlockProtection) { BlockProtection protection = Jobs.getBpManager().addP(block.getLocation(), protectedUntil, paid, true); @@ -64,9 +117,21 @@ public class ExploitProtectionManager { if (protectedUntil == null || protectedUntil == 0) return null; - CMIBlockPersistentDataContainer pdc = new CMIBlockPersistentDataContainer(block); - pdc.set(NAMEGENERAL, protectedUntil); - pdc.set(NAMEPAID, paid); + if (block == null) + return null; + + CMIChunkPersistentDataContainer pdc = getPDC(block); + + if (pdc == null) + return null; + + String locString = convertLoc(block.getLocation()); + + pdc.set(locString, NAMETIME, shortenLong(protectedUntil)); + if (!paid) + pdc.set(locString, NAMEPAID, paid); + else + pdc.remove(locString, NAMEPAID); pdc.save(); ExploitProtection ep = new ExploitProtection(block.getLocation().toVector()); @@ -77,7 +142,11 @@ public class ExploitProtectionManager { } public void remove(Block block) { -CMIDebug.d("remove protection", block.getType()); + if (!Jobs.getGCManager().useNewBlockProtection) { + Jobs.getBpManager().remove(block); + return; + } + // In case double plant was destroyed we should remove both blocks from records CMIMaterial cmat = CMIMaterial.get(block); switch (cmat) { @@ -94,9 +163,9 @@ CMIDebug.d("remove protection", block.getType()); return; } - CMIBlockPersistentDataContainer pdc = new CMIBlockPersistentDataContainer(block); - pdc.remove(NAMEGENERAL); - pdc.remove(NAMEPAID); + CMIChunkPersistentDataContainer pdc = getPDC(block); + String locString = convertLoc(block.getLocation()); + pdc.remove(locString); pdc.save(); } @@ -105,20 +174,35 @@ CMIDebug.d("remove protection", block.getType()); if (!Jobs.getGCManager().useNewBlockProtection) return Jobs.getBpManager().getTime(block); - CMIBlockPersistentDataContainer pdc = new CMIBlockPersistentDataContainer(block); - return pdc.getLong(NAMEGENERAL); + CMIChunkPersistentDataContainer pdc = getPDC(block); + String locString = convertLoc(block.getLocation()); + return deconvertLong(pdc.getInt(locString, NAMETIME)); } public Long getTime(Location loc) { return getTime(loc.getBlock()); } + @Deprecated public Integer getBlockProtectionTime(Block block) { - Integer time = Jobs.getRestrictedBlockManager().restrictedBlocksTimer.get(CMIMaterial.get(block)); - if (time == null && Jobs.getGCManager().useGlobalTimer) { - time = Jobs.getGCManager().globalblocktimer; + return getBlockProtectionTime(ActionType.PLACE, block); + } + + public Integer getBlockProtectionTime(ActionType action, Block block) { + + switch (action) { + case BREAK: + if (Jobs.getGCManager().useGlobalBreakTimer) + return Jobs.getGCManager().globalBlockBreakTimer; + break; + case PLACE: + Integer time = Jobs.getRestrictedBlockManager().restrictedBlocksTimer.get(CMIMaterial.get(block)); + if (time == null && Jobs.getGCManager().useGlobalTimer) + return Jobs.getGCManager().globalblocktimer; + return time == null ? 0 : time; } - return time; + + return 0; } public boolean isInProtection(Block block) { @@ -126,8 +210,13 @@ CMIDebug.d("remove protection", block.getType()); } public void setPaid(Block block, boolean paid) { - CMIBlockPersistentDataContainer pdc = new CMIBlockPersistentDataContainer(block); - pdc.set(NAMEPAID, paid); +// CMIDebug.d("Setting to paid", block.getLocation().toVector()); + CMIChunkPersistentDataContainer pdc = getPDC(block); + String locString = convertLoc(block.getLocation()); + if (!paid) + pdc.set(locString, NAMEPAID, paid); + else + pdc.remove(locString, NAMEPAID); pdc.save(); } @@ -135,17 +224,16 @@ CMIDebug.d("remove protection", block.getType()); ExploitProtection ep = new ExploitProtection(block.getLocation().toVector()); - CMIBlockPersistentDataContainer pdc = new CMIBlockPersistentDataContainer(block); - - ep.setPaid(pdc.getBoolean(NAMEPAID)); - ep.setProtectedUntil(pdc.getLong(NAMEGENERAL)); + CMIChunkPersistentDataContainer pdc = getPDC(block); + String locString = convertLoc(block.getLocation()); + Boolean paidValue = pdc.getBoolean(locString, NAMEPAID); + ep.setPaid(paidValue == null ? true : paidValue); + ep.setProtectedUntil(deconvertLong(pdc.getInt(locString, NAMETIME))); return ep; - } public boolean isProtectionValidAddIfNotExists(JobsPlayer player, ActionInfo info, Block block, boolean inform) { - if (!Jobs.getGCManager().useNewBlockProtection) return Jobs.getBpManager().isBpOk(player, info, block, inform); @@ -178,17 +266,10 @@ CMIDebug.d("remove protection", block.getType()); return false; } - Integer cd = getBlockProtectionTime(block); + addProtection(block, getBlockProtectionTime(info.getType(), block)); - if ((cd == null || cd == 0) && Jobs.getGCManager().useGlobalTimer) { - addProtection(block, Jobs.getGCManager().globalblocktimer); - return true; - } - - addProtection(block, cd); - - } else if (Jobs.getGCManager().useGlobalTimer) { - addProtection(block, Jobs.getGCManager().globalblocktimer); + } else { + addProtection(block, getBlockProtectionTime(info.getType(), block)); } } else if (info.getType() == ActionType.PLACE) { ExploitProtection exploitProtection = getProtection(block); @@ -196,7 +277,7 @@ CMIDebug.d("remove protection", block.getType()); long time = exploitProtection.getProtectedUntil(); - Integer cd = getBlockProtectionTime(block); + Integer cd = getBlockProtectionTime(info.getType(), block); if (time != -1L) { if (time < System.currentTimeMillis()) { addProtection(block, cd); @@ -218,9 +299,38 @@ CMIDebug.d("remove protection", block.getType()); } else addProtection(block, cd); } else - addProtection(block, getBlockProtectionTime(block)); + addProtection(block, getBlockProtectionTime(info.getType(), block)); } return true; } + + public void cleanChunk(Chunk chunk) { + + if (!Jobs.getGCManager().useNewBlockProtection) + return; + +// CompletableFuture.supplyAsync(() -> { + try { + CMIDebug.it(); + CMIChunkPersistentDataContainer pdc = getPDC(chunk); + + Set keys = pdc.getKeys(); + + for (NamespacedKey one : keys) { + Long time = deconvertLong(pdc.getInt(one.getKey(), NAMETIME)); + if (time != null && time < System.currentTimeMillis()) { + pdc.remove(one.getKey()); + } + } + pdc.save(); + CMIDebug.c(CMIDebug.getIT(), "ms chunk cleanup"); + } catch (Throwable e) { + e.printStackTrace(); + } + +// return null; +// }); + + } } diff --git a/src/main/java/com/gamingmesh/jobs/config/GeneralConfigManager.java b/src/main/java/com/gamingmesh/jobs/config/GeneralConfigManager.java index 008eff9d..6db0b67a 100644 --- a/src/main/java/com/gamingmesh/jobs/config/GeneralConfigManager.java +++ b/src/main/java/com/gamingmesh/jobs/config/GeneralConfigManager.java @@ -74,7 +74,7 @@ public class GeneralConfigManager { private String getSelectionTool, DecimalPlacesMoney, DecimalPlacesExp, DecimalPlacesPoints; public int jobExpiryTime, BlockProtectionDays, FireworkPower, ShootTime, blockOwnershipRange, - globalblocktimer, CowMilkingTimer, InfoUpdateInterval, JobsTopAmount, PlaceholdersPage, ConfirmExpiryTime, + globalblocktimer, globalBlockBreakTimer, CowMilkingTimer, InfoUpdateInterval, JobsTopAmount, PlaceholdersPage, ConfirmExpiryTime, SegmentCount, BossBarTimer, AutoJobJoinDelay, DBCleaningJobsLvl, DBCleaningUsersDays, BlastFurnacesMaxDefault, SmokersMaxDefault, levelLossPercentageFromMax, levelLossPercentage, SoundLevelupVolume, SoundLevelupPitch, SoundTitleChangeVolume, SoundTitleChangePitch, ToplistInScoreboardInterval; @@ -95,7 +95,7 @@ public class GeneralConfigManager { public boolean ignoreOreGenerators, useBlockProtection, useNewBlockProtection, useNewExploration, useBlockProtectionBlockTracker, enableSchedule, PayForRenaming, PayForEnchantingOnAnvil, PayForEachCraft, SignsEnabled, - SignsColorizeJobName, ShowToplistInScoreboard, useGlobalTimer, useSilkTouchProtection, UseCustomNames, + SignsColorizeJobName, ShowToplistInScoreboard, useGlobalTimer, useGlobalBreakTimer, useSilkTouchProtection, UseCustomNames, PreventSlimeSplit, PreventMagmaCubeSplit, PreventHopperFillUps, PreventBrewingStandFillUps, informOnPaymentDisable, BrowseUseNewLook, payExploringWhenGliding = false, resetExploringData = false, disablePaymentIfMaxLevelReached, disablePaymentIfRiding, boostedItemsInOffHand = false, boostedItemsInMainHand, boostedArmorItems, boostedItemsSlotSpecific, multiplyBoostedExtraValues, addPermissionBoost, @@ -424,7 +424,7 @@ public class GeneralConfigManager { UseAsWhiteListWorldList = c.get("Optimizations.DisabledWorlds.UseAsWhiteList", false); DisabledWorldsList = c.get("Optimizations.DisabledWorlds.List", Arrays.asList("Example", "Worlds")); CMIList.toLowerCase(DisabledWorldsList); - + if (Version.isCurrentEqualOrHigher(Version.v1_14_R1)) { c.addComment("Optimizations.Explore.NewMethod", "Do you want to use new exploration tracking method. Only for 1.14+ servers"); @@ -918,11 +918,19 @@ public class GeneralConfigManager { + " once you have broken the block in one place."); allowBreakPaymentForOreGenerators = c.get("ExploitProtections.General.AllowBreakPaymentForOreGenerators", false);*/ - c.addComment("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer", "All blocks will be protected X seconds after player places/breaks it"); - useGlobalTimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Use", true); - c.addComment("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Timer", "Time in seconds. This can only be positive number"); - globalblocktimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Timer", 3); - globalblocktimer = CMINumber.clamp(globalblocktimer, 1, 99999); + c.addComment("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Place", "All blocks will be protected X seconds after player places it"); + useGlobalTimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Place.Use", c.getC().getBoolean("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Use", true)); + c.addComment("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Place.Timer", + "Time in seconds. This can only be positive number and no higher than 900", + "If higher timers are needed then it can be defined in restrictedBlocks.yml file for each specific block"); + globalblocktimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Place.Timer", c.getC().getInt("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Timer", 3)); + globalblocktimer = CMINumber.clamp(globalblocktimer, 1, 900); + useGlobalBreakTimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Break.Use", true); + c.addComment("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Break.Timer", + "Time in seconds. This can only be positive number and no higher than 60", + "This is only to prevent player from placing blocks into same place and getting paid once more"); + globalBlockBreakTimer = c.get("ExploitProtections.General.PlaceAndBreak.GlobalBlockTimer.Break.Timer", 3); + globalBlockBreakTimer = CMINumber.clamp(globalBlockBreakTimer, 1, 60); c.addComment("ExploitProtections.General.PlaceAndBreak.SilkTouchProtection", "Enable silk touch protection.", "With this enabled players wont get paid for broken blocks from restrictedblocks list with silk touch tool."); diff --git a/src/main/java/com/gamingmesh/jobs/listeners/JobsListener.java b/src/main/java/com/gamingmesh/jobs/listeners/JobsListener.java index d8d0bee3..7fd16f7d 100644 --- a/src/main/java/com/gamingmesh/jobs/listeners/JobsListener.java +++ b/src/main/java/com/gamingmesh/jobs/listeners/JobsListener.java @@ -58,6 +58,7 @@ import org.bukkit.event.player.PlayerItemHeldEvent; import org.bukkit.event.player.PlayerJoinEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; +import org.bukkit.event.world.ChunkUnloadEvent; import org.bukkit.event.world.StructureGrowEvent; import org.bukkit.event.world.WorldLoadEvent; import org.bukkit.inventory.EquipmentSlot; @@ -118,23 +119,38 @@ public class JobsListener implements Listener { return time > 100; } + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onChunkUnload(ChunkUnloadEvent event) { + Jobs.getExploitManager().removePDC(event.getChunk()); + } + + @EventHandler(priority = EventPriority.NORMAL, ignoreCancelled = true) + public void onChunkUnload(JobsChunkChangeEvent event) { + Jobs.getExploitManager().cleanChunk(event.getOldChunk()); + } + @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) public void onBlockFromToEvent(BlockFromToEvent event) { if (!Jobs.getGCManager().useBlockProtection) return; + if (!Jobs.getGCManager().ignoreOreGenerators) return; + if (!Jobs.getGCManager().canPerformActionInWorld(event.getBlock().getWorld())) return; + // Ignoring air blocks + if (CMIMaterial.isAir(event.getToBlock().getType())) + return; + if (CMIMaterial.isWater(event.getBlock().getType())) return; - - if (Jobs.getGCManager().useNewBlockProtection) { - Jobs.getExploitManager().remove(event.getToBlock()); - } else - Jobs.getBpManager().remove(event.getToBlock()); + + CMIDebug.d(event.getBlock().getType(), event.getToBlock().getType()); + + Jobs.getExploitManager().remove(event.getToBlock()); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)