Skip to content

Commit

Permalink
0.8.0 | feat: Improved backup/restore
Browse files Browse the repository at this point in the history
  • Loading branch information
shobhit-pathak committed Jul 8, 2024
1 parent ae597e5 commit cf11bd5
Show file tree
Hide file tree
Showing 11 changed files with 422 additions and 134 deletions.
357 changes: 272 additions & 85 deletions BackupManagement.cs

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions ConfigConvars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ public partial class MatchZy

public FakeConVar<bool> showCreditsOnMatchStart = new("matchzy_show_credits_on_match_start", "Whether to show 'MatchZy Plugin by WD-' message on match start. Default: true", true);

public FakeConVar<string> hostnameFormat = new("matchzy_hostname_format", "The server hostname to use. Set to \"\" to disable/use existing. Default: MatchZy | {TEAM1} vs {TEAM2}", "MatchZy | {TEAM1} vs {TEAM2}");

[ConsoleCommand("matchzy_whitelist_enabled_default", "Whether Whitelist is enabled by default or not. Default value: false")]
public void MatchZyWLConvar(CCSPlayerController? player, CommandInfo command)
{
Expand Down
17 changes: 1 addition & 16 deletions DemoManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -24,7 +24,7 @@ public partial class MatchZy
public void StartDemoRecording()
{

string demoFileName = FormatDemoName();
string demoFileName = FormatCvarValue(demoNameFormat.Replace(" ", "_")) + ".dem";
try
{
string? directoryPath = Path.GetDirectoryName(Path.Join(Server.GameDirectory + "/csgo/", demoPath));
Expand Down Expand Up @@ -145,21 +145,6 @@ public async Task UploadDemoAsync(string? demoPath, long matchId, int mapNumber)
}


private string FormatDemoName()
{
string formattedTime = DateTime.Now.ToString("yyyy-MM-dd HH-mm-ss");

var demoName = demoNameFormat
.Replace("{TIME}", formattedTime)
.Replace("{MATCH_ID}", $"{liveMatchId}")
.Replace("{MAP}", Server.MapName)
.Replace("{MAPNUMBER}", matchConfig.CurrentMapNumber.ToString())
.Replace("{TEAM1}", matchzyTeam1.teamName)
.Replace("{TEAM2}", matchzyTeam2.teamName)
.Replace(" ", "_");
return $"{demoName}.dem";
}

[ConsoleCommand("get5_demo_upload_header_key", "If defined, a custom HTTP header with this name is added to the HTTP requests for demos")]
[ConsoleCommand("matchzy_demo_upload_header_key", "If defined, a custom HTTP header with this name is added to the HTTP requests for demos")]
public void DemoUploadHeaderKeyCommand(CCSPlayerController? player, CommandInfo command)
Expand Down
2 changes: 2 additions & 0 deletions EventHandlers.cs
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,7 @@ public HookResult EventPlayerConnectFullHandler(EventPlayerConnectFull @event, G
if (!whiteList.Contains(steamId.ToString()))
{
Log($"[EventPlayerConnectFull] KICKING PLAYER STEAMID: {steamId}, Name: {player.PlayerName} (Not whitelisted!)");
PrintToAllChat($"Kicking player {player.PlayerName} - Not whitelisted.");
KickPlayer(player);

return HookResult.Continue;
Expand All @@ -50,6 +51,7 @@ public HookResult EventPlayerConnectFullHandler(EventPlayerConnectFull @event, G
if (team == CsTeam.None)
{
Log($"[EventPlayerConnectFull] KICKING PLAYER STEAMID: {steamId}, Name: {player.PlayerName} (NOT ALLOWED!)");
PrintToAllChat($"Kicking player {player.PlayerName} - Not a player in this game.");
KickPlayer(player);
return HookResult.Continue;
}
Expand Down
55 changes: 47 additions & 8 deletions MatchConfig.cs
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
using System.Text.Json.Serialization;
using Newtonsoft.Json.Linq;


Expand All @@ -6,32 +7,70 @@ namespace MatchZy

public class MatchConfig
{
[JsonPropertyName("maplist")]
public List<string> Maplist { get; set; } = new List<string>();

[JsonPropertyName("maps_pool")]
public List<string> MapsPool { get; set; } = new List<string>();

[JsonPropertyName("maps_left_in_veto_pool")]
public List<string> MapsLeftInVetoPool { get; set; } = new List<string>();

[JsonPropertyName("map_ban_order")]
public List<string> MapBanOrder { get; set; } = new List<string>();
public bool SkipVeto = true;

[JsonPropertyName("skip_veto")]
public bool SkipVeto { get; set; } = true;

[JsonPropertyName("match_id")]
public long MatchId { get; set; }

[JsonPropertyName("num_maps")]
public int NumMaps { get; set; } = 1;

[JsonPropertyName("players_per_team")]
public int PlayersPerTeam { get; set; } = 5;

[JsonPropertyName("min_players_to_ready")]
public int MinPlayersToReady { get; set; } = 12;

[JsonPropertyName("min_spectators_to_ready")]
public int MinSpectatorsToReady { get; set; } = 0;
public int CurrentMapNumber = 0;

[JsonPropertyName("current_map_number")]
public int CurrentMapNumber { get; set; } = 0;

[JsonPropertyName("map_sides")]
public List<string> MapSides { get; set; } = new List<string>();

[JsonPropertyName("series_can_clinch")]
public bool SeriesCanClinch { get; set; } = true;

[JsonPropertyName("scrim")]
public bool Scrim { get; set; } = false;

[JsonPropertyName("wingman")]
public bool Wingman { get; set; } = false;

[JsonPropertyName("match_side_type")]
public string MatchSideType { get; set; } = "standard";

public Dictionary<string, string> ChangedCvars = new();
[JsonPropertyName("changed_cvars")]
public Dictionary<string, string> ChangedCvars { get; set; } = new();

[JsonPropertyName("original_cvars")]
public Dictionary<string, string> OriginalCvars { get; set; } = new();

[JsonPropertyName("spectators")]
public JToken Spectators { get; set; } = new JObject();

[JsonPropertyName("remote_log_url")]
public string RemoteLogURL { get; set; } = "";

[JsonPropertyName("remote_log_header_key")]
public string RemoteLogHeaderKey { get; set; } = "";

public Dictionary<string, string> OriginalCvars = new();
public JToken? Spectators;
public string RemoteLogURL = "";
public string RemoteLogHeaderKey = "";
public string RemoteLogHeaderValue = "";
[JsonPropertyName("remote_log_header_value")]
public string RemoteLogHeaderValue { get; set; } = "";
}
}
4 changes: 2 additions & 2 deletions MatchManagement.cs
Original file line number Diff line number Diff line change
Expand Up @@ -365,8 +365,8 @@ public bool LoadMatchFromJSON(string jsonData)
if(matchConfig.SkipVeto) SetMapSides();

SetTeamNames();

UpdatePlayersMap();
UpdateHostname();

var seriesStartedEvent = new MatchZySeriesStartedEvent
{
Expand Down Expand Up @@ -462,7 +462,7 @@ public void GetOptionalMatchValues(JObject jsonDataObject)
}
if (jsonDataObject["spectators"] != null && jsonDataObject["spectators"]!["players"] != null)
{
matchConfig.Spectators = jsonDataObject["spectators"]!["players"];
matchConfig.Spectators = jsonDataObject["spectators"]!["players"]!;
if (matchConfig.Spectators is JArray spectatorsArray && spectatorsArray.Count == 0)
{
// Convert the empty JArray to an empty JObject
Expand Down
2 changes: 1 addition & 1 deletion MatchZy.cs
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ public partial class MatchZy : BasePlugin
{

public override string ModuleName => "MatchZy";
public override string ModuleVersion => "0.7.11";
public override string ModuleVersion => "0.8.0";

public override string ModuleAuthor => "WD- (https://github.com/shobhit-pathak/)";

Expand Down
11 changes: 11 additions & 0 deletions Teams.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,20 +4,31 @@
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Utils;
using Newtonsoft.Json.Linq;
using System.Text.Json.Serialization;

namespace MatchZy
{

public class Team
{
[JsonPropertyName("id")]
public string id = "";

[JsonPropertyName("teamname")]
public required string teamName;

[JsonPropertyName("teamname")]
public string teamFlag = "";

[JsonPropertyName("teamflag")]
public string teamTag = "";

[JsonPropertyName("teamplayers")]
public JToken? teamPlayers;

public CCSPlayerController? coach;

[JsonPropertyName("seriesscore")]
public int seriesScore = 0;
}

Expand Down
99 changes: 78 additions & 21 deletions Utility.cs
Original file line number Diff line number Diff line change
Expand Up @@ -122,7 +122,14 @@ private void SendUnreadyPlayersMessage() {
string minimumReadyRequiredMessage = isMatchSetup ? "" : $"[Minimum ready players required: {ChatColors.Green}{minimumReadyRequired}{ChatColors.Default}]";

// Server.PrintToChatAll($"{chatPrefix} Unready players: {unreadyPlayerList}. Please type .ready to ready up! {minimumReadyRequiredMessage}");
PrintToAllChat(Localizer["matchzy.utility.unreadyplayers", unreadyPlayerList, minimumReadyRequiredMessage]);
if (isRoundRestorePending)
{
PrintToAllChat(Localizer["matchzy.ready.readytotestorebackupinfomessage", unreadyPlayerList, minimumReadyRequiredMessage]);
}
else
{
PrintToAllChat(Localizer["matchzy.utility.unreadyplayers", unreadyPlayerList, minimumReadyRequiredMessage]);
}
} else {
int countOfReadyPlayers = playerReadyStatus.Count(kv => kv.Value == true);
if (isMatchSetup)
Expand Down Expand Up @@ -219,23 +226,35 @@ private void StartAfterKnifeWarmup() {
// Server.PrintToChatAll($"{chatPrefix} {ChatColors.Green}{knifeWinnerName}{ChatColors.Default} Won the knife. Waiting for them to type {ChatColors.Green}.stay{ChatColors.Default} or {ChatColors.Green}.switch{ChatColors.Default}");
sideSelectionMessageTimer ??= AddTimer(chatTimerDelay, SendSideSelectionMessage, TimerFlags.REPEAT);
}

private void StartLive() {

// Setting match phases bools

private void SetLiveFlags()
{
isWarmup = false;
isSideSelectionPhase = false;
matchStarted = true;
isMatchLive = true;
readyAvailable = false;
isKnifeRound = false;
}

// Storing 0-0 score backup file as lastBackupFileName, so that .stop functions properly in first round.
lastBackupFileName = $"matchzy_{liveMatchId}_{matchConfig.CurrentMapNumber}_round00.txt";

private void SetupLiveFlagsAndCfg()
{
SetLiveFlags();
KillPhaseTimers();

ExecLiveCFG();
// Adding timer here to make sure that CFG execution is completed till then
AddTimer(1, () => {
HandlePlayoutConfig();
ExecuteChangedConvars();
});
}

private void StartLive() {
SetupLiveFlagsAndCfg();

// Storing 0-0 score backup file as lastBackupFileName, so that .stop functions properly in first round.
lastBackupFileName = $"matchzy_{liveMatchId}_{matchConfig.CurrentMapNumber}_round00.txt";
lastMatchZyBackupFileName = $"matchzy_data_backup_{liveMatchId}_{matchConfig.CurrentMapNumber}_round_00.json";

// This is to reload the map once it is over so that all flags are reset accordingly
Server.ExecuteCommand("mp_match_end_restart true");
Expand All @@ -244,12 +263,6 @@ private void StartLive() {
PrintToAllChat($"{ChatColors.Lime}LIVE!");
PrintToAllChat($"{ChatColors.Green}LIVE!");

// Adding timer here to make sure that CFG execution is completed till then
AddTimer(1, () => {
HandlePlayoutConfig();
ExecuteChangedConvars();
});

var goingLiveEvent = new GoingLiveEvent
{
MatchId = liveMatchId.ToString(),
Expand Down Expand Up @@ -312,6 +325,9 @@ private void ResetMatch(bool warmupCfgRequired = true)
isPreVeto = false;

lastBackupFileName = "";
lastMatchZyBackupFileName = "";

isRoundRestorePending = false;

// Unready all players
foreach (var key in playerReadyStatus.Keys) {
Expand Down Expand Up @@ -576,7 +592,13 @@ private void CheckLiveRequired() {
private void HandleMatchStart() {
isPractice = false;
isDryRun = false;

if (isRoundRestorePending)
{
RestoreRoundBackup(null, pendingRestoreFileName);
isRoundRestorePending = false;
pendingRestoreFileName = "";
return;
}
// If default names, we pick a player and use their name as their team name
if (matchzyTeam1.teamName == "COUNTER-TERRORISTS") {
// matchzyTeam1.teamName = teamName;
Expand Down Expand Up @@ -829,6 +851,7 @@ public void HandlePostRoundStartEvent(EventRoundStart @event) {
HandleCoaches();
CreateMatchZyRoundDataBackup();
InitPlayerDamageInfo();
UpdateHostname();
}

public void HandlePostRoundFreezeEndEvent(EventRoundFreezeEnd @event)
Expand Down Expand Up @@ -922,7 +945,8 @@ private void HandlePostRoundEndEvent(EventRoundEnd @event) {

string round = GetRoundNumer().ToString("D2");
lastBackupFileName = $"matchzy_{liveMatchId}_{matchConfig.CurrentMapNumber}_round{round}.txt";
Log($"[HandlePostRoundEndEvent] Setting lastBackupFileName to {lastBackupFileName}");
lastMatchZyBackupFileName = $"matchzy_data_backup_{liveMatchId}_{matchConfig.CurrentMapNumber}_round_{round}.json";
Log($"[HandlePostRoundEndEvent] Setting lastBackupFileName to {lastBackupFileName} and lastMatchZyBackupFileName to {lastMatchZyBackupFileName}");

// One of the team did not use .stop command hence display the proper message after the round has ended.
if (stopData["ct"] && !stopData["t"]) {
Expand Down Expand Up @@ -1081,11 +1105,11 @@ private void ForceUnpauseMatch(CCSPlayerController? player, CommandInfo? command
SendPlayerNotAdminMessage(player);
return;
}
Server.PrintToChatAll($"{chatPrefix} {ChatColors.Green}Admin{ChatColors.Default} has unpaused the match, resuming the match!");
PrintToAllChat(Localizer["matchzy.pause.adminunpausedthematch"]);
UnpauseMatch();

if (player == null) {
Server.PrintToConsole("[MatchZy] Admin has unpaused the match, resuming the match!");
Server.PrintToConsole("[MatchZy] Admin has unpaused, resuming the match!");
}
}
}
Expand Down Expand Up @@ -1165,7 +1189,9 @@ private string GetColorTreatedString(string message)
foreach (var field in typeof(ChatColors).GetFields())
{
string pattern = $"{{{field.Name}}}";
string replacement = field.GetValue(null).ToString();
string? replacement = field.GetValue(null)?.ToString();

if (replacement is null) return message;

// Create a case-insensitive regular expression pattern for the color name
string patternIgnoreCase = Regex.Escape(pattern);
Expand Down Expand Up @@ -1337,9 +1363,40 @@ public void ResetChangedConvars()
}
}

public string FormatCvarValue(string value)
{
string formattedTime = DateTime.Now.ToString("yyyy-MM-dd HH:mm:ss");
(int team1Score, int team2Score) = GetTeamsScore();

var formattedValue = value
.Replace("{TIME}", formattedTime.Replace(" ", "_"))
.Replace("{MATCH_ID}", $"{liveMatchId}")
.Replace("{MAP}", Server.MapName)
.Replace("{MAPNUMBER}", matchConfig.CurrentMapNumber.ToString())
.Replace("{TEAM1}", matchzyTeam1.teamName.Replace(" ", "_"))
.Replace("{TEAM2}", matchzyTeam2.teamName.Replace(" ", "_"))
.Replace("{TEAM1_SCORE}", team1Score.ToString())
.Replace("{TEAM2_SCORE}", team2Score.ToString());
return formattedValue;
}

public void UpdateHostname()
{
if (hostnameFormat.Value.Trim() == "") return;
string formattedHostname = FormatCvarValue(hostnameFormat.Value);
Log($"UPDATING HOSTNAME TO: {formattedHostname}");
Server.ExecuteCommand($"hostname {formattedHostname}");
// ConVar.Find("hostname")!.SetValue(formattedHostname);
}

public CCSGameRules GetGameRules()
{
return Utilities.FindAllEntitiesByDesignerName<CCSGameRulesProxy>("cs_gamerules").First().GameRules!;
}

public int GetGamePhase()
{
return Utilities.FindAllEntitiesByDesignerName<CCSGameRulesProxy>("cs_gamerules").First().GameRules!.GamePhase;
return GetGameRules().GamePhase;
}

public bool IsHalfTimePhase()
Expand Down
3 changes: 3 additions & 0 deletions cfg/MatchZy/config.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -99,3 +99,6 @@ matchzy_everyone_is_admin false

// Whether to show 'MatchZy Plugin by WD-' message on match start. Default: true
matchzy_show_credits_on_match_start true

// The server hostname to use. Set to "" to disable/use existing.
matchzy_hostname_format "MatchZy | {TEAM1} vs {TEAM2}"
Loading

0 comments on commit cf11bd5

Please sign in to comment.