From 22d8f0d1fb694f1d1ae5a85ad2e62ba3d2ab2e88 Mon Sep 17 00:00:00 2001 From: OmerBenGera Date: Fri, 13 Jan 2023 16:48:36 +0200 Subject: [PATCH] Fixed chunk loaders can be placed next to each other and overlap chunks (#64) --- .../wildloaders/handlers/DataHandler.java | 22 ++++--- .../wildloaders/handlers/LoadersHandler.java | 12 ++-- .../wildloaders/listeners/BlocksListener.java | 58 ++++++++++--------- .../wildloaders/loaders/WChunkLoader.java | 40 +------------ .../wildloaders/utils/ChunkLoaderChunks.java | 55 ++++++++++++++++++ 5 files changed, 111 insertions(+), 76 deletions(-) create mode 100644 src/main/java/com/bgsoftware/wildloaders/utils/ChunkLoaderChunks.java diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java index 1a34fed..cf89937 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/DataHandler.java @@ -2,15 +2,18 @@ package com.bgsoftware.wildloaders.handlers; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.loaders.LoaderData; +import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.utils.ServerVersion; import com.bgsoftware.wildloaders.utils.database.Database; import com.bgsoftware.wildloaders.utils.locations.LocationUtils; import com.bgsoftware.wildloaders.utils.threads.Executor; import org.bukkit.Bukkit; +import org.bukkit.Chunk; import org.bukkit.Location; import org.bukkit.Material; import java.io.File; +import java.util.List; import java.util.Optional; import java.util.UUID; @@ -18,20 +21,20 @@ public final class DataHandler { private final WildLoadersPlugin plugin; - public DataHandler(WildLoadersPlugin plugin){ + public DataHandler(WildLoadersPlugin plugin) { this.plugin = plugin; Executor.sync(() -> { try { Database.start(new File(plugin.getDataFolder(), "database.db")); loadDatabase(); - }catch (Exception ex){ + } catch (Exception ex) { ex.printStackTrace(); Bukkit.getPluginManager().disablePlugin(plugin); } }, 2L); } - public void loadDatabase(){ + public void loadDatabase() { Database.executeUpdate("CREATE TABLE IF NOT EXISTS npc_identifiers (location TEXT NOT NULL PRIMARY KEY, uuid TEXT NOT NULL);"); Database.executeQuery("SELECT * FROM npc_identifiers;", resultSet -> { while (resultSet.next()) { @@ -43,27 +46,30 @@ public final class DataHandler { Database.executeUpdate("CREATE TABLE IF NOT EXISTS chunk_loaders (location TEXT NOT NULL PRIMARY KEY, placer TEXT NOT NULL, loader_data TEXT NOT NULL, timeLeft BIGINT NOT NULL);"); Database.executeQuery("SELECT * FROM chunk_loaders;", resultSet -> { - while(resultSet.next()){ + while (resultSet.next()) { Location location = LocationUtils.getLocation(resultSet.getString("location")); UUID placer = UUID.fromString(resultSet.getString("placer")); Optional loaderData = plugin.getLoaders().getLoaderData(resultSet.getString("loader_data")); long timeLeft = resultSet.getLong("timeLeft"); - if(!loaderData.isPresent()) + if (!loaderData.isPresent()) continue; Material blockType = location.getBlock().getType(); - if(ServerVersion.isLegacy() && blockType == Material.CAULDRON){ + if (ServerVersion.isLegacy() && blockType == Material.CAULDRON) { blockType = Material.CAULDRON_ITEM; } - if(blockType != loaderData.get().getLoaderItem().getType()){ + if (blockType != loaderData.get().getLoaderItem().getType()) { WildLoadersPlugin.log("The chunk-loader at " + LocationUtils.getLocation(location) + " is invalid."); continue; } - plugin.getLoaders().addChunkLoader(loaderData.get(), placer, location, timeLeft); + List chunksToLoad = ChunkLoaderChunks.calculateChunks(loaderData.get(), placer, location); + chunksToLoad.removeIf(chunk -> plugin.getLoaders().getChunkLoader(chunk).isPresent()); + + plugin.getLoaders().addChunkLoaderWithoutDBSave(loaderData.get(), placer, location, timeLeft, chunksToLoad); } }); } diff --git a/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java b/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java index ae78c08..598692d 100644 --- a/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java +++ b/src/main/java/com/bgsoftware/wildloaders/handlers/LoadersHandler.java @@ -1,11 +1,12 @@ package com.bgsoftware.wildloaders.handlers; import com.bgsoftware.wildloaders.WildLoadersPlugin; -import com.bgsoftware.wildloaders.api.managers.LoadersManager; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.LoaderData; +import com.bgsoftware.wildloaders.api.managers.LoadersManager; import com.bgsoftware.wildloaders.loaders.WChunkLoader; import com.bgsoftware.wildloaders.loaders.WLoaderData; +import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition; import com.bgsoftware.wildloaders.utils.database.Query; import com.google.common.collect.Maps; @@ -28,7 +29,7 @@ public final class LoadersHandler implements LoadersManager { private final Map loadersData = Maps.newConcurrentMap(); private final WildLoadersPlugin plugin; - public LoadersHandler(WildLoadersPlugin plugin){ + public LoadersHandler(WildLoadersPlugin plugin) { this.plugin = plugin; } @@ -59,7 +60,8 @@ public final class LoadersHandler implements LoadersManager { @Override public ChunkLoader addChunkLoader(LoaderData loaderData, Player whoPlaced, Location location, long timeLeft) { - WChunkLoader chunkLoader = addChunkLoader(loaderData, whoPlaced.getUniqueId(), location, timeLeft); + WChunkLoader chunkLoader = addChunkLoaderWithoutDBSave(loaderData, whoPlaced.getUniqueId(), location, timeLeft, + ChunkLoaderChunks.calculateChunks(loaderData, whoPlaced.getUniqueId(), location)); Query.INSERT_CHUNK_LOADER.insertParameters() .setLocation(location) @@ -71,8 +73,8 @@ public final class LoadersHandler implements LoadersManager { return chunkLoader; } - public WChunkLoader addChunkLoader(LoaderData loaderData, UUID placer, Location location, long timeLeft){ - WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, location, timeLeft); + public WChunkLoader addChunkLoaderWithoutDBSave(LoaderData loaderData, UUID placer, Location location, long timeLeft, List loadedChunks) { + WChunkLoader chunkLoader = new WChunkLoader(loaderData, placer, location, loadedChunks.toArray(new Chunk[0]), timeLeft); chunkLoaders.put(location, chunkLoader); for (Chunk loadedChunk : chunkLoader.getLoadedChunks()) { chunkLoadersByChunks.put(ChunkPosition.of(loadedChunk), chunkLoader); diff --git a/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java b/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java index bce2571..c2523d9 100644 --- a/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java +++ b/src/main/java/com/bgsoftware/wildloaders/listeners/BlocksListener.java @@ -4,8 +4,10 @@ import com.bgsoftware.wildloaders.Locale; import com.bgsoftware.wildloaders.WildLoadersPlugin; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.LoaderData; +import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.utils.chunks.ChunkPosition; import com.bgsoftware.wildloaders.utils.legacy.Materials; +import org.bukkit.Chunk; import org.bukkit.GameMode; import org.bukkit.Location; import org.bukkit.block.Block; @@ -27,32 +29,34 @@ public final class BlocksListener implements Listener { private final WildLoadersPlugin plugin; - public BlocksListener(WildLoadersPlugin plugin){ + public BlocksListener(WildLoadersPlugin plugin) { this.plugin = plugin; } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onLoaderPlace(BlockPlaceEvent e){ + public void onLoaderPlace(BlockPlaceEvent e) { String loaderName = plugin.getNMSAdapter().getTag(e.getItemInHand(), "loader-name", ""); Optional optionalLoaderData = plugin.getLoaders().getLoaderData(loaderName); - if(!optionalLoaderData.isPresent()) + if (!optionalLoaderData.isPresent()) return; - if(!e.getPlayer().hasPermission("wildloaders.use")) { + if (!e.getPlayer().hasPermission("wildloaders.use")) { e.setCancelled(true); Locale.NO_PLACE_PERMISSION.send(e.getPlayer()); return; } - if(plugin.getLoaders().getChunkLoader(e.getBlock().getLocation().getChunk()).isPresent()){ - e.setCancelled(true); - Locale.ALREADY_LOADED.send(e.getPlayer()); - return; - } - LoaderData loaderData = optionalLoaderData.get(); + for (Chunk chunk : ChunkLoaderChunks.calculateChunks(loaderData, e.getPlayer().getUniqueId(), e.getBlock().getLocation())) { + if (plugin.getLoaders().getChunkLoader(chunk).isPresent()) { + e.setCancelled(true); + Locale.ALREADY_LOADED.send(e.getPlayer()); + return; + } + } + long timeLeft = plugin.getNMSAdapter().getTag(e.getItemInHand(), "loader-time", loaderData.getTimeLeft()); plugin.getLoaders().addChunkLoader(loaderData, e.getPlayer(), e.getBlock().getLocation(), timeLeft); @@ -61,33 +65,33 @@ public final class BlocksListener implements Listener { } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onLoaderBreak(BlockBreakEvent e){ - if(handleLoaderBreak(e.getBlock(), e.getPlayer().getGameMode() != GameMode.CREATIVE)) + public void onLoaderBreak(BlockBreakEvent e) { + if (handleLoaderBreak(e.getBlock(), e.getPlayer().getGameMode() != GameMode.CREATIVE)) Locale.BROKE_LOADER.send(e.getPlayer()); } @EventHandler(priority = EventPriority.HIGHEST, ignoreCancelled = true) - public void onLoaderExplode(EntityExplodeEvent e){ + public void onLoaderExplode(EntityExplodeEvent e) { e.blockList().removeIf(block -> handleLoaderBreak(block, true)); } @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true) - public void onSpawnerPlace(BlockPlaceEvent e){ - if(e.getBlock().getType() != Materials.SPAWNER.toBukkitType()) + public void onSpawnerPlace(BlockPlaceEvent e) { + if (e.getBlock().getType() != Materials.SPAWNER.toBukkitType()) return; - if(!plugin.getLoaders().getChunkLoader(e.getBlock().getChunk()).isPresent()) + if (!plugin.getLoaders().getChunkLoader(e.getBlock().getChunk()).isPresent()) return; plugin.getNMSAdapter().updateSpawner(e.getBlock().getLocation(), false); } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) - public void onLoaderInteract(PlayerInteractEvent e){ - if(e.getAction() != Action.RIGHT_CLICK_BLOCK) + public void onLoaderInteract(PlayerInteractEvent e) { + if (e.getAction() != Action.RIGHT_CLICK_BLOCK) return; - if(plugin.getLoaders().getChunkLoader(e.getClickedBlock().getLocation()).isPresent()) + if (plugin.getLoaders().getChunkLoader(e.getClickedBlock().getLocation()).isPresent()) e.setCancelled(true); } @@ -95,37 +99,39 @@ public final class BlocksListener implements Listener { public void onLoaderPistonRetract(BlockPistonRetractEvent e) { try { for (Block block : e.getBlocks()) { - if(plugin.getLoaders().getChunkLoader(block.getLocation()).isPresent()) { + if (plugin.getLoaders().getChunkLoader(block.getLocation()).isPresent()) { e.setCancelled(true); return; } } - } catch (Throwable ignored) {} + } catch (Throwable ignored) { + } } @EventHandler(priority = EventPriority.LOWEST, ignoreCancelled = true) public void onLoaderPistonExtend(BlockPistonExtendEvent e) { try { for (Block block : e.getBlocks()) { - if(plugin.getLoaders().getChunkLoader(block.getLocation()).isPresent()) { + if (plugin.getLoaders().getChunkLoader(block.getLocation()).isPresent()) { e.setCancelled(true); return; } } - } catch (Throwable ignored) {} + } catch (Throwable ignored) { + } } - private boolean handleLoaderBreak(Block block, boolean dropItem){ + private boolean handleLoaderBreak(Block block, boolean dropItem) { Location blockLoc = block.getLocation(); Optional optionalChunkLoader = plugin.getLoaders().getChunkLoader(blockLoc); - if(!optionalChunkLoader.isPresent()) + if (!optionalChunkLoader.isPresent()) return false; ChunkLoader chunkLoader = optionalChunkLoader.get(); chunkLoader.remove(); - if(dropItem) + if (dropItem) blockLoc.getWorld().dropItemNaturally(blockLoc, chunkLoader.getLoaderItem()); return true; diff --git a/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java b/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java index dd155f2..bc04431 100644 --- a/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java +++ b/src/main/java/com/bgsoftware/wildloaders/loaders/WChunkLoader.java @@ -5,6 +5,7 @@ import com.bgsoftware.wildloaders.api.holograms.Hologram; import com.bgsoftware.wildloaders.api.loaders.ChunkLoader; import com.bgsoftware.wildloaders.api.loaders.LoaderData; import com.bgsoftware.wildloaders.api.npc.ChunkLoaderNPC; +import com.bgsoftware.wildloaders.utils.ChunkLoaderChunks; import com.bgsoftware.wildloaders.utils.database.Query; import com.bgsoftware.wildloaders.utils.threads.Executor; import org.bukkit.Bukkit; @@ -14,7 +15,6 @@ import org.bukkit.Material; import org.bukkit.OfflinePlayer; import org.bukkit.inventory.ItemStack; -import java.util.ArrayList; import java.util.Collection; import java.util.List; import java.util.Optional; @@ -33,11 +33,11 @@ public final class WChunkLoader implements ChunkLoader { private boolean active = true; private long timeLeft; - public WChunkLoader(LoaderData loaderData, UUID whoPlaced, Location location, long timeLeft) { + public WChunkLoader(LoaderData loaderData, UUID whoPlaced, Location location, Chunk[] loadedChunks, long timeLeft) { this.loaderName = loaderData.getName(); this.whoPlaced = whoPlaced; this.location = location.clone(); - this.loadedChunks = calculateChunks(loaderData, whoPlaced, this.location); + this.loadedChunks = loadedChunks; this.timeLeft = timeLeft; this.tileEntityChunkLoader = plugin.getNMSAdapter().createLoader(this); } @@ -125,39 +125,5 @@ public final class WChunkLoader implements ChunkLoader { return isInfinite() ? plugin.getSettings().infiniteHologramLines : plugin.getSettings().hologramLines; } - private static Chunk[] calculateChunks(LoaderData loaderData, UUID whoPlaced, Location original) { - List chunkList = new ArrayList<>(); - - if (loaderData.isChunksSpread()) { - calculateClaimChunks(original.getChunk(), whoPlaced, chunkList); - } - - if (chunkList.isEmpty()) { - int chunkX = original.getBlockX() >> 4, chunkZ = original.getBlockZ() >> 4; - - for (int x = -loaderData.getChunksRadius(); x <= loaderData.getChunksRadius(); x++) - for (int z = -loaderData.getChunksRadius(); z <= loaderData.getChunksRadius(); z++) - chunkList.add(original.getWorld().getChunkAt(chunkX + x, chunkZ + z)); - } - - return chunkList.toArray(new Chunk[0]); - } - - private static void calculateClaimChunks(Chunk originalChunk, UUID whoPlaced, List chunkList) { - if (!plugin.getProviders().hasChunkAccess(whoPlaced, originalChunk)) - return; - - chunkList.add(originalChunk); - - int chunkX = originalChunk.getX(), chunkZ = originalChunk.getZ(); - - for (int x = -1; x <= 1; x++) { - for (int z = -1; z <= 1; z++) { - if (x != 0 || z != 0) // We don't want to add the originalChunk again. - calculateClaimChunks(originalChunk.getWorld().getChunkAt(chunkX + x, chunkZ + z), whoPlaced, chunkList); - } - } - - } } diff --git a/src/main/java/com/bgsoftware/wildloaders/utils/ChunkLoaderChunks.java b/src/main/java/com/bgsoftware/wildloaders/utils/ChunkLoaderChunks.java new file mode 100644 index 0000000..1702e8b --- /dev/null +++ b/src/main/java/com/bgsoftware/wildloaders/utils/ChunkLoaderChunks.java @@ -0,0 +1,55 @@ +package com.bgsoftware.wildloaders.utils; + +import com.bgsoftware.wildloaders.WildLoadersPlugin; +import com.bgsoftware.wildloaders.api.loaders.LoaderData; +import org.bukkit.Chunk; +import org.bukkit.Location; + +import java.util.LinkedList; +import java.util.List; +import java.util.UUID; + +public class ChunkLoaderChunks { + + private static final WildLoadersPlugin plugin = WildLoadersPlugin.getPlugin(); + + private ChunkLoaderChunks() { + + } + + public static List calculateChunks(LoaderData loaderData, UUID whoPlaced, Location original) { + List chunkList = new LinkedList<>(); + + if (loaderData.isChunksSpread()) { + calculateClaimChunksRecursive(original.getChunk(), whoPlaced, chunkList); + } + + if (chunkList.isEmpty()) { + int chunkX = original.getBlockX() >> 4, chunkZ = original.getBlockZ() >> 4; + + for (int x = -loaderData.getChunksRadius(); x <= loaderData.getChunksRadius(); x++) + for (int z = -loaderData.getChunksRadius(); z <= loaderData.getChunksRadius(); z++) + chunkList.add(original.getWorld().getChunkAt(chunkX + x, chunkZ + z)); + } + + return chunkList; + } + + private static void calculateClaimChunksRecursive(Chunk originalChunk, UUID whoPlaced, List chunkList) { + if (!plugin.getProviders().hasChunkAccess(whoPlaced, originalChunk)) + return; + + chunkList.add(originalChunk); + + int chunkX = originalChunk.getX(), chunkZ = originalChunk.getZ(); + + for (int x = -1; x <= 1; x++) { + for (int z = -1; z <= 1; z++) { + if (x != 0 || z != 0) // We don't want to add the originalChunk again. + calculateClaimChunksRecursive(originalChunk.getWorld().getChunkAt(chunkX + x, chunkZ + z), whoPlaced, chunkList); + } + } + + } + +}