sourcemod-plugins/scripting/l4d_reservetheserver.sp

201 lines
6.2 KiB
SourcePawn

#define PLUGIN_VERSION "1.1.0"
#define MAX_LINE_WIDTH 64
#define MESSAGE_FOR_PLAYERS_LINE1 ""
#define MESSAGE_FOR_PLAYERS_LINE2 "\x04RECEIVED SERVER RESERVATION REQUEST"
#define MESSAGE_FOR_PLAYERS_LINE3 "\x04YOU WILL BE RETURNED TO LOBBY"
#define MESSAGE_FOR_PLAYERS_LINE4 ""
#pragma semicolon 1
#include <sourcemod>
#pragma newdecls required
ConVar PluginCvarSearchKey, PluginCvarMode, PluginCvarTimeout, PluginCvarImmuneLevel,
SteamGroupExclusiveCvar, SearchKeyCvar, HibernationCvar;
int HibernationCvarValue;
bool isMapChange = false, doRestartMap = false;
char PluginSearchKeyString[MAX_LINE_WIDTH] = "", PluginCvarImmuneFlagString[MAX_LINE_WIDTH] = "", CurrentMapString[MAX_LINE_WIDTH] = "";
public Plugin myinfo =
{
name = "Reserve The Server",
author = "Jack'lul [Edited by Dosergen]",
description = "Frees the server from all players and reserves it.",
version = PLUGIN_VERSION,
url = "https://forums.alliedmods.net/showthread.php?p=2084993"
}
public void OnPluginStart() {
EngineVersion g_Game = GetEngineVersion();
if(g_Game != Engine_Left4Dead && g_Game != Engine_Left4Dead2) {
SetFailState("This plugin is for L4D/L4D2 only.");
}
CreateConVar("l4d_rts_version", PLUGIN_VERSION, "Reserve The Server plugin version", 0|FCVAR_NOTIFY|FCVAR_SPONLY|FCVAR_REPLICATED|FCVAR_DONTRECORD);
PluginCvarMode = CreateConVar("l4d_rts_mode", "1", "0 - only remove players using lobby vote, 1 - remove players using lobby vote and then disconnect server from matchmaking", 0, true, 0.0, true, 1.0);
PluginCvarSearchKey = CreateConVar("l4d_rts_searchkey", "", "sv_search_key will be set to this while server is reserved", 0);
PluginCvarTimeout = CreateConVar("l4d_rts_timeout", "30", "How long will the server stay disconnected from matchmaking? 0 - never restore matchmaking connection", 0, true, 0.0, true, 300.0);
PluginCvarImmuneLevel = CreateConVar("l4d_rts_immunelevel", "1", "Any player >= to this level will cancel the lobby vote.", 0);
RegAdminCmd("sm_rts", Command_MakeReservation, ADMFLAG_KICK, "Free the server from all players, then reserve it.");
RegAdminCmd("sm_cr", Command_CancelReservation, ADMFLAG_KICK, "Cancel reservation and make server public again.");
RegAdminCmd("sm_forcelobby", Command_ForceLobby, ADMFLAG_BAN, "Force call vote to return to lobby");
SteamGroupExclusiveCvar = FindConVar("sv_steamgroup_exclusive");
SearchKeyCvar = FindConVar("sv_search_key");
HibernationCvar = FindConVar("sv_hibernate_when_empty");
HibernationCvarValue = GetConVarInt(HibernationCvar);
AutoExecConfig(true, "l4d_rts");
}
public void OnClientDisconnect(int client) {
if (client == 0 || isMapChange || IsFakeClient(client))
return;
if(doRestartMap == true)
CreateTimer(1.0, MapReloadCheck);
}
public void OnMapEnd() {
isMapChange = true;
doRestartMap = false;
}
public void OnMapStart() {
isMapChange = false;
}
public Action Command_ForceLobby(int client, int args) {
Handle bf = StartMessageOne("VoteStart", client, USERMSG_RELIABLE);
BfWriteByte(bf, 0);
BfWriteByte(bf, client);
BfWriteString(bf, "returntolobby");
BfWriteString(bf, "");
BfWriteString(bf, "");
EndMessage();
PassVote();
}
public Action Command_MakeReservation(int client, int args) {
bool isAdminOnline, isServerEmpty = true;
if(client > 0) {
for (int i = 1; i <= MaxClients; i++) {
if (IsClientConnected(i) && IsClientInGame(i)) {
AdminId admin = GetUserAdmin(i);
if (admin != INVALID_ADMIN_ID && GetAdminImmunityLevel(admin) >= PluginCvarImmuneLevel.IntValue) {
isAdminOnline = true;
break;
}
if(isServerEmpty) isServerEmpty = false;
}
}
}
//If there is no admins playing OR request is from server itself then reserve:
if(!isAdminOnline)
{
LogMessage("Received server reservation request.");
if(!isServerEmpty) {
if(GetConVarInt(PluginCvarMode) == 1)
{
doRestartMap = true;
ReplyToCommand(client, "Server will be freed from all players and reserved.");
}
else
ReplyToCommand(client, "Server will be freed from all players.");
PrintToChatAll(MESSAGE_FOR_PLAYERS_LINE1);
PrintToChatAll(MESSAGE_FOR_PLAYERS_LINE2);
PrintToChatAll(MESSAGE_FOR_PLAYERS_LINE3);
PrintToChatAll(MESSAGE_FOR_PLAYERS_LINE4);
CreateTimer(5.0, FreeTheServer);
} else if(GetConVarInt(PluginCvarMode) == 1) {
DisconnectFromMatchmaking();
ReloadMap();
}
}
else
ReplyToCommand(client, "Server reservation request denied - admin is online!");
return Plugin_Handled;
}
public Action Command_CancelReservation(int client, int args) {
CreateTimer(0.1, MakeServerPublic);
}
public Action FreeTheServer(Handle timer) {
CallLobbyVote();
PassVote();
if(GetConVarInt(PluginCvarMode) == 1) {
DisconnectFromMatchmaking();
}
}
public Action MakeServerPublic(Handle timer) {
ConnectToMatchmaking();
int notConnected = 0;
for (int i = 1; i <= MaxClients; i++)
{
if (IsClientConnected (i) && IsClientInGame (i))
break;
else
notConnected++;
}
if(notConnected == MaxClients)
ReloadMap();
if(HibernationCvarValue != 0 && GetConVarInt(HibernationCvar) == 0)
SetConVarInt(HibernationCvar, 1);
}
public Action MapReloadCheck(Handle timer) {
if (!isMapChange && doRestartMap) {
doRestartMap = false;
ReloadMap();
}
}
void CallLobbyVote() {
for (int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsClientConnected (iClient) && IsClientInGame (iClient)) {
FakeClientCommand (iClient, "callvote returntolobby");
}
}
}
void PassVote() {
for(int iClient = 1; iClient <= MaxClients; iClient++) {
if (IsClientConnected (iClient) && IsClientInGame (iClient)) {
FakeClientCommand(iClient, "Vote Yes");
}
}
}
void ReloadMap() {
GetCurrentMap(CurrentMapString, sizeof(CurrentMapString));
ServerCommand("map %s", CurrentMapString);
}
void DisconnectFromMatchmaking() {
GetConVarString(PluginCvarSearchKey, PluginSearchKeyString, sizeof(PluginSearchKeyString));
SetConVarInt(SteamGroupExclusiveCvar, 1);
SetConVarString(SearchKeyCvar, PluginSearchKeyString);
if(HibernationCvarValue != 0)
SetConVarInt(HibernationCvar, 0);
if(GetConVarFloat(PluginCvarTimeout)>0)
CreateTimer(GetConVarFloat(PluginCvarTimeout), MakeServerPublic);
}
void ConnectToMatchmaking() {
SetConVarInt(SteamGroupExclusiveCvar, 0);
SetConVarString(SearchKeyCvar, "");
}