From be7b74e7c008f5a143650c3e0fe05fdb592fe576 Mon Sep 17 00:00:00 2001 From: braker <7152322+araszka@users.noreply.github.com> Date: Sun, 29 Sep 2024 17:01:47 +0200 Subject: [PATCH] 276 spec info (#293) Co-authored-by: snixtho --- EvoSC.sln | 22 +- src/EvoSC/EvoSC.csproj | 1 + src/EvoSC/InternalModules.cs | 4 +- .../Enums/GameModeUiComponents.cs | 20 + .../GameModeUiModule/GameModeUiModule.cs | 2 +- .../GameModeUiModule/GameModeUiModule.csproj | 2 - .../Interfaces/IGameModeUiModuleService.cs | 39 +- .../Models/GameModeUiComponentSettings.cs | 44 ++ .../Services/GameModeUiModuleService.cs | 263 ++++++----- src/Modules/Scoreboard/Scoreboard.csproj | 1 + .../Scoreboard/Services/ScoreboardService.cs | 72 ++- src/Modules/Scoreboard/info.toml | 3 + .../Config/ISpectatorCamModeSettings.cs | 20 + .../SpectatorCamModeEventController.cs | 22 + .../Interfaces/ISpectatorCamModeService.cs | 30 ++ .../SpectatorCamModeModule/Localization.resx | 19 + .../Services/SpectatorCamModeService.cs | 41 ++ .../SpectatorCamModeModule.cs | 17 + .../SpectatorCamModeModule.csproj | 25 + .../Templates/Scripts/SpectatorMode.ms | 302 ++++++++++++ .../Templates/SpectatorMode.mt | 55 +++ src/Modules/SpectatorCamModeModule/info.toml | 9 + .../Config/ISpectatorTargetInfoSettings.cs | 12 + .../SpectatorTargetInfoEventController.cs | 35 +- .../SpectatorTargetInfoManialinkController.cs | 26 ++ .../Interfaces/ISpectatorTargetInfoService.cs | 173 ++++++- .../Localization.resx | 19 + .../Models/CheckpointData.cs | 5 + .../Models/CheckpointsGroup.cs | 26 ++ .../Services/SpectatorTargetInfoService.cs | 269 ++++++++--- .../SpectatorTargetInfoModule.cs | 15 +- .../SpectatorTargetInfoModule.csproj | 7 + .../Templates/NewCpTime.mt | 24 - .../Templates/ReportSpecTarget.mt | 28 ++ .../Templates/ResetCpTimes.mt | 22 - .../Templates/Scripts/SpectatorTargetInfo.ms | 143 ++++++ .../Templates/SpectatorTargetInfo.mt | 357 ++++---------- .../SpectatorTargetInfoModule/info.toml | 3 + .../Services/GameModeUiModuleServiceTests.cs | 33 +- .../Services/SpectatorCamModeServiceTests.cs | 68 +++ .../SpectatorCamModeModule.Tests.csproj | 22 + .../SpectatorTargetEventControllerTests.cs | 76 +++ ...tatorTargetInfoManialinkControllerTests.cs | 71 +++ .../Models/CheckpointsGroupTests.cs | 101 ++++ .../SpectatorTargetInfoServiceTests.cs | 439 ++++++++++++++++++ .../SpectatorTargetInfoModule.Tests.csproj | 18 + .../TeamChatModule.Tests.csproj | 51 +- .../TeamInfoEventControllerTests.cs | 2 + 48 files changed, 2428 insertions(+), 630 deletions(-) create mode 100644 src/Modules/GameModeUiModule/Enums/GameModeUiComponents.cs create mode 100644 src/Modules/GameModeUiModule/Models/GameModeUiComponentSettings.cs create mode 100644 src/Modules/SpectatorCamModeModule/Config/ISpectatorCamModeSettings.cs create mode 100644 src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs create mode 100644 src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs create mode 100644 src/Modules/SpectatorCamModeModule/Localization.resx create mode 100644 src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs create mode 100644 src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.cs create mode 100644 src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.csproj create mode 100644 src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms create mode 100644 src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt create mode 100644 src/Modules/SpectatorCamModeModule/info.toml create mode 100644 src/Modules/SpectatorTargetInfoModule/Config/ISpectatorTargetInfoSettings.cs create mode 100644 src/Modules/SpectatorTargetInfoModule/Controllers/SpectatorTargetInfoManialinkController.cs create mode 100644 src/Modules/SpectatorTargetInfoModule/Localization.resx create mode 100644 src/Modules/SpectatorTargetInfoModule/Models/CheckpointData.cs create mode 100644 src/Modules/SpectatorTargetInfoModule/Models/CheckpointsGroup.cs delete mode 100644 src/Modules/SpectatorTargetInfoModule/Templates/NewCpTime.mt create mode 100644 src/Modules/SpectatorTargetInfoModule/Templates/ReportSpecTarget.mt delete mode 100644 src/Modules/SpectatorTargetInfoModule/Templates/ResetCpTimes.mt create mode 100644 src/Modules/SpectatorTargetInfoModule/Templates/Scripts/SpectatorTargetInfo.ms create mode 100644 tests/Modules/SpectatorCamModeModule.Tests/Services/SpectatorCamModeServiceTests.cs create mode 100644 tests/Modules/SpectatorCamModeModule.Tests/SpectatorCamModeModule.Tests.csproj create mode 100644 tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetEventControllerTests.cs create mode 100644 tests/Modules/SpectatorTargetInfoModule.Tests/Controllers/SpectatorTargetInfoManialinkControllerTests.cs create mode 100644 tests/Modules/SpectatorTargetInfoModule.Tests/Models/CheckpointsGroupTests.cs create mode 100644 tests/Modules/SpectatorTargetInfoModule.Tests/Services/SpectatorTargetInfoServiceTests.cs create mode 100644 tests/Modules/SpectatorTargetInfoModule.Tests/SpectatorTargetInfoModule.Tests.csproj diff --git a/EvoSC.sln b/EvoSC.sln index 8820dabb7..2ec61fa13 100644 --- a/EvoSC.sln +++ b/EvoSC.sln @@ -142,7 +142,12 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamChatModule", "src/Modul EndProject Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TeamChatModule.Tests", "tests\Modules\TeamChatModule.Tests\TeamChatModule.Tests.csproj", "{7BD60D6E-7B7E-4771-87C0-7F98FC82F990}" EndProject - +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpectatorTargetInfoModule.Tests", "tests\Modules\SpectatorTargetInfoModule.Tests\SpectatorTargetInfoModule.Tests.csproj", "{E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpectatorCamModeModule", "src\Modules\SpectatorCamModeModule\SpectatorCamModeModule.csproj", "{E9806703-6E24-4F05-A728-A04F7EB31749}" +EndProject +Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "SpectatorCamModeModule.Tests", "tests\Modules\SpectatorCamModeModule.Tests\SpectatorCamModeModule.Tests.csproj", "{09A88256-8008-4085-A8E6-CA6DEFAC63E3}" +EndProject @@ -430,6 +435,18 @@ Global {7BD60D6E-7B7E-4771-87C0-7F98FC82F990}.Debug|Any CPU.Build.0 = Debug|Any CPU {7BD60D6E-7B7E-4771-87C0-7F98FC82F990}.Release|Any CPU.ActiveCfg = Release|Any CPU {7BD60D6E-7B7E-4771-87C0-7F98FC82F990}.Release|Any CPU.Build.0 = Release|Any CPU + {E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE}.Release|Any CPU.Build.0 = Release|Any CPU + {E9806703-6E24-4F05-A728-A04F7EB31749}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {E9806703-6E24-4F05-A728-A04F7EB31749}.Debug|Any CPU.Build.0 = Debug|Any CPU + {E9806703-6E24-4F05-A728-A04F7EB31749}.Release|Any CPU.ActiveCfg = Release|Any CPU + {E9806703-6E24-4F05-A728-A04F7EB31749}.Release|Any CPU.Build.0 = Release|Any CPU + {09A88256-8008-4085-A8E6-CA6DEFAC63E3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU + {09A88256-8008-4085-A8E6-CA6DEFAC63E3}.Debug|Any CPU.Build.0 = Debug|Any CPU + {09A88256-8008-4085-A8E6-CA6DEFAC63E3}.Release|Any CPU.ActiveCfg = Release|Any CPU + {09A88256-8008-4085-A8E6-CA6DEFAC63E3}.Release|Any CPU.Build.0 = Release|Any CPU EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE @@ -497,5 +514,8 @@ Global {4AA1890A-1423-4831-95B2-E29B9A7A58D1} = {6D75D6A2-6ECD-4DE4-96C5-CAD7D134407A} {DDB0A249-BD1C-4556-BFE1-362B17EDA874} = {DC47658A-F421-4BA4-B617-090A7DFB3900} {7BD60D6E-7B7E-4771-87C0-7F98FC82F990} = {6D75D6A2-6ECD-4DE4-96C5-CAD7D134407A} + {E4BF17BE-A517-4D3C-8DCA-DA99A100EBFE} = {6D75D6A2-6ECD-4DE4-96C5-CAD7D134407A} + {E9806703-6E24-4F05-A728-A04F7EB31749} = {DC47658A-F421-4BA4-B617-090A7DFB3900} + {09A88256-8008-4085-A8E6-CA6DEFAC63E3} = {6D75D6A2-6ECD-4DE4-96C5-CAD7D134407A} EndGlobalSection EndGlobal diff --git a/src/EvoSC/EvoSC.csproj b/src/EvoSC/EvoSC.csproj index 12ca2d98b..844ecefc8 100644 --- a/src/EvoSC/EvoSC.csproj +++ b/src/EvoSC/EvoSC.csproj @@ -49,6 +49,7 @@ + diff --git a/src/EvoSC/InternalModules.cs b/src/EvoSC/InternalModules.cs index 94a8df479..a7fa2c43b 100644 --- a/src/EvoSC/InternalModules.cs +++ b/src/EvoSC/InternalModules.cs @@ -23,6 +23,7 @@ using EvoSC.Modules.Official.Scoreboard; using EvoSC.Modules.Official.ServerManagementModule; using EvoSC.Modules.Official.SetName; +using EvoSC.Modules.Official.SpectatorCamModeModule; using EvoSC.Modules.Official.SpectatorTargetInfoModule; using EvoSC.Modules.Official.TeamChatModule; using EvoSC.Modules.Official.TeamInfoModule; @@ -37,6 +38,7 @@ public static class InternalModules public static readonly Type[] Modules = [ //typeof(ExampleModule), + typeof(GameModeUiModule), typeof(PlayerModule), typeof(MapsModule), typeof(WorldRecordModule), @@ -55,6 +57,7 @@ public static class InternalModules typeof(MatchRankingModule), typeof(ASayModule), typeof(SpectatorTargetInfoModule), + typeof(SpectatorCamModeModule), typeof(MapQueueModule), typeof(MapListModule), typeof(LocalRecordsModule), @@ -62,7 +65,6 @@ public static class InternalModules typeof(TeamSettingsModule), typeof(ServerManagementModule), typeof(TeamInfoModule), - typeof(GameModeUiModule), typeof(TeamChatModule) ]; diff --git a/src/Modules/GameModeUiModule/Enums/GameModeUiComponents.cs b/src/Modules/GameModeUiModule/Enums/GameModeUiComponents.cs new file mode 100644 index 000000000..2d871da86 --- /dev/null +++ b/src/Modules/GameModeUiModule/Enums/GameModeUiComponents.cs @@ -0,0 +1,20 @@ +namespace EvoSC.Modules.Official.GameModeUiModule.Enums; + +public static class GameModeUiComponents +{ + public static readonly string Chrono = "Race_Chrono"; + public static readonly string RespawnHelper = "Race_RespawnHelper"; + public static readonly string Checkpoint = "Race_Checkpoint"; + public static readonly string LapsCounter = "Race_LapsCounter"; + public static readonly string TimeGap = "Race_TimeGap"; + public static readonly string ScoresTable = "Race_ScoresTable"; + public static readonly string DisplayMessage = "Race_DisplayMessage"; + public static readonly string Countdown = "Race_Countdown"; + public static readonly string SpectatorBaseName = "Race_SpectatorBase_Name"; + public static readonly string SpectatorBaseCommands = "Race_SpectatorBase_Commands"; + public static readonly string Record = "Race_Record"; + public static readonly string BigMessage = "Race_BigMessage"; + public static readonly string BlockHelper = "Race_BlockHelper"; + public static readonly string WarmUp = "Race_WarmUp"; + public static readonly string BestRaceViewer = "Race_BestRaceViewer"; +} diff --git a/src/Modules/GameModeUiModule/GameModeUiModule.cs b/src/Modules/GameModeUiModule/GameModeUiModule.cs index 6f3146424..e89eaa919 100644 --- a/src/Modules/GameModeUiModule/GameModeUiModule.cs +++ b/src/Modules/GameModeUiModule/GameModeUiModule.cs @@ -7,7 +7,7 @@ namespace EvoSC.Modules.Official.GameModeUiModule; [Module(IsInternal = true)] public class GameModeUiModule(IGameModeUiModuleService gameModeUiModuleService) : EvoScModule, IToggleable { - public Task EnableAsync() => gameModeUiModuleService.ApplyConfigurationAsync(); + public Task EnableAsync() => gameModeUiModuleService.ApplyComponentSettingsAsync(gameModeUiModuleService.GetDefaultSettings()); public Task DisableAsync() => Task.CompletedTask; } diff --git a/src/Modules/GameModeUiModule/GameModeUiModule.csproj b/src/Modules/GameModeUiModule/GameModeUiModule.csproj index 5d11a594b..881d331e5 100644 --- a/src/Modules/GameModeUiModule/GameModeUiModule.csproj +++ b/src/Modules/GameModeUiModule/GameModeUiModule.csproj @@ -12,8 +12,6 @@ - ResXFileCodeGenerator - Localization.Designer.cs diff --git a/src/Modules/GameModeUiModule/Interfaces/IGameModeUiModuleService.cs b/src/Modules/GameModeUiModule/Interfaces/IGameModeUiModuleService.cs index 0774afd55..eb2f5dcad 100644 --- a/src/Modules/GameModeUiModule/Interfaces/IGameModeUiModuleService.cs +++ b/src/Modules/GameModeUiModule/Interfaces/IGameModeUiModuleService.cs @@ -1,27 +1,50 @@ -namespace EvoSC.Modules.Official.GameModeUiModule.Interfaces; +using EvoSC.Modules.Official.GameModeUiModule.Models; + +namespace EvoSC.Modules.Official.GameModeUiModule.Interfaces; public interface IGameModeUiModuleService { /// - /// Applies the configured UI modules property values. + /// Applies the given game mode component settings collection. /// + /// /// - public Task ApplyConfigurationAsync(); + public Task ApplyComponentSettingsAsync(IEnumerable componentSettingsList); /// - /// Returns the configured UI modules properties as JSON string. + /// Applies the given game mode component settings. /// + /// /// - public Task GetUiModulesPropertiesJsonAsync(); + public Task ApplyComponentSettingsAsync(GameModeUiComponentSettings componentSettings); /// - /// Generates a UI properties object for the given values. + /// Applies the given game mode component settings. /// - /// + /// /// /// /// /// /// - public Task GeneratePropertyObjectAsync(string uiModuleName, bool visible, double x, double y, double scale); + public Task ApplyComponentSettingsAsync(string name, bool visible, double x, double y, double scale); + + /// + /// Returns the configured UI modules properties as JSON string. + /// + /// + public string GetUiModulesPropertiesJson(IEnumerable componentSettingsList); + + /// + /// Generates a UI properties object for the given values. + /// + /// + /// + public dynamic GeneratePropertyObject(GameModeUiComponentSettings componentSettings); + + /// + /// Gets the default game mode component settings collection. + /// + /// + public List GetDefaultSettings(); } diff --git a/src/Modules/GameModeUiModule/Models/GameModeUiComponentSettings.cs b/src/Modules/GameModeUiModule/Models/GameModeUiComponentSettings.cs new file mode 100644 index 000000000..b001de740 --- /dev/null +++ b/src/Modules/GameModeUiModule/Models/GameModeUiComponentSettings.cs @@ -0,0 +1,44 @@ +namespace EvoSC.Modules.Official.GameModeUiModule.Models; + +public class GameModeUiComponentSettings(string name, bool visible, double x, double y, double scale) +{ + /// + /// The Name/ID of the game mode UI component. + /// + public string Name { get; init; } = name; + + /// + /// Sets whether the component should be visible. + /// + public bool Visible { get; set; } = visible; + + /// + /// Sets the X position of the component. + /// + public double X { get; set; } = x; + + /// + /// Sets the Y position of the component. + /// + public double Y { get; set; } = y; + + /// + /// Sets the scale of the component. + /// + public double Scale { get; set; } = scale; + + /// + /// Sets whether the visibility of the component should be overwritten. + /// + public bool UpdateVisible { get; set; } = true; + + /// + /// Sets whether the position of the component should be overwritten. + /// + public bool UpdatePosition { get; set; } = true; + + /// + /// Sets whether the scale of the component should be overwritten. + /// + public bool UpdateScale { get; set; } = true; +} diff --git a/src/Modules/GameModeUiModule/Services/GameModeUiModuleService.cs b/src/Modules/GameModeUiModule/Services/GameModeUiModuleService.cs index 44ef2ba2c..8f87e5578 100644 --- a/src/Modules/GameModeUiModule/Services/GameModeUiModuleService.cs +++ b/src/Modules/GameModeUiModule/Services/GameModeUiModuleService.cs @@ -2,7 +2,9 @@ using EvoSC.Common.Services.Attributes; using EvoSC.Common.Services.Models; using EvoSC.Modules.Official.GameModeUiModule.Config; +using EvoSC.Modules.Official.GameModeUiModule.Enums; using EvoSC.Modules.Official.GameModeUiModule.Interfaces; +using EvoSC.Modules.Official.GameModeUiModule.Models; using Newtonsoft.Json; namespace EvoSC.Modules.Official.GameModeUiModule.Services; @@ -11,139 +13,148 @@ namespace EvoSC.Modules.Official.GameModeUiModule.Services; public class GameModeUiModuleService(IServerClient server, IGameModeUiModuleSettings settings) : IGameModeUiModuleService { - public async Task ApplyConfigurationAsync() + public Task ApplyComponentSettingsAsync(IEnumerable componentSettingsList) => + server.Remote.TriggerModeScriptEventArrayAsync("Common.UIModules.SetProperties", + GetUiModulesPropertiesJson(componentSettingsList)); + + public Task ApplyComponentSettingsAsync(GameModeUiComponentSettings componentSettings) => + ApplyComponentSettingsAsync([componentSettings]); + + public Task ApplyComponentSettingsAsync(string name, bool visible, double x, double y, double scale) => + ApplyComponentSettingsAsync([new GameModeUiComponentSettings(name, visible, x, y, scale)]); + + public string GetUiModulesPropertiesJson(IEnumerable componentSettingsList) { - var uiModuleProperties = await GetUiModulesPropertiesJsonAsync(); - await server.Remote.TriggerModeScriptEventArrayAsync("Common.UIModules.SetProperties", uiModuleProperties); + var propertyObjects = componentSettingsList + .Select(uiElement => GeneratePropertyObject(uiElement)) + .ToList(); + + return JsonConvert.SerializeObject(new { uimodules = propertyObjects }); } - public async Task GetUiModulesPropertiesJsonAsync() + public dynamic GeneratePropertyObject(GameModeUiComponentSettings componentSettings) { - return JsonConvert.SerializeObject(new + return new { - uimodules = new List - { - await GeneratePropertyObjectAsync( - "Race_Chrono", - settings.ChronoVisible, - settings.ChronoX, - settings.ChronoY, - settings.ChronoScale - ), - await GeneratePropertyObjectAsync( - "Race_RespawnHelper", - settings.RespawnHelperVisible, - settings.RespawnHelperX, - settings.RespawnHelperY, - settings.RespawnHelperScale - ), - await GeneratePropertyObjectAsync( - "Race_Checkpoint", - settings.CheckpointVisible, - settings.CheckpointX, - settings.CheckpointY, - settings.CheckpointScale - ), - await GeneratePropertyObjectAsync( - "Race_LapsCounter", - settings.LapsCounterVisible, - settings.LapsCounterX, - settings.LapsCounterY, - settings.LapsCounterScale - ), - await GeneratePropertyObjectAsync( - "Race_TimeGap", - settings.TimeGapVisible, - settings.TimeGapX, - settings.TimeGapY, - settings.TimeGapScale - ), - await GeneratePropertyObjectAsync( - "Race_ScoresTable", - settings.ScoresTableVisible, - settings.ScoresTableX, - settings.ScoresTableY, - settings.ScoresTableScale - ), - await GeneratePropertyObjectAsync( - "Race_DisplayMessage", - settings.DisplayMessageVisible, - settings.DisplayMessageX, - settings.DisplayMessageY, - settings.DisplayMessageScale - ), - await GeneratePropertyObjectAsync( - "Race_Countdown", - settings.CountdownVisible, - settings.CountdownX, - settings.CountdownY, - settings.CountdownScale - ), - await GeneratePropertyObjectAsync( - "Race_SpectatorBase_Name", - settings.SpectatorBaseNameVisible, - settings.SpectatorBaseNameX, - settings.SpectatorBaseNameY, - settings.SpectatorBaseNameScale - ), - await GeneratePropertyObjectAsync( - "Race_SpectatorBase_Commands", - settings.SpectatorBaseCommandsVisible, - settings.SpectatorBaseCommandsX, - settings.SpectatorBaseCommandsY, - settings.SpectatorBaseCommandsScale - ), - await GeneratePropertyObjectAsync( - "Race_Record", - settings.RecordVisible, - settings.RecordX, - settings.RecordY, - settings.RecordScale - ), - await GeneratePropertyObjectAsync( - "Race_BigMessage", - settings.BigMessageVisible, - settings.BigMessageX, - settings.BigMessageY, - settings.BigMessageScale - ), - await GeneratePropertyObjectAsync( - "Race_BlockHelper", - settings.BlockHelperVisible, - settings.BlockHelperX, - settings.BlockHelperY, - settings.BlockHelperScale - ), - await GeneratePropertyObjectAsync( - "Race_WarmUp", - settings.WarmUpVisible, - settings.WarmUpX, - settings.WarmUpY, - settings.WarmUpScale - ), - await GeneratePropertyObjectAsync( - "Race_BestRaceViewer", - settings.BestRaceViewerVisible, - settings.BestRaceViewerX, - settings.BestRaceViewerY, - settings.BestRaceViewerScale - ), - } - }); + id = componentSettings.Name, + position = (double[]) [componentSettings.X, componentSettings.Y], + visible = componentSettings.Visible, + scale = componentSettings.Scale, + position_update = componentSettings.UpdatePosition, + visible_update = componentSettings.UpdateVisible, + scale_update = componentSettings.UpdateScale, + }; } - public Task GeneratePropertyObjectAsync(string uiModuleName, bool visible, double x, double y, - double scale) + public List GetDefaultSettings() { - return Task.FromResult(new - { - id = uiModuleName, - position = (double[]) [x, y], - visible, - scale, - position_update = true, - visible_update = true, - scale_update = true, - }); + return + [ + new GameModeUiComponentSettings( + GameModeUiComponents.Chrono, + settings.ChronoVisible, + settings.ChronoX, + settings.ChronoY, + settings.ChronoScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.RespawnHelper, + settings.RespawnHelperVisible, + settings.RespawnHelperX, + settings.RespawnHelperY, + settings.RespawnHelperScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.Checkpoint, + settings.CheckpointVisible, + settings.CheckpointX, + settings.CheckpointY, + settings.CheckpointScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.LapsCounter, + settings.LapsCounterVisible, + settings.LapsCounterX, + settings.LapsCounterY, + settings.LapsCounterScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.TimeGap, + settings.TimeGapVisible, + settings.TimeGapX, + settings.TimeGapY, + settings.TimeGapScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.ScoresTable, + settings.ScoresTableVisible, + settings.ScoresTableX, + settings.ScoresTableY, + settings.ScoresTableScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.DisplayMessage, + settings.DisplayMessageVisible, + settings.DisplayMessageX, + settings.DisplayMessageY, + settings.DisplayMessageScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.Countdown, + settings.CountdownVisible, + settings.CountdownX, + settings.CountdownY, + settings.CountdownScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.SpectatorBaseName, + settings.SpectatorBaseNameVisible, + settings.SpectatorBaseNameX, + settings.SpectatorBaseNameY, + settings.SpectatorBaseNameScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.SpectatorBaseCommands, + settings.SpectatorBaseCommandsVisible, + settings.SpectatorBaseCommandsX, + settings.SpectatorBaseCommandsY, + settings.SpectatorBaseCommandsScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.Record, + settings.RecordVisible, + settings.RecordX, + settings.RecordY, + settings.RecordScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.BigMessage, + settings.BigMessageVisible, + settings.BigMessageX, + settings.BigMessageY, + settings.BigMessageScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.BlockHelper, + settings.BlockHelperVisible, + settings.BlockHelperX, + settings.BlockHelperY, + settings.BlockHelperScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.WarmUp, + settings.WarmUpVisible, + settings.WarmUpX, + settings.WarmUpY, + settings.WarmUpScale + ), + new GameModeUiComponentSettings( + GameModeUiComponents.BestRaceViewer, + settings.BestRaceViewerVisible, + settings.BestRaceViewerX, + settings.BestRaceViewerY, + settings.BestRaceViewerScale + ) + ]; } } diff --git a/src/Modules/Scoreboard/Scoreboard.csproj b/src/Modules/Scoreboard/Scoreboard.csproj index 7e97db700..b1ff40dea 100644 --- a/src/Modules/Scoreboard/Scoreboard.csproj +++ b/src/Modules/Scoreboard/Scoreboard.csproj @@ -9,6 +9,7 @@ + diff --git a/src/Modules/Scoreboard/Services/ScoreboardService.cs b/src/Modules/Scoreboard/Services/ScoreboardService.cs index d8e79f91b..4df4f2992 100644 --- a/src/Modules/Scoreboard/Services/ScoreboardService.cs +++ b/src/Modules/Scoreboard/Services/ScoreboardService.cs @@ -5,23 +5,33 @@ using EvoSC.Common.Services.Attributes; using EvoSC.Common.Services.Models; using EvoSC.Manialinks.Interfaces; +using EvoSC.Modules.Official.GameModeUiModule.Enums; +using EvoSC.Modules.Official.GameModeUiModule.Interfaces; using EvoSC.Modules.Official.Scoreboard.Interfaces; namespace EvoSC.Modules.Official.Scoreboard.Services; [Service(LifeStyle = ServiceLifeStyle.Transient)] -public class ScoreboardService(IManialinkManager manialinks, IServerClient server, - IMatchSettingsService matchSettingsService, IScoreboardTrackerService scoreboardTracker, IThemeManager themes) +public class ScoreboardService( + IManialinkManager manialinks, + IServerClient server, + IMatchSettingsService matchSettingsService, + IScoreboardTrackerService scoreboardTracker, + IGameModeUiModuleService gameModeUiModuleService, + IThemeManager themes +) : IScoreboardService { + private const string ScoreboardTemplate = "Scoreboard.Scoreboard"; + public async Task ShowScoreboardToAllAsync() { - await manialinks.SendPersistentManialinkAsync("Scoreboard.Scoreboard", await GetDataAsync()); + await manialinks.SendPersistentManialinkAsync(ScoreboardTemplate, await GetDataAsync()); } public async Task ShowScoreboardAsync(IPlayer playerLogin) { - await manialinks.SendManialinkAsync(playerLogin, "Scoreboard.Scoreboard", await GetDataAsync()); + await manialinks.SendManialinkAsync(playerLogin, ScoreboardTemplate, await GetDataAsync()); } private Task GetDataAsync() @@ -30,49 +40,18 @@ private Task GetDataAsync() { scoreboardTracker.MaxPlayers, scoreboardTracker.RoundsPerMap, - PositionColors = new Dictionary { { 1, themes.Theme.Gold }, { 2, themes.Theme.Silver }, { 3, themes.Theme.Bronze } }, + PositionColors = new Dictionary + { + { 1, themes.Theme.Gold }, { 2, themes.Theme.Silver }, { 3, themes.Theme.Bronze } + }, }); } - public async Task HideNadeoScoreboardAsync() - { - var hudSettings = new List - { - @"{ - ""uimodules"": [ - { - ""id"": ""Race_ScoresTable"", - ""position"": [-50,0], - ""scale"": 1, - ""visible"": false, - ""visible_update"": true - } - ] -}" - }; + public Task HideNadeoScoreboardAsync() => + gameModeUiModuleService.ApplyComponentSettingsAsync(GameModeUiComponents.ScoresTable, false, 0, 0, 1); - await server.Remote.TriggerModeScriptEventArrayAsync("Common.UIModules.SetProperties", hudSettings.ToArray()); - } - - public async Task ShowNadeoScoreboardAsync() - { - var hudSettings = new List - { - @"{ - ""uimodules"": [ - { - ""id"": ""Race_ScoresTable"", - ""position"": [-50,0], - ""scale"": 1, - ""visible"": true, - ""visible_update"": true - } - ] -}" - }; - - await server.Remote.TriggerModeScriptEventArrayAsync("Common.UIModules.SetProperties", hudSettings.ToArray()); - } + public Task ShowNadeoScoreboardAsync() => + gameModeUiModuleService.ApplyComponentSettingsAsync(GameModeUiComponents.ScoresTable, false, -50, 0, 1); public async Task SendRequiredAdditionalInfoAsync() { @@ -88,14 +67,15 @@ public async Task LoadAndSendRequiredAdditionalInfoAsync() { return; } - + var roundsPerMap = -1; var pointsLimit = -1; - + if (settings.TryGetValue("S_RoundsPerMap", out var rounds)) { roundsPerMap = (int)rounds; } + if (settings.TryGetValue("S_PointsLimit", out var pointsLimitValue)) { pointsLimit = (int)pointsLimitValue; @@ -104,7 +84,7 @@ public async Task LoadAndSendRequiredAdditionalInfoAsync() scoreboardTracker.MaxPlayers = (await server.Remote.GetMaxPlayersAsync()).CurrentValue; scoreboardTracker.RoundsPerMap = roundsPerMap; scoreboardTracker.PointsLimit = pointsLimit; - + await SendRequiredAdditionalInfoAsync(); } diff --git a/src/Modules/Scoreboard/info.toml b/src/Modules/Scoreboard/info.toml index f3c9a1dae..d957e2580 100644 --- a/src/Modules/Scoreboard/info.toml +++ b/src/Modules/Scoreboard/info.toml @@ -4,3 +4,6 @@ title = "Scoreboard" summary = "Custom EvoSC Scoreboards." version = "1.0.0" author = "Evo" + +[dependencies] +GameModeUiModule = "1.0.0" diff --git a/src/Modules/SpectatorCamModeModule/Config/ISpectatorCamModeSettings.cs b/src/Modules/SpectatorCamModeModule/Config/ISpectatorCamModeSettings.cs new file mode 100644 index 000000000..d1e36d61c --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Config/ISpectatorCamModeSettings.cs @@ -0,0 +1,20 @@ +using System.ComponentModel; +using Config.Net; +using EvoSC.Common.Util.Manialinks; +using EvoSC.Modules.Attributes; + +namespace EvoSC.Modules.Official.SpectatorCamModeModule.Config; + +[Settings] +public interface ISpectatorCamModeSettings +{ + [Option(DefaultValue = "right"), + Description("Specifies the alignment of the widget, allowed values are: left, right and center.")] + public WidgetPosition Alignment { get; set; } + + [Option(DefaultValue = 158.0), Description("Defines the horizontal position of the widget.")] + public double X { get; set; } + + [Option(DefaultValue = -82.5), Description("Defines the vertical position of the widget.")] + public double Y { get; set; } +} diff --git a/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs b/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs new file mode 100644 index 000000000..c253972b6 --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Controllers/SpectatorCamModeEventController.cs @@ -0,0 +1,22 @@ +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 new file mode 100644 index 000000000..7ffac03a6 --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Interfaces/ISpectatorCamModeService.cs @@ -0,0 +1,30 @@ +using EvoSC.Modules.Official.GameModeUiModule.Models; + +namespace EvoSC.Modules.Official.SpectatorCamModeModule.Interfaces; + +public interface ISpectatorCamModeService +{ + /// + /// Sends a persistent cam mode selection widget. + /// + /// + public Task SendPersistentCamModeWidgetAsync(); + + /// + /// Hides the previously send widget. + /// + /// + public Task HideCamModeWidgetAsync(); + + /// + /// Hides the default UI provided by the game mode. + /// + /// + public Task HideGameModeUiAsync(); + + /// + /// Gets the settings to hide the default UI component. + /// + /// + public GameModeUiComponentSettings GetGameModeUiSettings(); +} diff --git a/src/Modules/SpectatorCamModeModule/Localization.resx b/src/Modules/SpectatorCamModeModule/Localization.resx new file mode 100644 index 000000000..02cf34b4b --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Localization.resx @@ -0,0 +1,19 @@ + + + + + + + + text/microsoft-resx + + + 1.3 + + + System.Resources.ResXResourceReader, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + + System.Resources.ResXResourceWriter, System.Windows.Forms, Version=2.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089 + + \ No newline at end of file diff --git a/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs new file mode 100644 index 000000000..69212135b --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Services/SpectatorCamModeService.cs @@ -0,0 +1,41 @@ +using EvoSC.Common.Services.Attributes; +using EvoSC.Common.Services.Models; +using EvoSC.Manialinks.Interfaces; +using EvoSC.Modules.Official.GameModeUiModule.Enums; +using EvoSC.Modules.Official.GameModeUiModule.Interfaces; +using EvoSC.Modules.Official.GameModeUiModule.Models; +using EvoSC.Modules.Official.SpectatorCamModeModule.Config; +using EvoSC.Modules.Official.SpectatorCamModeModule.Interfaces; + +namespace EvoSC.Modules.Official.SpectatorCamModeModule.Services; + +[Service(LifeStyle = ServiceLifeStyle.Transient)] +public class SpectatorCamModeService( + IManialinkManager manialinks, + IGameModeUiModuleService gameModeUiModuleService, + ISpectatorCamModeSettings settings +) + : ISpectatorCamModeService +{ + private const string WidgetTemplate = "SpectatorCamModeModule.SpectatorMode"; + + public Task SendPersistentCamModeWidgetAsync() => + manialinks.SendPersistentManialinkAsync(WidgetTemplate, new { settings }); + + public Task HideCamModeWidgetAsync() => + manialinks.HideManialinkAsync(WidgetTemplate); + + public Task HideGameModeUiAsync() => + gameModeUiModuleService.ApplyComponentSettingsAsync(GetGameModeUiSettings()); + + public GameModeUiComponentSettings GetGameModeUiSettings() + { + return new GameModeUiComponentSettings( + GameModeUiComponents.SpectatorBaseCommands, + false, + 0.0, + 0.0, + 1.0 + ); + } +} diff --git a/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.cs b/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.cs new file mode 100644 index 000000000..68fe0079c --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.cs @@ -0,0 +1,17 @@ +using EvoSC.Modules.Attributes; +using EvoSC.Modules.Interfaces; +using EvoSC.Modules.Official.SpectatorCamModeModule.Interfaces; + +namespace EvoSC.Modules.Official.SpectatorCamModeModule; + +[Module(IsInternal = true)] +public class SpectatorCamModeModule(ISpectatorCamModeService spectatorCamModeService) : EvoScModule, IToggleable +{ + public async Task EnableAsync() + { + await spectatorCamModeService.SendPersistentCamModeWidgetAsync(); + await spectatorCamModeService.HideGameModeUiAsync(); + } + + public Task DisableAsync() => Task.CompletedTask; +} diff --git a/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.csproj b/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.csproj new file mode 100644 index 000000000..fa7c64cbc --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/SpectatorCamModeModule.csproj @@ -0,0 +1,25 @@ + + + + net8.0 + enable + enable + EvoSC.Modules.Official.SpectatorCamModeModule + false + SpectatorCamModeModule + + + + + + + + + + + + ResXFileCodeGenerator + Localization.Designer.cs + + + diff --git a/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms new file mode 100644 index 000000000..843927ebf --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Templates/Scripts/SpectatorMode.ms @@ -0,0 +1,302 @@ + \ No newline at end of file diff --git a/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt new file mode 100644 index 000000000..41d138210 --- /dev/null +++ b/src/Modules/SpectatorCamModeModule/Templates/SpectatorMode.mt @@ -0,0 +1,55 @@ + + + + + + + + + + + + + + + - \ No newline at end of file diff --git a/src/Modules/SpectatorTargetInfoModule/Templates/ReportSpecTarget.mt b/src/Modules/SpectatorTargetInfoModule/Templates/ReportSpecTarget.mt new file mode 100644 index 000000000..1fedbce88 --- /dev/null +++ b/src/Modules/SpectatorTargetInfoModule/Templates/ReportSpecTarget.mt @@ -0,0 +1,28 @@ + +