diff --git a/src/main/java/cn/lunadeer/dominion/Cache.java b/src/main/java/cn/lunadeer/dominion/Cache.java new file mode 100644 index 0000000..d27134d --- /dev/null +++ b/src/main/java/cn/lunadeer/dominion/Cache.java @@ -0,0 +1,120 @@ +package cn.lunadeer.dominion; + +import cn.lunadeer.dominion.dtos.DominionDTO; +import cn.lunadeer.dominion.dtos.PlayerPrivilegeDTO; +import cn.lunadeer.dominion.utils.Notification; +import cn.lunadeer.dominion.utils.XLogger; +import org.bukkit.entity.Player; + +import javax.annotation.Nullable; +import java.util.*; + +public class Cache { + + public Cache() { + player_current_dominion = new HashMap<>(); + loadDominions(); + loadPlayerPrivileges(); + } + + /** + * 从数据库加载所有领地 + */ + public void loadDominions() { + world_dominions = new HashMap<>(); + List dominions = DominionDTO.selectAll(); + for (DominionDTO d : dominions) { + if (!world_dominions.containsKey(d.getWorld())) { + world_dominions.put(d.getWorld(), new ArrayList<>()); + } + world_dominions.get(d.getWorld()).add(d); + } + } + + /** + * 从数据库加载所有玩家特权 + */ + public void loadPlayerPrivileges() { + player_current_dominion = new HashMap<>(); + List all_privileges = PlayerPrivilegeDTO.selectAll(); + if (all_privileges == null) { + XLogger.err("加载玩家特权失败"); + return; + } + player_uuid_to_privilege = new HashMap<>(); + for (PlayerPrivilegeDTO privilege : all_privileges) { + UUID player_uuid = privilege.getPlayerUUID(); + if (!player_uuid_to_privilege.containsKey(player_uuid)) { + player_uuid_to_privilege.put(player_uuid, new HashMap<>()); + } + player_uuid_to_privilege.get(player_uuid).put(privilege.getDomID(), privilege); + } + } + + /** + * 获取玩家当前所在领地 + * 此方法会先判断缓存中是否有玩家当前所在领地,如果没有则遍历所有领地判断玩家所在位置 + * 如果玩家不在任何领地内,则返回null + * 如果玩家在领地内,则返回领地信息 + * + * @param player 玩家 + * @return 玩家当前所在领地 + */ + public DominionDTO getPlayerCurrentDominion(Player player) { + DominionDTO dominion = player_current_dominion.get(player.getUniqueId()); + if (dominion != null) { + if (!isInDominion(dominion, player)) { + Notification.info(player, "您已离开领地:" + dominion.getName()); + Notification.info(player, dominion.getLeaveMessage()); + player_current_dominion.put(player.getUniqueId(), null); + dominion = null; + } + } + if (dominion == null) { + String world = player.getWorld().getName(); + List dominions = world_dominions.get(world); + if (dominions == null) return null; + List in_dominions = new ArrayList<>(); + for (DominionDTO d : dominions) { + if (isInDominion(d, player)) { + in_dominions.add(d); + } + } + if (in_dominions.size() == 0) return null; + in_dominions.sort(Comparator.comparingInt(DominionDTO::getId)); + dominion = in_dominions.get(in_dominions.size() - 1); + player_current_dominion.put(player.getUniqueId(), dominion); + Notification.info(player, "您正在进入领地:" + dominion.getName()); + Notification.info(player, dominion.getJoinMessage()); + } + return dominion; + } + + /** + * 获取玩家在指定领地的特权 + * 如果玩家不存在特权,则返回null + * + * @param player 玩家 + * @param dominion 领地 + * @return 特权表 + */ + public PlayerPrivilegeDTO getPlayerPrivilege(Player player, DominionDTO dominion) { + if (!player_uuid_to_privilege.containsKey(player.getUniqueId())) return null; + return player_uuid_to_privilege.get(player.getUniqueId()).get(dominion.getId()); + } + + private static boolean isInDominion(@Nullable DominionDTO dominion, Player player) { + if (dominion == null) return false; + double x = player.getLocation().getX(); + double y = player.getLocation().getY(); + double z = player.getLocation().getZ(); + return x >= dominion.getX1() && x <= dominion.getX2() && + y >= dominion.getY1() && y <= dominion.getY2() && + z >= dominion.getZ1() && z <= dominion.getZ2(); + } + + public static Cache instance; + private Map> world_dominions; // 所有领地 + private Map> player_uuid_to_privilege; // 玩家所有的特权 + private Map player_current_dominion; // 玩家当前所在领地 +} diff --git a/src/main/java/cn/lunadeer/dominion/Dominion.java b/src/main/java/cn/lunadeer/dominion/Dominion.java index 2482398..d3ef5ac 100644 --- a/src/main/java/cn/lunadeer/dominion/Dominion.java +++ b/src/main/java/cn/lunadeer/dominion/Dominion.java @@ -20,6 +20,7 @@ public final class Dominion extends JavaPlugin { config = new ConfigManager(this); dbConnection = Database.createConnection(); Database.migrate(); + Cache.instance = new Cache(); Bukkit.getPluginManager().registerEvents(new PlayerEvents(), this); Objects.requireNonNull(Bukkit.getPluginCommand("dominion")).setExecutor(new Commands()); diff --git a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java index 6683ef7..691ceaa 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/DominionDTO.java @@ -1,5 +1,6 @@ package cn.lunadeer.dominion.dtos; +import cn.lunadeer.dominion.Cache; import cn.lunadeer.dominion.utils.Database; import cn.lunadeer.dominion.utils.XLogger; @@ -69,6 +70,10 @@ public class DominionDTO { rs.getBoolean("harvest")); dominions.add(dominion); } + if (sql.contains("UPDATE") || sql.contains("DELETE") || sql.contains("INSERT")) { + // 如果是更新操作,重新加载缓存 + Cache.instance.loadDominions(); + } } catch (SQLException e) { XLogger.err("Database query failed: " + e.getMessage()); XLogger.err("SQL: " + sql); @@ -177,7 +182,7 @@ public class DominionDTO { "cake = " + dominion.getCake() + ", " + "container = " + dominion.getContainer() + ", " + "craft = " + dominion.getCraft() + ", " + - "creeper_explode = " + dominion.getCreeperExplode() + ", " + + "creeper_explode = " + dominion.getCreeperExplode() + ", " + // dom only "diode = " + dominion.getDiode() + ", " + "door = " + dominion.getDoor() + ", " + "dye = " + dominion.getDye() + ", " + @@ -185,8 +190,8 @@ public class DominionDTO { "enchant = " + dominion.getEnchant() + ", " + "ender_pearl = " + dominion.getEnderPearl() + ", " + "feed = " + dominion.getFeed() + ", " + - "fire_spread = " + dominion.getFireSpread() + ", " + - "flow_in_protection = " + dominion.getFlowInProtection() + ", " + + "fire_spread = " + dominion.getFireSpread() + ", " + // dom only + "flow_in_protection = " + dominion.getFlowInProtection() + ", " + // dom only "glow = " + dominion.getGlow() + ", " + "grow = " + dominion.getGrow() + ", " + "honey = " + dominion.getHoney() + ", " + @@ -199,10 +204,10 @@ public class DominionDTO { "riding = " + dominion.getRiding() + ", " + "shear = " + dominion.getShear() + ", " + "shoot = " + dominion.getShoot() + ", " + - "tnt_explode = " + dominion.getTntExplode() + ", " + + "tnt_explode = " + dominion.getTntExplode() + ", " + // dom only "trade = " + dominion.getTrade() + ", " + "vehicle_destroy = " + dominion.getVehicleDestroy() + ", " + - "wither_spawn = " + dominion.getWitherSpawn() + ", " + + "wither_spawn = " + dominion.getWitherSpawn() + ", " + // dom only "harvest = " + dominion.getHarvest() + " WHERE id = " + dominion.getId() + " RETURNING *;"; diff --git a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java index 4b1b293..a6961a8 100644 --- a/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java +++ b/src/main/java/cn/lunadeer/dominion/dtos/PlayerPrivilegeDTO.java @@ -1,5 +1,6 @@ package cn.lunadeer.dominion.dtos; +import cn.lunadeer.dominion.Cache; import cn.lunadeer.dominion.utils.Database; import cn.lunadeer.dominion.utils.XLogger; @@ -40,6 +41,11 @@ public class PlayerPrivilegeDTO { query(sql); } + public static List selectAll(){ + String sql = "SELECT * FROM player_privilege;"; + return query(sql); + } + private final Integer id; private final UUID playerUUID; private Boolean admin; @@ -476,6 +482,10 @@ public class PlayerPrivilegeDTO { ); players.add(player); } + if (sql.contains("UPDATE") || sql.contains("DELETE") || sql.contains("INSERT")){ + // 如果是更新操作,重新加载缓存 + Cache.instance.loadPlayerPrivileges(); + } } catch (Exception e) { XLogger.err("Database query failed: " + e.getMessage()); XLogger.err("SQL: " + sql); diff --git a/src/main/java/cn/lunadeer/dominion/utils/Database.java b/src/main/java/cn/lunadeer/dominion/utils/Database.java index f174a68..147b234 100644 --- a/src/main/java/cn/lunadeer/dominion/utils/Database.java +++ b/src/main/java/cn/lunadeer/dominion/utils/Database.java @@ -144,6 +144,7 @@ public class Database { " vehicle_destroy BOOLEAN NOT NULL DEFAULT FALSE," + " harvest BOOLEAN NOT NULL DEFAULT FALSE," + + " UNIQUE (player_uuid, dom_id)," + " FOREIGN KEY (player_uuid) REFERENCES player_name(uuid)," + " FOREIGN KEY (dom_id) REFERENCES dominion(id)" + ");";