Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@

<groupId>ict.minesunshineone</groupId>
<artifactId>LandmarkSystem</artifactId>
<version>1.6</version>
<version>1.7</version>

<properties>
<java.version>21</java.version>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand All @@ -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
Expand Down
Original file line number Diff line number Diff line change
@@ -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", "<red>该命令只能由玩家执行!</red>");
return;
}

Player player = (Player) sender;
plugin.getLandmarkManager().unlockAllLandmarks(player);
}

@Override
public String getPermission() {
return "landmark.unlock.all";
}

@Override
public List<String> onTabComplete(CommandSender sender, String[] args) {
return Collections.emptyList();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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 {

Expand Down Expand Up @@ -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) {
Expand Down Expand Up @@ -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);

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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());
}
Expand Down Expand Up @@ -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) {
Expand All @@ -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<String> 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", "<gradient:green:aqua>✧ 魔法师解开了所有锚点的封印!</gradient>");
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -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; // 在菜单中的列位置

Expand Down Expand Up @@ -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;
}
Expand Down
7 changes: 1 addition & 6 deletions src/main/resources/config.yml
Original file line number Diff line number Diff line change
Expand Up @@ -41,12 +41,7 @@ messages:
separator: '<gradient:gold:yellow>✧══════════ 魔法锚点咒语书 ══════════✧</gradient>'
command: '%prefix% <yellow>%command%</yellow>'
landmark-exists: '<gradient:red:dark_red>✧ 魔法师,这个锚点名称已被占用了!</gradient>'
create-title: '<gradient:gold:yellow>✧══════════ 魔法锚点 ══════════✧</gradient>'
create-subtitle: '<gradient:green:aqua>成功创造新的锚点!</gradient>'
delete-title: '<gradient:red:dark_red>✧══════════ 魔法锚点 ══════════✧</gradient>'
delete-subtitle: '<gradient:red:dark_red>锚点已被抹除!</gradient>'
rename-title: '<gradient:gold:yellow>✧══════════ 魔法锚点 ══════════✧</gradient>'
rename-subtitle: '<gradient:green:aqua>锚点重命名成功!</gradient>'
unlock-all-success: '<gradient:green:aqua>✧ 魔法师成功解开了所有锚点的封印!</gradient>'

# GUI设置
gui:
Expand Down
6 changes: 6 additions & 0 deletions src/main/resources/plugin.yml
Original file line number Diff line number Diff line change
Expand Up @@ -39,4 +39,10 @@ permissions:
default: true
landmark.admin:
description: 管理员权限
default: op
landmark.unlock.all:
description: 允许一键解锁所有锚点
default: op
landmark.bypass.cooldown:
description: 允许无视传送冷却
default: op
Loading