From a07c9ef42372ef28f09dddbf5e4fee1f91d10237 Mon Sep 17 00:00:00 2001 From: snixtho Date: Fri, 26 Jul 2024 07:41:50 +0100 Subject: [PATCH] Docker (#248) --- .gitignore | 1 + Dockerfile | 46 +++++ docker-compose.yml | 38 ---- docker/docker-compose.yml | 40 +++++ docker/evosc.env.example | 167 ++++++++++++++++++ src/EvoSC.CLI/CliStartup.cs | 5 +- .../Config/Stores/TomlConfigStore.cs | 2 +- src/EvoSC/ApplicationSetup.cs | 2 +- src/EvoSC/EvoSC.csproj | 4 + .../Services/SpectatorTargetInfoService.cs | 11 +- 10 files changed, 272 insertions(+), 44 deletions(-) create mode 100644 Dockerfile delete mode 100644 docker-compose.yml create mode 100644 docker/docker-compose.yml create mode 100644 docker/evosc.env.example diff --git a/.gitignore b/.gitignore index 78725866b..1730a86de 100644 --- a/.gitignore +++ b/.gitignore @@ -43,3 +43,4 @@ EvoSC/ext_plugins/* docker-compose.yml global.json +.env diff --git a/Dockerfile b/Dockerfile new file mode 100644 index 000000000..3dc39a4fb --- /dev/null +++ b/Dockerfile @@ -0,0 +1,46 @@ +# Build EvoSC# +FROM mcr.microsoft.com/dotnet/sdk:8.0 as build + +WORKDIR /source +COPY . . + +RUN dotnet publish "src/EvoSC/EvoSC.csproj" -r linux-musl-x64 --self-contained true -c Release -o /publish + +# Set user & permissions +FROM alpine:latest as run-chown + +WORKDIR /app +COPY --from=build /publish . +RUN true \ + && chown 9999:9999 -R /app \ + && true + +# Create the image +FROM mcr.microsoft.com/dotnet/runtime-deps:8.0-alpine3.20 as create-image + +ARG VERSION \ + BUILD_DATE \ + REVISION + +# Disable invariant mode which is enabled on alpine to make localization work +ENV DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=false + +LABEL org.opencontainers.image.title="EvoSC#" \ + org.opencontainers.image.description="Next-generation server controller for Trackmania." \ + org.opencontainers.image.authors="Evo" \ + org.opencontainers.image.vendor="Evo eSports e.V." \ + org.opencontainers.image.licenses="GPL-3.0 License " \ + org.opencontainers.image.version=${VERSION} \ + org.opencontainers.image.created=${BUILD_DATE} \ + org.opencontainers.image.revision=${REVISION} + +WORKDIR /app +COPY --from=run-chown /app . + +RUN true \ + && apk add --no-cache icu-libs \ + && adduser --disabled-password --home /app -u 9999 evosc \ + && true \ + +USER evosc +ENTRYPOINT ["./EvoSC", "run"] diff --git a/docker-compose.yml b/docker-compose.yml deleted file mode 100644 index d2be81813..000000000 --- a/docker-compose.yml +++ /dev/null @@ -1,38 +0,0 @@ -version: "3.8" -services: - trackmania: - image: evotm/trackmania - ports: - - 2350:2350/udp - - 2350:2350/tcp - - "5001:5000/tcp" # Be careful opening XMLRPC! Only if you really need to. - environment: - MASTER_LOGIN: "CHANGEME :)" # Create server credentials at https://www.trackmania.com/player/dedicated-servers - MASTER_PASSWORD: "CHANGEME :)" # Create server credentials at https://www.trackmania.com/player/dedicated-servers - XMLRPC_ALLOWREMOTE: "True" - volumes: - - UserData:/server/UserData - db: - image: postgres - restart: always - ports: - - "5432:5432" - volumes: - - PostgresData:/var/lib/postgresql/data - environment: - - POSTGRES_PASSWORD=evosc - #- POSTGRES_USER=CHANGEME :) for a production server please change those values! - #- POSTGRES_DB=CHANGEME :) - pgadmin: - image: dpage/pgadmin4 - restart: always - extra_hosts: - - "host.docker.internal:host-gateway" - environment: - PGADMIN_DEFAULT_EMAIL: PLEASE@CHANGE.ME - PGADMIN_DEFAULT_PASSWORD: CHANGEME - ports: - - "8081:80" -volumes: - UserData: null - PostgresData: null diff --git a/docker/docker-compose.yml b/docker/docker-compose.yml new file mode 100644 index 000000000..647e2f620 --- /dev/null +++ b/docker/docker-compose.yml @@ -0,0 +1,40 @@ +services: + trackmania: + image: evotm/trackmania + restart: always + ports: + - 2350:2350/udp + - 2350:2350/tcp + environment: + - MASTER_LOGIN= + - MASTER_PASSWORD= + - XMLRPC_ALLOWREMOTE=True + volumes: + - UserData:/server/UserData + + postgres: + image: postgres:latest + restart: always + environment: + - POSTGRES_PASSWORD=evosc_sharp + - POSTGRES_USER=evosc_sharp + - POSTGRES_DB=evosc_sharp + + evosc_sharp: + image: evoscsharp:latest + restart: always + depends_on: + - trackmania + - postgres + environment: + - EVOSC_DATABASE_HOST=postgres + - EVOSC_DATABASE_NAME=evosc_sharp + - EVOSC_DATABASE_USERNAME=evosc_sharp + - EVOSC_DATABASE_PASSWORD=evosc_sharp + - EVOSC_SERVER_HOST=trackmania + volumes: + - UserData:/server/UserData + +volumes: + PostgresData: null + UserData: null diff --git a/docker/evosc.env.example b/docker/evosc.env.example new file mode 100644 index 000000000..448d9aa02 --- /dev/null +++ b/docker/evosc.env.example @@ -0,0 +1,167 @@ +# +# EvoSC# Base Config +# + +# The type of database to use. Available types: PostgreSql, MySql, SQLite +#EVOSC_DATABASE_TYPE=PostgreSql + +# Address to the database +#EVOSC_DATABASE_HOST=127.0.0.1 + +# Port of the database +#EVOSC_DATABASE_PORT=5432 + +# The name of the database +#EVOSC_DATABASE_NAME=postgres + +# Name of the user to access the database +#EVOSC_DATABASE_USERNAME=evosc + +# Password of the user to access the database +#EVOSC_DATABASE_PASSWORD=evosc + +# A string prefix to add to all table names +#EVOSC_DATABASE_TABLEPREFIX= + +# Possible values lowest to highest verbosity: none, critical, error, warning, information, debug, trace +#EVOSC_LOGGING_LOGLEVEL=debug + +# Whether to output logs to the console in JSON. +#EVOSC_LOGGING_USEJSON=False + +# Address to the Trackmania server +#EVOSC_SERVER_HOST=127.0.0.1 + +# Port that the XMLRPC is listening to +#EVOSC_SERVER_PORT=5000 + +# Username of the super admin account +#EVOSC_SERVER_USERNAME=SuperAdmin + +# Password of the super admin account +#EVOSC_SERVER_PASSWORD=SuperAdmin + +# If enabled, the client will try to reconnect with the server every 1 second until a connection is established +#EVOSC_SERVER_RETRYCONNECTION=True + +# Path to the maps folder +#EVOSC_PATH_MAPS= + +# Default match settings file +#EVOSC_PATH_DEFAULTMATCHSETTINGS=example.txt + +# Signature verification of module's files. If enabled and verification fails, the module will not load. +#EVOSC_MODULES_REQUIRESIGNATUREVERIFICATION=True + +# Directories to scan for external modules. +#EVOSC_MODULES_MODULEDIRECTORIES=System.String[] + +# Modules that will not load on startup. Note that if a module depend on a disabled module, it will load anyways. +#EVOSC_MODULES_DISABLEDMODULES= + +# The default display language of the controller. Must be a "language tag" as found here: https://learn.microsoft.com/en-us/openspecs/windows_protocols/ms-lcid/a9eac961-e77d-41a6-90a5-ce1a8b0cdb9c +#EVOSC_LOCALE_DEFAULTLANGUAGE=en + +#EVOSC_THEME= + + + +# +# Module Config Options +# + + +## Module "ExampleModule" v1.0.0 ## + +#EVOSC_EXAMPLEMODULE_MYOPTION=default value + + + +## Module "RecordsModule" v1.0.0 ## + +# How to send a message about a new PB. +#EVOSC_RECORDSMODULE_ECHOPB=None + + + +## Module "MotdModule" v1.0.0 ## + +# The URL from which the controller fetches the motd. +#EVOSC_MOTDMODULE_MOTDURL= + +# The interval in which the motd gets fetched from the server. +#EVOSC_MOTDMODULE_MOTDFETCHINTERVAL=600000 + +# The locally stored Motd text if it should not be fetched from a server. +#EVOSC_MOTDMODULE_MOTDLOCALTEXT=This is the Motd! + +# Indicator if the locally stored motd should be used. +#EVOSC_MOTDMODULE_USELOCALMOTD=True + + + +## Module "OpenPlanetModule" v1.0.0 ## + +# Allowed signature types: Regular, DevMode, Official, Competition +#EVOSC_OPENPLANETMODULE_ALLOWEDSIGNATUREMODES=Regular, Official, TMGL + +# Time to wait before kicking the player. +#EVOSC_OPENPLANETMODULE_KICKTIMEOUT=30 + +# Enable continous check of the signature mode of the player while they are on the server. +#EVOSC_OPENPLANETMODULE_CONTINUOUSCHECKSENABLED=False + +# Number of milliseconds to wait between the continous checks. +#EVOSC_OPENPLANETMODULE_CHECKINTERVAL=5000 + +# Enable checking of the signature mode of a player when they join. +#EVOSC_OPENPLANETMODULE_SIGNATUREMODECHECKENABLED=True + +# Allow the use of openplanet. If false, no signature mode is allowed. +#EVOSC_OPENPLANETMODULE_ALLOWOPENPLANET=True + +# The minimum required OpenPlanet version to play on this server. +#EVOSC_OPENPLANETMODULE_MINIMUMREQUIREDVERSION=1.25.45 + + + +## Module "MatchTrackerModule" v1.0.0 ## + +# Whether to start tracking matches automatically. +#EVOSC_MATCHTRACKERMODULE_AUTOMATICTRACKING=False + +# Whether to automatically end a match when the EndMatch section is detected. +#EVOSC_MATCHTRACKERMODULE_AUTOMATICMATCHEND=True + +# Whether to store match state changes immediately instead of waiting until the match ends. +#EVOSC_MATCHTRACKERMODULE_IMMEDIATESTORING=True + +# Record end of map states. +#EVOSC_MATCHTRACKERMODULE_RECORDENDMAP=True + +# Record end of match states. +#EVOSC_MATCHTRACKERMODULE_RECORDENDMATCH=True + +# Record end of round states. +#EVOSC_MATCHTRACKERMODULE_RECORDENDROUND=True + +# Record pre end of match states. +#EVOSC_MATCHTRACKERMODULE_RECORDENDMATCHEARLY=False + +# Keep pre end of round states. +#EVOSC_MATCHTRACKERMODULE_RECORDPREENDROUND=False + + + +## Module "LocalRecordsModule" v1.0.0 ## + +# Max of rows to show in the local records widget. +#EVOSC_LOCALRECORDSMODULE_MAXWIDGETROWS=10 + +# Always show top N players in the widget. +#EVOSC_LOCALRECORDSMODULE_WIDGETSHOWTOP=3 + +# Maximum number of local records to keep track of per map. +#EVOSC_LOCALRECORDSMODULE_MAXRECORDSPERMAP=100 + + diff --git a/src/EvoSC.CLI/CliStartup.cs b/src/EvoSC.CLI/CliStartup.cs index 55bff2f26..04f710473 100644 --- a/src/EvoSC.CLI/CliStartup.cs +++ b/src/EvoSC.CLI/CliStartup.cs @@ -12,6 +12,7 @@ using EvoSC.Common.Permissions; using EvoSC.Common.Remote; using EvoSC.Common.Services; +using EvoSC.Common.Themes; using EvoSC.Manialinks; using EvoSC.Manialinks.Interfaces; using EvoSC.Modules.Extensions; @@ -43,7 +44,7 @@ public static void SetupBasePipeline(this IStartupPipeline pipeline, IEvoScBaseC .Services(AppFeature.GbxRemoteClient, s => s .AddGbxRemoteClient() - , "Logging", "Config", "Events", "ActionPipelines", "InitializeGbxRemoteConnection") + , "Logging", "Config", "Events", "ActionPipelines", "InitializeGbxRemoteConnection", "Themes") .Services(AppFeature.Modules, s => s .AddEvoScModules() @@ -94,6 +95,8 @@ public static void SetupBasePipeline(this IStartupPipeline pipeline, IEvoScBaseC .AddEvoScManialinks() , "Logging", "Events", "PlayerManager", "ControllerManager", "ActionPipelines", "GbxRemoteClient", "ActionInitializeTemplates") + .Services(AppFeature.Themes, s => s.AddEvoScThemes()) + // initialization of features .Action("ActionMigrateDatabase", MigrateDatabase) diff --git a/src/EvoSC.Common/Config/Stores/TomlConfigStore.cs b/src/EvoSC.Common/Config/Stores/TomlConfigStore.cs index 6c70f313f..6c0a2a60c 100644 --- a/src/EvoSC.Common/Config/Stores/TomlConfigStore.cs +++ b/src/EvoSC.Common/Config/Stores/TomlConfigStore.cs @@ -28,7 +28,6 @@ public TomlConfigStore(string path) _document = CreateDefaultConfig(); File.WriteAllText(path, _document.SerializedValue); - } else { @@ -41,6 +40,7 @@ private TomlDocument CreateDefaultConfig() { var rootType = typeof(TConfig); var document = BuildSubDocument(TomlDocument.CreateEmpty(), rootType, ""); + document.Put("Theme", new TomlTable()); // avoid inline writing which is more human readable document.ForceNoInline = false; diff --git a/src/EvoSC/ApplicationSetup.cs b/src/EvoSC/ApplicationSetup.cs index f358083cd..7b3204ff0 100644 --- a/src/EvoSC/ApplicationSetup.cs +++ b/src/EvoSC/ApplicationSetup.cs @@ -81,7 +81,7 @@ public static void SetupPipeline(this IStartupPipeline pipeline, IEvoScBaseConfi .Services(AppFeature.Manialinks, s => s.AddEvoScManialinks()) - .Services(AppFeature.Themes, s => s.AddEvoScThemes()) + .Services(AppFeature.Themes, s => s.AddEvoScThemes()) // initialize the application .Action("ActionMigrateDatabase", MigrateDatabase) diff --git a/src/EvoSC/EvoSC.csproj b/src/EvoSC/EvoSC.csproj index 5ce53b900..2fd3e1ba0 100644 --- a/src/EvoSC/EvoSC.csproj +++ b/src/EvoSC/EvoSC.csproj @@ -64,5 +64,9 @@ + + + + diff --git a/src/Modules/SpectatorTargetInfoModule/Services/SpectatorTargetInfoService.cs b/src/Modules/SpectatorTargetInfoModule/Services/SpectatorTargetInfoService.cs index 50e130a74..3ba7e5144 100644 --- a/src/Modules/SpectatorTargetInfoModule/Services/SpectatorTargetInfoService.cs +++ b/src/Modules/SpectatorTargetInfoModule/Services/SpectatorTargetInfoService.cs @@ -1,7 +1,9 @@ using EvoSC.Common.Interfaces; +using EvoSC.Common.Interfaces.Services; using EvoSC.Common.Remote.EventArgsModels; using EvoSC.Common.Services.Attributes; using EvoSC.Common.Services.Models; +using EvoSC.Common.Util; using EvoSC.Manialinks.Interfaces; using SpectatorTargetInfo.Interfaces; @@ -9,7 +11,7 @@ namespace EvoSC.Modules.Official.SpectatorTargetInfoModule.Services; [Service(LifeStyle = ServiceLifeStyle.Singleton)] public class SpectatorTargetInfoService - (IManialinkManager manialinks, IServerClient server) : ISpectatorTargetInfoService + (IManialinkManager manialinks, IServerClient server, IPlayerManagerService playerManagerService) : ISpectatorTargetInfoService { private const string WidgetTemplate = "SpectatorTargetInfoModule.SpectatorTargetInfo"; @@ -17,8 +19,11 @@ public async Task SendManiaLinkAsync() => await manialinks.SendManialinkAsync(WidgetTemplate); - public async Task SendManiaLinkAsync(string playerLogin) => - await manialinks.SendManialinkAsync(playerLogin, WidgetTemplate); + public async Task SendManiaLinkAsync(string playerLogin) + { + var player = await playerManagerService.GetOnlinePlayerAsync(PlayerUtils.ConvertLoginToAccountId(playerLogin)); + await manialinks.SendManialinkAsync(player, WidgetTemplate); + } public async Task HideManiaLinkAsync() => await manialinks.HideManialinkAsync(WidgetTemplate);