[c++] Timer Bugfix

08/21/2017 16:16 He3o Crysis#1
Viele von euch haben sich ja sicher schon gefragt, wieso man in einem timer questblock keinen weiteren timer starten kann, der den selben Namen trägt.

Bevor wir zum fix kommen sollten wir uns erst mal anschauen, wieso der Fehler überhaupt auftritt...

1) Ihr startet in eurer Quest einen timer.
2) Dies erstellt ein neues timer event. (questevent.cpp//quest_timer_event), welches eurem charakter zugeordnet wird. q.GetCurrentPC()->AddTimer
3) Wenn der timer "fällig" wird, wird der "when [...].timer" block in der quest ausgeführt.
4) In unserer quest versuchen wir, einen timer mit dem selben namen neu zu erstellen
5) Dies führt wieder q.GetCurrentPC()->AddTimer([...], quest_create_timer_event(...), [...]) aus
6) In AddTimer, wird bevor ein neuer timer hinzugefügt wird, der alte gecancelt (falls einer existent sein sollte)
7) Im CancelTimerEvent wird zum einen das event gecancelt, als auch quest_event_info::name gelöscht.
8) Der neue Timer, der in unserer quest im timer block erstellt wurde ist aktiv. (siehe sylog: QUEST add timer 0x3581e140 1)
9) Da unser "when [...].timer" block erfolgreich ausgeführt wurde, wird versucht, den timer in der EVENTFUNC aufzuräumen.
10) Timer versucht, auf quest_event_info::name zuzugreifen, um sich damit zu löschen. (RemoveTimerNotCancel(info->name))
11) Check, ob quest_event_info::name NULL ist, fehlt -> Server crasht.

Fix:
Code:
EVENTFUNC(quest_timer_event)
{
	quest_event_info * info = dynamic_cast<quest_event_info *>( event->info );
	if (info == NULL)
	{
		sys_err( "quest_timer_event> <Factor> Null pointer" );
		return 0;
	}

	CQuestManager & q = CQuestManager::instance();

	if (CHARACTER_MANAGER::instance().FindByPID(info->player_id))
	{
		if (!CQuestManager::instance().Timer(info->player_id, info->npc_id))
			return (passes_per_sec / 2 + 1);

		if (info->time_cycle != 0)
			return info->time_cycle;
	}

	if (info->name != NULL)
	{
		PC * pPC = q.GetPC(info->player_id);
		if (pPC)
			pPC->RemoveTimerNotCancel(info->name);
		else
			sys_err("quest::PC pointer null. player_id: %u", info->player_id);

		M2_DELETE_ARRAY(info->name);
		info->name = NULL;
	}
	return 0;
}
Beispiel zum Crash:

Code:
quest crash_test begin
	state start begin
		when login begin
			timer("test", 2)
			syschat("timer läuft.")
		end
		when test.timer begin
			syschat("timer ausgeführt.")
			cleartimer("test")
			timer("test", 2)
			syschat("timer läuft wieder.")
		end
	end
end
Fix ist experimentell+untested.
08/21/2017 16:20 Gl0bal#2
Nice Release :D Thanks Izz da.
Wird man hoffentlich auch auf deinem neuen Server sehen :D

MfG Gl0bal
08/22/2017 17:38 VIPDANGER#3
So sweet :3
TY:)
09/25/2017 14:31 Cyber36#4
Bug getestet. Bug gefixxt.

Dankeschön!

MfG
Cyber
09/25/2017 19:21 HKwork#5
Thank, nice work.
10/02/2017 12:27 'Crusher#6
Nice Release, Danke. :)