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;