From a6b1772ef68d1eeae65a4f9690784cfed7654431 Mon Sep 17 00:00:00 2001 From: LittleBigBug Date: Tue, 19 Dec 2023 02:18:08 -0700 Subject: [PATCH 1/3] feat: JSON config helpers --- src/ST-Config/Cfg.cs | 13 ++++++++ src/ST-Config/ConfigLoader.cs | 58 +++++++++++++++++++++++++++++++++++ src/ST-Config/DBCfg.cs | 14 +++++++++ src/ST-DB/DB.cs | 5 ++- src/SurfTimer.cs | 11 +++---- 5 files changed, 91 insertions(+), 10 deletions(-) create mode 100644 src/ST-Config/Cfg.cs create mode 100644 src/ST-Config/ConfigLoader.cs create mode 100644 src/ST-Config/DBCfg.cs diff --git a/src/ST-Config/Cfg.cs b/src/ST-Config/Cfg.cs new file mode 100644 index 0000000..df62b0c --- /dev/null +++ b/src/ST-Config/Cfg.cs @@ -0,0 +1,13 @@ +namespace SurfTimer; + +public class Cfg : Attribute +{ + + public string Path { get; private set; } + + public Cfg(string path) + { + this.Path = path; + } + +} \ No newline at end of file diff --git a/src/ST-Config/ConfigLoader.cs b/src/ST-Config/ConfigLoader.cs new file mode 100644 index 0000000..2cad7d5 --- /dev/null +++ b/src/ST-Config/ConfigLoader.cs @@ -0,0 +1,58 @@ +using System.Text.Json; +using System.Reflection; +using CounterStrikeSharp.API; + +namespace SurfTimer; + +public class ConfigLoader where T : class, new() +{ + + public T Config { get; private set; } + + private readonly string path; + private readonly string relativePath; + + private readonly JsonSerializerOptions jsonOpts = new JsonSerializerOptions { WriteIndented = true }; + + public ConfigLoader() + { + if (typeof(T).GetCustomAttribute(typeof(Cfg)) is not Cfg attr) + throw new Exception(); + + this.relativePath = attr.Path; + this.path = Server.GameDirectory + attr.Path; + this.Config = new T(); + + this.Load(); + } + + public void Save(T config) + { + string jsonRaw = JsonSerializer.Serialize(config, this.jsonOpts); + File.WriteAllText(this.path, jsonRaw); + } + + public void Save() + { + this.Save(this.Config); + } + + public void Load() + { + // Create default cfg + if (!File.Exists(this.path)) + { + Console.WriteLine($"Writing default config for '{this.relativePath}'"); + this.Save(); + return; + } + + string rawJson = File.ReadAllText(this.path); + T? cfg = JsonSerializer.Deserialize(rawJson); + + if (cfg == null) return; + + this.Config = cfg; + } + +} diff --git a/src/ST-Config/DBCfg.cs b/src/ST-Config/DBCfg.cs new file mode 100644 index 0000000..8ed38ad --- /dev/null +++ b/src/ST-Config/DBCfg.cs @@ -0,0 +1,14 @@ +namespace SurfTimer; + +[Cfg("/csgo/cfg/SurfTimer/database.json")] +public class DBCfg +{ + + public int Port { get; set; } = 3306; + public int Timeout { get; set; } = 10; + public string Host { get; set; } = "db.example.com"; + public string Database { get; set; } = "db-name"; + public string User { get; set; } = "username"; + public string Password { get; set; } = "password"; + +} \ No newline at end of file diff --git a/src/ST-DB/DB.cs b/src/ST-DB/DB.cs index 78ce507..5c7cf52 100644 --- a/src/ST-DB/DB.cs +++ b/src/ST-DB/DB.cs @@ -15,10 +15,9 @@ public TimerDatabase() // Null'd } - - public TimerDatabase(string host, string database, string user, string password, int port, int timeout) + public TimerDatabase(DBCfg cfg) { - this._connString = $"server={host};user={user};password={password};database={database};port={port};connect timeout={timeout};"; + this._connString = $"server={cfg.Host};user={cfg.User};password={cfg.Password};database={cfg.Database};port={cfg.Port};connect timeout={cfg.Timeout};"; this._db = new MySqlConnection(this._connString); this._db.Open(); } diff --git a/src/SurfTimer.cs b/src/SurfTimer.cs index b81578a..3759dc8 100644 --- a/src/SurfTimer.cs +++ b/src/SurfTimer.cs @@ -52,6 +52,9 @@ public partial class SurfTimer : BasePlugin public string PluginPath = Server.GameDirectory + "/csgo/addons/counterstrikesharp/plugins/SurfTimer/"; internal Map CurrentMap = null!; + // Configs + internal ConfigLoader databaseCfg = new ConfigLoader(); + /* ========== MAP START HOOKS ========== */ public void OnMapStart(string mapName) { @@ -78,13 +81,7 @@ public override void Load(bool hotReload) // Load database config & spawn database object try { - JsonElement dbConfig = JsonDocument.Parse(File.ReadAllText(Server.GameDirectory + "/csgo/cfg/SurfTimer/database.json")).RootElement; - DB = new TimerDatabase(dbConfig.GetProperty("host").GetString()!, - dbConfig.GetProperty("database").GetString()!, - dbConfig.GetProperty("user").GetString()!, - dbConfig.GetProperty("password").GetString()!, - dbConfig.GetProperty("port").GetInt32(), - dbConfig.GetProperty("timeout").GetInt32()); + DB = new TimerDatabase(databaseCfg.Config); Console.WriteLine("[CS2 Surf] Database connection established."); } From 96e328958bb8b30a2c2cdea4924cf54a5de58b47 Mon Sep 17 00:00:00 2001 From: LittleBigBug Date: Tue, 19 Dec 2023 02:29:50 -0700 Subject: [PATCH 2/3] fix: create subdirs if needed --- src/ST-Config/ConfigLoader.cs | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/ST-Config/ConfigLoader.cs b/src/ST-Config/ConfigLoader.cs index 2cad7d5..3b2cd53 100644 --- a/src/ST-Config/ConfigLoader.cs +++ b/src/ST-Config/ConfigLoader.cs @@ -28,6 +28,9 @@ public ConfigLoader() public void Save(T config) { + string dirName = Path.GetDirectoryName(this.path)!; + Directory.CreateDirectory(dirName); + string jsonRaw = JsonSerializer.Serialize(config, this.jsonOpts); File.WriteAllText(this.path, jsonRaw); } From 7f9a3b3a896f790ae5ea41b8a859bd9c1ec182df Mon Sep 17 00:00:00 2001 From: LittleBigBug Date: Tue, 19 Dec 2023 18:06:58 -0700 Subject: [PATCH 3/3] feat: General Plugin Cfg & remove to-dos --- src/ST-Commands/MapCommands.cs | 2 +- src/ST-Commands/PlayerCommands.cs | 6 +++--- src/ST-Config/ConfigLoader.cs | 30 +++++++++++++++++++++++++----- src/ST-Config/DBCfg.cs | 12 ++++++------ src/ST-Config/PluginCfg.cs | 12 ++++++++++++ src/ST-Events/Players.cs | 2 +- src/ST-Events/TriggerStartTouch.cs | 2 +- src/ST-Player/PlayerHUD.cs | 12 ++++++++---- src/SurfTimer.cs | 8 +++++--- 9 files changed, 62 insertions(+), 24 deletions(-) create mode 100644 src/ST-Config/PluginCfg.cs diff --git a/src/ST-Commands/MapCommands.cs b/src/ST-Commands/MapCommands.cs index 6ae6200..ae67fcf 100644 --- a/src/ST-Commands/MapCommands.cs +++ b/src/ST-Commands/MapCommands.cs @@ -19,7 +19,7 @@ public void MapTier(CCSPlayerController? player, CommandInfo command) if (player == null) return; - player.PrintToChat($"{PluginPrefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - {ChatColors.Yellow}{CurrentMap.Stages} Stages{ChatColors.Default}"); + player.PrintToChat($"{pluginCfg.Config.Prefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - {ChatColors.Yellow}{CurrentMap.Stages} Stages{ChatColors.Default}"); return; } diff --git a/src/ST-Commands/PlayerCommands.cs b/src/ST-Commands/PlayerCommands.cs index 251a421..57fe6a5 100644 --- a/src/ST-Commands/PlayerCommands.cs +++ b/src/ST-Commands/PlayerCommands.cs @@ -57,13 +57,13 @@ public void PlayerGoToStage(CCSPlayerController? player, CommandInfo command) player.PrintToChat($"CS2 Surf DEBUG >> css_s >> Arg#: {command.ArgCount} >> Args: {Int32.Parse(command.ArgByIndex(1))}"); #endif - player.PrintToChat($"{PluginPrefix} {ChatColors.Red}Invalid arguments. Usage: {ChatColors.Green}!s "); + player.PrintToChat($"{pluginCfg.Config.Prefix} {ChatColors.Red}Invalid arguments. Usage: {ChatColors.Green}!s "); return; } else if (CurrentMap.Stages <= 0) { - player.PrintToChat($"{PluginPrefix} {ChatColors.Red}This map has no stages."); + player.PrintToChat($"{pluginCfg.Config.Prefix} {ChatColors.Red}This map has no stages."); return; } @@ -82,6 +82,6 @@ public void PlayerGoToStage(CCSPlayerController? player, CommandInfo command) } else - player.PrintToChat($"{PluginPrefix} {ChatColors.Red}Invalid stage provided. Usage: {ChatColors.Green}!s "); + player.PrintToChat($"{pluginCfg.Config.Prefix} {ChatColors.Red}Invalid stage provided. Usage: {ChatColors.Green}!s "); } } \ No newline at end of file diff --git a/src/ST-Config/ConfigLoader.cs b/src/ST-Config/ConfigLoader.cs index 3b2cd53..386cb9f 100644 --- a/src/ST-Config/ConfigLoader.cs +++ b/src/ST-Config/ConfigLoader.cs @@ -7,7 +7,9 @@ namespace SurfTimer; public class ConfigLoader where T : class, new() { - public T Config { get; private set; } + public T Config {get; private set;} + + public bool Loaded {get; private set;} = false; private readonly string path; private readonly string relativePath; @@ -45,17 +47,35 @@ public void Load() // Create default cfg if (!File.Exists(this.path)) { - Console.WriteLine($"Writing default config for '{this.relativePath}'"); + Console.WriteLine($"[CS2 Surf] Writing default config for: {this.relativePath}"); this.Save(); return; } - string rawJson = File.ReadAllText(this.path); - T? cfg = JsonSerializer.Deserialize(rawJson); + string loadingText = this.Loaded ? "Re-loading" : "Loading"; + Console.WriteLine($"[CS2 Surf] {loadingText} configuration: {this.relativePath}"); + + T? cfg = null; + + try + { + string rawJson = File.ReadAllText(this.path); + cfg = JsonSerializer.Deserialize(rawJson); + } + catch (Exception e) + { + Console.WriteLine($"[CS2 Surf] Error while trying to load config: {this.relativePath}"); + Console.WriteLine($"[CS2 Surf] Config Error: {e.Message}"); + } - if (cfg == null) return; + if (cfg == null) + { + Console.WriteLine($"[CS2 Surf] Failed to load config! For file: {this.relativePath}"); + return; + } this.Config = cfg; + this.Loaded = true; } } diff --git a/src/ST-Config/DBCfg.cs b/src/ST-Config/DBCfg.cs index 8ed38ad..3c520db 100644 --- a/src/ST-Config/DBCfg.cs +++ b/src/ST-Config/DBCfg.cs @@ -4,11 +4,11 @@ public class DBCfg { - public int Port { get; set; } = 3306; - public int Timeout { get; set; } = 10; - public string Host { get; set; } = "db.example.com"; - public string Database { get; set; } = "db-name"; - public string User { get; set; } = "username"; - public string Password { get; set; } = "password"; + public int Port {get; set;} = 3306; + public int Timeout {get; set;} = 10; + public string Host {get; set;} = "db.example.com"; + public string Database {get; set;} = "db-name"; + public string User {get; set;} = "username"; + public string Password {get; set;} = "password"; } \ No newline at end of file diff --git a/src/ST-Config/PluginCfg.cs b/src/ST-Config/PluginCfg.cs new file mode 100644 index 0000000..9cd34c9 --- /dev/null +++ b/src/ST-Config/PluginCfg.cs @@ -0,0 +1,12 @@ +using CounterStrikeSharp.API.Modules.Utils; + +namespace SurfTimer; + +[Cfg("/csgo/cfg/SurfTimer/config.json")] +public class PluginCfg +{ + + public string Prefix {get; set;} = $"[{ChatColors.DarkBlue}CS2 Surf{ChatColors.Default}]"; + public bool IncludeZVelocity {get; set;} = true; + +} \ No newline at end of file diff --git a/src/ST-Events/Players.cs b/src/ST-Events/Players.cs index 011cbaf..6bfa1e6 100644 --- a/src/ST-Events/Players.cs +++ b/src/ST-Events/Players.cs @@ -104,7 +104,7 @@ public HookResult OnPlayerConnect(EventPlayerConnectFull @event, GameEventInfo i Profile); // Print join messages - Server.PrintToChatAll($"{PluginPrefix} {ChatColors.Green}{player.PlayerName}{ChatColors.Default} has connected from {playerList[player.UserId ?? 0].Profile.Country}."); + Server.PrintToChatAll($"{pluginCfg.Config.Prefix} {ChatColors.Green}{player.PlayerName}{ChatColors.Default} has connected from {playerList[player.UserId ?? 0].Profile.Country}."); Console.WriteLine($"[CS2 Surf] {player.PlayerName} has connected from {playerList[player.UserId ?? 0].Profile.Country}."); return HookResult.Continue; } diff --git a/src/ST-Events/TriggerStartTouch.cs b/src/ST-Events/TriggerStartTouch.cs index dee74ba..8d66aaa 100644 --- a/src/ST-Events/TriggerStartTouch.cs +++ b/src/ST-Events/TriggerStartTouch.cs @@ -38,7 +38,7 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler) player.Timer.Stop(); if (player.Stats.PB[0,0] == 0 || player.Timer.Ticks < player.Stats.PB[0,0]) player.Stats.PB[0,0] = player.Timer.Ticks; - player.Controller.PrintToChat($"{PluginPrefix} You finished the map in {player.HUD.FormatTime(player.Stats.PB[0,0])}!"); + player.Controller.PrintToChat($"{pluginCfg.Config.Prefix} You finished the map in {player.HUD.FormatTime(player.Stats.PB[0,0])}!"); // player.Timer.Reset(); } diff --git a/src/ST-Player/PlayerHUD.cs b/src/ST-Player/PlayerHUD.cs index a92978c..727cb59 100644 --- a/src/ST-Player/PlayerHUD.cs +++ b/src/ST-Player/PlayerHUD.cs @@ -50,10 +50,14 @@ public void Display() } string timerModule = FormatHUDElementHTML("", FormatTime(_player.Timer.Ticks), timerColor); - // Velocity Module - To-do: Make velocity module configurable (XY or XYZ velocity) - float velocity = (float)Math.Sqrt(_player.Controller.PlayerPawn.Value!.AbsVelocity.X * _player.Controller.PlayerPawn.Value!.AbsVelocity.X - + _player.Controller.PlayerPawn.Value!.AbsVelocity.Y * _player.Controller.PlayerPawn.Value!.AbsVelocity.Y - + _player.Controller.PlayerPawn.Value!.AbsVelocity.Z * _player.Controller.PlayerPawn.Value!.AbsVelocity.Z); + // Velocity Module + float sqVelocity = _player.Controller.PlayerPawn.Value!.AbsVelocity.X * _player.Controller.PlayerPawn.Value!.AbsVelocity.X + + _player.Controller.PlayerPawn.Value!.AbsVelocity.Y * _player.Controller.PlayerPawn.Value!.AbsVelocity.Y; + + if (SurfTimer.pluginCfg.Config.IncludeZVelocity) + sqVelocity += _player.Controller.PlayerPawn.Value!.AbsVelocity.Z * _player.Controller.PlayerPawn.Value!.AbsVelocity.Z; + + float velocity = (float) Math.Sqrt(sqVelocity); string velocityModule = FormatHUDElementHTML("Speed", velocity.ToString("000"), "#79d1ed") + " u/s"; // Rank Module string rankModule = FormatHUDElementHTML("Rank", "N/A", "#7882dd"); // IMPLEMENT IN PlayerStats diff --git a/src/SurfTimer.cs b/src/SurfTimer.cs index 3759dc8..777ad2f 100644 --- a/src/SurfTimer.cs +++ b/src/SurfTimer.cs @@ -44,7 +44,6 @@ public partial class SurfTimer : BasePlugin public override string ModuleVersion => "DEV-1"; public override string ModuleDescription => "Official Surf Timer by the CS2 Surf Initiative."; public override string ModuleAuthor => "The CS2 Surf Initiative - github.com/cs2surf"; - public string PluginPrefix => $"[{ChatColors.DarkBlue}CS2 Surf{ChatColors.Default}]"; // To-do: make configurable // Globals private Dictionary playerList = new Dictionary(); // This can probably be done way better, revisit @@ -53,7 +52,8 @@ public partial class SurfTimer : BasePlugin internal Map CurrentMap = null!; // Configs - internal ConfigLoader databaseCfg = new ConfigLoader(); + internal static ConfigLoader databaseCfg = new ConfigLoader(); + internal static ConfigLoader pluginCfg = new ConfigLoader(); /* ========== MAP START HOOKS ========== */ public void OnMapStart(string mapName) @@ -68,7 +68,9 @@ public void OnMapStart(string mapName) [GameEventHandler] public HookResult OnRoundStart(EventRoundStart @event, GameEventInfo info) { - // Load cvars/other configs here + // (Re)Load cvars/other configs here + pluginCfg.Load(); + // Execute server_settings.cfg Server.ExecuteCommand("execifexists SurfTimer/server_settings.cfg"); Console.WriteLine("[CS2 Surf] Executed configuration: server_settings.cfg");