From d03518deacf55c499b6f87537aca30cd38c02374 Mon Sep 17 00:00:00 2001 From: Acentech Dev Date: Sun, 26 Jul 2026 22:59:38 +0300 Subject: [PATCH] fix(heykel-savasi): allow /starths restart + accept unencrypted team-select Two TvT (Heykel Savasi) event fixes found during mobile+PC client work: - PeriodicTaskBasePlugIn: a forced start (GM /starths) no longer blocked while a previous run's TaskDuration window is still open. When an event finished early (team won / empty / before the 20-min duration) players are warped out but the periodic state stayed Started with a future NextRunUtc, so the guard returned on every tick and a re-start only worked after the full duration or a server restart. Force-finish the stale run when _isStartForced so the same execution falls through and prepares a fresh one; the NextRunUtc wait now applies to scheduled runs only. - HeykelSavasiTeamSelectHandlerPlugIn: IsEncryptionExpected => false. The AdaMu client sends client-to-server packets unencrypted (like walk / animation / talk-to-npc), so the server was dropping the team-select (JOIN) packet. Co-Authored-By: Claude Opus 4.8 (1M context) --- .../PeriodicTasks/PeriodicTaskBasePlugIn.cs | 16 +++++++++++++++- .../HeykelSavasiTeamSelectHandlerPlugIn.cs | 4 +++- 2 files changed, 18 insertions(+), 2 deletions(-) diff --git a/src/GameLogic/PlugIns/PeriodicTasks/PeriodicTaskBasePlugIn.cs b/src/GameLogic/PlugIns/PeriodicTasks/PeriodicTaskBasePlugIn.cs index 07883a5..442c4d5 100644 --- a/src/GameLogic/PlugIns/PeriodicTasks/PeriodicTaskBasePlugIn.cs +++ b/src/GameLogic/PlugIns/PeriodicTasks/PeriodicTaskBasePlugIn.cs @@ -43,7 +43,21 @@ public abstract class PeriodicTaskBasePlugIn : IPeriodic var state = this.GetStateByGameContext(gameContext); - if (state.NextRunUtc > DateTime.UtcNow) + // A forced start (GM command, e.g. /starths) must not be blocked while a previous run's + // TaskDuration window is still open. When an event finished early (e.g. a team won, a team was + // empty, or simply before the 20-minute TaskDuration elapsed) the players are warped out but the + // periodic state stays Started with a future NextRunUtc. Without this, the guard below returns on + // every tick and a re-start only worked after the full TaskDuration elapsed (or a server restart). + // Force-finish the stale run here so this same execution falls through and prepares a fresh one. + if (this._isStartForced && state.State == PeriodicTaskState.Started) + { + state.State = PeriodicTaskState.NotStarted; + state.NextRunUtc = DateTime.MinValue; + await this.OnFinishedAsync(state).ConfigureAwait(false); + } + + // The NextRunUtc wait applies to scheduled runs only; a forced start bypasses it. + if (!this._isStartForced && state.NextRunUtc > DateTime.UtcNow) { return; } diff --git a/src/GameServer/MessageHandler/MiniGames/HeykelSavasiTeamSelectHandlerPlugIn.cs b/src/GameServer/MessageHandler/MiniGames/HeykelSavasiTeamSelectHandlerPlugIn.cs index da76d98..7b2a3ca 100644 --- a/src/GameServer/MessageHandler/MiniGames/HeykelSavasiTeamSelectHandlerPlugIn.cs +++ b/src/GameServer/MessageHandler/MiniGames/HeykelSavasiTeamSelectHandlerPlugIn.cs @@ -25,7 +25,9 @@ public class HeykelSavasiTeamSelectHandlerPlugIn : IPacketHandlerPlugIn private readonly HeykelSavasiJoinAction _joinAction = new(); /// - public bool IsEncryptionExpected => true; + // The AdaMu client sends client-to-server packets unencrypted (like every other working handler: + // walk, animation, talk-to-npc), so this must be false or the server drops the team-select packet. + public bool IsEncryptionExpected => false; /// public byte Key => HeykelSavasiTeamSelect.Code;