Skip to content

Commit

Permalink
v0.6.0-alpha | feat: Get5 support
Browse files Browse the repository at this point in the history
  • Loading branch information
shobhit-pathak committed Dec 14, 2023
1 parent 94a5d2f commit 696b29e
Show file tree
Hide file tree
Showing 17 changed files with 1,810 additions and 114 deletions.
1 change: 1 addition & 0 deletions ConfigConvars.cs
Original file line number Diff line number Diff line change
Expand Up @@ -90,6 +90,7 @@ public void MatchZyDemoPath(CCSPlayerController? player, CommandInfo command)
}
}

[ConsoleCommand("get5_demo_upload_url", "If defined, recorded demos will be uploaded to this URL once the map ends.")]
[ConsoleCommand("matchzy_demo_upload_url", "If defined, recorded demos will be uploaded to this URL once the map ends.")]
public void MatchZyDemoUploadURL(CCSPlayerController? player, CommandInfo command)
{
Expand Down
58 changes: 53 additions & 5 deletions ConsoleCommands.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
using CounterStrikeSharp.API.Modules.Memory;
using CounterStrikeSharp.API.Modules.Utils;
using CounterStrikeSharp.API.Modules.Timers;
using System.Text.RegularExpressions;

namespace MatchZy
{
Expand Down Expand Up @@ -49,7 +50,7 @@ public void OnSaveNadesAsGlobalCommand(CCSPlayerController? player, CommandInfo?
[ConsoleCommand("css_ready", "Marks the player ready")]
public void OnPlayerReady(CCSPlayerController? player, CommandInfo? command) {
if (player == null) return;
Log($"[!ready command] Sent by: {player.UserId}, connectedPlayers: {connectedPlayers}");
Log($"[!ready command] Sent by: {player.UserId} readyAvailable: {readyAvailable} matchStarted: {matchStarted}");
if (readyAvailable && !matchStarted) {
if (player.UserId.HasValue) {
if (!playerReadyStatus.ContainsKey(player.UserId.Value)) {
Expand Down Expand Up @@ -101,6 +102,7 @@ public void OnTeamStay(CCSPlayerController? player, CommandInfo? command) {
}

[ConsoleCommand("css_switch", "Switch after knife round")]
[ConsoleCommand("css_swap", "Switch after knife round")]
public void OnTeamSwitch(CCSPlayerController? player, CommandInfo? command) {
if (player == null) return;

Expand Down Expand Up @@ -132,14 +134,16 @@ public void OnPauseCommand(CCSPlayerController? player, CommandInfo? command) {
}
}

[ConsoleCommand("css_fp", "Pause the matchas an admin")]
[ConsoleCommand("css_fp", "Pause the match an admin")]
[ConsoleCommand("css_forcepause", "Pause the match as an admin")]
[ConsoleCommand("sm_pause", "Pause the match as an admin")]
public void OnForcePauseCommand(CCSPlayerController? player, CommandInfo? command) {
ForcePauseMatch(player, command);
}

[ConsoleCommand("css_fup", "Pause the matchas an admin")]
[ConsoleCommand("css_forceunpause", "Pause the match as an admin")]
[ConsoleCommand("css_fup", "Unpause the match an admin")]
[ConsoleCommand("css_forceunpause", "Unpause the match as an admin")]
[ConsoleCommand("sm_unpause", "Unpause the match as an admin")]
public void OnForceUnpauseCommand(CCSPlayerController? player, CommandInfo? command) {
ForceUnpauseMatch(player, command);
}
Expand Down Expand Up @@ -253,13 +257,36 @@ public void OnMatchSettingsCommand(CCSPlayerController? player, CommandInfo? com
string playoutStatus = isPlayOutEnabled ? "Enabled" : "Disabled";
player.PrintToChat($"{chatPrefix} Current Settings:");
player.PrintToChat($"{chatPrefix} Knife: {ChatColors.Green}{knifeStatus}{ChatColors.Default}");
player.PrintToChat($"{chatPrefix} Minimum Ready Required: {ChatColors.Green}{minimumReadyRequired}{ChatColors.Default}");
if (isMatchSetup)
{
player.PrintToChat($"{chatPrefix} Minimum Ready Players Required (Per Team): {ChatColors.Green}{matchConfig.MinPlayersToReady}{ChatColors.Default}");
player.PrintToChat($"{chatPrefix} Minimum Ready Spectators Required: {ChatColors.Green}{matchConfig.MinSpectatorsToReady}{ChatColors.Default}");
}
else
{
player.PrintToChat($"{chatPrefix} Minimum Ready Required: {ChatColors.Green}{minimumReadyRequired}{ChatColors.Default}");
}
player.PrintToChat($"{chatPrefix} Playout: {ChatColors.Green}{playoutStatus}{ChatColors.Default}");
} else {
SendPlayerNotAdminMessage(player);
}
}

[ConsoleCommand("css_endmatch", "Ends and resets the current match")]
[ConsoleCommand("get5_endmatch", "Ends and resets the current match")]
public void OnEndMatchCommand(CCSPlayerController? player, CommandInfo? command) {
if (IsPlayerAdmin(player, "css_endmatch", "@css/config")) {
if (!isPractice) {
Server.PrintToChatAll($"{chatPrefix} An admin force-ended the match.");
ResetMatch();
} else {
ReplyToUserCommand(player, "Practice mode is active, cannot end the match.");
}
} else {
SendPlayerNotAdminMessage(player);
}
}

[ConsoleCommand("css_restart", "Restarts the match")]
public void OnRestartMatchCommand(CCSPlayerController? player, CommandInfo? command) {
if (IsPlayerAdmin(player, "css_restart", "@css/config")) {
Expand Down Expand Up @@ -415,5 +442,26 @@ public void OnPlayoutCommand(CCSPlayerController? player, CommandInfo? command)
SendPlayerNotAdminMessage(player);
}
}

[ConsoleCommand("version", "Returns server version")]
public void OnVersionCommand(CCSPlayerController? player, CommandInfo? command) {
if (command == null) return;
string steamInfFilePath = Path.Combine(Server.GameDirectory, "csgo", "steam.inf");

if (!File.Exists(steamInfFilePath))
{
command.ReplyToCommand("Unable to locate steam.inf file!");
}
var steamInfContent = File.ReadAllText(steamInfFilePath);

Regex regex = new(@"ServerVersion=(\d+)");
Match match = regex.Match(steamInfContent);

// Extract the version number
string? serverVersion = match.Success ? match.Groups[1].Value : null;

// Currently returning only server version to show server status as available on Get5
command.ReplyToCommand((serverVersion != null) ? $"Protocol version {serverVersion} [{serverVersion}/{serverVersion}]" : "Unable to get server version");
}
}
}
96 changes: 58 additions & 38 deletions DemoManagement.cs
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
using CounterStrikeSharp.API;
using CounterStrikeSharp.API.Core;
using CounterStrikeSharp.API.Core.Attributes.Registration;
using CounterStrikeSharp.API.Modules.Commands;
using CounterStrikeSharp.API.Modules.Cvars;
using System.IO.Compression;
using System.Net.Http.Json;
using System.Text;


namespace MatchZy
Expand All @@ -9,6 +14,8 @@ public partial class MatchZy
{
public string demoPath = "MatchZy/";
public string demoUploadURL = "";
public string demoUploadHeaderKey = "";
public string demoUploadHeaderValue = "";

public string activeDemoFile = "";

Expand Down Expand Up @@ -82,59 +89,72 @@ public async Task UploadDemoAsync(string? demoPath, long matchId, int mapNumber)

try
{
using (var httpClient = new HttpClient())
using (var formData = new MultipartFormDataContent())
{
Log($"[UploadDemoAsync] Going to upload demo on {demoUploadURL}. Complete path: {demoPath}");
using var httpClient = new HttpClient();
Log($"[UploadDemoAsync] Going to upload demo on {demoUploadURL}. Complete path: {demoPath}");

if (!File.Exists(demoPath))
{
Log($"[UploadDemoAsync ERROR] File not found: {demoPath}");
return;
}
if (!File.Exists(demoPath))
{
Log($"[UploadDemoAsync ERROR] File not found: {demoPath}");
return;
}

var compressedFilePath = Path.ChangeExtension(demoPath, "zip"); // Change to ".gz" for GZip compression
using FileStream fileStream = File.OpenRead(demoPath);

using (var compressedFileStream = new FileStream(compressedFilePath, FileMode.Create))
using (var zipArchive = new ZipArchive(compressedFileStream, ZipArchiveMode.Create))
{
// Add the .dem file to the zip archive
var zipEntry = zipArchive.CreateEntry(Path.GetFileName(demoPath));
using (var entryStream = zipEntry.Open())
using (var demoFileStream = new FileStream(demoPath, FileMode.Open, FileAccess.Read))
{
await demoFileStream.CopyToAsync(entryStream);
}
}
byte[] fileContent = new byte[fileStream.Length];
await fileStream.ReadAsync(fileContent, 0, (int)fileStream.Length);

var compressedFileStreamContent = new StreamContent(new FileStream(compressedFilePath, FileMode.Open, FileAccess.Read));
compressedFileStreamContent.Headers.Add("Content-Type", "application/zip");
using ByteArrayContent content = new ByteArrayContent(fileContent);
content.Headers.Add("Content-Type", "application/octet-stream");

formData.Add(compressedFileStreamContent, "file", Path.GetFileName(compressedFilePath));
content.Headers.Add("MatchZy-FileName", Path.GetFileName(demoPath));
content.Headers.Add("MatchZy-MatchId", matchId.ToString());
content.Headers.Add("MatchZy-MapNumber", mapNumber.ToString());

formData.Headers.Add("MatchZy-FileName", Path.GetFileName(compressedFilePath));
formData.Headers.Add("MatchZy-MatchId", matchId.ToString());
formData.Headers.Add("MatchZy-MapNumber", mapNumber.ToString());
// For Get5 Panel
content.Headers.Add("Get5-FileName", Path.GetFileName(demoPath));
content.Headers.Add("Get5-MatchId", matchId.ToString());
content.Headers.Add("Get5-MapNumber", mapNumber.ToString());

var response = await httpClient.PostAsync(demoUploadURL, formData).ConfigureAwait(false);
if (!string.IsNullOrEmpty(demoUploadHeaderKey))
{
httpClient.DefaultRequestHeaders.Add(demoUploadHeaderKey, demoUploadHeaderValue);
}

if (response.IsSuccessStatusCode)
{
Log($"[UploadDemoAsync] File upload successful for matchId: {matchId} mapNumber: {mapNumber} fileName: {Path.GetFileName(compressedFilePath)}.");
}
else
{
Log($"[UploadDemoAsync ERROR] Failed to upload file. Status code: {response.StatusCode}");
}
HttpResponseMessage response = await httpClient.PostAsync(demoUploadURL, content);

// Clean up: Delete the temporary compressed file
File.Delete(compressedFilePath);
if (response.IsSuccessStatusCode)
{
Log($"[UploadDemoAsync] File upload successful for matchId: {matchId} mapNumber: {mapNumber} fileName: {Path.GetFileName(demoPath)}.");
}
else
{
Log($"[UploadDemoAsync ERROR] Failed to upload file. Status code: {response.StatusCode} Response: {await response.Content.ReadAsStringAsync()}");
}
}
catch (Exception e)
{
Log($"[UploadDemoAsync FATAL] An error occurred: {e.Message}");
}
}

[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)
{
if (player != null) return;
string header = command.ArgByIndex(1).Trim();

if (header != "") demoUploadHeaderKey = header;
}

[ConsoleCommand("get5_demo_upload_header_value", "If defined, the value of the custom header added to the demos sent over HTTP")]
[ConsoleCommand("matchzy_demo_upload_header_value", "If defined, the value of the custom header added to the demos sent over HTTP")]
public void DemoUploadHeaderValueCommand(CCSPlayerController? player, CommandInfo command)
{
if (player != null) return;
string headerValue = command.ArgByIndex(1).Trim();

if (headerValue != "") demoUploadHeaderValue = headerValue;
}
}
}
Loading

0 comments on commit 696b29e

Please sign in to comment.