@@ -52,14 +52,15 @@ public void startPeek(Player peeker, Player target) {
5252 }
5353
5454 // 防止并发修改
55+ final PeekData data ;
5556 synchronized (activePeeks ) {
5657 if (activePeeks .containsKey (peeker .getUniqueId ())) {
5758 plugin .getMessages ().send (peeker , "already-peeking" );
5859 return ;
5960 }
6061
6162 logDebug ("Starting peek: %s -> %s" , peeker .getName (), target .getName ());
62- PeekData data = new PeekData (
63+ data = new PeekData (
6364 peeker .getLocation ().clone (),
6465 peeker .getGameMode (),
6566 target .getUniqueId (),
@@ -70,12 +71,13 @@ public void startPeek(Player peeker, Player target) {
7071 peeker .getActivePotionEffects ());
7172
7273 activePeeks .put (peeker .getUniqueId (), data );
73- plugin .getStateManager ().savePlayerState (peeker , data );
74- plugin .getStatisticsManager ().recordPeekStart (peeker , target );
75-
76- teleportAndSetGameMode (peeker , target );
7774 }
7875
76+ plugin .getStateManager ().savePlayerState (peeker , data );
77+ plugin .getStatisticsManager ().recordPeekStart (peeker , target );
78+
79+ teleportAndSetGameMode (peeker , target );
80+
7981 // 检查是否静默 peek(有 bypass 权限)
8082 boolean silentPeek = plugin .getTargetHandler ().shouldSilentPeek (peeker );
8183
@@ -246,69 +248,68 @@ public void endPeek(Player peeker) {
246248 // ==================== 私有方法 ====================
247249
248250 private void teleportAndSetGameMode (Player peeker , Player target ) {
251+ final Runnable onFailed = () -> {
252+ plugin .getMessages ().send (peeker , "teleport-failed" );
253+ endPeek (peeker );
254+ };
255+
249256 // 先切换游戏模式
250- plugin .getServer ().getRegionScheduler ().run (plugin , peeker .getLocation (), task -> {
251- try {
252- // 清理骑乘状态,准备进入旁观者模式
253- PlayerStateUtil .prepareForSpectatorMode (peeker , plugin .getLogger ());
254-
255- // 设置为旁观模式
256- peeker .setGameMode (GameMode .SPECTATOR );
257-
258- // 等待2 tick后再传送
259- plugin .getServer ().getRegionScheduler ().runDelayed (plugin , peeker .getLocation (), delayedTask -> {
260- peeker .teleportAsync (target .getLocation (), TeleportCause .PLUGIN ).thenAccept (success -> {
261- if (!success ) {
262- plugin .getMessages ().send (peeker , "teleport-failed" );
263- endPeek (peeker );
264- } else {
265- // 传送成功后,使用玩家的实体调度器确保在正确线程执行
266- peeker .getScheduler ().run (plugin , scheduledTask -> {
267- bossBarHandler .createDistanceBossBar (peeker , target );
268- startNormalRangeChecker (peeker , target );
269- }, null );
270- }
271- });
272- }, 2L ); // 2 tick 延迟
273- } catch (Exception e ) {
274- plugin .getLogger ().warning (String .format ("为玩家 %s 切换游戏模式时发生错误" , peeker .getName ()));
275- peeker .setSneaking (false ); // 确保异常时也恢复状态
276- endPeek (peeker );
257+ final boolean firstRoundScheduled = peeker .getScheduler ().execute (plugin , () -> {
258+ // 清理骑乘状态,准备进入旁观者模式
259+ PlayerStateUtil .prepareForSpectatorMode (peeker );
260+
261+ // 设置为旁观模式
262+ peeker .setGameMode (GameMode .SPECTATOR );
263+
264+ // 等待2 tick后再传送
265+ final boolean secondRoundScheduled = peeker .getScheduler ().execute (plugin , () -> {
266+ peeker .teleportAsync (target .getLocation (), TeleportCause .PLUGIN ).thenAccept (success -> {
267+ if (!success ) {
268+ onFailed .run ();
269+ } else {
270+ // 传送成功后,使用玩家的实体调度器确保在正确线程执行
271+ bossBarHandler .createDistanceBossBar (peeker , target );
272+ startNormalRangeChecker (peeker , target );
273+ }
274+ });
275+ }, onFailed , 2L ); // 2 tick 延迟
276+
277+ if (!secondRoundScheduled ) {
278+ onFailed .run ();
277279 }
278- });
280+ }, onFailed , 1L );
281+
282+ if (!firstRoundScheduled ) {
283+ onFailed .run ();
284+ }
279285 }
280286
281287 private void setSelfPeekGameMode (Player peeker ) {
282- plugin . getServer ().getRegionScheduler (). run ( plugin , peeker . getLocation (), task -> {
283- try {
284- if (!peeker .isOnline ()) {
285- plugin .getLogger ().warning (String .format ("玩家 %s 在设置自我观察模式时已离线" , peeker .getName ()));
286- endPeek (peeker , false );
287- return ;
288- }
288+ peeker . getScheduler ().execute ( plugin , () -> {
289+ // 这里如果玩家离线了调度器会自动退役
290+ /* if (!peeker.isOnline()) {
291+ plugin.getLogger().warning(String.format("玩家 %s 在设置自我观察模式时已离线", peeker.getName()));
292+ endPeek(peeker, false);
293+ return;
294+ }*/
289295
290- if (peeker .isDead ()) {
291- plugin .getLogger ().warning ( String . format ( "玩家 %s 在设置自我观察模式时已死亡" , peeker .getName () ));
292- plugin .getMessages ().send (peeker , "cannot-peek-while-dead" );
293- endPeek (peeker , false );
294- return ;
295- }
296+ if (peeker .isDead ()) {
297+ plugin .getSLF4JLogger ().warn ( "玩家 {} 在设置自我观察模式时已死亡" , peeker .getName ());
298+ plugin .getMessages ().send (peeker , "cannot-peek-while-dead" );
299+ endPeek (peeker , false );
300+ return ;
301+ }
296302
297- // 清理骑乘状态,准备进入旁观者模式
298- PlayerStateUtil .prepareForSpectatorMode (peeker , plugin . getLogger () );
303+ // 清理骑乘状态,准备进入旁观者模式
304+ PlayerStateUtil .prepareForSpectatorMode (peeker );
299305
300- peeker .setGameMode (GameMode .SPECTATOR );
306+ peeker .setGameMode (GameMode .SPECTATOR );
301307
302- logDebug ("Successfully set self peek game mode for player: %s" , peeker .getName ());
303- } catch (Exception e ) {
304- plugin .getLogger ().warning (String .format ("为玩家 %s 设置自我观察模式时发生错误: %s" , peeker .getName (), e .getMessage ()));
305- if (plugin .getConfig ().getBoolean ("debug" , false )) {
306- e .printStackTrace ();
307- }
308- peeker .setSneaking (false ); // 确保异常时也恢复状态
309- endPeek (peeker );
310- }
311- });
308+ logDebug ("Successfully set self peek game mode for player: %s" , peeker .getName ());
309+ }, () -> {
310+ plugin .getSLF4JLogger ().warn ("玩家 {} 在设置自我观察模式时已离线" , peeker .getName ());
311+ endPeek (peeker , false );
312+ }, 1L );
312313 }
313314
314315 private void startNormalRangeChecker (Player peeker , Player target ) {
0 commit comments