Raised This Month: $32 Target: $400
 8% 

[L4D2] server crash


Post New Thread Reply   
 
Thread Tools Display Modes
Author Message
midnight9
Senior Member
Join Date: Nov 2012
Old 04-26-2018 , 13:57   [L4D2] server crash
Reply With Quote #1

Hello, my servers sometimes crash on map change. Prior the crash there is player(s) with k9Q6CK42 as name. I've tried to find any documentation on this but didnt find anything what is k9Q6CK42 related to. All i could find that one of the plugin im using has this code:

Code:
public OnClientAuthorized(client, const String:auth[])
{
	decl String:name[MAX_NAME_LENGTH];
	if (IsFakeClient(client) && GetClientName(client, name, sizeof(name)) && StrContains(name, "k9Q6CK42") > -1)
	{
		KickClient(client);
	}
}
Any ideas?

Last edited by midnight9; 12-16-2018 at 11:26.
midnight9 is offline
Visual77
Veteran Member
Join Date: Jan 2009
Old 04-26-2018 , 15:49   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #2

This may not be the true reason of your crash(es?), it's too generic and simple to be causing a crash.

Some questions. Why are you kicking BOTS with this name? Have you tried switching to OnClientPostAdminCheck/OnClientPutInServer? OnClientAuthorized is worthless when you're not even checking steamid.

Last edited by Visual77; 04-26-2018 at 15:51.
Visual77 is offline
midnight9
Senior Member
Join Date: Nov 2012
Old 04-26-2018 , 16:47   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #3

It seems to be related to fixing bot counts.

I've attached the complete code:

Code:
/*
	SourcePawn is Copyright (C) 2006-2008 AlliedModders LLC.  All rights reserved.
	SourceMod is Copyright (C) 2006-2008 AlliedModders LLC.  All rights reserved.
	Pawn and SMALL are Copyright (C) 1997-2008 ITB CompuPhase.
	Source is Copyright (C) Valve Corporation.
	All trademarks are property of their respective owners.

	This program is free software: you can redistribute it and/or modify it
	under the terms of the GNU General Public License as published by the
	Free Software Foundation, either version 3 of the License, or (at your
	option) any later version.

	This program is distributed in the hope that it will be useful, but
	WITHOUT ANY WARRANTY; without even the implied warranty of
	MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
	General Public License for more details.

	You should have received a copy of the GNU General Public License along
	with this program.  If not, see <http://www.gnu.org/licenses/>.
*/
#pragma semicolon 1

#include <sourcemod>
#include <sdktools>
#include <colors>

#define ZC_TANK 8

public Plugin:myinfo =
{
	name = "Player Management Plugin",
	author = "CanadaRox",
	description = "Player management!  Swap players/teams and spectate!",
	version = "8",
	url = ""
};

enum L4D2Team
{
	L4D2Team_None = 0,
	L4D2Team_Spectator,
	L4D2Team_Survivor,
	L4D2Team_Infected
}

new const L4D2Team:oppositeTeamMap[] =
{
	L4D2Team_None,
	L4D2Team_Spectator,
	L4D2Team_Infected,
	L4D2Team_Survivor
};

new Handle:survivor_limit;
new Handle:z_max_player_zombies;

new L4D2Team:pendingSwaps[MAXPLAYERS+1];
new bool:blockVotes[MAXPLAYERS+1];
new bool:isMapActive = false;

new Handle:l4d_pm_supress_spectate;

public OnPluginStart()
{
	LoadTranslations("common.phrases");

	RegAdminCmd("sm_swap", Swap_Cmd, ADMFLAG_KICK, "sm_swap <player1> [player2] ... [playerN] - swap all listed players to opposite teams");
	RegAdminCmd("sm_swapto", SwapTo_Cmd, ADMFLAG_KICK, "sm_swapto [force] <teamnum> <player1> [player2] ... [playerN] - swap all listed players to <teamnum> (1,2, or 3)");
	RegAdminCmd("sm_swapteams", SwapTeams_Cmd, ADMFLAG_KICK, "sm_swapteams - swap the players between both teams");
	RegAdminCmd("sm_fixbots", FixBots_Cmd, ADMFLAG_BAN, "sm_fixbots - Spawns survivor bots to match survivor_limit");
	RegConsoleCmd("sm_spectate", Spectate_Cmd, "Moves you to the spectator team");
	RegConsoleCmd("sm_spec", Spectate_Cmd, "Moves you to the spectator team");
	RegConsoleCmd("sm_s", Spectate_Cmd, "Moves you to the spectator team");

	AddCommandListener(Vote_Listener, "vote");
	AddCommandListener(Vote_Listener, "callvote");

	survivor_limit = FindConVar("survivor_limit");
	SetConVarBounds(survivor_limit, ConVarBound_Upper, false);
	HookConVarChange(survivor_limit, survivor_limitChanged);

	z_max_player_zombies = FindConVar("z_max_player_zombies");
	SetConVarBounds(z_max_player_zombies, ConVarBound_Upper, false);

	l4d_pm_supress_spectate = CreateConVar("l4d_pm_supress_spectate", "0", "Don't print messages when players spectate", FCVAR_PLUGIN, true, 0.0, true, 1.0);
}

public OnMapStart()
{
	isMapActive = true;
}

public OnMapEnd()
{
	isMapActive = false;
}

public Action:FixBots_Cmd(client, args)
{
	if (client != 0)
	{
		PrintToChatAll("[SM] %N is attempting to fix bot counts");
	}
	else
	{
		PrintToChatAll("[SM] Console is attempting to fix bot counts");
	}
	FixBotCount();
	return Plugin_Handled;
}

public survivor_limitChanged(Handle:convar, const String:oldValue[], const String:newValue[])
{
	FixBotCount();
}

public OnClientAuthorized(client, const String:auth[])
{
	decl String:name[MAX_NAME_LENGTH];
	if (IsFakeClient(client) && GetClientName(client, name, sizeof(name)) && StrContains(name, "k9Q6CK42") > -1)
	{
		KickClient(client);
	}
}

public OnClientDisconnect_Post(client)
{
	if (isMapActive)
		FixBotCount();
}

public Action:Spectate_Cmd(client, args)
{
	if (!GetConVarBool(l4d_pm_supress_spectate))
	{
		CPrintToChatAllEx(client, "{teamcolor}%N{default} has become a spectator!", client);
	}
	new L4D2Team:team = GetClientTeamEx(client);
	if (team == L4D2Team_Survivor)
	{
		ChangeClientTeamEx(client, L4D2Team_Spectator, true);
	}
	else if (team == L4D2Team_Infected)
	{
		if (GetZombieClass(client) != ZC_TANK)
		{
			ForcePlayerSuicide(client);
		}
		ChangeClientTeamEx(client, L4D2Team_Spectator, true);
	}
	else
	{
		blockVotes[client] = true;
		ChangeClientTeamEx(client, L4D2Team_Infected, true);
		CreateTimer(0.1, RespecDelay_Timer, client);
	}
	return Plugin_Handled;
}

public Action:RespecDelay_Timer(Handle:timer, any:client)
{
	ChangeClientTeamEx(client, L4D2Team_Spectator, true);
	blockVotes[client] = false;
}

public Action:Vote_Listener(client, const String:command[], argc)
{
	return blockVotes[client] ? Plugin_Handled : Plugin_Continue;
}

public Action:SwapTeams_Cmd(client, args)
{
	for (new cli = 1; cli <= MaxClients; cli++)
	{
		if(IsClientInGame(cli) && !IsFakeClient(cli) && IsPlayer(cli))
		{
			pendingSwaps[cli] = oppositeTeamMap[GetClientTeamEx(cli)];
		}
	}
	ApplySwaps(client, false);
	return Plugin_Handled;
}

public Action:Swap_Cmd(client, args)
{
	if (args < 1)
	{
		ReplyToCommand(client, "[SM] Usage: sm_swap <player1> <player2> ... <playerN>");
		return Plugin_Handled;
	}

	decl String:argbuf[MAX_NAME_LENGTH];

	decl targets[MaxClients+1];
	decl target;
	decl targetCount;
	decl String:target_name[MAX_TARGET_LENGTH];
	decl bool:tn_is_ml;

	for (new i = 1; i <= args; i++)
	{
		GetCmdArg(i, argbuf, sizeof(argbuf));
		targetCount = ProcessTargetString(
				argbuf,
				0,
				targets,
				MaxClients+1,
				COMMAND_FILTER_NO_BOTS,
				target_name,
				sizeof(target_name),
				tn_is_ml);
		
		for (new j = 0; j < targetCount; j++)
		{
			target = targets[j];
			if(IsClientInGame(target))
			{
				pendingSwaps[target] = oppositeTeamMap[GetClientTeamEx(target)];
			}
		}
	}

	ApplySwaps(client, false);

	return Plugin_Handled;
}

public Action:SwapTo_Cmd(client, args)
{
	if (args < 2)
	{
		ReplyToCommand(client, "[SM] Usage: sm_swapto <teamnum> <player1> <player2> ... <playerN>\n%d = Spectators, %d = Survivors, %d = Infected", L4D2Team_Spectator, L4D2Team_Survivor, L4D2Team_Infected);
		ReplyToCommand(client, "[SM] Usage: sm_swapto force <teamnum> <player1> <player2> ... <playerN>\n%d = Spectators, %d = Survivors, %d = Infected", L4D2Team_Spectator, L4D2Team_Survivor, L4D2Team_Infected);
		return Plugin_Handled;
	}

	decl String:argbuf[MAX_NAME_LENGTH];
	new bool:force = false;

	GetCmdArg(1, argbuf, sizeof(argbuf));
	if (StrEqual(argbuf, "force"))
	{
		force = true;
		GetCmdArg(2, argbuf, sizeof(argbuf));
	}

	new L4D2Team:team = L4D2Team:StringToInt(argbuf);
	if (team < L4D2Team_Spectator || team > L4D2Team_Infected)
	{
		ReplyToCommand(client, "[SM] Valid teams: %d = Spectators, %d = Survivors, %d = Infected", L4D2Team_Spectator, L4D2Team_Survivor, L4D2Team_Infected);
		return Plugin_Handled;
	}

	decl targets[MaxClients+1];
	decl target;
	decl targetCount;
	decl String:target_name[MAX_TARGET_LENGTH];
	decl bool:tn_is_ml;

	for (new i = force?3:2; i <= args; i++)
	{
		GetCmdArg(i, argbuf, sizeof(argbuf));
		targetCount = ProcessTargetString(
				argbuf,
				0,
				targets,
				MaxClients+1,
				COMMAND_FILTER_NO_BOTS,
				target_name,
				sizeof(target_name),
				tn_is_ml);
		
		for (new j = 0; j < targetCount; j++)
		{
			target = targets[j];
			if(IsClientInGame(target))
			{
				pendingSwaps[target] = team;
			}
		}
	}

	ApplySwaps(client, force);

	return Plugin_Handled;
}

stock ApplySwaps(sender, bool:force)
{
	decl L4D2Team:clientTeam;
	/* Swap everyone to spec first so we know the correct number of slots on the teams */
	for (new client = 1; client <= MaxClients; client++)
	{
		if(IsClientInGame(client))
		{
			clientTeam = GetClientTeamEx(client);
			if (clientTeam != pendingSwaps[client] && pendingSwaps[client] != L4D2Team_None)
			{
				if (clientTeam == L4D2Team_Infected && GetZombieClass(client) != ZC_TANK)
					ForcePlayerSuicide(client);
				ChangeClientTeamEx(client, L4D2Team_Spectator, true);
			}
		}
	}

	/* Now lets try to put them on teams */
	for (new client = 1; client <= MaxClients; client++)
	{
		if(IsClientInGame(client) && pendingSwaps[client] != L4D2Team_None)
		{
			if (!ChangeClientTeamEx(client, pendingSwaps[client], force))
			{
				if (sender > 0)
				{
					PrintToChat(sender, "%N could not be switched because the target team was full or has no bot to take over.", client);
				}
			}
			pendingSwaps[client] = L4D2Team_None;

		}
	}

	/* Just in case MaxClients ever changes */
	for (new i = MaxClients+1; i <= MAXPLAYERS; i++)
	{
		pendingSwaps[i] = L4D2Team_None;
	}
}

stock bool:ChangeClientTeamEx(client, L4D2Team:team, bool:force)
{
	if (GetClientTeamEx(client) == team)
		return true;
	else if (!force && GetTeamHumanCount(team) == GetTeamMaxHumans(team))
		return false;

	if (team != L4D2Team_Survivor)
	{
		ChangeClientTeam(client, _:team);
		return true;
	}
	else
	{
		new bot = FindSurvivorBot();
		if (bot > 0)
		{
			new flags = GetCommandFlags("sb_takecontrol");
			SetCommandFlags("sb_takecontrol", flags & ~FCVAR_CHEAT);
			FakeClientCommand(client, "sb_takecontrol");
			SetCommandFlags("sb_takecontrol", flags);
			return true;
		}
	}
	return false;
}

stock GetTeamHumanCount(L4D2Team:team)
{
	new humans = 0;
	
	for (new client = 1; client <= MaxClients; client++)
	{
		if (IsClientInGame(client) && !IsFakeClient(client) && GetClientTeamEx(client) == team)
		{
			humans++;
		}
	}
	
	return humans;
}

stock GetTeamMaxHumans(L4D2Team:team)
{
	if (team == L4D2Team_Survivor)
	{
		return GetConVarInt(survivor_limit);
	}
	else if (team == L4D2Team_Infected)
	{
		return GetConVarInt(z_max_player_zombies);
	}
	return MaxClients;
}

/* return -1 if no bot found, clientid otherwise */
stock FindSurvivorBot()
{
	for (new client = 1; client <= MaxClients; client++)
	{
		if(IsClientInGame(client) && IsFakeClient(client) && GetClientTeamEx(client) == L4D2Team_Survivor)
		{
			return client;
		}
	}
	return -1;
}

stock IsPlayer(client)
{
	new L4D2Team:team = GetClientTeamEx(client);
	return (team == L4D2Team_Survivor || team == L4D2Team_Infected);
}

stock GetZombieClass(client) return GetEntProp(client, Prop_Send, "m_zombieClass");

stock FixBotCount()
{
	new survivor_count = 0;
	for (new client = 1; client <= MaxClients; client++)
	{
		if(IsClientInGame(client) && GetClientTeamEx(client) == L4D2Team_Survivor)
		{
			survivor_count++;
		}
	}
	new limit = GetConVarInt(survivor_limit);
	if (survivor_count < limit)
	{
		decl bot;
		for (; survivor_count < limit; survivor_count++)
		{
			bot = CreateFakeClient("k9Q6CK42");
			if (bot != 0)
			{
				ChangeClientTeam(bot, _:L4D2Team_Survivor);
				if (DispatchKeyValue(bot, "classname", "survivorbot") )
				{
					DispatchSpawn(bot);
				}
			}
		}
	}
	else if (survivor_count > limit)
	{
		for (new client = 1; client <= MaxClients; client++)
		{
			if(IsClientInGame(client) && GetClientTeamEx(client) == L4D2Team_Survivor)
			{
				if (IsFakeClient(client))
				{
					KickClient(client);
				}
			}
		}
		PrintToChatAll("[SM] Make sure there are no duplicate survivors and everyone is able to gain points, or restart the map.");
	}
}


stock L4D2Team:GetClientTeamEx(client)
{
	return L4D2Team:GetClientTeam(client);
}
midnight9 is offline
Visual77
Veteran Member
Join Date: Jan 2009
Old 04-26-2018 , 19:06   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #4

That plugin looks like a total mess. You should probably find other alternatives or ask the author for a total rewrite, with special care taken to simplify all of it.

When you spawn survivor bots, it is better to do the kick action with a 0.1 timer or even quicker with RequestFrame (new in SM 1.7-1.9 ). Using OnClientAuthorized is not ideal. Also, neither DispatchKeyValue or DispatchSpawn is needed in the creation of survivor bots anymore.

Last edited by Visual77; 04-26-2018 at 19:11.
Visual77 is offline
midnight9
Senior Member
Join Date: Nov 2012
Old 04-27-2018 , 01:26   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #5

This plugin is being used by all competitive servers. The author has been inactive from l4d2 for years, so i doubt he will do anything. Do you think this may be related to crashes anyhow?
midnight9 is offline
Visual77
Veteran Member
Join Date: Jan 2009
Old 04-27-2018 , 04:33   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #6

Quote:
Originally Posted by midnight9 View Post
This plugin is being used by all competitive servers. The author has been inactive from l4d2 for years, so i doubt he will do anything. Do you think this may be related to crashes anyhow?
I think so. Because when spawning bots, you have to kick them immediately. (If you kick in the same frame there's a risk of a T-pose facing bot, which is why you do it 0.1 sec later or a frame later (0.033s).

Sometimes the game also kicks the bot by itself. -> (louis(1) left the survivor team.) which can cause issues if a plugin kicks at the same time. I think your plugin kicks the bot too late which could be the cause of your crashes.

Last edited by Visual77; 04-27-2018 at 04:34.
Visual77 is offline
midnight9
Senior Member
Join Date: Nov 2012
Old 04-27-2018 , 09:21   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #7

Do you think this kicking/spawning bots part in this plugin is necessary or it could be simply removed?
midnight9 is offline
Visual77
Veteran Member
Join Date: Jan 2009
Old 04-27-2018 , 17:44   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #8

Quote:
Originally Posted by midnight9 View Post
Do you think this kicking/spawning bots part in this plugin is necessary or it could be simply removed?
Can't answer that. Every server setup is different. Is your server 4vs4 (if yes, doesn't the game already handle bots by itself?

Btw, what's really FixBotCount() for?

Is it supposed to add/remove bots when the server administrator raises the survivor_limit from 4 to 8, and vice versa?
Visual77 is offline
midnight9
Senior Member
Join Date: Nov 2012
Old 04-27-2018 , 17:58   Re: [L4D2] server crash k9Q6CK42
Reply With Quote #9

I think its to fix duplicated survivor bug/exploit. So i guess im gonna try removing that part of code and see if the crashes still occurs.
midnight9 is offline
Reply


Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off

Forum Jump


All times are GMT -4. The time now is 01:16.


Powered by vBulletin®
Copyright ©2000 - 2024, vBulletin Solutions, Inc.
Theme made by Freecode