Skip to content

Commit 1fc5cce

Browse files
修复
1 parent 047a3d1 commit 1fc5cce

4 files changed

Lines changed: 46 additions & 14 deletions

File tree

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

Lines changed: 30 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -9,12 +9,14 @@
99
import org.bukkit.plugin.java.JavaPlugin;
1010

1111
import ict.minesunshineone.peek.command.PeekCommand;
12+
import ict.minesunshineone.peek.data.PeekData;
1213
import ict.minesunshineone.peek.handler.PeekStateHandler;
1314
import ict.minesunshineone.peek.handler.PeekTargetHandler;
1415
import ict.minesunshineone.peek.listener.PeekInteractionListener;
1516
import ict.minesunshineone.peek.listener.PeekListener;
1617
import ict.minesunshineone.peek.listener.PeekPacketListener;
1718
import ict.minesunshineone.peek.manager.CooldownManager;
19+
import java.util.UUID;
1820
import ict.minesunshineone.peek.manager.PrivacyManager;
1921
import ict.minesunshineone.peek.manager.StateManager;
2022
import ict.minesunshineone.peek.manager.StatisticsManager;
@@ -81,14 +83,35 @@ public void onEnable() {
8183
@Override
8284
public void onDisable() {
8385
if (stateHandler != null) {
84-
new HashMap<>(stateHandler.getActivePeeks()).forEach((uuid, data) -> {
85-
Player player = getServer().getPlayer(uuid);
86-
if (player != null && player.isOnline()) {
87-
stateHandler.endPeek(player, true);
88-
}
89-
});
90-
// 清理所有剩余资源(BossBar、距离检查器等)
86+
// 先取消所有定时任务(RangeChecker、BossBar等)
9187
stateHandler.cleanup();
88+
89+
// 同步恢复所有观察中的玩家状态
90+
// 服务器关闭时不能依赖异步任务完成
91+
for (Map.Entry<UUID, PeekData> entry : new HashMap<>(stateHandler.getActivePeeks()).entrySet()) {
92+
Player player = getServer().getPlayer(entry.getKey());
93+
PeekData data = entry.getValue();
94+
if (player == null || !player.isOnline()) {
95+
continue;
96+
}
97+
98+
// 记录统计
99+
long duration = (System.currentTimeMillis() - data.getStartTime()) / 1000;
100+
statisticsManager.recordPeekEnd(player, duration);
101+
102+
if (!player.isDead()) {
103+
try {
104+
ict.minesunshineone.peek.util.PlayerStateUtil.forceExitRidingState(player);
105+
player.teleport(data.getOriginalLocation());
106+
stateHandler.getStateRestorer().applyRestoredState(player, data);
107+
} catch (Exception e) {
108+
getLogger().warning(String.format("关服时无法恢复玩家 %s 的状态,将在重连时恢复: %s",
109+
player.getName(), e.getMessage()));
110+
// 状态文件保留在磁盘上,下次登录时 onPlayerJoin 自动恢复
111+
}
112+
}
113+
// 死亡玩家的状态文件保留,下次登录时自动恢复
114+
}
92115
}
93116

94117
if (statisticsManager != null) {

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

Lines changed: 4 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -214,10 +214,6 @@ public void endPeek(Player peeker, boolean shouldRestore) {
214214
}
215215
}
216216

217-
if (shouldRestore && !peeker.isDead()) {
218-
plugin.getStateManager().clearPlayerState(peeker);
219-
}
220-
221217
// 发送消息
222218
if (peeker.isOnline()) {
223219
plugin.getMessages().send(peeker, "peek-end");
@@ -274,6 +270,10 @@ private void teleportAndSetGameMode(Player peeker, Player target) {
274270
startNormalRangeChecker(peeker, target);
275271
}, () -> logDebug("Peeker %s went offline after teleport", peeker.getName()));
276272
}
273+
}).exceptionally(ex -> {
274+
plugin.getLogger().warning(String.format("传送玩家 %s 时发生异常: %s", peeker.getName(), ex.getMessage()));
275+
onFailed.run();
276+
return null;
277277
});
278278
}, onFailed, 2L); // 2 tick 延迟
279279

@@ -373,7 +373,6 @@ private void startRespawnWatcher(Player peeker, PeekData data) {
373373
if (!peeker.isDead()) {
374374
task.cancel();
375375
stateRestorer.restorePlayerState(peeker, data);
376-
plugin.getStateManager().clearPlayerState(peeker);
377376
plugin.getMessages().send(peeker, "peek-end-respawn");
378377
}
379378
},

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

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -51,6 +51,10 @@ public void restorePlayerState(Player peeker, PeekData data) {
5151
} else {
5252
onFailed.run();
5353
}
54+
}).exceptionally(ex -> {
55+
plugin.getLogger().warning(String.format("恢复玩家 %s 传送时发生异常: %s", peeker.getName(), ex.getMessage()));
56+
onFailed.run();
57+
return null;
5458
});
5559
}, onFailed, 1L);
5660

@@ -91,6 +95,10 @@ public void handleTeleportFailure(Player peeker, PeekData data) {
9195
} else {
9296
onFailed.run();
9397
}
98+
}).exceptionally(ex -> {
99+
plugin.getLogger().warning(String.format("传送玩家 %s 到重生点时发生异常: %s", peeker.getName(), ex.getMessage()));
100+
onFailed.run();
101+
return null;
94102
});
95103
}, onFailed, 1L);
96104

@@ -163,6 +171,9 @@ public void applyRestoredState(Player peeker, PeekData data) {
163171
// 清除现有效果并应用保存的效果
164172
peeker.getActivePotionEffects().forEach(effect -> peeker.removePotionEffect(effect.getType()));
165173
data.getPotionEffects().forEach(effect -> peeker.addPotionEffect(effect));
174+
175+
// 游戏模式已恢复,现在安全地清除状态文件
176+
plugin.getStateManager().clearPlayerState(peeker);
166177
}
167178

168179
/**

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

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -70,9 +70,8 @@ public void onPlayerJoin(PlayerJoinEvent event) {
7070
task -> {
7171
if (!player.isDead()) {
7272
task.cancel();
73-
// 直接恢复状态
73+
// 直接恢复状态(clearPlayerState 在 applyRestoredState 中执行)
7474
plugin.getStateHandler().getStateRestorer().restorePlayerState(player, savedState);
75-
plugin.getStateManager().clearPlayerState(player);
7675
// 发送断线重连提示
7776
plugin.getMessages().send(player, "peek-end-offline");
7877
}

0 commit comments

Comments
 (0)