From d09c2240f9924ada342dc7b779c244cad47ed15e Mon Sep 17 00:00:00 2001 From: Llm Dl Date: Thu, 30 Jun 2022 11:41:24 -0500 Subject: [PATCH] Add unclaimEntityTypeDelete to TownyWorld. Allows Towny to delete all Entities of a given type from a TownBlock when it is unclaimed by a town. New Config Options: - new_world_settings.plot_management.entity_delete.enabled - Default: false - new_world_settings.plot_management.entity_delete.unclaim_delete - Default: "ENDERCRYSTAL" - These entities will be deleted upon a plot being unclaimed Closes #5953. --- .../bukkit/config/ConfigNodes.java | 14 +++++ .../bukkit/towny/TownySettings.java | 8 +++ .../bukkit/towny/db/SQL_Schema.java | 2 + .../bukkit/towny/db/TownyDatabaseHandler.java | 2 + .../bukkit/towny/db/TownyFlatFileSource.java | 26 +++++++++ .../bukkit/towny/db/TownySQLSource.java | 24 ++++++++ .../bukkit/towny/object/TownyWorld.java | 22 +++++++ .../bukkit/towny/regen/TownyRegenAPI.java | 58 +++++++++++++++++++ .../towny/tasks/RepeatingTimerTask.java | 4 ++ 9 files changed, 160 insertions(+) diff --git a/src/com/palmergames/bukkit/config/ConfigNodes.java b/src/com/palmergames/bukkit/config/ConfigNodes.java index b1a535bb9c..f91b05fb9d 100644 --- a/src/com/palmergames/bukkit/config/ConfigNodes.java +++ b/src/com/palmergames/bukkit/config/ConfigNodes.java @@ -406,6 +406,20 @@ public enum ConfigNodes { "", "# These items will be deleted upon a plot being unclaimed"), + NWS_PLOT_MANAGEMENT_ENTITY_DELETE_HEADER( + "new_world_settings.plot_management.entity_delete", + "", + "", + "# This section is applied to new worlds as default settings when new worlds are detected."), + NWS_PLOT_MANAGEMENT_ENTITY_DELETE_ENABLE( + "new_world_settings.plot_management.entity_delete.enabled", + "false"), + NWS_PLOT_MANAGEMENT_ENTITY_DELETE( + "new_world_settings.plot_management.entity_delete.unclaim_delete", + "ENDERCRYSTAL", + "", + "# These entities will be deleted upon a plot being unclaimed"), + NWS_PLOT_MANAGEMENT_MAYOR_DELETE_HEADER( "new_world_settings.plot_management.mayor_plotblock_delete", "", diff --git a/src/com/palmergames/bukkit/towny/TownySettings.java b/src/com/palmergames/bukkit/towny/TownySettings.java index 4be799928b..03015b5c02 100644 --- a/src/com/palmergames/bukkit/towny/TownySettings.java +++ b/src/com/palmergames/bukkit/towny/TownySettings.java @@ -2047,6 +2047,14 @@ public static boolean isForcingFire() { return getBoolean(ConfigNodes.NWS_FORCE_FIRE_ON); } + public static boolean isDeletingEntitiesOnUnclaim() { + return getBoolean(ConfigNodes.NWS_PLOT_MANAGEMENT_ENTITY_DELETE_ENABLE); + } + + public static EnumSet getUnclaimDeleteEntityTypes() { + return toEntityTypeEnumSet(getStrArr(ConfigNodes.NWS_PLOT_MANAGEMENT_ENTITY_DELETE)); + } + public static boolean isUsingPlotManagementDelete() { return getBoolean(ConfigNodes.NWS_PLOT_MANAGEMENT_DELETE_ENABLE); diff --git a/src/com/palmergames/bukkit/towny/db/SQL_Schema.java b/src/com/palmergames/bukkit/towny/db/SQL_Schema.java index 042f4e8ece..209d953d90 100644 --- a/src/com/palmergames/bukkit/towny/db/SQL_Schema.java +++ b/src/com/palmergames/bukkit/towny/db/SQL_Schema.java @@ -50,6 +50,8 @@ private static List getWorldColumns() { columns.add("`unclaimedZoneIgnoreIds` mediumtext NOT NULL"); columns.add("`usingPlotManagementDelete` bool NOT NULL DEFAULT '0'"); columns.add("`plotManagementDeleteIds` mediumtext NOT NULL"); + columns.add("`isDeletingEntitiesOnUnclaim` bool NOT NULL DEFAULT '0'"); + columns.add("`unclaimDeleteEntityTypes` mediumtext NOT NULL"); columns.add("`usingPlotManagementMayorDelete` bool NOT NULL DEFAULT '0'"); columns.add("`plotManagementMayorDelete` mediumtext NOT NULL"); columns.add("`usingPlotManagementRevert` bool NOT NULL DEFAULT '0'"); diff --git a/src/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java b/src/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java index 15e043b016..75ba580b54 100644 --- a/src/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java +++ b/src/com/palmergames/bukkit/towny/db/TownyDatabaseHandler.java @@ -469,6 +469,8 @@ public void removeTownBlock(TownBlock townBlock) { universe.removeTownBlock(townBlock); deleteTownBlock(townBlock); + if (townBlock.getWorld().isDeletingEntitiesOnUnclaim()) + TownyRegenAPI.addDeleteTownBlockEntityQueue(townBlock.getWorldCoord()); if (townBlock.getWorld().isUsingPlotManagementDelete()) TownyRegenAPI.addDeleteTownBlockIdQueue(townBlock.getWorldCoord()); diff --git a/src/com/palmergames/bukkit/towny/db/TownyFlatFileSource.java b/src/com/palmergames/bukkit/towny/db/TownyFlatFileSource.java index 266f98c842..61886e81a5 100644 --- a/src/com/palmergames/bukkit/towny/db/TownyFlatFileSource.java +++ b/src/com/palmergames/bukkit/towny/db/TownyFlatFileSource.java @@ -1330,6 +1330,25 @@ public boolean loadWorld(TownyWorld world) { } catch (Exception ignored) { } + line = keys.get("isDeletingEntitiesOnUnclaim"); + if (line != null) + try { + world.setDeletingEntitiesOnUnclaim(Boolean.parseBoolean(line)); + } catch (Exception ignored) { + } + + line = keys.get("unclaimDeleteEntityTypes"); + if (line != null) + try { + List entityTypes = new ArrayList<>(); + for (String s : line.split(",")) + if (!s.isEmpty()) + entityTypes.add(s); + + world.setUnclaimDeleteEntityTypes(entityTypes); + } catch (Exception ignored) { + } + line = keys.get("usingPlotManagementDelete"); if (line != null) try { @@ -2139,6 +2158,13 @@ public boolean saveWorld(TownyWorld world) { if (world.getPlotManagementDeleteIds() != null) list.add("plotManagementDeleteIds=" + StringMgmt.join(world.getPlotManagementDeleteIds(), ",")); + // EntityType removal on unclaim. + list.add(""); + list.add("# The following settings control what EntityTypes are deleted upon a townblock being unclaimed"); + list.add("isDeletingEntitiesOnUnclaim=" + world.isDeletingEntitiesOnUnclaim()); + if (world.getUnclaimDeleteEntityTypes() != null) + list.add("unclaimDeleteEntityTypes=" + StringMgmt.join(world.getUnclaimDeleteEntityTypes(), ",")); + // PlotManagement list.add(""); list.add("# The following settings control what blocks are deleted upon a mayor issuing a '/plot clear' command"); diff --git a/src/com/palmergames/bukkit/towny/db/TownySQLSource.java b/src/com/palmergames/bukkit/towny/db/TownySQLSource.java index 43247b5039..9e480e67c9 100644 --- a/src/com/palmergames/bukkit/towny/db/TownySQLSource.java +++ b/src/com/palmergames/bukkit/towny/db/TownySQLSource.java @@ -1535,6 +1535,25 @@ private boolean loadWorld(ResultSet rs) { } catch (Exception ignored) { } + result = rs.getBoolean("isDeletingEntitiesOnUnclaim"); + try { + world.setDeletingEntitiesOnUnclaim(result); + } catch (Exception ignored) { + } + + line = rs.getString("unclaimDeleteEntityTypes"); + if (line != null) + try { + List entityTypes = new ArrayList<>(); + search = (line.contains("#")) ? "#" : ","; + for (String split : line.split(search)) + if (!split.isEmpty()) + entityTypes.add(split); + + world.setUnclaimDeleteEntityTypes(entityTypes); + } catch (Exception ignored) { + } + result = rs.getBoolean("usingPlotManagementDelete"); try { world.setUsingPlotManagementDelete(result); @@ -2312,6 +2331,11 @@ public synchronized boolean saveWorld(TownyWorld world) { if (world.getUnclaimedZoneIgnoreMaterials() != null) nat_hm.put("unclaimedZoneIgnoreIds", StringMgmt.join(world.getUnclaimedZoneIgnoreMaterials(), "#")); + // Deleting EntityTypes from Townblocks on Unclaim. + nat_hm.put("isDeletingEntitiesOnUnclaim", world.isDeletingEntitiesOnUnclaim()); + if (world.getUnclaimDeleteEntityTypes() != null) + nat_hm.put("unclaimDeleteEntityTypes", StringMgmt.join(world.getUnclaimDeleteEntityTypes(), "#")); + // Using PlotManagement Delete nat_hm.put("usingPlotManagementDelete", world.isUsingPlotManagementDelete()); // Plot Management Delete Ids diff --git a/src/com/palmergames/bukkit/towny/object/TownyWorld.java b/src/com/palmergames/bukkit/towny/object/TownyWorld.java index 6eaec5b6e3..2cad59e9f5 100644 --- a/src/com/palmergames/bukkit/towny/object/TownyWorld.java +++ b/src/com/palmergames/bukkit/towny/object/TownyWorld.java @@ -27,6 +27,9 @@ public class TownyWorld extends TownyObject { private HashMap towns = new HashMap<>(); + private boolean isDeletingEntitiesOnUnclaim = TownySettings.isDeletingEntitiesOnUnclaim(); + private EnumSet unclaimDeleteEntityTypes = null; + private boolean isUsingPlotManagementDelete = TownySettings.isUsingPlotManagementDelete(); private EnumSet plotManagementDeleteIds = null; @@ -319,6 +322,25 @@ public boolean isUsingPlotManagementDelete() { return isUsingPlotManagementDelete; } + public void setDeletingEntitiesOnUnclaim(boolean using) { + isDeletingEntitiesOnUnclaim = using; + } + + public boolean isDeletingEntitiesOnUnclaim() { + return isDeletingEntitiesOnUnclaim; + } + + public EnumSet getUnclaimDeleteEntityTypes() { + if (unclaimDeleteEntityTypes == null) + return TownySettings.getUnclaimDeleteEntityTypes(); + else + return unclaimDeleteEntityTypes; + } + + public void setUnclaimDeleteEntityTypes(List entityTypes) { + this.unclaimDeleteEntityTypes = TownySettings.toEntityTypeEnumSet(entityTypes); + } + public void setUsingPlotManagementMayorDelete(boolean using) { isUsingPlotManagementMayorDelete = using; diff --git a/src/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java b/src/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java index ede0aaf6b0..0909ab8c11 100644 --- a/src/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java +++ b/src/com/palmergames/bukkit/towny/regen/TownyRegenAPI.java @@ -14,11 +14,13 @@ import org.bukkit.Material; import org.bukkit.World; import org.bukkit.block.Block; +import org.bukkit.entity.Entity; import org.bukkit.event.Event; import org.bukkit.event.block.BlockExplodeEvent; import org.bukkit.event.entity.EntityExplodeEvent; import java.util.ArrayList; +import java.util.Collection; import java.util.EnumSet; import java.util.HashSet; import java.util.Hashtable; @@ -38,6 +40,9 @@ public class TownyRegenAPI { // table containing snapshot data of active reversions. private static Hashtable PlotChunks = new Hashtable<>(); + // List of all old plots still to be procesws for Entity removal + private static List deleteTownBlockEntityQueue = new ArrayList<>(); + // List of all old plots still to be processed for Block removal private static List deleteTownBlockIdQueue = new ArrayList<>(); @@ -506,6 +511,59 @@ public static String getPlotKey(WorldCoord wc) { // // } + /* + * TownBlock Entity Deleting Queue. + */ + + /** + * @return true if there are any chunks being processed. + */ + public static boolean hasDeleteTownBlockEntityQueue() { + + return !deleteTownBlockEntityQueue.isEmpty(); + } + + public static boolean isDeleteTownBlockEntityQueue(WorldCoord plot) { + + return deleteTownBlockEntityQueue.contains(plot); + } + + public static void addDeleteTownBlockEntityQueue(WorldCoord plot) { + if (!deleteTownBlockEntityQueue.contains(plot)) + deleteTownBlockEntityQueue.add(plot); + } + + public static WorldCoord getDeleteTownBlockEntityQueue() { + + if (!deleteTownBlockEntityQueue.isEmpty()) { + WorldCoord wc = deleteTownBlockEntityQueue.get(0); + deleteTownBlockEntityQueue.remove(0); + return wc; + } + return null; + } + + + /** + * Deletes all of a specified entity type from a TownBlock + * + * @param worldCoord - WorldCoord for the Town Block + */ + public static void doDeleteTownBlockEntities(WorldCoord worldCoord) { + TownyWorld world = worldCoord.getTownyWorld(); + if (!world.isDeletingEntitiesOnUnclaim()) + return; + List toRemove = new ArrayList<>(); + Collection entities = worldCoord.getBukkitWorld().getNearbyEntities(worldCoord.getBoundingBox()); + for (Entity entity : entities) { + if (world.getUnclaimDeleteEntityTypes().contains(entity.getType())) + toRemove.add(entity); + } + + for (Entity entity : toRemove) + entity.remove(); + } + /* * TownBlock Material Deleting Queue. */ diff --git a/src/com/palmergames/bukkit/towny/tasks/RepeatingTimerTask.java b/src/com/palmergames/bukkit/towny/tasks/RepeatingTimerTask.java index f49605c906..f752e67584 100644 --- a/src/com/palmergames/bukkit/towny/tasks/RepeatingTimerTask.java +++ b/src/com/palmergames/bukkit/towny/tasks/RepeatingTimerTask.java @@ -34,6 +34,10 @@ public void run() { makeNextPlotSnapshot(); } + // Perform the next plot_management entity_delete + if (TownyRegenAPI.hasDeleteTownBlockEntityQueue()) + TownyRegenAPI.doDeleteTownBlockEntities(TownyRegenAPI.getDeleteTownBlockEntityQueue()); + // Perform the next plot_management block_delete if (TownyRegenAPI.hasDeleteTownBlockIdQueue()) { TownyRegenAPI.doDeleteTownBlockIds(TownyRegenAPI.getDeleteTownBlockIdQueue());