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