Skip to content

Commit 9349fdc

Browse files
优化代码
1 parent 0922e32 commit 9349fdc

3 files changed

Lines changed: 103 additions & 45 deletions

File tree

pom.xml

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,9 +31,9 @@
3131

3232
<dependencies>
3333
<dependency>
34-
<groupId>dev.folia</groupId>
35-
<artifactId>folia-api</artifactId>
36-
<version>1.20.1-R0.1-SNAPSHOT</version>
34+
<groupId>io.papermc.paper</groupId>
35+
<artifactId>paper-api</artifactId>
36+
<version>1.21.1-R0.1-SNAPSHOT</version>
3737
<scope>provided</scope>
3838
</dependency>
3939
<dependency>

src/main/java/ict/minesunshineone/peek/handler/PeekStateHandler.java

Lines changed: 89 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,10 @@
88
import org.bukkit.GameMode;
99
import org.bukkit.Location;
1010
import org.bukkit.Sound;
11+
import org.bukkit.attribute.Attribute;
12+
import org.bukkit.attribute.AttributeInstance;
1113
import org.bukkit.entity.Player;
14+
import org.bukkit.event.player.PlayerTeleportEvent.TeleportCause;
1215
import org.bukkit.util.Vector;
1316

1417
import ict.minesunshineone.peek.PeekPlugin;
@@ -263,7 +266,7 @@ private void teleportAndSetGameMode(Player peeker, Player target) {
263266

264267
// 等待1 tick后再传送
265268
plugin.getServer().getRegionScheduler().runDelayed(plugin, peeker.getLocation(), delayedTask -> {
266-
peeker.teleportAsync(target.getLocation()).thenAccept(success -> {
269+
peeker.teleportAsync(target.getLocation(), TeleportCause.PLUGIN).thenAccept(success -> {
267270
if (!success) {
268271
plugin.getMessages().send(peeker, "teleport-failed");
269272
endPeek(peeker);
@@ -290,58 +293,102 @@ public void restorePlayerState(Player peeker, PeekData data) {
290293
// 在传送前先清除动量
291294
peeker.setVelocity(new Vector(0, 0, 0));
292295

293-
peeker.teleportAsync(data.getOriginalLocation()).thenAccept(success -> {
296+
peeker.teleportAsync(data.getOriginalLocation(), TeleportCause.PLUGIN).thenAccept(success -> {
294297
if (success) {
295298
// 传送成功后再改变游戏模式
296299
plugin.getServer().getRegionScheduler().run(plugin, data.getOriginalLocation(), modeTask -> {
297-
// 再次确保动量为0
298-
peeker.setVelocity(new Vector(0, 0, 0));
299-
300-
peeker.setGameMode(data.getOriginalGameMode());
301-
// 恢复新增状态
302-
peeker.setHealth(Math.min(data.getHealth(), 20));
303-
peeker.setFoodLevel(data.getFoodLevel());
304-
peeker.setSaturation(data.getSaturation());
305-
306-
// 清除现有效果并应用保存的效果
307-
peeker.getActivePotionEffects().forEach(effect
308-
-> peeker.removePotionEffect(effect.getType()));
309-
data.getPotionEffects().forEach(effect
310-
-> peeker.addPotionEffect(effect));
300+
applyRestoredState(peeker, data);
311301
});
312302
} else {
313-
plugin.getLogger().warning(String.format(
314-
"无法将玩家 %s 传送回原位置,正在尝试传送到重生点",
315-
peeker.getName()
316-
));
317-
318-
Location spawnLoc = peeker.getBedSpawnLocation() != null
319-
? peeker.getBedSpawnLocation()
320-
: peeker.getWorld().getSpawnLocation();
321-
322-
if (spawnLoc != null) {
323-
plugin.getServer().getRegionScheduler().run(plugin, spawnLoc, spawnTask -> {
324-
peeker.teleportAsync(spawnLoc).thenAccept(spawnSuccess -> {
325-
if (spawnSuccess) {
326-
// 传送到重生点成功后再改变游戏模式
327-
plugin.getServer().getRegionScheduler().run(plugin, spawnLoc, modeTask -> {
328-
peeker.setGameMode(data.getOriginalGameMode());
329-
});
330-
} else {
331-
plugin.getLogger().severe(String.format(
332-
"无法将玩家 %s 传送到任何安全位置",
333-
peeker.getName()
334-
));
335-
}
336-
});
303+
handleTeleportFailure(peeker, data);
304+
}
305+
});
306+
});
307+
}
308+
309+
private void handleTeleportFailure(Player peeker, PeekData data) {
310+
plugin.getLogger().warning(String.format(
311+
"无法将玩家 %s 传送回原位置,正在尝试传送到重生点",
312+
peeker.getName()
313+
));
314+
315+
Location spawnLoc = resolveSpawnLocation(peeker);
316+
317+
if (spawnLoc != null) {
318+
plugin.getServer().getRegionScheduler().run(plugin, spawnLoc, spawnTask -> {
319+
peeker.teleportAsync(spawnLoc, TeleportCause.PLUGIN).thenAccept(spawnSuccess -> {
320+
if (spawnSuccess) {
321+
plugin.getServer().getRegionScheduler().run(plugin, spawnLoc, modeTask -> {
322+
applyRestoredState(peeker, data);
337323
});
324+
} else {
325+
plugin.getLogger().severe(String.format(
326+
"无法将玩家 %s 传送到任何安全位置",
327+
peeker.getName()
328+
));
329+
forceStateRestoreWithoutTeleport(peeker, data);
338330
}
339-
plugin.getMessages().send(peeker, "teleport-failed");
340-
}
331+
});
341332
});
333+
} else {
334+
plugin.getLogger().severe(String.format(
335+
"未找到可用的重生点,强制恢复玩家 %s 的状态",
336+
peeker.getName()
337+
));
338+
forceStateRestoreWithoutTeleport(peeker, data);
339+
}
340+
341+
plugin.getMessages().send(peeker, "teleport-failed");
342+
}
343+
344+
private Location resolveSpawnLocation(Player peeker) {
345+
Location respawnLocation = peeker.getRespawnLocation();
346+
if (respawnLocation != null) {
347+
return respawnLocation;
348+
}
349+
350+
if (peeker.getWorld() != null) {
351+
return peeker.getWorld().getSpawnLocation();
352+
}
353+
354+
return plugin.getServer().getWorlds().isEmpty()
355+
? null
356+
: plugin.getServer().getWorlds().get(0).getSpawnLocation();
357+
}
358+
359+
private void forceStateRestoreWithoutTeleport(Player peeker, PeekData data) {
360+
plugin.getServer().getRegionScheduler().run(plugin, peeker.getLocation(), modeTask -> {
361+
applyRestoredState(peeker, data);
342362
});
343363
}
344364

365+
private void applyRestoredState(Player peeker, PeekData data) {
366+
// 再次确保动量为0
367+
peeker.setVelocity(new Vector(0, 0, 0));
368+
369+
// 确保观察者附身关系被清除
370+
if (peeker.getGameMode() == GameMode.SPECTATOR && peeker.getSpectatorTarget() != null) {
371+
peeker.setSpectatorTarget(null);
372+
}
373+
374+
peeker.setGameMode(data.getOriginalGameMode());
375+
double maxHealth = getMaxHealth(peeker);
376+
peeker.setHealth(Math.min(data.getHealth(), maxHealth));
377+
peeker.setFoodLevel(data.getFoodLevel());
378+
peeker.setSaturation(data.getSaturation());
379+
380+
// 清除现有效果并应用保存的效果
381+
peeker.getActivePotionEffects().forEach(effect
382+
-> peeker.removePotionEffect(effect.getType()));
383+
data.getPotionEffects().forEach(effect
384+
-> peeker.addPotionEffect(effect));
385+
}
386+
387+
private double getMaxHealth(Player peeker) {
388+
AttributeInstance instance = peeker.getAttribute(Attribute.GENERIC_MAX_HEALTH);
389+
return instance != null ? instance.getValue() : 20.0D;
390+
}
391+
345392
public Map<UUID, PeekData> getActivePeeks() {
346393
return Collections.unmodifiableMap(activePeeks);
347394
}

src/main/java/ict/minesunshineone/peek/listener/PeekListener.java

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import java.util.UUID;
66

77
import org.bukkit.entity.Player;
8+
import org.bukkit.GameMode;
89
import org.bukkit.event.EventHandler;
910
import org.bukkit.event.EventPriority;
1011
import org.bukkit.event.Listener;
@@ -55,6 +56,16 @@ public void onPlayerQuit(PlayerQuitEvent event) {
5556

5657
// 取消所有相关的请求
5758
plugin.getPrivacyManager().cancelAllRequests(player);
59+
60+
// 额外修复:确保所有处于 SPECTATOR 且有保存状态的在线玩家在被观察对象下线时恢复状态
61+
for (Player online : plugin.getServer().getOnlinePlayers()) {
62+
PeekData saved = plugin.getStateManager().getPlayerState(online);
63+
if (saved != null && online.getGameMode() == GameMode.SPECTATOR) {
64+
// 调用 endPeek 来安全地恢复玩家状态(会处理冷却、消息与清理)
65+
plugin.getLogger().info(String.format("Restoring peek state for player %s due to target quit", online.getName()));
66+
plugin.getStateHandler().endPeek(online);
67+
}
68+
}
5869
}
5970

6071
@EventHandler(priority = EventPriority.MONITOR)

0 commit comments

Comments
 (0)