256 lines
6.4 KiB
SourcePawn
256 lines
6.4 KiB
SourcePawn
#pragma semicolon 1
|
|
#include <sourcemod>
|
|
|
|
ConVar g_hTvEnabled;
|
|
ConVar g_hAutoRecord;
|
|
ConVar g_hMinPlayersStart;
|
|
ConVar g_hIgnoreBots;
|
|
ConVar g_hTimeStart;
|
|
ConVar g_hTimeStop;
|
|
ConVar g_hFinishMap;
|
|
ConVar g_hDemoPath;
|
|
ConVar g_hMaxLength;
|
|
|
|
bool g_bIsRecording = false;
|
|
bool g_bIsManual = false;
|
|
|
|
int g_iStartedRecording;
|
|
int g_iRecordingNumber;
|
|
int g_iRecordingFromTick;
|
|
|
|
// Default: o=rx,g=rx,u=rwx | 755
|
|
#define DIRECTORY_PERMISSIONS (FPERM_O_READ|FPERM_O_EXEC | FPERM_G_READ|FPERM_G_EXEC | FPERM_U_READ|FPERM_U_WRITE|FPERM_U_EXEC)
|
|
|
|
public Plugin myinfo =
|
|
{
|
|
name = "Auto Recorder",
|
|
author = "Stevo.TVR",
|
|
description = "Automates SourceTV recording based on player count and time of day.",
|
|
version = "1.2.0",
|
|
url = "http://www.theville.org"
|
|
}
|
|
|
|
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
|
{
|
|
CreateNative("IsDemoRecording", Native_IsDemoRecording);
|
|
|
|
CreateNative("GetDemoRecordingNumber", Native_GetDemoRecordingNumber);
|
|
CreateNative("GetDemoRecordingTick", Native_GetDemoRecordingTick);
|
|
|
|
RegPluginLibrary("AutoRecorder");
|
|
return APLRes_Success;
|
|
}
|
|
|
|
public void OnPluginStart()
|
|
{
|
|
g_hAutoRecord = CreateConVar("sm_autorecord_enable", "1", "Enable automatic recording", _, true, 0.0, true, 1.0);
|
|
g_hMinPlayersStart = CreateConVar("sm_autorecord_minplayers", "4", "Minimum players on server to start recording", _, true, 0.0);
|
|
g_hIgnoreBots = CreateConVar("sm_autorecord_ignorebots", "1", "Ignore bots in the player count", _, true, 0.0, true, 1.0);
|
|
g_hTimeStart = CreateConVar("sm_autorecord_timestart", "-1", "Hour in the day to start recording (0-23, -1 disables)");
|
|
g_hTimeStop = CreateConVar("sm_autorecord_timestop", "-1", "Hour in the day to stop recording (0-23, -1 disables)");
|
|
g_hFinishMap = CreateConVar("sm_autorecord_finishmap", "1", "If 1, continue recording until the map ends", _, true, 0.0, true, 1.0);
|
|
g_hDemoPath = CreateConVar("sm_autorecord_path", "demos/", "Path to store recorded demos");
|
|
g_hMaxLength = CreateConVar("sm_autorecord_maxlength", "0", "Maximum length of demos in seconds, 0 to disable", _, true, 0.0);
|
|
|
|
AutoExecConfig(true, "autorecorder");
|
|
|
|
RegAdminCmd("sm_record", Command_Record, ADMFLAG_KICK, "Starts a SourceTV demo");
|
|
RegAdminCmd("sm_stoprecord", Command_StopRecord, ADMFLAG_KICK, "Stops the current SourceTV demo");
|
|
|
|
HookEvent("round_start", OnRoundStart);
|
|
|
|
g_hTvEnabled = FindConVar("tv_enable");
|
|
|
|
static char sPath[PLATFORM_MAX_PATH];
|
|
GetConVarString(g_hDemoPath, sPath, sizeof(sPath));
|
|
|
|
if(!DirExists(sPath))
|
|
CreateDirectory(sPath, DIRECTORY_PERMISSIONS);
|
|
|
|
HookConVarChange(g_hMinPlayersStart, OnConVarChanged);
|
|
HookConVarChange(g_hIgnoreBots, OnConVarChanged);
|
|
HookConVarChange(g_hTimeStart, OnConVarChanged);
|
|
HookConVarChange(g_hTimeStop, OnConVarChanged);
|
|
HookConVarChange(g_hDemoPath, OnConVarChanged);
|
|
|
|
CreateTimer(300.0, Timer_CheckStatus, _, TIMER_REPEAT);
|
|
|
|
StopRecord();
|
|
CheckStatus();
|
|
}
|
|
|
|
public void OnRoundStart(Event hEvent, const char[] sEvent, bool bDontBroadcast)
|
|
{
|
|
int maxLength = GetConVarInt(g_hMaxLength);
|
|
if(g_bIsRecording && maxLength > 0 && GetTime() >= g_iStartedRecording + maxLength)
|
|
{
|
|
StopRecord();
|
|
CheckStatus();
|
|
}
|
|
}
|
|
|
|
public void OnConVarChanged(ConVar convar, const char[] oldValue, const char[] newValue)
|
|
{
|
|
if(convar == g_hDemoPath)
|
|
{
|
|
if(!DirExists(newValue))
|
|
CreateDirectory(newValue, DIRECTORY_PERMISSIONS);
|
|
}
|
|
else
|
|
CheckStatus();
|
|
}
|
|
|
|
public void OnMapEnd()
|
|
{
|
|
if(g_bIsRecording)
|
|
{
|
|
StopRecord();
|
|
g_bIsManual = false;
|
|
}
|
|
|
|
g_iRecordingNumber = 0;
|
|
}
|
|
|
|
public void OnClientPutInServer(int client)
|
|
{
|
|
CheckStatus();
|
|
}
|
|
|
|
public void OnClientDisconnect_Post(int client)
|
|
{
|
|
CheckStatus();
|
|
}
|
|
|
|
public Action Timer_CheckStatus(Handle hTimer)
|
|
{
|
|
CheckStatus();
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action Command_Record(int client, int args)
|
|
{
|
|
if(g_bIsRecording)
|
|
{
|
|
ReplyToCommand(client, "[SM] SourceTV is already recording!");
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
StartRecord();
|
|
g_bIsManual = true;
|
|
|
|
ReplyToCommand(client, "[SM] SourceTV is now recording...");
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
public Action Command_StopRecord(int client, int args)
|
|
{
|
|
if(!g_bIsRecording)
|
|
{
|
|
ReplyToCommand(client, "[SM] SourceTV is not recording!");
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
StopRecord();
|
|
|
|
if(g_bIsManual)
|
|
{
|
|
g_bIsManual = false;
|
|
CheckStatus();
|
|
}
|
|
|
|
ReplyToCommand(client, "[SM] Stopped recording.");
|
|
|
|
return Plugin_Handled;
|
|
}
|
|
|
|
void CheckStatus()
|
|
{
|
|
if(GetConVarBool(g_hAutoRecord) && !g_bIsManual)
|
|
{
|
|
int iMinClients = GetConVarInt(g_hMinPlayersStart);
|
|
|
|
int iTimeStart = GetConVarInt(g_hTimeStart);
|
|
int iTimeStop = GetConVarInt(g_hTimeStop);
|
|
bool bReverseTimes = (iTimeStart > iTimeStop);
|
|
|
|
static char sCurrentTime[4];
|
|
FormatTime(sCurrentTime, sizeof(sCurrentTime), "%H", GetTime());
|
|
int iCurrentTime = StringToInt(sCurrentTime);
|
|
|
|
if(GetPlayerCount() >= iMinClients+1 && (iTimeStart < 0 || (iCurrentTime >= iTimeStart && (bReverseTimes || iCurrentTime < iTimeStop))))
|
|
{
|
|
StartRecord();
|
|
}
|
|
else if(g_bIsRecording && !GetConVarBool(g_hFinishMap) && (iTimeStop < 0 || iCurrentTime >= iTimeStop))
|
|
{
|
|
StopRecord();
|
|
}
|
|
}
|
|
}
|
|
|
|
int GetPlayerCount()
|
|
{
|
|
if(!GetConVarBool(g_hIgnoreBots))
|
|
return GetClientCount(false) - 1;
|
|
|
|
int iNumPlayers = 0;
|
|
for(int i = 1; i <= MaxClients; i++)
|
|
{
|
|
if(IsClientConnected(i) && !IsFakeClient(i))
|
|
iNumPlayers++;
|
|
}
|
|
|
|
return iNumPlayers;
|
|
}
|
|
|
|
void StartRecord()
|
|
{
|
|
if(GetConVarBool(g_hTvEnabled) && !g_bIsRecording)
|
|
{
|
|
static char sPath[PLATFORM_MAX_PATH];
|
|
static char sMap[PLATFORM_MAX_PATH];
|
|
static char sTime[16];
|
|
|
|
GetConVarString(g_hDemoPath, sPath, sizeof(sPath));
|
|
FormatTime(sTime, sizeof(sTime), "%Y%m%d-%H%M%S", GetTime());
|
|
GetCurrentMap(sMap, sizeof(sMap));
|
|
|
|
// replace slashes in map path name with dashes, to prevent fail on workshop maps
|
|
ReplaceString(sMap, sizeof(sMap), "/", "-", false);
|
|
|
|
g_iRecordingNumber++;
|
|
g_iRecordingFromTick = GetGameTickCount();
|
|
|
|
ServerCommand("tv_record \"%s/auto-%s-%s-%d\"", sPath, sTime, sMap, g_iRecordingNumber);
|
|
g_bIsRecording = true;
|
|
g_iStartedRecording = GetTime();
|
|
|
|
LogMessage("Recording to auto-%s-%s-%d.dem", sTime, sMap, g_iRecordingNumber);
|
|
}
|
|
}
|
|
|
|
void StopRecord()
|
|
{
|
|
if(GetConVarBool(g_hTvEnabled))
|
|
{
|
|
ServerCommand("tv_stoprecord");
|
|
g_bIsRecording = false;
|
|
}
|
|
}
|
|
|
|
public int Native_IsDemoRecording(Handle hPlugin, int numParams)
|
|
{
|
|
return g_bIsRecording;
|
|
}
|
|
|
|
public int Native_GetDemoRecordingNumber(Handle hPlugin, int numParams)
|
|
{
|
|
return g_iRecordingNumber;
|
|
}
|
|
|
|
public int Native_GetDemoRecordingTick(Handle hPlugin, int numParams)
|
|
{
|
|
return GetGameTickCount() - g_iRecordingFromTick;
|
|
}
|