diff --git a/pom.xml b/pom.xml index 90fde81..8c3431e 100644 --- a/pom.xml +++ b/pom.xml @@ -6,7 +6,7 @@ ict.minesunshineone LandmarkSystem - 1.6 + 1.7 21 diff --git a/src/main/java/ict/minesunshineone/landmark/command/LandmarkCommand.java b/src/main/java/ict/minesunshineone/landmark/command/LandmarkCommand.java index 1cf0a67..11e72f7 100644 --- a/src/main/java/ict/minesunshineone/landmark/command/LandmarkCommand.java +++ b/src/main/java/ict/minesunshineone/landmark/command/LandmarkCommand.java @@ -20,6 +20,7 @@ import ict.minesunshineone.landmark.command.impl.ReloadCommand; import ict.minesunshineone.landmark.command.impl.RenameCommand; import ict.minesunshineone.landmark.command.impl.TeleportCommand; +import ict.minesunshineone.landmark.command.impl.UnlockAllCommand; public class LandmarkCommand implements CommandExecutor, TabCompleter { @@ -40,6 +41,7 @@ private void registerSubCommands() { subCommands.put("rename", new RenameCommand(plugin)); subCommands.put("edit", new EditCommand(plugin)); subCommands.put("reload", new ReloadCommand(plugin)); + subCommands.put("unlockall", new UnlockAllCommand(plugin)); } @Override diff --git a/src/main/java/ict/minesunshineone/landmark/command/impl/UnlockAllCommand.java b/src/main/java/ict/minesunshineone/landmark/command/impl/UnlockAllCommand.java new file mode 100644 index 0000000..7ae1dc6 --- /dev/null +++ b/src/main/java/ict/minesunshineone/landmark/command/impl/UnlockAllCommand.java @@ -0,0 +1,38 @@ +package ict.minesunshineone.landmark.command.impl; + +import java.util.Collections; +import java.util.List; + +import org.bukkit.command.CommandSender; +import org.bukkit.entity.Player; + +import ict.minesunshineone.landmark.LandmarkPlugin; +import ict.minesunshineone.landmark.command.SubCommand; + +public class UnlockAllCommand extends SubCommand { + + public UnlockAllCommand(LandmarkPlugin plugin) { + super(plugin); + } + + @Override + public void execute(CommandSender sender, String[] args) { + if (!(sender instanceof Player)) { + plugin.getConfigManager().sendMessage(sender, "command-player-only", "该命令只能由玩家执行!"); + return; + } + + Player player = (Player) sender; + plugin.getLandmarkManager().unlockAllLandmarks(player); + } + + @Override + public String getPermission() { + return "landmark.unlock.all"; + } + + @Override + public List onTabComplete(CommandSender sender, String[] args) { + return Collections.emptyList(); + } +} diff --git a/src/main/java/ict/minesunshineone/landmark/listener/PlayerListener.java b/src/main/java/ict/minesunshineone/landmark/listener/PlayerListener.java index bf28c32..0c68877 100644 --- a/src/main/java/ict/minesunshineone/landmark/listener/PlayerListener.java +++ b/src/main/java/ict/minesunshineone/landmark/listener/PlayerListener.java @@ -8,17 +8,13 @@ import org.bukkit.Location; import org.bukkit.Particle; import org.bukkit.Sound; -import org.bukkit.block.Block; import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.entity.Entity; -import org.bukkit.entity.Interaction; import org.bukkit.entity.Player; import org.bukkit.event.EventHandler; import org.bukkit.event.EventPriority; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.inventory.InventoryClickEvent; -import org.bukkit.event.player.PlayerInteractAtEntityEvent; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerMoveEvent; import org.bukkit.event.player.PlayerQuitEvent; @@ -283,44 +279,27 @@ public void cleanup() { lastCheckTimes.clear(); } - @EventHandler + @EventHandler(priority = EventPriority.LOWEST) public void onPlayerInteract(PlayerInteractEvent event) { - if (event.getAction() != Action.RIGHT_CLICK_BLOCK) { - return; - } - - Block block = event.getClickedBlock(); - if (block == null) { - return; - } + Action action = event.getAction(); + Player player = event.getPlayer(); - // 检查是否是锚点中心方块 - for (Landmark landmark : plugin.getLandmarkManager().getLandmarks().values()) { - Location landmarkLoc = landmark.getLocation(); - if (block.getLocation().equals(landmarkLoc)) { - event.setCancelled(true); - new LandmarkMenu(plugin, event.getPlayer()).open(); - break; + // 检查是否是左键动作,并且点击的是空气(不要问为什么不右键,因为右键的事件好像有问题) + if (action == Action.LEFT_CLICK_AIR) { + // 检查权限 + if (!player.hasPermission("landmark.menu")) { + return; } - } - } - - @EventHandler - public void onPlayerInteractAtEntity(PlayerInteractAtEntityEvent event) { - Entity entity = event.getRightClicked(); - if (!(entity instanceof Interaction)) { - return; - } - - Player player = event.getPlayer(); - // 检查是否是锚点交互实体 - for (Landmark landmark : plugin.getLandmarkManager().getLandmarks().values()) { - if (landmark.getInteractionEntityId() != null - && landmark.getInteractionEntityId().equals(entity.getUniqueId())) { - event.setCancelled(true); - new LandmarkMenu(plugin, player).open(); - break; + // 检查玩家是否在任意锚点范围内 + for (Landmark landmark : plugin.getLandmarkManager().getLandmarks().values()) { + if (plugin.getLandmarkManager().isPlayerNearLandmark(player, landmark.getLocation())) { + // 在锚点范围内,打开菜单 + plugin.getServer().getRegionScheduler().execute(plugin, player.getLocation(), () -> { + new LandmarkMenu(plugin, player).open(); + }); + return; + } } } } diff --git a/src/main/java/ict/minesunshineone/landmark/manager/LandmarkManager.java b/src/main/java/ict/minesunshineone/landmark/manager/LandmarkManager.java index f020292..e2e939c 100644 --- a/src/main/java/ict/minesunshineone/landmark/manager/LandmarkManager.java +++ b/src/main/java/ict/minesunshineone/landmark/manager/LandmarkManager.java @@ -10,17 +10,14 @@ import java.util.Set; import java.util.UUID; -import org.bukkit.Bukkit; import org.bukkit.Location; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.entity.Entity; -import org.bukkit.entity.Interaction; import org.bukkit.entity.Player; import ict.minesunshineone.landmark.LandmarkPlugin; import ict.minesunshineone.landmark.model.Landmark; -import net.kyori.adventure.text.Component; public class LandmarkManager { @@ -55,9 +52,6 @@ public void createLandmark(String name, Location location, String description) { Landmark landmark = new Landmark(name, location, description, menuPosition[0], menuPosition[1]); landmarks.put(name.toLowerCase(), landmark); - // 使用统一的方法创建实体 - createLandmarkEntities(landmark); - plugin.getSLF4JLogger().info("成功创建锚点展示实体: {}", name); saveData(); } catch (IllegalArgumentException | IllegalStateException e) { @@ -107,25 +101,6 @@ public void deleteLandmark(String name) { String lowerName = name.toLowerCase(); Landmark landmark = landmarks.get(lowerName); if (landmark != null) { - // 移除交互实体 - if (landmark.getInteractionEntityId() != null) { - Location loc = landmark.getLocation(); - if (loc != null && loc.getWorld() != null) { - // 移除交互实体 - Entity entity = Bukkit.getEntity(landmark.getInteractionEntityId()); - if (entity != null) { - entity.remove(); - } - - // 移除同位置的所有具有相同名称的交互实体 - loc.getWorld().getNearbyEntities(loc, 2, 2, 2).stream() - .filter(e -> e instanceof Interaction) - .filter(e -> e.customName() != null && e.customName().equals(Component.text("§e[点击打开]"))) - .forEach(Entity::remove); - } - landmark.setInteractionEntityId(null); - } - // 移除锚点数据 landmarks.remove(lowerName); @@ -156,6 +131,10 @@ public void unlockLandmark(Player player, String landmarkName) { } public boolean canTeleport(Player player) { + // 如果玩家有无视冷却权限,直接返回true + if (player.hasPermission("landmark.bypass.cooldown")) { + return true; + } long lastTeleport = cooldowns.getOrDefault(player.getUniqueId(), 0L); long cooldownTime = plugin.getConfigManager().getCooldownTime() * 1000L; return System.currentTimeMillis() - lastTeleport >= cooldownTime; @@ -254,19 +233,7 @@ public final void loadData() { int menuColumn = landmarkSection.getInt("menu_column", 1); Landmark landmark = new Landmark(key, location, description, menuRow, menuColumn); - String interactionId = landmarkSection.getString("interaction_entity_id"); - if (interactionId != null) { - landmark.setInteractionEntityId(UUID.fromString(interactionId)); - } - landmarks.put(key.toLowerCase(), landmark); - - // 延迟创建实体,确保世界加载完成 - plugin.getServer().getRegionScheduler().runDelayed(plugin, location, task -> { - if (location.getWorld() != null && location.getChunk().isLoaded()) { - createLandmarkEntities(landmark); - } - }, 100L); } } catch (IllegalArgumentException | IllegalStateException e) { plugin.getSLF4JLogger().error("加载锚点 {} 时发生错误: {}", key, e.getMessage()); @@ -308,8 +275,6 @@ public void saveData() { Landmark landmark = entry.getValue(); landmarkSection.set("location", landmark.getLocation()); landmarkSection.set("description", landmark.getDescription()); - landmarkSection.set("interaction_entity_id", landmark.getInteractionEntityId() != null - ? landmark.getInteractionEntityId().toString() : null); landmarkSection.set("menu_row", landmark.getMenuRow()); landmarkSection.set("menu_column", landmark.getMenuColumn()); } @@ -428,68 +393,13 @@ public boolean isPlayerNearLandmark(Player player, Location landmarkLoc) { && playerLoc.distance(landmarkLoc) <= plugin.getConfigManager().getUnlockRadius(); } - private void createLandmarkEntities(Landmark landmark) { - try { - Location location = landmark.getLocation(); - if (location.getWorld() == null || !location.getChunk().isLoaded()) { - return; - } - - // 确保位置是方块中心 - Location centerLoc = location.clone(); - centerLoc.setX(location.getBlockX() + 0.5); - centerLoc.setY(location.getBlockY()); - centerLoc.setZ(location.getBlockZ() + 0.5); - - // 创建交互实体 - Location interactLoc = centerLoc.clone().add(0, 0, 0); - Interaction interaction = location.getWorld().spawn(interactLoc, Interaction.class, entity -> { - entity.setInteractionWidth(3.5f); - entity.setInteractionHeight(2.0f); - entity.setPersistent(true); - entity.setInvulnerable(true); - entity.setCustomNameVisible(true); - entity.customName(Component.text("§e[点击打开]")); - entity.setGravity(false); - }); - - landmark.setInteractionEntityId(interaction.getUniqueId()); - saveData(); // 保存实体ID - } catch (IllegalArgumentException | IllegalStateException e) { - plugin.getSLF4JLogger().error("重建锚点实体时发生错误: {}", e.getMessage()); - } - } - public void cleanup() { - // 清理所有实体 - for (Landmark landmark : landmarks.values()) { - removeLandmarkEntities(landmark); - } - // 清理数据结构 landmarks.clear(); unlockedLandmarks.clear(); cooldowns.clear(); } - private void removeLandmarkEntities(Landmark landmark) { - if (landmark.getDisplayEntityId() != null) { - Entity entity = Bukkit.getEntity(landmark.getDisplayEntityId()); - if (entity != null) { - entity.remove(); - } - landmark.setDisplayEntityId(null); - } - - if (landmark.getInteractionEntityId() != null) { - Entity entity = Bukkit.getEntity(landmark.getInteractionEntityId()); - if (entity != null) { - entity.remove(); - } - landmark.setInteractionEntityId(null); - } - } - public void updateMenuPosition(String landmarkName, int newRow, int newColumn) { Landmark landmark = landmarks.get(landmarkName.toLowerCase()); if (landmark != null) { @@ -501,4 +411,17 @@ public void updateMenuPosition(String landmarkName, int newRow, int newColumn) { } } } + + // 新增一键解锁所有锚点的方法 + public void unlockAllLandmarks(Player player) { + if (!player.hasPermission("landmark.unlock.all")) { + return; + } + Set playerUnlocked = unlockedLandmarks.computeIfAbsent(player.getUniqueId(), k -> new HashSet<>()); + for (String landmarkName : landmarks.keySet()) { + playerUnlocked.add(landmarkName.toLowerCase()); + } + savePlayerData(player.getUniqueId()); + plugin.getConfigManager().sendMessage(player, "unlock-all-success", "✧ 魔法师解开了所有锚点的封印!"); + } } diff --git a/src/main/java/ict/minesunshineone/landmark/model/Landmark.java b/src/main/java/ict/minesunshineone/landmark/model/Landmark.java index 66c198e..82c7ec7 100644 --- a/src/main/java/ict/minesunshineone/landmark/model/Landmark.java +++ b/src/main/java/ict/minesunshineone/landmark/model/Landmark.java @@ -10,7 +10,6 @@ public class Landmark { private Location location; private String description; private UUID displayEntityId; - private UUID interactionEntityId; private int menuRow; // 在菜单中的行位置 private int menuColumn; // 在菜单中的列位置 @@ -62,14 +61,6 @@ public void setDisplayEntityId(UUID displayEntityId) { this.displayEntityId = displayEntityId; } - public UUID getInteractionEntityId() { - return interactionEntityId; - } - - public void setInteractionEntityId(UUID interactionEntityId) { - this.interactionEntityId = interactionEntityId; - } - public int getMenuRow() { return menuRow; } diff --git a/src/main/resources/config.yml b/src/main/resources/config.yml index 0532c90..9e86db0 100644 --- a/src/main/resources/config.yml +++ b/src/main/resources/config.yml @@ -41,12 +41,7 @@ messages: separator: '✧══════════ 魔法锚点咒语书 ══════════✧' command: '%prefix% %command%' landmark-exists: '✧ 魔法师,这个锚点名称已被占用了!' - create-title: '✧══════════ 魔法锚点 ══════════✧' - create-subtitle: '成功创造新的锚点!' - delete-title: '✧══════════ 魔法锚点 ══════════✧' - delete-subtitle: '锚点已被抹除!' - rename-title: '✧══════════ 魔法锚点 ══════════✧' - rename-subtitle: '锚点重命名成功!' + unlock-all-success: '✧ 魔法师成功解开了所有锚点的封印!' # GUI设置 gui: diff --git a/src/main/resources/plugin.yml b/src/main/resources/plugin.yml index d12f910..074d5d4 100644 --- a/src/main/resources/plugin.yml +++ b/src/main/resources/plugin.yml @@ -39,4 +39,10 @@ permissions: default: true landmark.admin: description: 管理员权限 + default: op + landmark.unlock.all: + description: 允许一键解锁所有锚点 + default: op + landmark.bypass.cooldown: + description: 允许无视传送冷却 default: op \ No newline at end of file