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;
 | 
						|
}
 |