From 3a117feb3cefd62f68ae35ada16bed9d5c3b15eb Mon Sep 17 00:00:00 2001 From: Referix Date: Thu, 18 Sep 2025 17:44:10 +0300 Subject: [PATCH 1/4] Start work refactor --- src/main/java/dev/lotus/studio/Main.java | 16 +++---- .../dev/lotus/studio/command/MainCommand.java | 6 +-- .../lotus/studio/command/SafeZoneCommand.java | 46 +++++++++++-------- .../studio/database/DatabaseInitializer.java | 18 +++----- ...itory.java => SafeZoneDataRepository.java} | 4 +- ...aService.java => SafeZoneDataService.java} | 2 +- ...Impl.java => SafeZoneDataServiceImpl.java} | 18 ++++---- .../dev/lotus/studio/safezone/SafeZone.java | 4 -- .../studio/safezone/SafeZoneManager.java | 33 +++++++------ .../dev/lotus/studio/utils/MapperUtils.java | 13 ++++++ 10 files changed, 89 insertions(+), 71 deletions(-) rename src/main/java/dev/lotus/studio/database/savezone/{SaveZoneDataRepository.java => SafeZoneDataRepository.java} (96%) rename src/main/java/dev/lotus/studio/database/savezone/{SaveZoneDataService.java => SafeZoneDataService.java} (90%) rename src/main/java/dev/lotus/studio/database/savezone/{SaveZoneDataServiceImpl.java => SafeZoneDataServiceImpl.java} (80%) create mode 100644 src/main/java/dev/lotus/studio/utils/MapperUtils.java diff --git a/src/main/java/dev/lotus/studio/Main.java b/src/main/java/dev/lotus/studio/Main.java index 14a127e..d4c58c2 100644 --- a/src/main/java/dev/lotus/studio/Main.java +++ b/src/main/java/dev/lotus/studio/Main.java @@ -1,13 +1,10 @@ package dev.lotus.studio; -import com.j256.ormlite.support.ConnectionSource; import dev.lotus.studio.database.DatabaseInitializer; import dev.lotus.studio.database.playerdata.PlayerDataService; import org.bukkit.event.HandlerList; import org.bukkit.plugin.java.JavaPlugin; -import dev.lotus.studio.database.playerdata.PlayerDataServiceImpl; -import dev.lotus.studio.database.savezone.SaveZoneDataService; -import dev.lotus.studio.database.savezone.SaveZoneDataServiceImpl; +import dev.lotus.studio.database.savezone.SafeZoneDataService; import dev.lotus.studio.event.EatEvent; import dev.lotus.studio.event.JoinLeaveEvent; import dev.lotus.studio.item.CustomItemManager; @@ -17,8 +14,6 @@ import dev.lotus.studio.playerdata.PlayerManager; import dev.lotus.studio.safezone.SafeZoneManager; -import java.sql.SQLException; - public final class Main extends JavaPlugin { private static Main instance; @@ -28,7 +23,7 @@ public final class Main extends JavaPlugin { private PlayerDataService playerDataBase; - private SaveZoneDataService saveZoneDataService; + private SafeZoneDataService safeZoneDataService; private DatabaseInitializer databaseInitializer; @@ -42,7 +37,7 @@ public void onEnable() { itemManager = new CustomItemManager(); databaseInitializer = new DatabaseInitializer(this); playerDataBase = databaseInitializer.getPlayerDataBase(); - saveZoneDataService = databaseInitializer.getSaveZoneDataService(); + safeZoneDataService = databaseInitializer.getSaveZoneDataService(); @@ -55,15 +50,16 @@ public void onEnable() { new PlayerBar(this,itemManager); - new MainCommand("lotus", itemManager,saveZoneDataService); + new MainCommand("lotus", itemManager); - SafeZoneManager.getInstance().initializeZones(saveZoneDataService); + SafeZoneManager.getInstance().initializeZones(safeZoneDataService); } @Override public void onDisable() { PlayerManager.getInstance().getGlobalTask().cancel(); + SafeZoneManager.getInstance().saveAllSafeZoneToDatabase(); // Закриття DataBase if (databaseInitializer != null) { databaseInitializer.closeConnection(); diff --git a/src/main/java/dev/lotus/studio/command/MainCommand.java b/src/main/java/dev/lotus/studio/command/MainCommand.java index da7256f..568e037 100644 --- a/src/main/java/dev/lotus/studio/command/MainCommand.java +++ b/src/main/java/dev/lotus/studio/command/MainCommand.java @@ -4,7 +4,7 @@ import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.bukkit.inventory.ItemStack; -import dev.lotus.studio.database.savezone.SaveZoneDataService; +import dev.lotus.studio.database.savezone.SafeZoneDataService; import dev.lotus.studio.item.CustomItemManager; import java.util.ArrayList; @@ -14,10 +14,10 @@ public class MainCommand extends AbstractCommand { private final CustomItemManager itemManager; private final SafeZoneCommand saveZoneCommand; - public MainCommand(String command, CustomItemManager itemManager, SaveZoneDataService saveZoneDataService) { + public MainCommand(String command, CustomItemManager itemManager ) { super(command); this.itemManager = itemManager; - this.saveZoneCommand =new SafeZoneCommand(saveZoneDataService); + this.saveZoneCommand =new SafeZoneCommand(); } @Override diff --git a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java index 2b15641..4b2a36d 100644 --- a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java +++ b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java @@ -1,23 +1,28 @@ package dev.lotus.studio.command; +import dev.lotus.studio.safezone.SafeZone; +import dev.lotus.studio.safezone.SafeZoneManager; +import net.kyori.adventure.text.Component; +import org.apache.commons.lang3.tuple.ImmutablePair; +import org.apache.commons.lang3.tuple.Pair; import org.bukkit.Location; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; -import dev.lotus.studio.database.savezone.SafeZoneDataBase; -import dev.lotus.studio.database.savezone.SaveZoneDataService; import java.util.HashMap; import java.util.List; +import static dev.lotus.studio.utils.MapperUtils.formatLocation; + public class SafeZoneCommand { - private final SaveZoneDataService service; + private SafeZoneManager safeZoneManager = SafeZoneManager.getInstance(); + private Location pos1 = null; private Location pos2 = null; - public SafeZoneCommand(SaveZoneDataService service) { - this.service = service; + public SafeZoneCommand() { } public boolean execute(CommandSender sender, String label, String[] args) { @@ -70,17 +75,26 @@ public boolean execute(CommandSender sender, String label, String[] args) { } private void removeZoneToDB(Player player, int id) { - service.getAllSaveZones().forEach(safeZoneDataBase -> { - if (safeZoneDataBase.getSafeZoneId() == id){ - player.sendMessage("Сейв зону удаленно с названием: " + safeZoneDataBase.getSafeZoneName() + " ID: " + safeZoneDataBase.getSafeZoneId()); + List safeZones = safeZoneManager.getAllSafeZones(); + safeZones.forEach(zone -> { + if (zone.getZoneID() == id) { + safeZoneManager.removeSafeZone(id); + player.sendMessage(Component.text("Safe zone deleted!")); } }); - service.removeProtectZone(id); + + +// service.getAllSaveZones().forEach(safeZoneDataBase -> { +// if (safeZoneDataBase.getSafeZoneId() == id){ +// player.sendMessage("Сейв зону удаленно с названием: " + safeZoneDataBase.getSafeZoneName() + " ID: " + safeZoneDataBase.getSafeZoneId()); +// } +// }); +// service.removeProtectZone(id); } private void listZoneToDB(Player player) { // Отримуємо всі збережені зони з бази даних - List safeZoneDataBases = service.getAllSaveZones(); + List safeZoneDataBases = safeZoneManager.getAllSafeZones(); // Якщо зон немає, повідомляємо гравця if (safeZoneDataBases.isEmpty()) { @@ -90,7 +104,7 @@ private void listZoneToDB(Player player) { // Формуємо мапу з імен зон і їх ідентифікаторів HashMap saveId = new HashMap<>(); - safeZoneDataBases.forEach(saveZoneData -> saveId.put(saveZoneData.getSafeZoneName(), saveZoneData.getSafeZoneId())); + safeZoneDataBases.forEach(saveZoneData -> saveId.put(saveZoneData.getZoneName(), saveZoneData.getZoneID())); // Виводимо гравцю список зон player.sendMessage("Список зон:"); @@ -102,18 +116,14 @@ private void listZoneToDB(Player player) { private void saveZoneToDB(Player player, Location pos1, Location pos2, String zoneName) { if (pos1 != null && pos2 != null) { - String positionData = formatLocation(pos1) + "|" + formatLocation(pos2); - service.saveProtectZone(zoneName, positionData); + Pair zoneLoc = new ImmutablePair<>(pos1, pos2); + SafeZone safeZone = new SafeZone(zoneName,zoneLoc); + safeZoneManager.addSafeZone(safeZone); player.sendMessage("Зона '" + zoneName + "' успішно збережена."); } else { player.sendMessage("Будь ласка, спочатку встановіть обидві точки (pos1 і pos2)."); } } - private String formatLocation(Location location) { - return location.getBlockX() + "," + - location.getBlockY() + "," + - location.getBlockZ(); - } } diff --git a/src/main/java/dev/lotus/studio/database/DatabaseInitializer.java b/src/main/java/dev/lotus/studio/database/DatabaseInitializer.java index 243967e..42a33d2 100644 --- a/src/main/java/dev/lotus/studio/database/DatabaseInitializer.java +++ b/src/main/java/dev/lotus/studio/database/DatabaseInitializer.java @@ -7,8 +7,8 @@ import dev.lotus.studio.database.playerdata.PlayerDataService; import dev.lotus.studio.database.playerdata.PlayerDataServiceImpl; import dev.lotus.studio.database.savezone.SafeZoneDataBase; -import dev.lotus.studio.database.savezone.SaveZoneDataService; -import dev.lotus.studio.database.savezone.SaveZoneDataServiceImpl; +import dev.lotus.studio.database.savezone.SafeZoneDataService; +import dev.lotus.studio.database.savezone.SafeZoneDataServiceImpl; import org.bukkit.plugin.java.JavaPlugin; import java.io.File; @@ -25,7 +25,7 @@ public class DatabaseInitializer { private PlayerDataService playerDataBase; - private SaveZoneDataService saveZoneDataService; + private SafeZoneDataService safeZoneDataService; public DatabaseInitializer(JavaPlugin plugin) { this.plugin = plugin; @@ -70,17 +70,12 @@ public void initialDataService() { try { ConnectionSource connectionSource = openConnection(); this.playerDataBase = new PlayerDataServiceImpl(connectionSource); - this.saveZoneDataService = new SaveZoneDataServiceImpl(connectionSource); + this.safeZoneDataService = new SafeZoneDataServiceImpl(connectionSource); } catch (SQLException e) { throw new RuntimeException(e); } } - - - - - /** * Повертає ORMLite ConnectionSource */ @@ -127,11 +122,12 @@ public void closeConnection() { public PlayerDataService getPlayerDataBase() { return playerDataBase; } + /** * This method * @return SaveZoneDataService */ - public SaveZoneDataService getSaveZoneDataService() { - return saveZoneDataService; + public SafeZoneDataService getSaveZoneDataService() { + return safeZoneDataService; } } diff --git a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataRepository.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java similarity index 96% rename from src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataRepository.java rename to src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java index 565a97f..1c06981 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataRepository.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java @@ -11,11 +11,11 @@ import java.util.ArrayList; import java.util.List; -public class SaveZoneDataRepository { +public class SafeZoneDataRepository { private final Dao safeZoneDao; - public SaveZoneDataRepository(ConnectionSource connectionSource) throws SQLException { + public SafeZoneDataRepository(ConnectionSource connectionSource) throws SQLException { this.safeZoneDao = DaoManager.createDao(connectionSource, SafeZoneDataBase.class); } diff --git a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataService.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java similarity index 90% rename from src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataService.java rename to src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java index cf751fc..f8eede7 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataService.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java @@ -5,7 +5,7 @@ import java.util.List; -public interface SaveZoneDataService { +public interface SafeZoneDataService { void saveProtectZone(String name, String location); diff --git a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataServiceImpl.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java similarity index 80% rename from src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataServiceImpl.java rename to src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java index dfee2b6..2e1fa46 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SaveZoneDataServiceImpl.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java @@ -7,19 +7,19 @@ import java.sql.SQLException; import java.util.List; -public class SaveZoneDataServiceImpl implements SaveZoneDataService { +public class SafeZoneDataServiceImpl implements SafeZoneDataService { - private final SaveZoneDataRepository saveZoneDataRepository; + private final SafeZoneDataRepository safeZoneDataRepository; - public SaveZoneDataServiceImpl(ConnectionSource connectionSource) throws SQLException { - this.saveZoneDataRepository = new SaveZoneDataRepository(connectionSource); + public SafeZoneDataServiceImpl(ConnectionSource connectionSource) throws SQLException { + this.safeZoneDataRepository = new SafeZoneDataRepository(connectionSource); } @Override public void saveProtectZone(String name, String location) { try { SafeZoneDataBase safeZoneDataBase = new SafeZoneDataBase(name, location); - saveZoneDataRepository.saveStructureData(safeZoneDataBase); + safeZoneDataRepository.saveStructureData(safeZoneDataBase); } catch (SQLException e) { e.printStackTrace(); } @@ -28,7 +28,7 @@ public void saveProtectZone(String name, String location) { @Override public void removeProtectZone(int id) { try { - saveZoneDataRepository.removeProtectZone(id); + safeZoneDataRepository.removeProtectZone(id); } catch (SQLException e) { e.printStackTrace(); } @@ -37,7 +37,7 @@ public void removeProtectZone(int id) { @Override public List getAllSaveZones() { try { - return saveZoneDataRepository.getAllStructuresData(); + return safeZoneDataRepository.getAllStructuresData(); } catch (SQLException e) { e.printStackTrace(); return List.of(); @@ -47,7 +47,7 @@ public List getAllSaveZones() { @Override public boolean isProtectZone(Location playerLocation) { try { - List> saveZoneDataZones = saveZoneDataRepository.getSaveZoneDataZones(); + List> saveZoneDataZones = safeZoneDataRepository.getSaveZoneDataZones(); for (Pair zone : saveZoneDataZones) { if (isLocationInZone(playerLocation, zone.getLeft(), zone.getRight())) { return true; @@ -62,7 +62,7 @@ public boolean isProtectZone(Location playerLocation) { @Override public List> getSaveZones() { try { - return saveZoneDataRepository.getSaveZoneDataZones(); + return safeZoneDataRepository.getSaveZoneDataZones(); } catch (SQLException e) { e.printStackTrace(); return List.of(); diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZone.java b/src/main/java/dev/lotus/studio/safezone/SafeZone.java index 8357854..c9e6a43 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZone.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZone.java @@ -19,10 +19,6 @@ public void setZoneName(String zoneName) { this.zoneName = zoneName; } - public void setZoneID(int zoneID) { - this.zoneID = zoneID; - } - public Pair getLocationPair() { return locationPair; } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java index 137f43e..f9b1fda 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java @@ -6,25 +6,42 @@ import org.bukkit.plugin.Plugin; import dev.lotus.studio.Main; import dev.lotus.studio.database.savezone.SafeZoneDataBase; -import dev.lotus.studio.database.savezone.SaveZoneDataService; +import dev.lotus.studio.database.savezone.SafeZoneDataService; import java.util.ArrayList; import java.util.List; +import static dev.lotus.studio.utils.MapperUtils.formatLocation; + public class SafeZoneManager { private static final SafeZoneManager instance = new SafeZoneManager(); private final List safeZones = new ArrayList<>(); private final Plugin plugin = Main.getInstance(); + + private SafeZoneDataService safeZoneDataService; + public static SafeZoneManager getInstance() { return instance; } + // Добавление новой зоны public void addSafeZone(SafeZone safeZone) { safeZones.add(safeZone); } + public void saveAllSafeZoneToDatabase() { + safeZones.forEach(safeZone -> { + String positionData = formatLocation(safeZone.getLocationPair().getLeft()) + "|" + formatLocation(safeZone.getLocationPair().getRight()); + safeZoneDataService.saveProtectZone(safeZone.getZoneName(),positionData); + }); + + } + + + + // Удаление зоны по ID public boolean removeSafeZone(int zoneID) { return safeZones.removeIf(zone -> zone.getZoneID() == zoneID); @@ -38,16 +55,6 @@ public SafeZone getSafeZoneByName(String name) { .orElse(null); } - // Проверка, находится ли игрок в какой-либо зоне - public SafeZone getZoneContainingPlayer(Player player) { - Location playerLocation = player.getLocation(); - return safeZones.stream() - .filter(zone -> isLocationInZone(playerLocation, - zone.getLocationPair().getLeft(), - zone.getLocationPair().getRight())) - .findFirst() - .orElse(null); - } // Проверка, находится ли игрок в какой-либо зоне public boolean isPlayerInAnyZone(Player player) { @@ -58,8 +65,8 @@ public boolean isPlayerInAnyZone(Player player) { zone.getLocationPair().getRight())); } - public void initializeZones(SaveZoneDataService saveZoneDataService) { - List zonesData = saveZoneDataService.getAllSaveZones(); + public void initializeZones(SafeZoneDataService safeZoneDataService) { + List zonesData = safeZoneDataService.getAllSaveZones(); try { for (SafeZoneDataBase data : zonesData) { diff --git a/src/main/java/dev/lotus/studio/utils/MapperUtils.java b/src/main/java/dev/lotus/studio/utils/MapperUtils.java new file mode 100644 index 0000000..412028d --- /dev/null +++ b/src/main/java/dev/lotus/studio/utils/MapperUtils.java @@ -0,0 +1,13 @@ +package dev.lotus.studio.utils; + +import org.bukkit.Location; + +public class MapperUtils { + + + public static String formatLocation(Location location) { + return location.getBlockX() + "," + + location.getBlockY() + "," + + location.getBlockZ(); + } +} From 289e193ce7165735365af15a4960d8d33b68c166 Mon Sep 17 00:00:00 2001 From: Referix Date: Tue, 23 Sep 2025 12:55:15 +0300 Subject: [PATCH 2/4] feat: add SafeZonePreloader with lazy DB loading and caching --- build.gradle | 1 + src/main/java/dev/lotus/studio/Main.java | 5 +- .../dev/lotus/studio/command/MainCommand.java | 20 +-- .../lotus/studio/command/SafeZoneCommand.java | 94 +++++----- .../savezone/SafeZoneDataRepository.java | 65 ++++--- .../savezone/SafeZoneDataService.java | 3 + .../savezone/SafeZoneDataServiceImpl.java | 73 +++++++- .../dev/lotus/studio/safezone/SafeZone.java | 7 + .../studio/safezone/SafeZoneManager.java | 165 +++++------------- .../studio/safezone/SafeZonePreloader.java | 51 ++++++ .../dev/lotus/studio/utils/SafeZoneUtils.java | 59 +++++++ src/main/resources/plugin.yml | 1 + 12 files changed, 318 insertions(+), 226 deletions(-) create mode 100644 src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java create mode 100644 src/main/java/dev/lotus/studio/utils/SafeZoneUtils.java diff --git a/build.gradle b/build.gradle index 4600616..af79678 100644 --- a/build.gradle +++ b/build.gradle @@ -31,6 +31,7 @@ dependencies { compileOnly("io.papermc.paper:paper-api:1.21.1-R0.1-SNAPSHOT") compileOnly 'io.th0rgal:oraxen:1.184.1' compileOnly("com.sk89q.worldedit:worldedit-bukkit:7.2.15") + implementation("com.google.guava:guava:10.0.1") implementation("org.xerial:sqlite-jdbc:3.50.3.0") implementation("com.j256.ormlite:ormlite-jdbc:6.1") } diff --git a/src/main/java/dev/lotus/studio/Main.java b/src/main/java/dev/lotus/studio/Main.java index d4c58c2..d3b00cb 100644 --- a/src/main/java/dev/lotus/studio/Main.java +++ b/src/main/java/dev/lotus/studio/Main.java @@ -50,16 +50,15 @@ public void onEnable() { new PlayerBar(this,itemManager); - new MainCommand("lotus", itemManager); + new MainCommand("lotus", itemManager,safeZoneDataService); - SafeZoneManager.getInstance().initializeZones(safeZoneDataService); + SafeZoneManager.getInstance().initialize(safeZoneDataService); } @Override public void onDisable() { PlayerManager.getInstance().getGlobalTask().cancel(); - SafeZoneManager.getInstance().saveAllSafeZoneToDatabase(); // Закриття DataBase if (databaseInitializer != null) { databaseInitializer.closeConnection(); diff --git a/src/main/java/dev/lotus/studio/command/MainCommand.java b/src/main/java/dev/lotus/studio/command/MainCommand.java index 568e037..84433e2 100644 --- a/src/main/java/dev/lotus/studio/command/MainCommand.java +++ b/src/main/java/dev/lotus/studio/command/MainCommand.java @@ -14,10 +14,10 @@ public class MainCommand extends AbstractCommand { private final CustomItemManager itemManager; private final SafeZoneCommand saveZoneCommand; - public MainCommand(String command, CustomItemManager itemManager ) { + public MainCommand(String command, CustomItemManager itemManager , SafeZoneDataService saveZoneDataService) { super(command); this.itemManager = itemManager; - this.saveZoneCommand =new SafeZoneCommand(); + this.saveZoneCommand =new SafeZoneCommand(saveZoneDataService); } @Override @@ -286,20 +286,6 @@ private void sendEatHelp(Player player, String label) { } - - - - - - - - - - - - - - @Override public List complete(CommandSender sender, String[] args) { List suggestions = new ArrayList<>(); @@ -313,7 +299,7 @@ public List complete(CommandSender sender, String[] args) { suggestions.addAll(List.of("armor", "view", "eat", "help")); } else if ("savezone".equals(category)) { - suggestions.addAll(List.of("pos1", "pos2", "save","list")); + suggestions.addAll(List.of("pos1", "pos2", "save","list","remove")); } } else if (args.length == 3) { String category = args[0].toLowerCase(); diff --git a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java index 4b2a36d..7a0c9d6 100644 --- a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java +++ b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java @@ -1,6 +1,7 @@ package dev.lotus.studio.command; - +import dev.lotus.studio.database.savezone.SafeZoneDataBase; +import dev.lotus.studio.database.savezone.SafeZoneDataService; import dev.lotus.studio.safezone.SafeZone; import dev.lotus.studio.safezone.SafeZoneManager; import net.kyori.adventure.text.Component; @@ -16,13 +17,14 @@ import static dev.lotus.studio.utils.MapperUtils.formatLocation; public class SafeZoneCommand { - private SafeZoneManager safeZoneManager = SafeZoneManager.getInstance(); - + private final SafeZoneManager safeZoneManager = SafeZoneManager.getInstance(); + private final SafeZoneDataService dataService; // нова система private Location pos1 = null; private Location pos2 = null; - public SafeZoneCommand() { + public SafeZoneCommand(SafeZoneDataService dataService) { + this.dataService = dataService; } public boolean execute(CommandSender sender, String label, String[] args) { @@ -42,12 +44,12 @@ public boolean execute(CommandSender sender, String label, String[] args) { switch (args[1].toLowerCase()) { case "pos1": pos1 = player.getLocation(); - player.sendMessage("fist point: " + formatLocation(pos1)); + player.sendMessage("first point: " + formatLocation(pos1)); break; case "pos2": pos2 = player.getLocation(); - player.sendMessage("second points: " + formatLocation(pos2)); + player.sendMessage("second point: " + formatLocation(pos2)); break; case "save": @@ -55,75 +57,69 @@ public boolean execute(CommandSender sender, String label, String[] args) { player.sendMessage("set name to savezone: /lotus savezone save <назва>"); return true; } - saveZoneToDB(player, pos1, pos2, args[2]); + saveZone(player, pos1, pos2, args[2]); break; + case "list": - player.sendMessage("Укажіть назву для зони. Наприклад: /<команда> save <назва>"); - listZoneToDB(player); + listZones(player); return true; + case "remove": if (args.length < 3) { - player.sendMessage("Укажіть назву для зони. Наприклад: /<команда> save <назва>"); + player.sendMessage("Укажіть ID зони: /lotus savezone remove "); return true; } - removeZoneToDB(player, Integer.parseInt(args[1])); + removeZone(player, Integer.parseInt(args[2])); break; + default: - player.sendMessage("Невідома команда. Використовуйте: pos1, pos2 або save."); + player.sendMessage("Невідома команда. Використовуйте: pos1, pos2, save, list, remove."); } return true; } - private void removeZoneToDB(Player player, int id) { - List safeZones = safeZoneManager.getAllSafeZones(); - safeZones.forEach(zone -> { - if (zone.getZoneID() == id) { - safeZoneManager.removeSafeZone(id); - player.sendMessage(Component.text("Safe zone deleted!")); - } - }); - - -// service.getAllSaveZones().forEach(safeZoneDataBase -> { -// if (safeZoneDataBase.getSafeZoneId() == id){ -// player.sendMessage("Сейв зону удаленно с названием: " + safeZoneDataBase.getSafeZoneName() + " ID: " + safeZoneDataBase.getSafeZoneId()); -// } -// }); -// service.removeProtectZone(id); + private void saveZone(Player player, Location pos1, Location pos2, String zoneName) { + if (pos1 != null && pos2 != null) { + Pair zoneLoc = new ImmutablePair<>(pos1, pos2); + SafeZone safeZone = new SafeZone(zoneName, zoneLoc); + + // runtime + safeZoneManager.addSafeZone(safeZone); + + // database + String locationString = formatLocation(pos1) + "|" + formatLocation(pos2); + dataService.saveProtectZone(zoneName, locationString); + + player.sendMessage("Зона '" + zoneName + "' успішно збережена."); + } else { + player.sendMessage("Будь ласка, спочатку встановіть обидві точки (pos1 і pos2)."); + } } - private void listZoneToDB(Player player) { - // Отримуємо всі збережені зони з бази даних - List safeZoneDataBases = safeZoneManager.getAllSafeZones(); + private void listZones(Player player) { + List safeZones = dataService.getAllSaveZones(); - // Якщо зон немає, повідомляємо гравця - if (safeZoneDataBases.isEmpty()) { - player.sendMessage("нет зон."); + if (safeZones.isEmpty()) { + player.sendMessage("немає зон."); return; } - // Формуємо мапу з імен зон і їх ідентифікаторів HashMap saveId = new HashMap<>(); - safeZoneDataBases.forEach(saveZoneData -> saveId.put(saveZoneData.getZoneName(), saveZoneData.getZoneID())); + safeZones.forEach(zone -> saveId.put(zone.getSafeZoneName(), zone.getSafeZoneId())); - // Виводимо гравцю список зон player.sendMessage("Список зон:"); saveId.forEach((name, id) -> - player.sendMessage(" - Имя: " + name + ", ID: " + id) + player.sendMessage(" - Назва: " + name + ", ID: " + id) ); } + private void removeZone(Player player, int id) { + // runtime + safeZoneManager.removeSafeZone(id); - private void saveZoneToDB(Player player, Location pos1, Location pos2, String zoneName) { - if (pos1 != null && pos2 != null) { - Pair zoneLoc = new ImmutablePair<>(pos1, pos2); - SafeZone safeZone = new SafeZone(zoneName,zoneLoc); - safeZoneManager.addSafeZone(safeZone); - player.sendMessage("Зона '" + zoneName + "' успішно збережена."); - } else { - player.sendMessage("Будь ласка, спочатку встановіть обидві точки (pos1 і pos2)."); - } - } - + // database + dataService.removeProtectZone(id); + player.sendMessage(Component.text("Safe zone with ID " + id + " deleted!")); + } } diff --git a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java index 1c06981..843b40f 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataRepository.java @@ -19,58 +19,55 @@ public SafeZoneDataRepository(ConnectionSource connectionSource) throws SQLExcep this.safeZoneDao = DaoManager.createDao(connectionSource, SafeZoneDataBase.class); } - /** - * Видалити зону по id - */ public void removeProtectZone(int id) throws SQLException { safeZoneDao.deleteById(id); } - /** - * Зберегти/оновити структуру - */ - public void saveStructureData(SafeZoneDataBase safeZoneDataBase) throws SQLException { + public void saveZoneDataBase(SafeZoneDataBase safeZoneDataBase) throws SQLException { safeZoneDao.createOrUpdate(safeZoneDataBase); } - /** - * Отримати всі структури - */ - public List getAllStructuresData() throws SQLException { + public List getAllZoneDataBase() throws SQLException { return safeZoneDao.queryForAll(); } + /** Новий метод */ + public SafeZoneDataBase getZoneById(int id) throws SQLException { + return safeZoneDao.queryForId(id); + } + /** - * Повертає список зон у форматі пар локацій (лок1, лок2) + * Отримати всі зони у вигляді пар локацій */ - public List> getSaveZoneDataZones() throws SQLException { + public List> getSafeZoneDataZones() throws SQLException { List> zones = new ArrayList<>(); - List structures = getAllStructuresData(); + List structures = getAllZoneDataBase(); for (SafeZoneDataBase structure : structures) { - String[] coordinates = structure.getLocationValue().split("\\|"); - if (coordinates.length == 2) { - String[] loc1 = coordinates[0].split(","); - String[] loc2 = coordinates[1].split(","); + zones.add(parseZone(structure.getLocationValue())); + } + return zones; + } - Location location1 = new Location( - Bukkit.getWorld("world"), // або передавати динамічно - Double.parseDouble(loc1[0].trim()), - Double.parseDouble(loc1[1].trim()), - Double.parseDouble(loc1[2].trim()) - ); + private Pair parseZone(String raw) { + String[] coordinates = raw.split("\\|"); + String[] loc1 = coordinates[0].split(","); + String[] loc2 = coordinates[1].split(","); - Location location2 = new Location( - Bukkit.getWorld("world"), - Double.parseDouble(loc2[0].trim()), - Double.parseDouble(loc2[1].trim()), - Double.parseDouble(loc2[2].trim()) - ); + Location location1 = new Location( + Bukkit.getWorld("world"), + Double.parseDouble(loc1[0].trim()), + Double.parseDouble(loc1[1].trim()), + Double.parseDouble(loc1[2].trim()) + ); - zones.add(Pair.of(location1, location2)); - } - } + Location location2 = new Location( + Bukkit.getWorld("world"), + Double.parseDouble(loc2[0].trim()), + Double.parseDouble(loc2[1].trim()), + Double.parseDouble(loc2[2].trim()) + ); - return zones; + return Pair.of(location1, location2); } } diff --git a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java index f8eede7..1128419 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataService.java @@ -11,6 +11,9 @@ public interface SafeZoneDataService { void removeProtectZone(int id); + SafeZoneDataBase getZoneById(int id); + List getNearbyZoneIds(Location predicted); + List getAllSaveZones(); boolean isProtectZone(Location playerLocation); diff --git a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java index 2e1fa46..5844e04 100644 --- a/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java +++ b/src/main/java/dev/lotus/studio/database/savezone/SafeZoneDataServiceImpl.java @@ -5,6 +5,7 @@ import org.bukkit.Location; import java.sql.SQLException; +import java.util.ArrayList; import java.util.List; public class SafeZoneDataServiceImpl implements SafeZoneDataService { @@ -19,7 +20,7 @@ public SafeZoneDataServiceImpl(ConnectionSource connectionSource) throws SQLExce public void saveProtectZone(String name, String location) { try { SafeZoneDataBase safeZoneDataBase = new SafeZoneDataBase(name, location); - safeZoneDataRepository.saveStructureData(safeZoneDataBase); + safeZoneDataRepository.saveZoneDataBase(safeZoneDataBase); } catch (SQLException e) { e.printStackTrace(); } @@ -34,10 +35,21 @@ public void removeProtectZone(int id) { } } + /** Реалізація getZoneById */ + @Override + public SafeZoneDataBase getZoneById(int id) { + try { + return safeZoneDataRepository.getZoneById(id); + } catch (SQLException e) { + e.printStackTrace(); + return null; + } + } + @Override public List getAllSaveZones() { try { - return safeZoneDataRepository.getAllStructuresData(); + return safeZoneDataRepository.getAllZoneDataBase(); } catch (SQLException e) { e.printStackTrace(); return List.of(); @@ -47,7 +59,7 @@ public List getAllSaveZones() { @Override public boolean isProtectZone(Location playerLocation) { try { - List> saveZoneDataZones = safeZoneDataRepository.getSaveZoneDataZones(); + List> saveZoneDataZones = safeZoneDataRepository.getSafeZoneDataZones(); for (Pair zone : saveZoneDataZones) { if (isLocationInZone(playerLocation, zone.getLeft(), zone.getRight())) { return true; @@ -62,13 +74,30 @@ public boolean isProtectZone(Location playerLocation) { @Override public List> getSaveZones() { try { - return safeZoneDataRepository.getSaveZoneDataZones(); + return safeZoneDataRepository.getSafeZoneDataZones(); } catch (SQLException e) { e.printStackTrace(); return List.of(); } } + /** ✅ Новий метод */ + public List getNearbyZoneIds(Location predicted) { + List result = new ArrayList<>(); + try { + List zones = safeZoneDataRepository.getAllZoneDataBase(); + for (SafeZoneDataBase zone : zones) { + Pair locPair = parseZone(zone.getLocationValue()); + if (isNear(predicted, locPair.getLeft(), locPair.getRight(), 20)) { // радіус 20 блоків + result.add(zone.getSafeZoneId()); + } + } + } catch (SQLException e) { + e.printStackTrace(); + } + return result; + } + private boolean isLocationInZone(Location location, Location loc1, Location loc2) { int x1 = Math.min(loc1.getBlockX(), loc2.getBlockX()); int y1 = Math.min(loc1.getBlockY(), loc2.getBlockY()); @@ -86,4 +115,40 @@ private boolean isLocationInZone(Location location, Location loc1, Location loc2 (py >= y1 && py <= y2) && (pz >= z1 && pz <= z2); } + + private boolean isNear(Location player, Location l1, Location l2, int radius) { + int x1 = Math.min(l1.getBlockX(), l2.getBlockX()) - radius; + int y1 = Math.min(l1.getBlockY(), l2.getBlockY()) - radius; + int z1 = Math.min(l1.getBlockZ(), l2.getBlockZ()) - radius; + + int x2 = Math.max(l1.getBlockX(), l2.getBlockX()) + radius; + int y2 = Math.max(l1.getBlockY(), l2.getBlockY()) + radius; + int z2 = Math.max(l1.getBlockZ(), l2.getBlockZ()) + radius; + + int px = player.getBlockX(); + int py = player.getBlockY(); + int pz = player.getBlockZ(); + + return (px >= x1 && px <= x2) && + (py >= y1 && py <= y2) && + (pz >= z1 && pz <= z2); + } + + private Pair parseZone(String raw) { + String[] coordinates = raw.split("\\|"); + String[] loc1 = coordinates[0].split(","); + String[] loc2 = coordinates[1].split(","); + + Location location1 = new Location(null, + Double.parseDouble(loc1[0].trim()), + Double.parseDouble(loc1[1].trim()), + Double.parseDouble(loc1[2].trim())); + + Location location2 = new Location(null, + Double.parseDouble(loc2[0].trim()), + Double.parseDouble(loc2[1].trim()), + Double.parseDouble(loc2[2].trim())); + + return Pair.of(location1, location2); + } } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZone.java b/src/main/java/dev/lotus/studio/safezone/SafeZone.java index c9e6a43..b5b7b43 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZone.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZone.java @@ -15,6 +15,13 @@ public SafeZone(String zoneName, Pair locationPair) { } + public SafeZone(int id, String zoneName, Pair locationPair) { + this.zoneID = id; + this.zoneName = zoneName; + this.locationPair = locationPair; + + } + public void setZoneName(String zoneName) { this.zoneName = zoneName; } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java index f9b1fda..ca41463 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java @@ -1,6 +1,8 @@ package dev.lotus.studio.safezone; -import org.apache.commons.lang3.tuple.Pair; +import com.google.common.cache.Cache; +import com.google.common.cache.CacheBuilder; +import dev.lotus.studio.utils.SafeZoneUtils; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; @@ -8,150 +10,75 @@ import dev.lotus.studio.database.savezone.SafeZoneDataBase; import dev.lotus.studio.database.savezone.SafeZoneDataService; -import java.util.ArrayList; -import java.util.List; - -import static dev.lotus.studio.utils.MapperUtils.formatLocation; +import java.util.concurrent.TimeUnit; public class SafeZoneManager { private static final SafeZoneManager instance = new SafeZoneManager(); - private final List safeZones = new ArrayList<>(); private final Plugin plugin = Main.getInstance(); private SafeZoneDataService safeZoneDataService; - public static SafeZoneManager getInstance() { - return instance; - } + // Кеш із TTL (щоб вивантажувати непотрібні зони) + private final Cache zoneCache = CacheBuilder.newBuilder() + .expireAfterAccess(10, TimeUnit.MINUTES) // якщо 10 хв ніхто не юзав — вивантажуємо + .maximumSize(500) // захист від переповнення + .build(); + private SafeZonePreloader preloader; - // Добавление новой зоны - public void addSafeZone(SafeZone safeZone) { - safeZones.add(safeZone); + public static SafeZoneManager getInstance() { + return instance; } - public void saveAllSafeZoneToDatabase() { - safeZones.forEach(safeZone -> { - String positionData = formatLocation(safeZone.getLocationPair().getLeft()) + "|" + formatLocation(safeZone.getLocationPair().getRight()); - safeZoneDataService.saveProtectZone(safeZone.getZoneName(),positionData); - }); + public void initialize(SafeZoneDataService safeZoneDataService) { + this.safeZoneDataService = safeZoneDataService; + this.preloader = new SafeZonePreloader(this, safeZoneDataService, plugin); + plugin.getLogger().info("SafeZoneManager ініціалізовано з lazy-загрузкою та кешем."); } - - - - // Удаление зоны по ID - public boolean removeSafeZone(int zoneID) { - return safeZones.removeIf(zone -> zone.getZoneID() == zoneID); + // Додавання нової зони + public void addSafeZone(SafeZone safeZone) { + zoneCache.put(safeZone.getZoneID(), safeZone); + safeZoneDataService.saveProtectZone( + safeZone.getZoneName(), + SafeZoneUtils.serializeZone(safeZone.getLocationPair()) + ); } - // Поиск зоны по имени - public SafeZone getSafeZoneByName(String name) { - return safeZones.stream() - .filter(zone -> zone.getZoneName().equalsIgnoreCase(name)) - .findFirst() - .orElse(null); + // Видалення + public void removeSafeZone(int zoneID) { + zoneCache.invalidate(zoneID); + safeZoneDataService.removeProtectZone(zoneID); } + // Отримання зони з кешу (або БД, якщо немає в кеші) + public void getZoneById(int zoneID) { + SafeZone cached = zoneCache.getIfPresent(zoneID); + if (cached != null) return; - // Проверка, находится ли игрок в какой-либо зоне - public boolean isPlayerInAnyZone(Player player) { - Location playerLocation = player.getLocation(); - return safeZones.stream() - .anyMatch(zone -> isLocationInZone(playerLocation, - zone.getLocationPair().getLeft(), - zone.getLocationPair().getRight())); - } - - public void initializeZones(SafeZoneDataService safeZoneDataService) { - List zonesData = safeZoneDataService.getAllSaveZones(); - - try { - for (SafeZoneDataBase data : zonesData) { - try { - // Парсим данные координат - List> parsedZones = parseZonesFromString(data.getLocationValue()); - if (!parsedZones.isEmpty()) { - // Берём первую пару координат для SafeZone - Pair zoneCoordinates = parsedZones.get(0); - SafeZone safeZone = new SafeZone( - data.getSafeZoneName(), - zoneCoordinates - ); - addSafeZone(safeZone); // Добавляем загруженную зону в менеджер - - // Успешная инициализация - plugin.getLogger().info("Успешно инициализирована зона: " - + data.getSafeZoneName() + " (ID: " + data.getSafeZoneId() + ")"); - } - } catch (Exception e) { - plugin.getLogger().warning("Ошибка при инициализации зоны: " - + data.getSafeZoneName() + " (ID: " + data.getSafeZoneId() + ")"); - e.printStackTrace(); - } - } - } catch (Exception e) { - plugin.getLogger().severe("Ошибка при загрузке данных зон безопасности."); - e.printStackTrace(); - } finally { - plugin.getLogger().info("Процесс инициализации зон завершён."); + SafeZoneDataBase dbData = safeZoneDataService.getZoneById(zoneID); + if (dbData != null) { + SafeZone zone = SafeZoneUtils.fromDatabase(dbData); + zoneCache.put(zoneID, zone); } } - public List> parseZonesFromString(String data) { - List> zones = new ArrayList<>(); - try { - String[] zoneEntries = data.split(";"); // Разделяем по ';', чтобы получить отдельные зоны - for (String entry : zoneEntries) { - String[] coordinates = entry.split("\\|"); // Разделяем первую и вторую координаты - if (coordinates.length == 2) { - String[] loc1 = coordinates[0].split(","); // Координаты первой точки - String[] loc2 = coordinates[1].split(","); // Координаты второй точки - - Location location1 = new Location(null, // `null` - добавьте мир, если необходимо - Integer.parseInt(loc1[0].trim()), - Integer.parseInt(loc1[1].trim()), - Integer.parseInt(loc1[2].trim())); - - Location location2 = new Location(null, - Integer.parseInt(loc2[0].trim()), - Integer.parseInt(loc2[1].trim()), - Integer.parseInt(loc2[2].trim())); - - zones.add(Pair.of(location1, location2)); - } + // Перевірка чи гравець в якійсь зоні + public boolean isPlayerInAnyZone(Player player) { + Location playerLoc = player.getLocation(); + for (SafeZone zone : zoneCache.asMap().values()) { + if (SafeZoneUtils.isLocationInZone(playerLoc, + zone.getLocationPair().getLeft(), + zone.getLocationPair().getRight())) { + return true; } - } catch (Exception e) { - e.printStackTrace(); } - return zones; - } - - - - // Проверка, находится ли местоположение внутри зоны - private boolean isLocationInZone(Location playerLoc, Location posLoc1, Location posLoc2) { - int x1 = Math.min(posLoc1.getBlockX(), posLoc2.getBlockX()); - int y1 = Math.min(posLoc1.getBlockY(), posLoc2.getBlockY()); - int z1 = Math.min(posLoc1.getBlockZ(), posLoc2.getBlockZ()); - - int x2 = Math.max(posLoc1.getBlockX(), posLoc2.getBlockX()); - int y2 = Math.max(posLoc1.getBlockY(), posLoc2.getBlockY()); - int z2 = Math.max(posLoc1.getBlockZ(), posLoc2.getBlockZ()); - - int px = playerLoc.getBlockX(); - int py = playerLoc.getBlockY(); - int pz = playerLoc.getBlockZ(); - - return (px >= x1 && px <= x2) && - (py >= y1 && py <= y2) && - (pz >= z1 && pz <= z2); + return false; } - // Получение всех зон - public List getAllSafeZones() { - return new ArrayList<>(safeZones); + public SafeZonePreloader getPreloader() { + return preloader; } } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java b/src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java new file mode 100644 index 0000000..1c301f5 --- /dev/null +++ b/src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java @@ -0,0 +1,51 @@ +package dev.lotus.studio.safezone; + + +import dev.lotus.studio.database.savezone.SafeZoneDataService; +import org.bukkit.Location; +import org.bukkit.entity.Player; +import org.bukkit.plugin.Plugin; +import org.bukkit.scheduler.BukkitRunnable; + +import java.util.List; + +public class SafeZonePreloader { + + private final SafeZoneManager manager; + private final SafeZoneDataService dataService; + private final Plugin plugin; + + public SafeZonePreloader(SafeZoneManager manager, SafeZoneDataService dataService, Plugin plugin) { + this.manager = manager; + this.dataService = dataService; + this.plugin = plugin; + startTask(); + } + + private void startTask() { + new BukkitRunnable() { + @Override + public void run() { + for (Player player : plugin.getServer().getOnlinePlayers()) { + preloadZonesForPlayer(player); + } + } + }.runTaskTimerAsynchronously(plugin, 20L, 40L); // кожні 2 сек + } + + private void preloadZonesForPlayer(Player player) { + Location current = player.getLocation(); + Location velocity = player.getVelocity().toLocation(player.getWorld()); + + // Прогноз наступної позиції + Location predicted = current.clone().add(velocity.multiply(3)); // умовно 3 сек вперед + + // Отримуємо зони поруч з передбаченою позицією + List nearbyZoneIds = dataService.getNearbyZoneIds(predicted); + + for (int zoneId : nearbyZoneIds) { + manager.getZoneById(zoneId); // Підвантажуємо в кеш + } + } +} + diff --git a/src/main/java/dev/lotus/studio/utils/SafeZoneUtils.java b/src/main/java/dev/lotus/studio/utils/SafeZoneUtils.java new file mode 100644 index 0000000..e4044c4 --- /dev/null +++ b/src/main/java/dev/lotus/studio/utils/SafeZoneUtils.java @@ -0,0 +1,59 @@ +package dev.lotus.studio.utils; + + +import dev.lotus.studio.safezone.SafeZone; +import org.apache.commons.lang3.tuple.Pair; +import org.bukkit.Location; +import dev.lotus.studio.database.savezone.SafeZoneDataBase; + +public class SafeZoneUtils { + + public static boolean isLocationInZone(Location playerLoc, Location posLoc1, Location posLoc2) { + int x1 = Math.min(posLoc1.getBlockX(), posLoc2.getBlockX()); + int y1 = Math.min(posLoc1.getBlockY(), posLoc2.getBlockY()); + int z1 = Math.min(posLoc1.getBlockZ(), posLoc2.getBlockZ()); + + int x2 = Math.max(posLoc1.getBlockX(), posLoc2.getBlockX()); + int y2 = Math.max(posLoc1.getBlockY(), posLoc2.getBlockY()); + int z2 = Math.max(posLoc1.getBlockZ(), posLoc2.getBlockZ()); + + int px = playerLoc.getBlockX(); + int py = playerLoc.getBlockY(); + int pz = playerLoc.getBlockZ(); + + return (px >= x1 && px <= x2) && + (py >= y1 && py <= y2) && + (pz >= z1 && pz <= z2); + } + + public static String serializeZone(Pair pair) { + return formatLoc(pair.getLeft()) + "|" + formatLoc(pair.getRight()); + } + + private static String formatLoc(Location loc) { + return loc.getBlockX() + "," + loc.getBlockY() + "," + loc.getBlockZ(); + } + + public static SafeZone fromDatabase(SafeZoneDataBase dbData) { + Pair coords = parseZone(dbData.getLocationValue()); + return new SafeZone(dbData.getSafeZoneId(), dbData.getSafeZoneName(), coords); + } + + private static Pair parseZone(String value) { + String[] parts = value.split("\\|"); + String[] loc1 = parts[0].split(","); + String[] loc2 = parts[1].split(","); + + Location l1 = new Location(null, + Integer.parseInt(loc1[0]), + Integer.parseInt(loc1[1]), + Integer.parseInt(loc1[2])); + + Location l2 = new Location(null, + Integer.parseInt(loc2[0]), + Integer.parseInt(loc2[1]), + Integer.parseInt(loc2[2])); + + return Pair.of(l1, l2); + } +} diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index 7cb9b90..4ed9bf1 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -6,6 +6,7 @@ soft-depend: [Oraxen] libraries: - org.xerial:sqlite-jdbc:3.50.3.0 - com.j256.ormlite:ormlite-jdbc:6.1 + - com.google.guava:guava:10.0.1 commands: lotus: description: Перезагрузка конфигурации плагина. From 7d3da9fb604d98b018d9806776af6a3d4c70e029 Mon Sep 17 00:00:00 2001 From: Referix Date: Tue, 23 Sep 2025 13:35:32 +0300 Subject: [PATCH 3/4] fix: architecture depend SafeZone && rename from SafeZonePreloader.java to SafeZonePreloaded.java --- src/main/java/dev/lotus/studio/Main.java | 8 ++---- .../dev/lotus/studio/command/MainCommand.java | 4 +-- .../lotus/studio/command/SafeZoneCommand.java | 13 +-------- .../studio/safezone/SafeZoneManager.java | 24 +++++++++++++---- ...ePreloader.java => SafeZonePreloaded.java} | 27 +++++++++++-------- 5 files changed, 40 insertions(+), 36 deletions(-) rename src/main/java/dev/lotus/studio/safezone/{SafeZonePreloader.java => SafeZonePreloaded.java} (68%) diff --git a/src/main/java/dev/lotus/studio/Main.java b/src/main/java/dev/lotus/studio/Main.java index d3b00cb..2375c27 100644 --- a/src/main/java/dev/lotus/studio/Main.java +++ b/src/main/java/dev/lotus/studio/Main.java @@ -19,15 +19,10 @@ public final class Main extends JavaPlugin { private static Main instance; private CustomItemManager itemManager; - - - private PlayerDataService playerDataBase; private SafeZoneDataService safeZoneDataService; private DatabaseInitializer databaseInitializer; - - @Override public void onEnable() { @@ -50,7 +45,7 @@ public void onEnable() { new PlayerBar(this,itemManager); - new MainCommand("lotus", itemManager,safeZoneDataService); + new MainCommand("lotus", itemManager); SafeZoneManager.getInstance().initialize(safeZoneDataService); @@ -59,6 +54,7 @@ public void onEnable() { @Override public void onDisable() { PlayerManager.getInstance().getGlobalTask().cancel(); + SafeZoneManager.getInstance().getPreloaded().stopTask(); // Закриття DataBase if (databaseInitializer != null) { databaseInitializer.closeConnection(); diff --git a/src/main/java/dev/lotus/studio/command/MainCommand.java b/src/main/java/dev/lotus/studio/command/MainCommand.java index 84433e2..2c8c652 100644 --- a/src/main/java/dev/lotus/studio/command/MainCommand.java +++ b/src/main/java/dev/lotus/studio/command/MainCommand.java @@ -14,10 +14,10 @@ public class MainCommand extends AbstractCommand { private final CustomItemManager itemManager; private final SafeZoneCommand saveZoneCommand; - public MainCommand(String command, CustomItemManager itemManager , SafeZoneDataService saveZoneDataService) { + public MainCommand(String command, CustomItemManager itemManager) { super(command); this.itemManager = itemManager; - this.saveZoneCommand =new SafeZoneCommand(saveZoneDataService); + this.saveZoneCommand =new SafeZoneCommand(); } @Override diff --git a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java index 7a0c9d6..38dd1d7 100644 --- a/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java +++ b/src/main/java/dev/lotus/studio/command/SafeZoneCommand.java @@ -18,14 +18,10 @@ public class SafeZoneCommand { private final SafeZoneManager safeZoneManager = SafeZoneManager.getInstance(); - private final SafeZoneDataService dataService; // нова система private Location pos1 = null; private Location pos2 = null; - public SafeZoneCommand(SafeZoneDataService dataService) { - this.dataService = dataService; - } public boolean execute(CommandSender sender, String label, String[] args) { if (!(sender instanceof Player player)) { @@ -86,10 +82,6 @@ private void saveZone(Player player, Location pos1, Location pos2, String zoneNa // runtime safeZoneManager.addSafeZone(safeZone); - // database - String locationString = formatLocation(pos1) + "|" + formatLocation(pos2); - dataService.saveProtectZone(zoneName, locationString); - player.sendMessage("Зона '" + zoneName + "' успішно збережена."); } else { player.sendMessage("Будь ласка, спочатку встановіть обидві точки (pos1 і pos2)."); @@ -97,7 +89,7 @@ private void saveZone(Player player, Location pos1, Location pos2, String zoneNa } private void listZones(Player player) { - List safeZones = dataService.getAllSaveZones(); + List safeZones = safeZoneManager.getDataZones(); if (safeZones.isEmpty()) { player.sendMessage("немає зон."); @@ -117,9 +109,6 @@ private void removeZone(Player player, int id) { // runtime safeZoneManager.removeSafeZone(id); - // database - dataService.removeProtectZone(id); - player.sendMessage(Component.text("Safe zone with ID " + id + " deleted!")); } } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java index ca41463..9fc03f4 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java @@ -10,6 +10,7 @@ import dev.lotus.studio.database.savezone.SafeZoneDataBase; import dev.lotus.studio.database.savezone.SafeZoneDataService; +import java.util.List; import java.util.concurrent.TimeUnit; public class SafeZoneManager { @@ -21,11 +22,11 @@ public class SafeZoneManager { // Кеш із TTL (щоб вивантажувати непотрібні зони) private final Cache zoneCache = CacheBuilder.newBuilder() - .expireAfterAccess(10, TimeUnit.MINUTES) // якщо 10 хв ніхто не юзав — вивантажуємо + .expireAfterAccess(10, TimeUnit.SECONDS) // якщо 10 хв ніхто не юзав — вивантажуємо .maximumSize(500) // захист від переповнення .build(); - private SafeZonePreloader preloader; + private SafeZonePreloaded preloader; public static SafeZoneManager getInstance() { return instance; @@ -33,7 +34,7 @@ public static SafeZoneManager getInstance() { public void initialize(SafeZoneDataService safeZoneDataService) { this.safeZoneDataService = safeZoneDataService; - this.preloader = new SafeZonePreloader(this, safeZoneDataService, plugin); + this.preloader = new SafeZonePreloaded(this, safeZoneDataService, plugin); plugin.getLogger().info("SafeZoneManager ініціалізовано з lazy-загрузкою та кешем."); } @@ -56,15 +57,23 @@ public void removeSafeZone(int zoneID) { // Отримання зони з кешу (або БД, якщо немає в кеші) public void getZoneById(int zoneID) { SafeZone cached = zoneCache.getIfPresent(zoneID); - if (cached != null) return; + if (cached != null) { + return; + } SafeZoneDataBase dbData = safeZoneDataService.getZoneById(zoneID); if (dbData != null) { SafeZone zone = SafeZoneUtils.fromDatabase(dbData); zoneCache.put(zoneID, zone); + + plugin.getLogger().info("[SafeZoneManager] Loaded zone from DB and cached: " + + zone.getZoneName() + " (ID: " + zone.getZoneID() + ")"); + } else { + plugin.getLogger().warning("[SafeZoneManager] Zone " + zoneID + " not found in DB."); } } + // Перевірка чи гравець в якійсь зоні public boolean isPlayerInAnyZone(Player player) { Location playerLoc = player.getLocation(); @@ -78,7 +87,12 @@ public boolean isPlayerInAnyZone(Player player) { return false; } - public SafeZonePreloader getPreloader() { + public List getDataZones(){ + return safeZoneDataService.getAllSaveZones(); + } + + + public SafeZonePreloaded getPreloaded() { return preloader; } } diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java b/src/main/java/dev/lotus/studio/safezone/SafeZonePreloaded.java similarity index 68% rename from src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java rename to src/main/java/dev/lotus/studio/safezone/SafeZonePreloaded.java index 1c301f5..20aa699 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZonePreloader.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZonePreloaded.java @@ -1,21 +1,23 @@ package dev.lotus.studio.safezone; - import dev.lotus.studio.database.savezone.SafeZoneDataService; import org.bukkit.Location; import org.bukkit.entity.Player; import org.bukkit.plugin.Plugin; import org.bukkit.scheduler.BukkitRunnable; +import org.bukkit.scheduler.BukkitTask; import java.util.List; -public class SafeZonePreloader { +public class SafeZonePreloaded { private final SafeZoneManager manager; private final SafeZoneDataService dataService; private final Plugin plugin; - public SafeZonePreloader(SafeZoneManager manager, SafeZoneDataService dataService, Plugin plugin) { + private BukkitTask preloadTask; // зберігаємо таску + + public SafeZonePreloaded(SafeZoneManager manager, SafeZoneDataService dataService, Plugin plugin) { this.manager = manager; this.dataService = dataService; this.plugin = plugin; @@ -23,7 +25,8 @@ public SafeZonePreloader(SafeZoneManager manager, SafeZoneDataService dataServic } private void startTask() { - new BukkitRunnable() { + // Запускаємо і зберігаємо таску + this.preloadTask = new BukkitRunnable() { @Override public void run() { for (Player player : plugin.getServer().getOnlinePlayers()) { @@ -33,19 +36,21 @@ public void run() { }.runTaskTimerAsynchronously(plugin, 20L, 40L); // кожні 2 сек } + public void stopTask() { + if (preloadTask != null && !preloadTask.isCancelled()) { + preloadTask.cancel(); + plugin.getLogger().info("[SafeZonePreloaded] Preload task stopped."); + } + } + private void preloadZonesForPlayer(Player player) { Location current = player.getLocation(); Location velocity = player.getVelocity().toLocation(player.getWorld()); - // Прогноз наступної позиції - Location predicted = current.clone().add(velocity.multiply(3)); // умовно 3 сек вперед - - // Отримуємо зони поруч з передбаченою позицією + Location predicted = current.clone().add(velocity.multiply(3)); List nearbyZoneIds = dataService.getNearbyZoneIds(predicted); - for (int zoneId : nearbyZoneIds) { - manager.getZoneById(zoneId); // Підвантажуємо в кеш + manager.getZoneById(zoneId); } } } - From 7682ccd85f32ba45addde340b87546bd0fb35e17 Mon Sep 17 00:00:00 2001 From: Referix Date: Tue, 23 Sep 2025 15:10:14 +0300 Subject: [PATCH 4/4] fix: fix time delete --- src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java index 9fc03f4..596bd81 100644 --- a/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java +++ b/src/main/java/dev/lotus/studio/safezone/SafeZoneManager.java @@ -22,7 +22,7 @@ public class SafeZoneManager { // Кеш із TTL (щоб вивантажувати непотрібні зони) private final Cache zoneCache = CacheBuilder.newBuilder() - .expireAfterAccess(10, TimeUnit.SECONDS) // якщо 10 хв ніхто не юзав — вивантажуємо + .expireAfterAccess(5, TimeUnit.MINUTES) .maximumSize(500) // захист від переповнення .build();