forked from TheVilleOrg/sourcemod
-
Notifications
You must be signed in to change notification settings - Fork 0
/
autorecorder.sp
264 lines (219 loc) · 6.45 KB
/
autorecorder.sp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
/*
*
* Auto Recorder
* http://forums.alliedmods.net/showthread.php?t=92072
*
* Description:
* Automates SourceTV recording based on player count
* and time of day. Also allows admins to manually record.
*
* Changelog
* May 09, 2009 - v.1.0.0:
* [*] Initial Release
* May 11, 2009 - v.1.1.0:
* [+] Added path cvar to control where demos are stored
* [*] Changed manual recording to override automatic recording
* [+] Added seconds to demo names
* May 04, 2016 - v.1.1.1:
* [*] Changed demo file names to replace slashes with hyphens [ajmadsen]
* Aug 26, 2016 - v.1.2.0:
* [*] Now ignores bots in the player count by default
* [*] The SourceTV client is now always ignored in the player count
* [+] Added sm_autorecord_ignorebots to control whether to ignore bots
* [*] Now checks the status of the server immediately when a setting is changed
* Jun 21, 2017 - v.1.3.0:
* [*] Fixed minimum player count setting being off by one
* [*] Fixed player counting code getting out of range
* [*] Updated source code to the new syntax
*
*/
#include <sourcemod>
#pragma semicolon 1
#pragma newdecls required
#define PLUGIN_VERSION "1.3.0"
public Plugin myinfo =
{
name = "Auto Recorder",
author = "Stevo.TVR",
description = "Automates SourceTV recording based on player count and time of day.",
version = PLUGIN_VERSION,
url = "http://www.theville.org"
}
ConVar g_hTvEnabled = null;
ConVar g_hAutoRecord = null;
ConVar g_hMinPlayersStart = null;
ConVar g_hIgnoreBots = null;
ConVar g_hTimeStart = null;
ConVar g_hTimeStop = null;
ConVar g_hFinishMap = null;
ConVar g_hDemoPath = null;
bool g_bIsRecording = false;
bool g_bIsManual = false;
public void OnPluginStart()
{
CreateConVar("sm_autorecord_version", PLUGIN_VERSION, "Auto Recorder plugin version", FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_NOTIFY|FCVAR_DONTRECORD);
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", ".", "Path to store recorded demos");
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");
g_hTvEnabled = FindConVar("tv_enable");
char sPath[PLATFORM_MAX_PATH];
g_hDemoPath.GetString(sPath, sizeof(sPath));
if(!DirExists(sPath))
{
InitDirectory(sPath);
}
g_hMinPlayersStart.AddChangeHook(OnConVarChanged);
g_hIgnoreBots.AddChangeHook(OnConVarChanged);
g_hTimeStart.AddChangeHook(OnConVarChanged);
g_hTimeStop.AddChangeHook(OnConVarChanged);
g_hDemoPath.AddChangeHook(OnConVarChanged);
CreateTimer(300.0, Timer_CheckStatus, _, TIMER_REPEAT);
StopRecord();
CheckStatus();
}
public void OnConVarChanged(ConVar convar, const char[] oldValue, const char [] newValue)
{
if(convar == g_hDemoPath)
{
if(!DirExists(newValue))
{
InitDirectory(newValue);
}
}
else
{
CheckStatus();
}
}
public void OnMapEnd()
{
if(g_bIsRecording)
{
StopRecord();
g_bIsManual = false;
}
}
public void OnClientPutInServer(int client)
{
CheckStatus();
}
public void OnClientDisconnect_Post(int client)
{
CheckStatus();
}
public Action Timer_CheckStatus(Handle timer)
{
CheckStatus();
}
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(g_hAutoRecord.BoolValue && !g_bIsManual)
{
int iMinClients = g_hMinPlayersStart.IntValue;
int iTimeStart = g_hTimeStart.IntValue;
int iTimeStop = g_hTimeStop.IntValue;
bool bReverseTimes = (iTimeStart > iTimeStop);
char sCurrentTime[4];
FormatTime(sCurrentTime, sizeof(sCurrentTime), "%H", GetTime());
int iCurrentTime = StringToInt(sCurrentTime);
if(GetPlayerCount() >= iMinClients && (iTimeStart < 0 || (iCurrentTime >= iTimeStart && (bReverseTimes || iCurrentTime < iTimeStop))))
{
StartRecord();
}
else if(g_bIsRecording && !g_hFinishMap.BoolValue && (iTimeStop < 0 || iCurrentTime >= iTimeStop))
{
StopRecord();
}
}
}
int GetPlayerCount()
{
bool bIgnoreBots = g_hIgnoreBots.BoolValue;
int iNumPlayers = 0;
for(int i = 1; i <= MaxClients; i++)
{
if(IsClientConnected(i) && (!bIgnoreBots || !IsFakeClient(i)))
{
iNumPlayers++;
}
}
if(!bIgnoreBots)
{
iNumPlayers--;
}
return iNumPlayers;
}
void StartRecord()
{
if(g_hTvEnabled.BoolValue && !g_bIsRecording)
{
char sPath[PLATFORM_MAX_PATH];
char sTime[16];
char sMap[32];
g_hDemoPath.GetString(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);
ServerCommand("tv_record \"%s/auto-%s-%s\"", sPath, sTime, sMap);
g_bIsRecording = true;
LogMessage("Recording to auto-%s-%s.dem", sTime, sMap);
}
}
void StopRecord()
{
if(g_hTvEnabled.BoolValue)
{
ServerCommand("tv_stoprecord");
g_bIsRecording = false;
}
}
void InitDirectory(const char[] sDir)
{
char sPieces[32][PLATFORM_MAX_PATH];
char sPath[PLATFORM_MAX_PATH];
int iNumPieces = ExplodeString(sDir, "/", sPieces, sizeof(sPieces), sizeof(sPieces[]));
for(int i = 0; i < iNumPieces; i++)
{
Format(sPath, sizeof(sPath), "%s/%s", sPath, sPieces[i]);
if(!DirExists(sPath))
{
CreateDirectory(sPath, 509);
}
}
}