diff --git a/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs b/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs new file mode 100644 index 000000000..742fe68c0 --- /dev/null +++ b/src/EvoSC.Common/Remote/EventArgsModels/WarmUpRoundEventArgs.cs @@ -0,0 +1,14 @@ +namespace EvoSC.Common.Remote.EventArgsModels; + +public class WarmUpRoundEventArgs: EventArgs +{ + /// + /// The current warm-up round. + /// + public required int Current { get; init; } + + /// + /// The total amount of warm-ups. + /// + public required int Total { get; init; } +} diff --git a/src/EvoSC.Common/Remote/ModeScriptEvent.cs b/src/EvoSC.Common/Remote/ModeScriptEvent.cs index ca84fcb2e..6a0295874 100644 --- a/src/EvoSC.Common/Remote/ModeScriptEvent.cs +++ b/src/EvoSC.Common/Remote/ModeScriptEvent.cs @@ -46,6 +46,18 @@ public enum ModeScriptEvent [Identifier(Name = "ModeScript.WarmUpStart")] WarmUpStart, + /// + /// When a warm-up round starts. + /// + [Identifier(Name = "ModeScript.WarmUpStartRound")] + WarmUpStartRound, + + /// + /// When a warm-up round starts. + /// + [Identifier(Name = "ModeScript.WarmUpEndRound")] + WarmUpEndRound, + /// /// When a player got eliminated by an obstacle. /// diff --git a/src/EvoSC.Common/Remote/ServerCallbackHandler.cs b/src/EvoSC.Common/Remote/ServerCallbackHandler.cs index 731929538..7098943a3 100644 --- a/src/EvoSC.Common/Remote/ServerCallbackHandler.cs +++ b/src/EvoSC.Common/Remote/ServerCallbackHandler.cs @@ -114,6 +114,22 @@ await _events.RaiseAsync(ModeScriptEvent.StartLine, case "Trackmania.WarmUp.Start": await _events.RaiseAsync(ModeScriptEvent.WarmUpStart, EventArgs.Empty); break; + case "Trackmania.WarmUp.StartRound": + await _events.RaiseAsync(ModeScriptEvent.WarmUpStartRound, + new WarmUpRoundEventArgs + { + Current = data.GetValue("current", StringComparison.Ordinal).ToObject(), + Total = data.GetValue("total", StringComparison.Ordinal).ToObject() + }); + break; + case "Trackmania.WarmUp.EndRound": + await _events.RaiseAsync(ModeScriptEvent.WarmUpEndRound, + new WarmUpRoundEventArgs + { + Current = data.GetValue("current", StringComparison.Ordinal).ToObject(), + Total = data.GetValue("total", StringComparison.Ordinal).ToObject() + }); + break; case "Trackmania.Event.Eliminated": await _events.RaiseAsync(ModeScriptEvent.Eliminated, new PlayerUpdateEventArgs diff --git a/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs b/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs deleted file mode 100644 index c253972b6..000000000 --- a/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs +++ /dev/null @@ -1,22 +0,0 @@ -using EvoSC.Common.Controllers; -using EvoSC.Common.Controllers.Attributes; -using EvoSC.Common.Controllers.Context; -using EvoSC.Common.Events.Attributes; -using EvoSC.Common.Remote; -using EvoSC.Common.Remote.EventArgsModels; -using EvoSC.Modules.Official.SpectatorCamModeModule.Interfaces; - -namespace EvoSC.Modules.Official.SpectatorCamModeModule.Controllers; - -[Controller] -public class SpectatorCamModeEventController(ISpectatorCamModeService camModeService) - : EvoScController -{ - [Subscribe(ModeScriptEvent.EndRoundStart)] - public Task OnEndRoundStartAsync(object sender, RoundEventArgs eventArgs) => - camModeService.HideCamModeWidgetAsync(); - - [Subscribe(ModeScriptEvent.StartRoundStart)] - public Task OnStartRoundStartAsync(object sender, RoundEventArgs eventArgs) => - camModeService.SendPersistentCamModeWidgetAsync(); -} diff --git a/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs b/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs index 7ffac03a6..256bfd51d 100644 --- a/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs +++ b/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs @@ -9,12 +9,6 @@ public interface ISpectatorCamModeService /// /// public Task SendPersistentCamModeWidgetAsync(); - - /// - /// Hides the previously send widget. - /// - /// - public Task HideCamModeWidgetAsync(); /// /// Hides the default UI provided by the game mode. diff --git a/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs index 69212135b..7b469b7c6 100644 --- a/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs +++ b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs @@ -22,9 +22,6 @@ ISpectatorCamModeSettings settings public Task SendPersistentCamModeWidgetAsync() => manialinks.SendPersistentManialinkAsync(WidgetTemplate, new { settings }); - public Task HideCamModeWidgetAsync() => - manialinks.HideManialinkAsync(WidgetTemplate); - public Task HideGameModeUiAsync() => gameModeUiModuleService.ApplyComponentSettingsAsync(GetGameModeUiSettings()); diff --git a/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms index 843927ebf..8108480cc 100644 --- a/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms +++ b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms @@ -39,29 +39,24 @@ Void SetCamModeNameAndIcon(Integer _CamMode, CMlFrame camModeFrame) { } declare Real spacing = 1.0; - declare Real offset = 0.0; - declare Real width = 0.0; - if (camModeLabel != Null){ - camModeLabel.Value = TextLib::ToUpperCase(Text_CamMode); - offset = spacing * 2.0 + camModeLabel.ComputeWidth(camModeLabel.Value); - width = spacing * 2.0 + camModeLabel.ComputeWidth(camModeLabel.Value); - } if (camModeQuad != Null){ camModeQuad.ImageUrl = Icon_CamMode; - camModeQuad.RelativePosition_V3.X = offset + spacing; - width = width + spacing + camModeQuad.Size.X; + camModeQuad.RelativePosition_V3.X = {{ width }} * 1.0 - spacing - camModeQuad.Size.X; + } + if (camModeLabel != Null){ + camModeLabel.Value = TextLib::ToUpperCase(Text_CamMode); + camModeLabel.RelativePosition_V3.X = camModeQuad.RelativePosition_V3.X - spacing; } - width = width + spacing * 2.0; - camModeFrame.Size.X = width; - camModeBg.Size.X = width; + camModeFrame.Size.X = 32.0; + camModeBg.Size.X = 32.0; declare Integer targetCamMode for camModeFrame; targetCamMode = _CamMode; if({{ settings.Alignment == WidgetPosition.Right ? "True" : "False" }}){ - camModeFrame.RelativePosition_V3.X = width * -1.0; + camModeFrame.RelativePosition_V3.X = camModeFrame.Size.X * -1.0; }else if({{ settings.Alignment == WidgetPosition.Center ? "True" : "False" }}){ - camModeFrame.RelativePosition_V3.X = width / -2.0; + camModeFrame.RelativePosition_V3.X = camModeFrame.Size.X / -2.0; } } @@ -236,7 +231,9 @@ main(){ while(True){ yield; - declare shouldBeDisplayed = InputPlayer != Null && InputPlayer.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned; + declare shouldBeDisplayed = InputPlayer != Null + && InputPlayer.SpawnStatus == CSmPlayer::ESpawnStatus::NotSpawned + && UI.UISequence == CUIConfig::EUISequence::Playing; if(!shouldBeDisplayed){ if(mainFrame.Visible){ diff --git a/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt index 41d138210..cd5a668c5 100644 --- a/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt +++ b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt @@ -8,7 +8,7 @@ - + diff --git a/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs b/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs index 5afc8f94b..7631644ea 100644 --- a/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs +++ b/src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoEventController.cs @@ -34,5 +34,14 @@ public async Task OnNewRoundAsync(object sender, RoundEventArgs roundEventArgs) { await spectatorTargetInfoService.ClearCheckpointsAsync(); await spectatorTargetInfoService.FetchAndCacheTeamInfoAsync(); + await spectatorTargetInfoService.ResetWidgetForSpectatorsAsync(); + } + + [Subscribe(ModeScriptEvent.WarmUpStartRound)] + public async Task OnNewWarmUpRoundAsync(object sender, WarmUpRoundEventArgs roundEventArgs) + { + await spectatorTargetInfoService.ClearCheckpointsAsync(); + await spectatorTargetInfoService.FetchAndCacheTeamInfoAsync(); + await spectatorTargetInfoService.ResetWidgetForSpectatorsAsync(); } } diff --git a/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms b/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms index 3bc6f9edc..aba5f6be8 100644 --- a/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms +++ b/src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms @@ -70,37 +70,37 @@ Void FocusPlayer(CSmPlayer _Player) { } } -Text SpecPrevious(CMlLabel button, Boolean focus){ +Void SpecPrevious(CMlLabel button, Boolean focus){ AnimatePop(button); declare CSmPlayer target <=> GetNextSpawnedPlayer(); - if(focus){ + if(target == Null && focus){ FocusPlayer(target); } - return target.User.Login; } -Text SpecNext(CMlLabel button, Boolean focus){ +Void SpecNext(CMlLabel button, Boolean focus){ AnimatePop(button); declare CSmPlayer target <=> GetNextSpawnedPlayer(); - if(focus){ + if(target != Null && focus){ FocusPlayer(target); } - return target.User.Login; } main() { declare mainFrame <=> (Page.MainFrame.GetFirstChild("main_frame") as CMlFrame); declare previousButton <=> (Page.MainFrame.GetFirstChild("left_button") as CMlLabel); declare nextButton <=> (Page.MainFrame.GetFirstChild("right_button") as CMlLabel); - declare targetLogin = "{{ playerLogin }}"; while(True){ yield; - if(GUIPlayer == Null){ + declare shouldBeDisplayed = GUIPlayer != Null && UI.UISequence == CUIConfig::EUISequence::Playing; + + if(!shouldBeDisplayed){ if(mainFrame.Visible){ mainFrame.Hide(); } + sleep(100); continue; } @@ -122,10 +122,10 @@ main() { foreach(Event in PendingEvents){ if(Event.Type == CMlScriptEvent::Type::MouseClick){ if(Event.Control == previousButton){ - targetLogin = SpecPrevious(previousButton, True); + SpecPrevious(previousButton, True); continue; }else if(Event.Control == nextButton){ - targetLogin = SpecNext(nextButton, True); + SpecNext(nextButton, True); continue; } } diff --git a/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt b/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt index 4d7e5dabf..fbb54191e 100644 --- a/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt +++ b/src/Modules/SpectatorTargetInfoModule/Templates/SpectatorTargetInfo.mt @@ -53,7 +53,7 @@ size="{{ (h*3.4)*0.8 }} {{ h }}" textsize="{{ Theme.UI_FontSize*2 }}" textfont="{{ Font.Regular }}" - text='{{ timeDifference > 0 ? RaceTime.FromMilliseconds(timeDifference) : "000" }}' + text='{{ RaceTime.FromMilliseconds(timeDifference) }}' textprefix="+" halign="center" valign="center2" diff --git a/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs b/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs index 6e2420dba..c52fbab37 100644 --- a/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs +++ b/tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs @@ -35,16 +35,6 @@ public async Task SendsPersistentCamModeWidget() m.SendPersistentManialinkAsync("SpectatorCamModeModule.SpectatorMode", It.IsAny()), Times.Once); } - [Fact] - public async Task HidesCamModeWidget() - { - var camModeService = CamModeServiceMock(); - await camModeService.HideCamModeWidgetAsync(); - - _manialinkManager.Verify(m => - m.HideManialinkAsync("SpectatorCamModeModule.SpectatorMode"), Times.Once); - } - [Fact] public async Task HidesDefaultGameModeUi() { diff --git a/tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetEventControllerTests.cs b/tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetEventControllerTests.cs index a74ff90b4..b2e30ce90 100644 --- a/tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetEventControllerTests.cs +++ b/tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetEventControllerTests.cs @@ -73,4 +73,13 @@ public async Task Resets_Collected_Data_On_New_Round() _spectatorTargetService.Verify(sts => sts.ClearCheckpointsAsync()); _spectatorTargetService.Verify(sts => sts.FetchAndCacheTeamInfoAsync()); } + + [Fact] + public async Task Resets_Collected_Data_On_New_Warm_Up_Round() + { + await Controller.OnNewWarmUpRoundAsync(null, new WarmUpRoundEventArgs { Total = 3, Current = 1 }); + + _spectatorTargetService.Verify(sts => sts.ClearCheckpointsAsync()); + _spectatorTargetService.Verify(sts => sts.FetchAndCacheTeamInfoAsync()); + } } diff --git a/tests/Modules/TeamChatModule.Tests/TeamChatModule.Tests.csproj b/tests/Modules/TeamChatModule.Tests/TeamChatModule.Tests.csproj index 144ec22f2..c5823fc9d 100644 --- a/tests/Modules/TeamChatModule.Tests/TeamChatModule.Tests.csproj +++ b/tests/Modules/TeamChatModule.Tests/TeamChatModule.Tests.csproj @@ -10,9 +10,8 @@ - - - + + runtime; build; native; contentfiles; analyzers; buildtransitive all