Skip to content

Commit 04d6723

Browse files
拆分代码,新增bossbar可自定义
1 parent 698aaf0 commit 04d6723

11 files changed

Lines changed: 747 additions & 361 deletions

File tree

src/main/java/ict/minesunshineone/peek/PeekPlugin.java

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,8 @@ public void onDisable() {
8787
stateHandler.endPeek(player, true);
8888
}
8989
});
90+
// 清理所有剩余资源(BossBar、距离检查器等)
91+
stateHandler.cleanup();
9092
}
9193

9294
if (statisticsManager != null) {
Lines changed: 214 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,214 @@
1+
package ict.minesunshineone.peek.handler;
2+
3+
import java.util.HashMap;
4+
import java.util.Map;
5+
import java.util.UUID;
6+
7+
import org.bukkit.Bukkit;
8+
import org.bukkit.boss.BarColor;
9+
import org.bukkit.boss.BarStyle;
10+
import org.bukkit.boss.BossBar;
11+
import org.bukkit.entity.Player;
12+
13+
import ict.minesunshineone.peek.PeekPlugin;
14+
import ict.minesunshineone.peek.data.PeekData;
15+
16+
/**
17+
* 负责管理 Peek 模式下的 BossBar 显示
18+
* 包括创建、更新、删除 BossBar 以及配置解析
19+
*/
20+
public class BossBarHandler {
21+
22+
private final PeekPlugin plugin;
23+
private final Map<UUID, BossBar> distanceBossBars = new HashMap<>();
24+
25+
// BossBar 配置
26+
private final boolean enabled;
27+
private final String titleFormat;
28+
private final BarStyle style;
29+
private final BarColor colorSafe;
30+
private final BarColor colorWarning;
31+
private final BarColor colorDanger;
32+
private final double thresholdWarning;
33+
private final double thresholdDanger;
34+
private final double maxPeekDistance;
35+
36+
public BossBarHandler(PeekPlugin plugin) {
37+
this.plugin = plugin;
38+
this.maxPeekDistance = plugin.getConfig().getDouble("limits.max-peek-distance", 50.0);
39+
40+
// 加载 BossBar 配置
41+
this.enabled = plugin.getConfig().getBoolean("bossbar.enabled", true);
42+
this.titleFormat = plugin.getConfig().getString("bossbar.title", "&d距离 &f{target}&d: &e{distance} &7/ &e{max_distance} &d格");
43+
this.style = parseBarStyle(plugin.getConfig().getString("bossbar.style", "SEGMENTED_10"));
44+
this.colorSafe = parseBarColor(plugin.getConfig().getString("bossbar.colors.safe", "GREEN"));
45+
this.colorWarning = parseBarColor(plugin.getConfig().getString("bossbar.colors.warning", "YELLOW"));
46+
this.colorDanger = parseBarColor(plugin.getConfig().getString("bossbar.colors.danger", "RED"));
47+
this.thresholdWarning = plugin.getConfig().getDouble("bossbar.thresholds.warning", 0.5);
48+
this.thresholdDanger = plugin.getConfig().getDouble("bossbar.thresholds.danger", 0.75);
49+
}
50+
51+
private BarStyle parseBarStyle(String style) {
52+
try {
53+
return BarStyle.valueOf(style.toUpperCase());
54+
} catch (IllegalArgumentException e) {
55+
plugin.getLogger().warning(String.format("无效的 BossBar 样式: %s,使用默认值 SEGMENTED_10", style));
56+
return BarStyle.SEGMENTED_10;
57+
}
58+
}
59+
60+
private BarColor parseBarColor(String color) {
61+
try {
62+
return BarColor.valueOf(color.toUpperCase());
63+
} catch (IllegalArgumentException e) {
64+
plugin.getLogger().warning(String.format("无效的 BossBar 颜色: %s,使用默认值 GREEN", color));
65+
return BarColor.GREEN;
66+
}
67+
}
68+
69+
/**
70+
* 为观察者创建距离显示 BossBar
71+
* @param peeker 观察者
72+
* @param target 目标玩家
73+
*/
74+
public void createDistanceBossBar(Player peeker, Player target) {
75+
if (!enabled) return;
76+
77+
removeDistanceBossBar(peeker); // 确保没有残留
78+
79+
String title = formatBossBarTitle(target.getName(), 0.0);
80+
BossBar bar = Bukkit.createBossBar(
81+
title,
82+
colorSafe,
83+
style
84+
);
85+
bar.setProgress(0.0);
86+
bar.addPlayer(peeker);
87+
distanceBossBars.put(peeker.getUniqueId(), bar);
88+
logDebug("Created BossBar for player %s, target: %s", peeker.getName(), target.getName());
89+
}
90+
91+
/**
92+
* 为自我观察模式创建距离显示 BossBar
93+
* @param peeker 观察者(同时也是目标)
94+
* @param selfPeekLabel 自我观察的标签(如"原点")
95+
*/
96+
public void createSelfPeekBossBar(Player peeker, String selfPeekLabel) {
97+
if (!enabled) return;
98+
99+
removeDistanceBossBar(peeker); // 确保没有残留
100+
101+
String title = formatBossBarTitle(selfPeekLabel, 0.0);
102+
BossBar bar = Bukkit.createBossBar(
103+
title,
104+
colorSafe,
105+
style
106+
);
107+
bar.setProgress(0.0);
108+
bar.addPlayer(peeker);
109+
distanceBossBars.put(peeker.getUniqueId(), bar);
110+
logDebug("Created self-peek BossBar for player %s", peeker.getName());
111+
}
112+
113+
private String formatBossBarTitle(String targetName, double distance) {
114+
return titleFormat
115+
.replace("{target}", targetName)
116+
.replace("{distance}", String.format("%.1f", distance))
117+
.replace("{max_distance}", String.format("%.1f", maxPeekDistance))
118+
.replace("&", "§");
119+
}
120+
121+
/**
122+
* 更新观察者的距离 BossBar
123+
* @param peeker 观察者
124+
* @param distance 当前距离
125+
* @param targetName 目标玩家名称
126+
*/
127+
public void updateDistanceBossBar(Player peeker, double distance, String targetName) {
128+
if (!enabled) return;
129+
130+
BossBar bar = distanceBossBars.get(peeker.getUniqueId());
131+
if (bar == null) return;
132+
133+
double progress = Math.min(distance / maxPeekDistance, 1.0);
134+
bar.setProgress(progress);
135+
136+
// 根据配置的阈值改变颜色
137+
if (progress < thresholdWarning) {
138+
bar.setColor(colorSafe);
139+
} else if (progress < thresholdDanger) {
140+
bar.setColor(colorWarning);
141+
} else {
142+
bar.setColor(colorDanger);
143+
}
144+
145+
bar.setTitle(formatBossBarTitle(targetName, distance));
146+
}
147+
148+
/**
149+
* 更新观察者的距离 BossBar(从 PeekData 获取目标信息)
150+
* @param peeker 观察者
151+
* @param distance 当前距离
152+
* @param data PeekData 数据
153+
*/
154+
public void updateDistanceBossBar(Player peeker, double distance, PeekData data) {
155+
if (!enabled || data == null) return;
156+
157+
Player target = plugin.getServer().getPlayer(data.getTargetUUID());
158+
String targetName = target != null ? target.getName() : "未知";
159+
updateDistanceBossBar(peeker, distance, targetName);
160+
}
161+
162+
/**
163+
* 移除观察者的距离 BossBar
164+
* @param peeker 观察者
165+
*/
166+
public void removeDistanceBossBar(Player peeker) {
167+
BossBar bar = distanceBossBars.remove(peeker.getUniqueId());
168+
if (bar != null) {
169+
bar.removeAll();
170+
}
171+
}
172+
173+
/**
174+
* 安全地移除 BossBar(使用正确的线程调度)
175+
* @param peeker 观察者
176+
*/
177+
public void safeRemoveDistanceBossBar(Player peeker) {
178+
// 如果插件已禁用,直接移除而不使用调度器
179+
if (!plugin.isEnabled()) {
180+
removeDistanceBossBar(peeker);
181+
return;
182+
}
183+
184+
if (peeker.isOnline()) {
185+
peeker.getScheduler().run(plugin, scheduledTask -> removeDistanceBossBar(peeker), null);
186+
} else {
187+
removeDistanceBossBar(peeker);
188+
}
189+
}
190+
191+
/**
192+
* 检查是否启用 BossBar
193+
* @return 是否启用
194+
*/
195+
public boolean isEnabled() {
196+
return enabled;
197+
}
198+
199+
/**
200+
* 清理所有 BossBar
201+
*/
202+
public void cleanup() {
203+
new HashMap<>(distanceBossBars).forEach((uuid, bar) -> {
204+
bar.removeAll();
205+
distanceBossBars.remove(uuid);
206+
});
207+
}
208+
209+
private void logDebug(String message, Object... args) {
210+
if (plugin.getConfig().getBoolean("debug", false)) {
211+
plugin.getLogger().info(String.format(message, args));
212+
}
213+
}
214+
}

0 commit comments

Comments
 (0)