Jump to content
  • Chmurka
  • Boróweczka
  • Jabłuszko
  • Limonka
  • Czekoladka
  • Węgielek
Sign in to follow this  
Master

[Rozwiązane] Problem z timerem (Invalid timer handle)

Recommended Posts

Witam!

 

Poniższy error strasznie spami mi logi. Analizuje kod już 10 raz i nie potrafię znaleźć przyczyny. Proszę o pomoc.

 

Error

Spoiler

L 09/22/2018 - 00:00:12: [SM] Exception reported: Invalid timer handle a58d46b7 (error 1)
L 09/22/2018 - 00:00:12: [SM] Blaming: arena/multi1v1_drug_rounds.smx
L 09/22/2018 - 00:00:12: [SM] Call stack trace:
L 09/22/2018 - 00:00:12: [SM]   [0] KillTimer
L 09/22/2018 - 00:00:12: [SM]   [1] Line 102, C:\Users\Admin\Desktop\New Arena\multi1v1_drug_rounds.sp::KillDrugTimer
L 09/22/2018 - 00:00:12: [SM]   [2] Line 45, C:\Users\Admin\Desktop\New Arena\multi1v1_drug_rounds.sp::Event_RoundEnd
L 09/22/2018 - 00:00:12: [SM]   [4] CS_TerminateRound
L 09/22/2018 - 00:00:12: [SM]   [5] Line 1171, ./scripting/multi1v1.sp::Timer_CheckRoundComplete
L 09/22/2018 - 00:00:34: [SM] Exception reported: Invalid timer handle a58d46b7 (error 1)
L 09/22/2018 - 00:00:34: [SM] Blaming: arena/multi1v1_drug_rounds.smx
L 09/22/2018 - 00:00:34: [SM] Call stack trace:
L 09/22/2018 - 00:00:34: [SM]   [0] KillTimer
L 09/22/2018 - 00:00:34: [SM]   [1] Line 102, C:\Users\Admin\Desktop\New Arena\multi1v1_drug_rounds.sp::KillDrugTimer
L 09/22/2018 - 00:00:34: [SM]   [2] Line 45, C:\Users\Admin\Desktop\New Arena\multi1v1_drug_rounds.sp::Event_RoundEnd
L 09/22/2018 - 00:00:34: [SM]   [4] CS_TerminateRound
L 09/22/2018 - 00:00:34: [SM]   [5] Line 1171, ./scripting/multi1v1.sp::Timer_CheckRoundComplete

 

 

Kod

Spoiler

#pragma semicolon 1

#include <clientprefs>
#include <sdktools>
#include <multi1v1>

#include "multi1v1/generic.sp"

#pragma newdecls required

#define TAG " [\x0FArena\x01]"

bool g_bDrug[MAXPLAYERS + 1];
Handle g_hDrugCookie = INVALID_HANDLE;

Handle g_DrugTimers[MAXPLAYERS + 1];
float g_DrugAngles[20] = {0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 20.0, 15.0, 10.0, 5.0, 0.0, -5.0, -10.0, -15.0, -20.0, -25.0, -20.0, -15.0, -10.0, -5.0};
UserMsg g_FadeUserMsgId;

public void OnPluginStart() 
{
	g_FadeUserMsgId = GetUserMessageId("Fade");
	g_hDrugCookie = RegClientCookie("multi1v1_drug", "", CookieAccess_Protected);
	HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
	LoadTranslations("multi1v1.phrases");
}

public void OnMapEnd()
{
	for(int client = 1; client <= MaxClients; client++)
	{
		if(isValidClient(client))
		{
			KillDrugTimer(client);
		}
	}
}

public Action Event_RoundEnd(Event event, char[] name, bool dontBroadcast)
{
	for(int client = 1; client <= MaxClients; client++)
	{
		if(isValidClient(client))
		{
			KillDrugTimer(client);
		}
	}
}

public void OnClientConnected(int client) 
{
	g_bDrug[client] = false;
}

public void Multi1v1_OnGunsMenuCreated(int client, Menu menu)
{
	char sEnabledString[32];
	GetEnabledString(sEnabledString, sizeof(sEnabledString), g_bDrug[client], client);
	AddMenuOption(menu, "drug", "Na Haju: %s", sEnabledString);
}

public void Multi1v1_GunsMenuCallback(Menu menu, MenuAction action, int client, int param2)
{
	if(action == MenuAction_Select)
	{
		char buffer[64];
		menu.GetItem(param2, buffer, sizeof(buffer));
		if(StrEqual(buffer, "drug")) 
		{
			g_bDrug[client] = !g_bDrug[client];
			SetCookieBool(client, g_hDrugCookie, g_bDrug[client]);
			Multi1v1_GiveWeaponsMenu(client, GetMenuSelectionPosition());
		}
	}
}

public void Multi1v1_AfterPlayerSetup(int client)
{
	if(!IsActivePlayer(client))
		return;

	int iArena = Multi1v1_GetArenaNumber(client);
	int iPlayer1 = Multi1v1_GetArenaPlayer1(iArena);
	int iPlayer2 = Multi1v1_GetArenaPlayer2(iArena);

	if(iPlayer1 >= 0 && iPlayer2 >= 0 && g_bDrug[iPlayer1] && g_bDrug[iPlayer2])
	{
        PrintToChat(client, "%s \x0FR\x02u\x03n\x04d\x05a \x06n\x07a \x08H\x09a\x0Aj\x0Bu\x10!", TAG);
        CreateDrug(client);
	}
}

void CreateDrug(int client)
{
	g_DrugTimers[client] = CreateTimer(1.0, Timer_Drug, client, TIMER_REPEAT);	
}

void KillDrugTimer(int client)
{
	if(g_DrugTimers[client] != INVALID_HANDLE)
	{
		KillTimer(g_DrugTimers[client]);
	}

	g_DrugTimers[client] = INVALID_HANDLE;
}

public Action Timer_Drug(Handle timer, any client)
{
	if(!IsClientInGame(client) || g_DrugTimers[client] != timer)
	{
		KillTimer(timer);
		return Plugin_Handled;
	}

	if(!IsPlayerAlive(client))
	{
		return Plugin_Handled;
	}

	float angs[3];
	GetClientEyeAngles(client, angs);
	
	angs[2] = g_DrugAngles[GetRandomInt(0,19)];
	
	TeleportEntity(client, NULL_VECTOR, angs, NULL_VECTOR);

	int clients[2];
	clients[0] = client;	

	int duration = 255;
	int holdtime = 255;
	int flags = 0x0002;
	int color[4] = { 0, 0, 0, 128 };
	color[0] = GetRandomInt(0,255);
	color[1] = GetRandomInt(0,255);
	color[2] = GetRandomInt(0,255);

	Handle message = StartMessageEx(g_FadeUserMsgId, clients, 1);

	if(GetUserMessageType() == UM_Protobuf)
	{
		Protobuf pb = UserMessageToProtobuf(message);
		pb.SetInt("duration", duration);
		pb.SetInt("hold_time", holdtime);
		pb.SetInt("flags", flags);
		pb.SetColor("clr", color);
	}
	else
	{
		BfWriteShort(message, duration);
		BfWriteShort(message, holdtime);
		BfWriteShort(message, flags);
		BfWriteByte(message, color[0]);
		BfWriteByte(message, color[1]);
		BfWriteByte(message, color[2]);
		BfWriteByte(message, color[3]);
	}

	EndMessage();

	return Plugin_Handled;
}

public void OnClientCookiesCached(int client) 
{
	if(IsFakeClient(client))
		return;

	g_bDrug[client] = GetCookieBool(client, g_hDrugCookie);
}

bool isValidClient(int client)
{
	return (1 <= client <= MaxClients && IsClientInGame(client));
}

 

 

  • Lubię to! 1
By MAGNET,

Plus za ładnie dodany kod w spoilerach ^^

Share this post


Link to post
Share on other sites

Funkcja jest przestarzała i pokazuje ostrzeżenie przy kompilacji, oczywiście można skompilować, ale chyba nie ma sensu używać przestarzałych funkcji.

 

SHU_1537636975234-1805.png.29a488e58399094bf6384ba301849b2f.png

Edited by Master

Share this post


Link to post
Share on other sites

Hmm no tak, ma to sens...

 

przejrzałem na szybko kod i strzelam, że błąd mógłby występować tutaj:

public Action Timer_Drug(Handle timer, any client)
{
	if(!IsClientInGame(client) || g_DrugTimers[client] != timer)
....

Nie jestem do końca przekonany, czy przy zastosowaniu flagi REPEAT id uchwytu pozostaje takie samo, przez co timer 'killuje' się wcześniej

Spróbuj usunąć tę drugą część warunku.

 

 

Ponadto, nie powinieneś przekazywać w timerze client'a, ponieważ w trakcie tej sekundy gracz mógł się rozłączyć i na jego miejsce wskoczyć nowy.

Aby wykonać to poprawnie, powinieneś przekazywać UserId, który jest unikalnym numerem dla każdego gracza - działa on mniej więcej tak, że po zmianie mapy (albo restarcie serwera, nieważne) playerowi przypisywana jest wartość zmiennej, która inkrementuje się za każdym razem, gdy łączy się nowy gracz. A zatem, będąc jako pierwszy na serwerze dostaniesz UserId = 1, kolejny gracz 2 itd..., a gdybyś wykonał reconnect, uzyskałbyś już UserId= 3

 

Na podstawie UserId można bezproblemowo uzyskać id clienta - jeśli będzie miało ono wartość 0, oznacza to że dany gracz się rozłączył

Uzyskiwanie UserId: https://go-code.pl/dokumentacja-sourcemod/client/GetClientUserId
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

Uzyskiwanie id clienta na podstawie UserId: https://go-code.pl/dokumentacja-sourcemod/client/GetClientOfUserId
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

 

Po zastosowaniu powyższej metody, Twój kod powinien wyglądać mniej więcej tak:

 

void CreateDrug(int client)
{
	g_DrugTimers[client] = CreateTimer(1.0, Timer_Drug, GetClientUserId(client), TIMER_REPEAT);	
}


public Action Timer_Drug(Handle timer, any clientUserId)
{
	int client = GetClientOfUserId(clientUserId);
	if(!client)
	{
		KillTimer(timer);	
		return Plugin_Handled;
	}

....

 

  • Lubię to! 4

Share this post


Link to post
Share on other sites

Niestety problem nadal występuje. Dodam, że error występuje w bardzo dużej częstotliwości. 

 

Spoiler

 

SHU_zpNegKd.thumb.png.5b42e6abdc4b821b976aa159bb736225.png

Aktualny kod

 

Spoiler

#pragma semicolon 1

#include <clientprefs>
#include <sdktools>
#include <multi1v1>

#include "multi1v1/generic.sp"

#pragma newdecls required

#define TAG " [\x0FArena\x01]"

bool g_bDrug[MAXPLAYERS + 1];
Handle g_hDrugCookie = INVALID_HANDLE;

Handle g_DrugTimers[MAXPLAYERS + 1];
float g_DrugAngles[20] = {0.0, 5.0, 10.0, 15.0, 20.0, 25.0, 20.0, 15.0, 10.0, 5.0, 0.0, -5.0, -10.0, -15.0, -20.0, -25.0, -20.0, -15.0, -10.0, -5.0};
UserMsg g_FadeUserMsgId;

public void OnPluginStart() 
{
	g_FadeUserMsgId = GetUserMessageId("Fade");
	g_hDrugCookie = RegClientCookie("multi1v1_drug", "", CookieAccess_Protected);
	HookEvent("round_end", Event_RoundEnd, EventHookMode_PostNoCopy);
	LoadTranslations("multi1v1.phrases");
}

public void OnMapEnd()
{
	for(int client = 1; client <= MaxClients; client++)
	{
		if(isValidClient(client))
		{
			KillDrugTimer(client);
		}
	}
}

public Action Event_RoundEnd(Event event, char[] name, bool dontBroadcast)
{
	for(int client = 1; client <= MaxClients; client++)
	{
		if(isValidClient(client))
		{
			KillDrugTimer(client);
		}
	}
}

public void OnClientConnected(int client) 
{
	g_bDrug[client] = false;
}

public void Multi1v1_OnGunsMenuCreated(int client, Menu menu)
{
	char sEnabledString[32];
	GetEnabledString(sEnabledString, sizeof(sEnabledString), g_bDrug[client], client);
	AddMenuOption(menu, "drug", "Na Haju: %s", sEnabledString);
}

public void Multi1v1_GunsMenuCallback(Menu menu, MenuAction action, int client, int param2)
{
	if(action == MenuAction_Select)
	{
		char buffer[64];
		menu.GetItem(param2, buffer, sizeof(buffer));
		if(StrEqual(buffer, "drug")) 
		{
			g_bDrug[client] = !g_bDrug[client];
			SetCookieBool(client, g_hDrugCookie, g_bDrug[client]);
			Multi1v1_GiveWeaponsMenu(client, GetMenuSelectionPosition());
		}
	}
}

public void Multi1v1_AfterPlayerSetup(int client)
{
	if(!IsActivePlayer(client))
		return;

	int iArena = Multi1v1_GetArenaNumber(client);
	int iPlayer1 = Multi1v1_GetArenaPlayer1(iArena);
	int iPlayer2 = Multi1v1_GetArenaPlayer2(iArena);

	if(iPlayer1 >= 0 && iPlayer2 >= 0 && g_bDrug[iPlayer1] && g_bDrug[iPlayer2])
	{
        PrintToChat(client, "%s \x0FR\x02u\x03n\x04d\x05a \x06n\x07a \x08H\x09a\x0Aj\x0Bu\x10!", TAG);
        CreateDrug(client);
	}
}

void CreateDrug(int client)
{
	g_DrugTimers[client] = CreateTimer(1.0, Timer_Drug, GetClientUserId(client), TIMER_REPEAT);
}

void KillDrugTimer(int client)
{
	if(g_DrugTimers[client] != INVALID_HANDLE)
	{
		KillTimer(g_DrugTimers[client]);
	}

	g_DrugTimers[client] = INVALID_HANDLE;
}

public Action Timer_Drug(Handle timer, any clientUserId)
{
	int client = GetClientOfUserId(clientUserId);

	if(!client || !IsPlayerAlive(client))
	{
		KillTimer(timer);
		return Plugin_Handled;
	}

	float angs[3];
	GetClientEyeAngles(client, angs);
	
	angs[2] = g_DrugAngles[GetRandomInt(0,19)];
	
	TeleportEntity(client, NULL_VECTOR, angs, NULL_VECTOR);

	int clients[2];
	clients[0] = client;	

	int duration = 255;
	int holdtime = 255;
	int flags = 0x0002;
	int color[4] = { 0, 0, 0, 128 };
	color[0] = GetRandomInt(0,255);
	color[1] = GetRandomInt(0,255);
	color[2] = GetRandomInt(0,255);

	Handle message = StartMessageEx(g_FadeUserMsgId, clients, 1);

	if(GetUserMessageType() == UM_Protobuf)
	{
		Protobuf pb = UserMessageToProtobuf(message);
		pb.SetInt("duration", duration);
		pb.SetInt("hold_time", holdtime);
		pb.SetInt("flags", flags);
		pb.SetColor("clr", color);
	}
	else
	{
		BfWriteShort(message, duration);
		BfWriteShort(message, holdtime);
		BfWriteShort(message, flags);
		BfWriteByte(message, color[0]);
		BfWriteByte(message, color[1]);
		BfWriteByte(message, color[2]);
		BfWriteByte(message, color[3]);
	}

	EndMessage();

	return Plugin_Handled;
}

public void OnClientCookiesCached(int client) 
{
	if(IsFakeClient(client))
		return;

	g_bDrug[client] = GetCookieBool(client, g_hDrugCookie);
}

bool isValidClient(int client)
{
	return (1 <= client <= MaxClients && IsClientInGame(client));
}

 

 

Share this post


Link to post
Share on other sites

Na te chwile jedyna sensowna możliwość do rozpatrzenia to dodanie g_DrugTimers[client] = INVALID_HANDLE;

public Action Timer_Drug(Handle timer, any clientUserId)
{
	int client = GetClientOfUserId(clientUserId);

	if(!client || !IsPlayerAlive(client))
	{
		KillTimer(timer);
		g_DrugTimers[client] = INVALID_HANDLE;
		return Plugin_Handled;
	}

 

  • Lubię to! 1

Share this post


Link to post
Share on other sites
1 godzinę temu, MAGNET napisał:

Na te chwile jedyna sensowna możliwość do rozpatrzenia to dodanie g_DrugTimers[client] = INVALID_HANDLE;


public Action Timer_Drug(Handle timer, any clientUserId)
{
	int client = GetClientOfUserId(clientUserId);

	if(!client || !IsPlayerAlive(client))
	{
		KillTimer(timer);
		g_DrugTimers[client] = INVALID_HANDLE;
		return Plugin_Handled;
	}

 

Według referencji z timers.inc powyższe działanie jest zbędne. Funkcja KillTimer jest używana do zatrzymania Timera spoza obszaru funkcji typu CallBack tego Timera. Natomiast jeżeli samopowtarzający się Timer jest zatrzymywany w jego własnym CallBack`u, to wystarczy ustawić wartość zmiennej g_DrugTimers jako INVALID_HANDLE i zwrócić Plugin_Stop. Nie twierdzę, że sposób z KillTimer nie zadziała, tylko że istnieje pewniejsze rozwiązanie.

 

źródło: https://go-code.pl/dokumentacja-sourcemod/timers/Timer
Hej! Skorzystałeś z linku lub pobrałeś załącznik? Uhonoruj naszą pracę poprzez rejestrację na forum i rośnij razem z nami!

kod:

public Action Timer_Drug(Handle timer, any clientUserId)
{
	int client = GetClientOfUserId(clientUserId);

	if(!client || !IsPlayerAlive(client))
	{
		g_DrugTimers[client] = INVALID_HANDLE;
		return Plugin_Stop;
	}

 

  • Lubię to! 1
  • Kocham to! 1
By MAGNET,

dzięki za poprawienie :)

Share this post


Link to post
Share on other sites
Guest
This topic is now closed to further replies.
Sign in to follow this  

  • Recently Browsing   0 members

    No registered users viewing this page.

Nasza historia

Na początku byliśmy małą grupą internetowych znajomych, którzy stwierdzili, że potrzebne jest solidne forum, na którym znajdą się ludzie z dużą wiedzą programistyczną ukierunkowaną na CS:GO. Pomysł powstał na początku 2018 roku, a parę miesięcy później, 19 kwietnia, powstała ta strona internetowa. Jako alternatywna odpowiedź na inne tego typu miejsca, poważnie podeszliśmy do tematu, najpierw tłumacząc angielską dokumentację SourceMod'a na język polski, a potem pisząc rozległe poradniki i wypełniając forum najpotrzebniejszymi rzeczami dla właścicieli serwerów i programistów. Cała nasza Ekipa jest dumna z pracy jaką w to włożyliśmy i cieszymy się że zbierają się wokół nas zarówno ludzie znający tematy sourcepawn'a i konfiguracji, jak i również nowe twarze w tym "biznesie", którym z chęcią niesiemy wiedzę oraz pomoc w rozwiązywaniu problemów.

Największe modyfikacje serwerowe

×
×
  • Create New...