Vit_ amin
Добрая душа
- Сообщения
- 1,504
- Реакции
- 660
Доброго времени суток
Есть код (старый и заведово "плохой", по не понятной мне причине он ложит сервер)
Данный кусок код (подчеркиваю именно данный кусок кода, так как я все продебажил и пришёл к выводу что это из-за него), ложит сервер. Так сервер падает таким образом, что в логах нету ошибок и даже Acelerator молчит. Сервер на ОС Linux. Я уже всё что можно поменял в данном куске кода, но так и не смог понять почему (делал RequestFrame и CreateTimer на удаление Ragdoll'ов, думал уже надо делать проверку на то, жив ли игрок или нет - написал в консоли
Все нормально, никаких проблем. Странно только то, что сервер падает только в том случае, если трупы удаляются через MultiFilter (@Dead, @All и прочие) так как удаляю ragdoll'ы я через RegCmdAdmin
Ошибка: Alarm Clock, Segment Fault
А вот следующий код работает стабильно:
Я даже не знаю куда копать, может я в скриптинге что-то перестал понимать
Собственно вопрос интереса, так как я уже написал готовое решение.
Почему так и где у меня ошибка ?
P.S. Полный код, если нужно:
Есть код (старый и заведово "плохой", по не понятной мне причине он ложит сервер)
PHP:
void RemoveSurvivorRagdoll(int iSurvivorCharacter)
{
int iCharacterType;
while ((iEntity = FindEntityByClassname(MaxClients + 1, "survivor_death_model")) != INVALID_ENT_REFERENCE)
{
iCharacterType = GetEntProp(iEntity, Prop_Send, "m_nCharacterType");
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientInGame(i) || GetClientTeam(i) != TEAM_SURVIVOR || iCharacterType != iSurvivorCharacter)
{
continue;
}
if (IsValidEntity(iEntity))
{
RemoveEntity(iEntity);
}
}
}
}
C-подобный:
ent_fire survivor_death_model Kill
Ошибка: Alarm Clock, Segment Fault
А вот следующий код работает стабильно:
PHP:
void RemoveSurvivorRagdoll(int iSurvivorCharacter)
{
int iMaxEntities = GetMaxEntities();
char szClassname[32];
for (int iEntity = MaxClients + 1; iEntity < iMaxEntities; iEntity++)
{
if (!IsValidEntity(iEntity))
{
continue;
}
GetEntityClassname(iEntity, szClassname, sizeof(szClassname));
if (strcmp(szClassname, "survivor_death_model", false) != 0)
{
continue;
}
for (int iClient = 1; iClient <= MaxClients; iClient++)
{
if (!IsClientInGame(iClient) || GetClientTeam(iClient) != TEAM_SURVIVOR)
{
continue;
}
if (iSurvivorCharacter != GetEntProp(iEntity, Prop_Send, "m_nCharacterType"))
{
continue;
}
RemoveEntity(iEntity);
return;
}
}
}
Собственно вопрос интереса, так как я уже написал готовое решение.
Почему так и где у меня ошибка ?
P.S. Полный код, если нужно:
PHP:
//float g_flPosition[3];
Handle g_hRespawnPlayer = null;
TopMenu g_hTopMenu = null;
public void OnPluginStart()
{
LoadTranslations("common.phrases");
LoadTranslations("l4d2_respawn.phrases");
RegAdminCmd("sm_respawn", Command_Respawn, ADMFLAG_SLAY, "sm_respawn <#userid|name>");
RegisterTeamFilter();
// ========================================================================================
/* Account for late loading */
// ========================================================================================
TopMenu hTopMenu;
if (LibraryExists("adminmenu") && ((hTopMenu = GetAdminTopMenu()) != null))
{
OnAdminMenuReady(hTopMenu);
}
// ========================================================================================
GameData hGameData = new GameData("l4d2_gamedata");
if (hGameData == null)
{
delete hGameData;
SetFailState("Failed to load \"l4d2_gamedata.txt\" gamedata");
}
// ========================================================================================
// CTerrorPlayer::RoundRespawn - Signature
// ========================================================================================
StartPrepSDKCall(SDKCall_Player);
if (!PrepSDKCall_SetFromConf(hGameData, SDKConf_Signature, "CTerrorPlayer::RoundRespawn"))
{
delete hGameData;
SetFailState("Error finding the 'CTerrorPlayer::RoundRespawn' signature.");
}
g_hRespawnPlayer = EndPrepSDKCall();
if (g_hRespawnPlayer == null)
{
delete hGameData;
SetFailState("Unable to prep SDKCall 'CTerrorPlayer::RoundRespawn'");
}
// ========================================================================================
delete hGameData;
}
// ========================================================================================
// RegCmdAdmin
// ========================================================================================
public Action Command_Respawn(int iClient, int iArgs)
{
if (iArgs < 1)
{
ReplyToCommand(iClient, "%s Usage: sm_respawn <#userid|name>", MESSAGE_PREFIX);
return Plugin_Handled;
}
char arg[19];
GetCmdArg(1, arg, sizeof(arg));
char target_name[MAX_TARGET_LENGTH];
int target_list[MAXPLAYERS_L4D2], target_count;
bool tn_is_ml;
if ((target_count = ProcessTargetString(
arg,
iClient,
target_list,
MAXPLAYERS,
COMMAND_FILTER_DEAD,
target_name,
sizeof(target_name),
tn_is_ml)) <= 0)
{
ReplyToTargetError(iClient, target_count);
return Plugin_Handled;
}
int iTarget;
int iTargetCountPost;
// Team filter dead players, re-order target_list array with iTargetCountPost
for (int i = 0; i < target_count; i++)
{
iTarget = target_list[i];
if (GetClientTeam(iTarget) == TEAM_SURVIVOR)
{
target_list[iTargetCountPost] = iTarget; // re-order
iTargetCountPost++;
}
}
if (iTargetCountPost == COMMAND_TARGET_NONE)
{
ReplyToTargetError(iClient, iTargetCountPost);
return Plugin_Handled;
}
// re-set new value
target_count = iTargetCountPost;
if (tn_is_ml)
{
ShowActivity2(iClient, MESSAGE_PREFIX_COLOR, "%t", "Respawned survivors", target_name);
}
else
{
ShowActivity2(iClient, MESSAGE_PREFIX_COLOR, "%t", "Respawned survivor", "_s", target_name);
}
for (int i = 0; i < target_count; i++)
{
PerformRespawn(iClient, target_list[i]);
}
return Plugin_Handled;
}
// ========================================================================================
// Spawn Survivor Entity
// ========================================================================================
void PerformRespawn(int iClient, int iTarget)
{
LogAction(iClient, iTarget, "\"%L\" respawned \"%L\"", iClient, iTarget);
//RespawnPlayer(iTarget);
SDKCall(g_hRespawnPlayer, iTarget);
RemoveSurvivorRagdoll(GetEntProp(iTarget, Prop_Send, "m_survivorCharacter"));
}
/*void RespawnPlayer(int iClient)
{
int iFlags = GetCommandFlags("respawn");
SetCommandFlags("respawn", iFlags &~FCVAR_CHEAT);
FakeClientCommand(iClient, "respawn");
SetCommandFlags("respawn", iFlags|FCVAR_CHEAT);
}*/
// ========================================================================================
// Remove Old Ragdoll
// ========================================================================================
void RemoveSurvivorRagdoll(int iSurvivorCharacter)
{
int iMaxEntities = GetMaxEntities();
char szClassname[32];
for (int iEntity = MaxClients + 1; iEntity < iMaxEntities; iEntity++)
{
if (!IsValidEntity(iEntity))
{
continue;
}
GetEntityClassname(iEntity, szClassname, sizeof(szClassname));
if (strcmp(szClassname, "survivor_death_model", false) != 0)
{
continue;
}
for (int iClient = 1; iClient <= MaxClients; iClient++)
{
if (!IsClientInGame(iClient) || GetClientTeam(iClient) != TEAM_SURVIVOR)
{
continue;
}
if (iSurvivorCharacter != GetEntProp(iEntity, Prop_Send, "m_nCharacterType"))
{
continue;
}
RemoveEntity(iEntity);
return;
}
}
/*int iCharacterType;
while ((iEntity = FindEntityByClassname(MaxClients + 1, "survivor_death_model")) != INVALID_ENT_REFERENCE)
{
iCharacterType = GetEntProp(iEntity, Prop_Send, "m_nCharacterType");
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientInGame(i) || GetClientTeam(i) != TEAM_SURVIVOR || iCharacterType != iSurvivorCharacter)
{
continue;
}
if (IsValidEntity(iEntity))
{
RemoveEntity(iEntity);
}
}
}*/
}
// ========================================================================================
// OnAdminMenuReady - Building Menu Section in Main Menu
// ========================================================================================
public void OnAdminMenuReady(Handle aTopMenu)
{
TopMenu hTopMenu = TopMenu.FromHandle(aTopMenu);
/* Block us from being called twice */
if (hTopMenu == g_hTopMenu)
{
return;
}
/* Save the Handle */
g_hTopMenu = hTopMenu;
/* Build the "Player Commands" category */
TopMenuObject player_commands = g_hTopMenu.FindCategory(ADMINMENU_PLAYERCOMMANDS);
if (player_commands != INVALID_TOPMENUOBJECT)
{
g_hTopMenu.AddItem("sm_respawn", AdminMenu_Respawn, player_commands, "", ADMFLAG_SLAY);
}
}
// ========================================================================================
public void AdminMenu_Respawn(TopMenu hTopMenu,
TopMenuAction hAction,
TopMenuObject hObject,
int iAdminID,
char[] szBuffer,
int iMaxLength)
// ========================================================================================
{
switch (hAction)
{
case TopMenuAction_DisplayOption:
{
FormatEx(szBuffer, iMaxLength, "%T", "Respawn player", iAdminID);
}
case TopMenuAction_SelectOption:
{
DisplayRespawnMenu(iAdminID);
}
}
}
// ========================================================================================
void DisplayRespawnMenu(int iAdminID)
{
Menu hMenu = new Menu(MenuHandler_RespawnPlayer, MENU_ACTIONS_DEFAULT | MenuAction_Display);
char szBuffer[40];
char szUserID[8];
int iDeadSurvivors = 0;
for (int i = 1; i <= MaxClients; i++)
{
if (!IsClientInGame(i) || GetClientTeam(i) != TEAM_SURVIVOR || IsPlayerAlive(i))
{
continue;
}
FormatEx(szUserID, sizeof(szUserID), "%i", GetClientUserId(i));
FormatEx(szBuffer, sizeof(szBuffer), "%N (%s)", i, szUserID);
hMenu.AddItem(szUserID, szBuffer);
iDeadSurvivors++;
}
switch (iDeadSurvivors)
{
case 0:
{
PrintToChat(iAdminID, "%s %t", MESSAGE_PREFIX_COLOR, "No matching clients");
g_hTopMenu.Display(iAdminID, TopMenuPosition_LastCategory);
}
default:
{
hMenu.ExitBackButton = true;
hMenu.Display(iAdminID, MENU_TIME_FOREVER);
}
}
}
// ========================================================================================
public int MenuHandler_RespawnPlayer(Menu hMenu, MenuAction hAction, int iAdminID, int iItem)
{
switch (hAction)
{
case MenuAction_Cancel:
{
if (iItem == MenuCancel_ExitBack && g_hTopMenu != null)
{
g_hTopMenu.Display(iAdminID, TopMenuPosition_LastCategory);
}
}
case MenuAction_Display:
{
char szTitle[128];
FormatEx(szTitle, sizeof(szTitle), "%T:", "Respawn player", iAdminID);
(view_as<Panel>(iItem)).SetTitle(szTitle);
}
case MenuAction_End:
{
delete hMenu;
}
case MenuAction_Select:
{
char szUserID[8];
int iTarget;
hMenu.GetItem(iItem, szUserID, sizeof(szUserID));
if ((iTarget = GetClientOfUserId(StringToInt(szUserID))) == 0)
{
PrintToChat(iAdminID, "%s %t", MESSAGE_PREFIX_COLOR, "Player no longer available");
}
else if (!CanUserTarget(iAdminID, iTarget))
{
PrintToChat(iAdminID, "%s %t", MESSAGE_PREFIX_COLOR, "Unable to target");
}
else
{
LogAction(iAdminID, iTarget, "\"%L\" respawned \"%L\"", iAdminID, iTarget);
PerformRespawn(iAdminID, iTarget);
}
/* Re-draw the menu if they're still valid */
if (IsClientInGame(iAdminID) && !IsClientInKickQueue(iAdminID))
{
DisplayRespawnMenu(iAdminID);
}
}
}
}