plugins/reservedslots.sp
author Scott Ehlert <ds@alliedmods.net>
Sun Mar 30 07:00:22 2008 +0000 (2008-03-30)
changeset 1952 b7aa2b626807
child 2006 13876843132e
permissions -rw-r--r--
Spring Cleaning, Part Ichi (1)
Various minor things done to project files
Updated sample extension project file and updated makefile to the new unified version (more changes likely on the way)
Updated regex project file and makefile
ds@1952
     1
/**
ds@1952
     2
 * vim: set ts=4 :
ds@1952
     3
 * =============================================================================
ds@1952
     4
 * SourceMod Reserved Slots Plugin
ds@1952
     5
 * Provides basic reserved slots.
ds@1952
     6
 *
ds@1952
     7
 * SourceMod (C)2004-2008 AlliedModders LLC.  All rights reserved.
ds@1952
     8
 * =============================================================================
ds@1952
     9
 *
ds@1952
    10
 * This program is free software; you can redistribute it and/or modify it under
ds@1952
    11
 * the terms of the GNU General Public License, version 3.0, as published by the
ds@1952
    12
 * Free Software Foundation.
ds@1952
    13
 * 
ds@1952
    14
 * This program is distributed in the hope that it will be useful, but WITHOUT
ds@1952
    15
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
ds@1952
    16
 * FOR A PARTICULAR PURPOSE.  See the GNU General Public License for more
ds@1952
    17
 * details.
ds@1952
    18
 *
ds@1952
    19
 * You should have received a copy of the GNU General Public License along with
ds@1952
    20
 * this program.  If not, see <http://www.gnu.org/licenses/>.
ds@1952
    21
 *
ds@1952
    22
 * As a special exception, AlliedModders LLC gives you permission to link the
ds@1952
    23
 * code of this program (as well as its derivative works) to "Half-Life 2," the
ds@1952
    24
 * "Source Engine," the "SourcePawn JIT," and any Game MODs that run on software
ds@1952
    25
 * by the Valve Corporation.  You must obey the GNU General Public License in
ds@1952
    26
 * all respects for all other code used.  Additionally, AlliedModders LLC grants
ds@1952
    27
 * this exception to all derivative works.  AlliedModders LLC defines further
ds@1952
    28
 * exceptions, found in LICENSE.txt (as of this writing, version JULY-31-2007),
ds@1952
    29
 * or <http://www.sourcemod.net/license.php>.
ds@1952
    30
 *
ds@1952
    31
 * Version: $Id$
ds@1952
    32
 */
ds@1952
    33
ds@1952
    34
#pragma semicolon 1
ds@1952
    35
ds@1952
    36
#include <sourcemod>
ds@1952
    37
ds@1952
    38
public Plugin:myinfo = 
ds@1952
    39
{
ds@1952
    40
	name = "Reserved Slots",
ds@1952
    41
	author = "AlliedModders LLC",
ds@1952
    42
	description = "Provides basic reserved slots",
ds@1952
    43
	version = SOURCEMOD_VERSION,
ds@1952
    44
	url = "http://www.sourcemod.net/"
ds@1952
    45
};
ds@1952
    46
ds@1952
    47
/* Maximum number of clients that can connect to server */
ds@1952
    48
new g_MaxClients;
ds@1952
    49
ds@1952
    50
/* Handles to convars used by plugin */
ds@1952
    51
new Handle:sm_reserved_slots;
ds@1952
    52
new Handle:sm_hide_slots;
ds@1952
    53
new Handle:sv_visiblemaxplayers;
ds@1952
    54
new Handle:sm_reserve_type;
ds@1952
    55
ds@1952
    56
public OnPluginStart()
ds@1952
    57
{
ds@1952
    58
	LoadTranslations("reservedslots.phrases");
ds@1952
    59
	
ds@1952
    60
	sm_reserved_slots = CreateConVar("sm_reserved_slots", "0", "Number of reserved player slots", 0, true, 0.0);
ds@1952
    61
	sm_hide_slots = CreateConVar("sm_hide_slots", "0", "If set to 1, reserved slots will hidden (subtracted from the max slot count)", 0, true, 0.0, true, 1.0);
ds@1952
    62
	sv_visiblemaxplayers = FindConVar("sv_visiblemaxplayers");
ds@1952
    63
	sm_reserve_type = CreateConVar("sm_reserve_type", "0", "Method of reserving slots", 0, true, 0.0, true, 1.0);
ds@1952
    64
	
ds@1952
    65
	HookConVarChange(sm_reserved_slots, SlotsChanged);
ds@1952
    66
	HookConVarChange(sm_hide_slots, SlotsChanged);
ds@1952
    67
}
ds@1952
    68
ds@1952
    69
public OnPluginEnd()
ds@1952
    70
{
ds@1952
    71
	/* 	If the plugin has been unloaded, reset visiblemaxplayers. In the case of the server shutting down this effect will not be visible */
ds@1952
    72
	SetConVarInt(sv_visiblemaxplayers, g_MaxClients);
ds@1952
    73
}
ds@1952
    74
ds@1952
    75
public OnMapStart()
ds@1952
    76
{
ds@1952
    77
	g_MaxClients = GetMaxClients();
ds@1952
    78
	
ds@1952
    79
	if (GetConVarBool(sm_hide_slots))
ds@1952
    80
	{		
ds@1952
    81
		SetVisibleMaxSlots(GetClientCount(false), g_MaxClients - GetConVarInt(sm_reserved_slots));
ds@1952
    82
	}
ds@1952
    83
}
ds@1952
    84
ds@1952
    85
public OnConfigsExecuted()
ds@1952
    86
{
ds@1952
    87
	if (GetConVarBool(sm_hide_slots))
ds@1952
    88
	{
ds@1952
    89
		SetVisibleMaxSlots(GetClientCount(false), g_MaxClients - GetConVarInt(sm_reserved_slots));
ds@1952
    90
	}	
ds@1952
    91
}
ds@1952
    92
ds@1952
    93
public Action:OnTimedKick(Handle:timer, any:client)
ds@1952
    94
{	
ds@1952
    95
	if (!client || !IsClientInGame(client))
ds@1952
    96
	{
ds@1952
    97
		return Plugin_Handled;
ds@1952
    98
	}
ds@1952
    99
	
ds@1952
   100
	KickClient(client, "%T", "Slot reserved", client);
ds@1952
   101
	
ds@1952
   102
	if (GetConVarBool(sm_hide_slots))
ds@1952
   103
	{				
ds@1952
   104
		SetVisibleMaxSlots(GetClientCount(false), g_MaxClients - GetConVarInt(sm_reserved_slots));
ds@1952
   105
	}
ds@1952
   106
	
ds@1952
   107
	return Plugin_Handled;
ds@1952
   108
}
ds@1952
   109
ds@1952
   110
public OnClientPostAdminCheck(client)
ds@1952
   111
{
ds@1952
   112
	new reserved = GetConVarInt(sm_reserved_slots);
ds@1952
   113
ds@1952
   114
	if (reserved > 0)
ds@1952
   115
	{
ds@1952
   116
		new clients = GetClientCount(false);
ds@1952
   117
		new limit = g_MaxClients - reserved;
ds@1952
   118
		new flags = GetUserFlagBits(client);
ds@1952
   119
		
ds@1952
   120
		new type = GetConVarInt(sm_reserve_type);
ds@1952
   121
		
ds@1952
   122
		if (type == 0)
ds@1952
   123
		{
ds@1952
   124
			if (clients <= limit || IsFakeClient(client) || flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION)
ds@1952
   125
			{
ds@1952
   126
				if (GetConVarBool(sm_hide_slots))
ds@1952
   127
				{
ds@1952
   128
					SetVisibleMaxSlots(clients, limit);
ds@1952
   129
				}
ds@1952
   130
				
ds@1952
   131
				return;
ds@1952
   132
			}
ds@1952
   133
			
ds@1952
   134
			/* Kick player because there are no public slots left */
ds@1952
   135
			CreateTimer(0.1, OnTimedKick, client);
ds@1952
   136
		}
ds@1952
   137
		else
ds@1952
   138
		{		
ds@1952
   139
			if (clients > limit)
ds@1952
   140
			{	
ds@1952
   141
				if (flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION)
ds@1952
   142
				{
ds@1952
   143
					new target = SelectKickClient();
ds@1952
   144
						
ds@1952
   145
					if (target)
ds@1952
   146
					{
ds@1952
   147
						/* Kick public player to free the reserved slot again */
ds@1952
   148
						CreateTimer(0.1, OnTimedKick, target);
ds@1952
   149
					}
ds@1952
   150
				}
ds@1952
   151
				else
ds@1952
   152
				{				
ds@1952
   153
					/* Kick player because there are no public slots left */
ds@1952
   154
					CreateTimer(0.1, OnTimedKick, client);
ds@1952
   155
				}
ds@1952
   156
			}
ds@1952
   157
		}
ds@1952
   158
	}
ds@1952
   159
}
ds@1952
   160
ds@1952
   161
public OnClientDisconnect_Post(client)
ds@1952
   162
{
ds@1952
   163
	if (GetConVarBool(sm_hide_slots))
ds@1952
   164
	{		
ds@1952
   165
		SetVisibleMaxSlots(GetClientCount(false), g_MaxClients - GetConVarInt(sm_reserved_slots));
ds@1952
   166
	}
ds@1952
   167
}
ds@1952
   168
ds@1952
   169
public SlotsChanged(Handle:convar, const String:oldValue[], const String:newValue[])
ds@1952
   170
{
ds@1952
   171
	/* Reserved slots or hidden slots have been disabled - reset sv_visiblemaxplayers */
ds@1952
   172
	if (StringToInt(newValue) == 0)
ds@1952
   173
	{
ds@1952
   174
		SetConVarInt(sv_visiblemaxplayers, g_MaxClients);
ds@1952
   175
	}
ds@1952
   176
}
ds@1952
   177
ds@1952
   178
SetVisibleMaxSlots(clients, limit)
ds@1952
   179
{
ds@1952
   180
	new num = clients;
ds@1952
   181
	
ds@1952
   182
	if (clients == g_MaxClients)
ds@1952
   183
	{
ds@1952
   184
		num = g_MaxClients;
ds@1952
   185
	} else if (clients < limit) {
ds@1952
   186
		num = limit;
ds@1952
   187
	}
ds@1952
   188
	
ds@1952
   189
	SetConVarInt(sv_visiblemaxplayers, num);
ds@1952
   190
}
ds@1952
   191
ds@1952
   192
SelectKickClient()
ds@1952
   193
{
ds@1952
   194
	new Float:highestLatency;
ds@1952
   195
	new highestLatencyId;
ds@1952
   196
	
ds@1952
   197
	new Float:highestSpecLatency;
ds@1952
   198
	new highestSpecLatencyId;
ds@1952
   199
	
ds@1952
   200
	new bool:specFound;
ds@1952
   201
	
ds@1952
   202
	new Float:latency;
ds@1952
   203
	
ds@1952
   204
	for (new i=1; i<=g_MaxClients; i++)
ds@1952
   205
	{	
ds@1952
   206
		if (!IsClientConnected(i))
ds@1952
   207
		{
ds@1952
   208
			continue;
ds@1952
   209
		}
ds@1952
   210
	
ds@1952
   211
		new flags = GetUserFlagBits(i);
ds@1952
   212
		
ds@1952
   213
		if (IsFakeClient(i) || flags & ADMFLAG_ROOT || flags & ADMFLAG_RESERVATION || CheckCommandAccess(i, "sm_reskick_immunity", ADMFLAG_RESERVATION, false))
ds@1952
   214
		{
ds@1952
   215
			continue;
ds@1952
   216
		}
ds@1952
   217
		
ds@1952
   218
		latency = 0.0;
ds@1952
   219
			
ds@1952
   220
		if (IsClientInGame(i))
ds@1952
   221
		{		
ds@1952
   222
			latency = GetClientAvgLatency(i, NetFlow_Outgoing);
ds@1952
   223
			
ds@1952
   224
			LogMessage("Latency : %f",latency);
ds@1952
   225
			
ds@1952
   226
			if (IsClientObserver(i))
ds@1952
   227
			{			
ds@1952
   228
				specFound = true;
ds@1952
   229
				
ds@1952
   230
				if (latency > highestSpecLatency)
ds@1952
   231
				{
ds@1952
   232
					highestSpecLatency = latency;
ds@1952
   233
					highestSpecLatencyId = i;
ds@1952
   234
				}
ds@1952
   235
			}
ds@1952
   236
		}
ds@1952
   237
		
ds@1952
   238
		if (latency >= highestLatency)
ds@1952
   239
		{
ds@1952
   240
			highestLatency = latency;
ds@1952
   241
			highestLatencyId = i;
ds@1952
   242
		}
ds@1952
   243
	}
ds@1952
   244
	
ds@1952
   245
	if (specFound)
ds@1952
   246
	{
ds@1952
   247
		return highestSpecLatencyId;
ds@1952
   248
	}
ds@1952
   249
	
ds@1952
   250
	return highestLatencyId;
ds@1952
   251
}