Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 3 additions & 2 deletions src/ST-Commands/MapCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -20,9 +20,10 @@ public void MapTier(CCSPlayerController? player, CommandInfo command)
return;

if (CurrentMap.Stages > 0)
player.PrintToChat($"{PluginPrefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - Staged {ChatColors.Yellow}{CurrentMap.Stages} Stages{ChatColors.Default}");
player.PrintToChat($"{pluginCfg.Config.Prefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - Staged {ChatColors.Yellow}{CurrentMap.Stages} Stages{ChatColors.Default}");
else
player.PrintToChat($"{PluginPrefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - Linear {ChatColors.Yellow}{CurrentMap.Checkpoints} Checkpoints{ChatColors.Default}");
player.PrintToChat($"{pluginCfg.Config.Prefix} {CurrentMap.Name} - {ChatColors.Green}Tier {CurrentMap.Tier}{ChatColors.Default} - Linear {ChatColors.Yellow}{CurrentMap.Checkpoints} Checkpoints{ChatColors.Default}");

return;
}

Expand Down
6 changes: 3 additions & 3 deletions src/ST-Commands/PlayerCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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 <stage>");
player.PrintToChat($"{pluginCfg.Config.Prefix} {ChatColors.Red}Invalid arguments. Usage: {ChatColors.Green}!s <stage>");
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;
}

Expand All @@ -82,6 +82,6 @@ public void PlayerGoToStage(CCSPlayerController? player, CommandInfo command)
}

else
player.PrintToChat($"{PluginPrefix} {ChatColors.Red}Invalid stage provided. Usage: {ChatColors.Green}!s <stage>");
player.PrintToChat($"{pluginCfg.Config.Prefix} {ChatColors.Red}Invalid stage provided. Usage: {ChatColors.Green}!s <stage>");
}
}
13 changes: 13 additions & 0 deletions src/ST-Config/Cfg.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
namespace SurfTimer;

public class Cfg : Attribute
{

public string Path { get; private set; }

public Cfg(string path)
{
this.Path = path;
}

}
81 changes: 81 additions & 0 deletions src/ST-Config/ConfigLoader.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,81 @@
using System.Text.Json;
using System.Reflection;
using CounterStrikeSharp.API;

namespace SurfTimer;

public class ConfigLoader<T> where T : class, new()
{

public T Config {get; private set;}

public bool Loaded {get; private set;} = false;

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 dirName = Path.GetDirectoryName(this.path)!;
Directory.CreateDirectory(dirName);

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($"[CS2 Surf] Writing default config for: {this.relativePath}");
this.Save();
return;
}

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<T>(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)
{
Console.WriteLine($"[CS2 Surf] Failed to load config! For file: {this.relativePath}");
return;
}

this.Config = cfg;
this.Loaded = true;
}

}
14 changes: 14 additions & 0 deletions src/ST-Config/DBCfg.cs
Original file line number Diff line number Diff line change
@@ -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";

}
12 changes: 12 additions & 0 deletions src/ST-Config/PluginCfg.cs
Original file line number Diff line number Diff line change
@@ -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;

}
5 changes: 2 additions & 3 deletions src/ST-DB/DB.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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();
}
Expand Down
2 changes: 1 addition & 1 deletion src/ST-Events/Players.cs
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public HookResult OnPlayerConnect(EventPlayerConnectFull @event, GameEventInfo i
playerList[player.UserId ?? 0].Stats.PB[0].LoadCheckpointsForRun(DB); // To-do: This really should go inside `LoadMapTimesData` imo cuz here we hardcoding load for Style 0

// Print join messages
Server.PrintToChatAll($"{PluginPrefix} {ChatColors.Green}{player.PlayerName}{ChatColors.Default} has connected from {ChatColors.Lime}{playerList[player.UserId ?? 0].Profile.Country}{ChatColors.Default}.");
Server.PrintToChatAll($"{pluginCfg.Config.Prefix} {ChatColors.Green}{player.PlayerName}{ChatColors.Default} has connected from {ChatColors.Lime}{playerList[player.UserId ?? 0].Profile.Country}{ChatColors.Default}.");
Console.WriteLine($"[CS2 Surf] {player.PlayerName} has connected from {playerList[player.UserId ?? 0].Profile.Country}.");
return HookResult.Continue;
}
Expand Down
6 changes: 3 additions & 3 deletions src/ST-Events/TriggerStartTouch.cs
Original file line number Diff line number Diff line change
Expand Up @@ -59,15 +59,15 @@ internal HookResult OnTriggerStartTouch(DynamicHook handler)
// To-do: make Style (currently 0) be dynamic
if (player.Stats.PB[0].RunTime <= 0) // Player first ever PersonalBest for the map
{
Server.PrintToChatAll($"{PluginPrefix} {player.Controller.PlayerName} finished the map in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} ({player.Timer.Ticks})!");
Server.PrintToChatAll($"{pluginCfg.Config.Prefix} {player.Controller.PlayerName} finished the map in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} ({player.Timer.Ticks})!");
}
else if (player.Timer.Ticks < player.Stats.PB[0].RunTime) // Player beating their existing PersonalBest for the map
{
Server.PrintToChatAll($"{PluginPrefix} {ChatColors.Lime}{player.Profile.Name}{ChatColors.Default} beat their PB in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} (Old: {ChatColors.BlueGrey}{player.HUD.FormatTime(player.Stats.PB[0].RunTime)}{ChatColors.Default})!");
Server.PrintToChatAll($"{pluginCfg.Config.Prefix} {ChatColors.Lime}{player.Profile.Name}{ChatColors.Default} beat their PB in {ChatColors.Gold}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default} (Old: {ChatColors.BlueGrey}{player.HUD.FormatTime(player.Stats.PB[0].RunTime)}{ChatColors.Default})!");
}
else // Player did not beat their existing PersonalBest for the map
{
player.Controller.PrintToChat($"{PluginPrefix} You finished the map in {ChatColors.Yellow}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default}!");
player.Controller.PrintToChat($"{pluginCfg.Config.Prefix} You finished the map in {ChatColors.Yellow}{player.HUD.FormatTime(player.Timer.Ticks)}{ChatColors.Default}!");
return HookResult.Continue; // Exit here so we don't write to DB
}

Expand Down
12 changes: 8 additions & 4 deletions src/ST-Player/PlayerHUD.cs
Original file line number Diff line number Diff line change
Expand Up @@ -70,10 +70,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("0"), "#79d1ed") + " u/s";
// Rank Module
string rankModule = FormatHUDElementHTML("Rank", $"N/A", "#7882dd");
Expand Down
17 changes: 8 additions & 9 deletions src/SurfTimer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,17 @@ 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<int, Player> playerList = new Dictionary<int, Player>(); // This can probably be done way better, revisit
internal TimerDatabase? DB = new TimerDatabase();
public string PluginPath = Server.GameDirectory + "/csgo/addons/counterstrikesharp/plugins/SurfTimer/";
internal Map CurrentMap = null!;

// Configs
internal static ConfigLoader<DBCfg> databaseCfg = new ConfigLoader<DBCfg>();
internal static ConfigLoader<PluginCfg> pluginCfg = new ConfigLoader<PluginCfg>();

/* ========== MAP START HOOKS ========== */
public void OnMapStart(string mapName)
{
Expand All @@ -73,7 +76,9 @@ public void OnMapEnd()
[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");
Expand All @@ -86,13 +91,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.");
}

Expand Down