mirror of
https://github.com/Jackzmc/sourcemod-plugins.git
synced 2025-05-05 23:03:20 +00:00
321 lines
11 KiB
SourcePawn
321 lines
11 KiB
SourcePawn
#pragma semicolon 1
|
|
#pragma newdecls required
|
|
|
|
//#define DEBUG
|
|
#define PUSH_TIMER 60.0
|
|
|
|
#define PLUGIN_VERSION "1.0"
|
|
|
|
#include <sourcemod>
|
|
#include <sdktools>
|
|
//#include <sdkhooks>
|
|
|
|
public Plugin myinfo =
|
|
{
|
|
name = "Admin Activity Log",
|
|
author = "jackzmc",
|
|
description = "",
|
|
version = PLUGIN_VERSION,
|
|
url = "https://github.com/Jackzmc/sourcemod-plugins"
|
|
};
|
|
|
|
enum struct Log {
|
|
char name[32];
|
|
char clientSteamID[32];
|
|
char targetSteamID[32];
|
|
char message[256];
|
|
int timestamp;
|
|
}
|
|
// Plugin data
|
|
static ArrayList logs;
|
|
static Database g_db;
|
|
static char serverID[64];
|
|
static Handle pushTimer;
|
|
static ConVar hLogCvarChanges;
|
|
static char lastMap[64];
|
|
|
|
//Plugin related
|
|
static bool lateLoaded;
|
|
static EngineVersion g_Game;
|
|
|
|
//L4d2 Specific
|
|
static char L4D2_ZDifficulty[16];
|
|
//Generic
|
|
static char currentGamemode[32];
|
|
|
|
char playerLastName[MAXPLAYERS+1][32];
|
|
|
|
public APLRes AskPluginLoad2(Handle myself, bool late, char[] error, int err_max)
|
|
{
|
|
CreateNative("ActivityMonitor_AddLog", Native_AddLog);
|
|
lateLoaded = late;
|
|
return APLRes_Success;
|
|
}
|
|
|
|
public void OnPluginStart() {
|
|
g_Game = GetEngineVersion();
|
|
logs = new ArrayList(sizeof(Log));
|
|
|
|
if(!SQL_CheckConfig("activitymonitor")) {
|
|
SetFailState("No database entry for 'activitymonitor'; no database to connect to.");
|
|
} else if(!ConnectDB()) {
|
|
SetFailState("Failed to connect to database.");
|
|
}
|
|
|
|
hLogCvarChanges = CreateConVar("sm_activitymonitor_log_cvar", "0", "Should this plugin log cvar changes (when using sm_cvar from console)");
|
|
ConVar hServerID = CreateConVar("sm_activitymonitor_id", "", "The name to use for the 'server' column", FCVAR_DONTRECORD);
|
|
hServerID.GetString(serverID, sizeof(serverID));
|
|
hServerID.AddChangeHook(CVAR_ServerIDChanged);
|
|
|
|
HookEvent("player_first_spawn", Event_Connection);
|
|
HookEvent("player_disconnect", Event_Connection);
|
|
if(g_Game == Engine_Left4Dead2 || g_Game == Engine_Left4Dead) {
|
|
HookEvent("player_incapacitated", Event_L4D2_Incapped);
|
|
HookEvent("player_death", Event_L4D2_Death);
|
|
ConVar zDifficulty = FindConVar("z_difficulty");
|
|
zDifficulty.GetString(L4D2_ZDifficulty, sizeof(L4D2_ZDifficulty));
|
|
CVAR_DifficultyChanged(zDifficulty, "", L4D2_ZDifficulty);
|
|
zDifficulty.AddChangeHook(CVAR_DifficultyChanged);
|
|
|
|
zDifficulty.GetString(L4D2_ZDifficulty, sizeof(L4D2_ZDifficulty));
|
|
CVAR_DifficultyChanged(zDifficulty, "", L4D2_ZDifficulty);
|
|
zDifficulty.AddChangeHook(CVAR_DifficultyChanged);
|
|
}
|
|
|
|
ConVar mpGamemode = FindConVar("mp_gamemode");
|
|
if(mpGamemode != null) {
|
|
mpGamemode.GetString(currentGamemode, sizeof(currentGamemode));
|
|
mpGamemode.AddChangeHook(CVAR_GamemodeChanged);
|
|
}
|
|
|
|
|
|
if(!lateLoaded) {
|
|
AddLog("INFO", "", "", "Server has started up");
|
|
}
|
|
|
|
pushTimer = CreateTimer(PUSH_TIMER, Timer_PushLogs, _, TIMER_REPEAT);
|
|
// AutoExecConfig(true, "activitymonitor");
|
|
}
|
|
|
|
public void OnPluginEnd() {
|
|
TriggerTimer(pushTimer, true);
|
|
}
|
|
|
|
public void OnMapEnd() {
|
|
TriggerTimer(pushTimer, true);
|
|
}
|
|
|
|
public void OnMapStart() {
|
|
static char curMap[64];
|
|
GetCurrentMap(curMap, sizeof(curMap));
|
|
if(!StrEqual(lastMap, curMap)) {
|
|
strcopy(lastMap, sizeof(lastMap), curMap);
|
|
if(g_Game == Engine_Left4Dead2 || g_Game == Engine_Left4Dead)
|
|
Format(curMap, sizeof(curMap), "Map changed to %s (%s %s)", curMap, L4D2_ZDifficulty, currentGamemode);
|
|
else
|
|
Format(curMap, sizeof(curMap), "Map changed to %s (%s)", curMap, currentGamemode);
|
|
AddLog("INFO", "", "", curMap);
|
|
}
|
|
TriggerTimer(pushTimer, true);
|
|
}
|
|
|
|
public void CVAR_GamemodeChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
|
|
strcopy(currentGamemode, sizeof(currentGamemode), newValue);
|
|
}
|
|
|
|
public void CVAR_ServerIDChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
|
|
strcopy(serverID, sizeof(serverID), newValue);
|
|
}
|
|
|
|
public void CVAR_DifficultyChanged(ConVar convar, const char[] oldValue, const char[] newValue) {
|
|
if(StrEqual(newValue, "Hard", false)) strcopy(L4D2_ZDifficulty, sizeof(L4D2_ZDifficulty), "Advanced");
|
|
else if(StrEqual(newValue, "Impossible", false)) strcopy(L4D2_ZDifficulty, sizeof(L4D2_ZDifficulty), "Expert");
|
|
else {
|
|
strcopy(L4D2_ZDifficulty, sizeof(L4D2_ZDifficulty), newValue);
|
|
// CVAR value could be lowercase 'normal', convert to 'Normal'
|
|
L4D2_ZDifficulty[0] = CharToUpper(L4D2_ZDifficulty[0]);
|
|
}
|
|
}
|
|
|
|
bool ConnectDB() {
|
|
char error[255];
|
|
g_db = SQL_Connect("activitymonitor", true, error, sizeof(error));
|
|
if (g_db == null) {
|
|
LogError("Database error %s", error);
|
|
delete g_db;
|
|
return false;
|
|
} else {
|
|
PrintToServer("[ACTM] Connected to database \"activitymonitor\"");
|
|
SQL_LockDatabase(g_db);
|
|
SQL_FastQuery(g_db, "SET NAMES \"UTF8mb4\"");
|
|
SQL_UnlockDatabase(g_db);
|
|
g_db.SetCharset("utf8mb4");
|
|
return true;
|
|
}
|
|
}
|
|
|
|
public Action Timer_PushLogs(Handle h) {
|
|
static char query[1024];
|
|
static Log log;
|
|
int length = logs.Length;
|
|
|
|
if(length > 0) {
|
|
Transaction transaction = new Transaction();
|
|
for(int i = 0; i < length; i++) {
|
|
logs.GetArray(i, log, sizeof(log));
|
|
g_db.Format(query, sizeof(query), "INSERT INTO `activity_log` (`timestamp`, `server`, `type`, `client`, `target`, `message`) VALUES (%d, NULLIF('%s', ''), '%s', NULLIF('%s', ''), NULLIF('%s', ''), NULLIF('%s', ''))",
|
|
log.timestamp,
|
|
serverID,
|
|
log.name,
|
|
log.clientSteamID,
|
|
log.targetSteamID,
|
|
log.message
|
|
);
|
|
transaction.AddQuery(query);
|
|
}
|
|
logs.Resize(logs.Length - length);
|
|
g_db.Execute(transaction, _, SQL_TransactionFailed, length, DBPrio_Low);
|
|
}
|
|
return Plugin_Continue;
|
|
}
|
|
void SQL_TransactionFailed(Database db, any data, int numQueries, const char[] error, int failIndex, any[] queryData) {
|
|
LogError("Push transaction failed: %s at query %d/%d", error, failIndex, numQueries);
|
|
}
|
|
|
|
public void Event_Connection(Event event, const char[] name, bool dontBroadcast) {
|
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
|
if(client > 0 && !IsFakeClient(client)) {
|
|
static char clientName[32];
|
|
if(GetClientAuthId(client, AuthId_Steam2, clientName, sizeof(clientName))) {
|
|
if(name[7] == 'f') {
|
|
AddLog("JOIN", clientName, "", "");
|
|
GetClientName(client, playerLastName[client], 32);
|
|
} else {
|
|
static char reason[64];
|
|
event.GetString("reason", reason, sizeof(reason));
|
|
Format(reason, sizeof(reason), " left: \"%s\"", reason);
|
|
AddLog("QUIT", clientName, "", reason);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void Event_PlayerInfo(Event event, const char[] name, bool dontBroadcast) {
|
|
int client = GetClientOfUserId(event.GetInt("userid"));
|
|
if(client && !IsFakeClient(client) && GetUserAdmin(client) == INVALID_ADMIN_ID) {
|
|
char clientName[32];
|
|
if(GetClientAuthId(client, AuthId_Steam2, clientName, sizeof(clientName))) {
|
|
AddLogCustom("INFO", clientName, "", "\"%s\" changed their name to \"%L\"", playerLastName[client], client);
|
|
GetClientName(client, playerLastName[client], 32);
|
|
}
|
|
}
|
|
}
|
|
|
|
public Action OnLogAction(Handle source, Identity identity, int client, int target, const char[] message) {
|
|
// Ignore cvar changed msgs (from server.cfg)
|
|
if(client == 0 && !hLogCvarChanges.BoolValue && strcmp(message[31], "changed cvar") >= 0) return Plugin_Continue;
|
|
|
|
static char clientName[32], targetName[32];
|
|
if(client == 0) clientName = "Server";
|
|
else if(client > 0) GetClientAuthId(client, AuthId_Steam2, clientName, sizeof(clientName));
|
|
else clientName[0] = '\0';
|
|
|
|
if(target > 0 && !IsFakeClient(target)) GetClientAuthId(target, AuthId_Steam2, targetName, sizeof(targetName));
|
|
else targetName[0] = '\0';
|
|
|
|
AddLog("ACTION", clientName, targetName, message);
|
|
return Plugin_Continue;
|
|
}
|
|
|
|
public void OnClientSayCommand_Post(int client, const char[] command, const char[] sArgs) {
|
|
if(client > 0 && !IsFakeClient(client)) {
|
|
static char clientName[32];
|
|
GetClientAuthId(client, AuthId_Steam2, clientName, sizeof(clientName));
|
|
AddLog("CHAT", clientName, "", sArgs);
|
|
}
|
|
}
|
|
|
|
public void Event_L4D2_Death(Event event, const char[] name, bool dontBroadcast) {
|
|
int victim = GetClientOfUserId(event.GetInt("userid"));
|
|
int attacker = GetClientOfUserId(event.GetInt("attacker"));
|
|
if(victim > 0 && GetClientTeam(victim) == 2) { //victim is a survivor
|
|
static char victimName[32], attackerName[32];
|
|
|
|
if(IsFakeClient(victim)) GetClientName(victim, victimName, sizeof(victimName));
|
|
else GetClientAuthId(victim, AuthId_Steam2, victimName, sizeof(victimName));
|
|
|
|
if(attacker > 0 && attacker != victim) {
|
|
if(IsFakeClient(attacker)) GetClientName(attacker, attackerName, sizeof(attackerName));
|
|
else GetClientAuthId(attacker, AuthId_Steam2, attackerName, sizeof(attackerName));
|
|
|
|
if(GetClientTeam(attacker) == 2) {
|
|
char weaponName[32];
|
|
event.GetString("weapon", weaponName, sizeof(weaponName));
|
|
if(weaponName[0] != '\0') {
|
|
AddLogCustom("STATE", attackerName, victimName, "\"%L\" killed \"%L\" with \"%s\"", attacker, victim, weaponName);
|
|
return;
|
|
}
|
|
}
|
|
AddLogCustom("STATE", attackerName, victimName, "\"%L\" killed \"%L\"", attacker, victim);
|
|
} else {
|
|
AddLogCustom("STATE", "", victimName, "\"%L\" died", victim);
|
|
}
|
|
}
|
|
}
|
|
//Player was incapped by Jockey
|
|
//Player was incapped (by world/zombie, no msg)
|
|
public void Event_L4D2_Incapped(Event event, const char[] name, bool dontBroadcast) {
|
|
int victim = GetClientOfUserId(event.GetInt("userid"));
|
|
int attacker = GetClientOfUserId(event.GetInt("attacker"));
|
|
if(victim > 0 && GetClientTeam(victim) == 2) {
|
|
static char victimName[32], attackerName[32];
|
|
if(IsFakeClient(victim)) GetClientName(victim, victimName, sizeof(victimName));
|
|
else GetClientAuthId(victim, AuthId_Steam2, victimName, sizeof(victimName));
|
|
|
|
if(attacker > 0 && attacker != victim) {
|
|
if(IsFakeClient(attacker)) GetClientName(attacker, attackerName, sizeof(attackerName));
|
|
else GetClientAuthId(attacker, AuthId_Steam2, attackerName, sizeof(attackerName));
|
|
|
|
if(GetClientTeam(attacker) == 2) {
|
|
char weaponName[32];
|
|
event.GetString("weapon", weaponName, sizeof(weaponName));
|
|
if(weaponName[0] != '\0') {
|
|
AddLogCustom("STATE", attackerName, victimName, "\"%L\" incapped \"%L\" with \"%s\"", attacker, victim, weaponName);
|
|
return;
|
|
}
|
|
}
|
|
AddLogCustom("STATE", attackerName, victimName, "\"%L\" incapped \"%L\"", attacker, victim);
|
|
} else {
|
|
AddLogCustom("STATE", "", victimName, "\"%L\" was incapped", victim);
|
|
}
|
|
}
|
|
}
|
|
|
|
void AddLog(const char[] type, const char[] clientName, const char[] targetName, const char[] message) {
|
|
if(StrEqual(clientName, "Bot")) return;
|
|
Log log;
|
|
strcopy(log.name, sizeof(log.name), type);
|
|
strcopy(log.clientSteamID, sizeof(log.clientSteamID), clientName);
|
|
strcopy(log.targetSteamID, sizeof(log.targetSteamID), targetName);
|
|
strcopy(log.message, sizeof(log.message), message);
|
|
log.timestamp = GetTime();
|
|
logs.PushArray(log);
|
|
}
|
|
|
|
void AddLogCustom(const char[] type, const char[] clientName, const char[] targetName, const char[] format, any ...) {
|
|
static char message[254];
|
|
if(StrEqual(clientName, "Bot")) return;
|
|
|
|
VFormat(message, sizeof(message), format, 5);
|
|
AddLog(type, clientName, targetName, message);
|
|
}
|
|
|
|
public any Native_AddLog(Handle plugin, int numParams) {
|
|
char type[32], clientName[32], targetName[32], message[256];
|
|
if(GetNativeString(1, type, sizeof(type)) != SP_ERROR_NONE) return false;
|
|
if(GetNativeString(2, clientName, sizeof(clientName)) != SP_ERROR_NONE) return false;
|
|
if(GetNativeString(3, targetName, sizeof(targetName)) != SP_ERROR_NONE) return false;
|
|
if(GetNativeString(4, message, sizeof(message)) != SP_ERROR_NONE) return false;
|
|
AddLog(type, clientName, targetName, message);
|
|
return true;
|
|
}
|