Hallo zusammen,
heute ist wiederholt bei uns ein Fehler aufgetreten, der schon mal reported wurde, aber IMHO falsch interpretiert wurde. Das Thema ist leider geschlossen, darum hier nochmal:
[02-Jul-2009 12:01:30] PHP Fatal error: Call to a member function update() on a non-object in /xxx/xxxxx/xxxx/adminmod/classes/mod.class.php on line 835
Das Problem ist nämlich bei uns folgendes gewesen:
1246527014 [02.07.09 11:30:15] Notice: Player 'XXX' joined, PID: 2, GUID: 1111111111
...
1246527410 [02.07.09 11:36:50] Notice: Player 'XXX' quit, PID: 2, GUID: 1111111111
1246527433 [02.07.09 11:37:13] Notice: Player 'XXX' joined, PID: 26, GUID: 1111111111
...
1246527885 [02.07.09 11:44:46] Notice: Player 'XXX's PID was changed from 26 to 24, GUID: 1111111111
...
1246528179 [02.07.09 11:49:39] Notice: Player 'XXX' quit, PID: 24, GUID: 1111111111
1246528275 [02.07.09 11:51:16] !! Warning: DAMAGETAKEN by player 'XXX' who is actually not on the server: PID: 24, GUID: 1111111111
...
1246528890 [02.07.09 12:01:30] PHP-Error: Notice in classes/mod.class.php:835 => Undefined index: 1111111111
[02-Jul-2009 12:01:30] PHP Fatal error: Call to a member function update() on a non-object in /xxx/xxxxx/xxxx/adminmod/classes/mod.class.php on line 835
Alles anzeigen
Die Zeile
ist definitiv FALSCH, denn im Log (games_mp.log) steht eindeutig:
also PID 26 und nicht 24!
Ich nehme an, dass sowas passiert, wenn der Spieler einen Spielabsturz hatte oder die Verbindung irgendwie getrennt wurde. Der QUIT kommt also nach dem nächsten JOIN, d.h. der Spieler ist wieder im Spiel und dann kommt ein QUIT für den alten Slot. Da aber bei einem QUIT das Spieler-Objekt anhand der GUID gelöscht wird, ist der Spieler, obwohl sich ja nur die PID geändert hat, im MAM nicht mehr sichtbar.
Eine Möglichkeit das zu beheben wäre, sich bei einem "update" der PID die alte PID mit dem Spieler zu merken und beim QUIT nachzuschauen, ob die ausgelesene PID die alte ist. Wenn das der Fall ist, wird keine QUIT-Aktion ausgeführt/getriggert sondern nur die alte gemerkte PID zurückgesetzt.
Hier das DIFF für die player.class.php:
33a34
> public $oldpid = -1;
112c113
< $oldpid = $this->pid;
---
> $this->oldpid = $this->pid;
114c115
< $this->mod->triggerEvent("playerPIDChange", array($this->guid, $oldpid, $pid));
---
> $this->mod->triggerEvent("playerPIDChange", array($this->guid, $this->oldpid, $pid));
und für die mod.class.php:
592,594c592,598
< //Can't trigger this event in destructor, because then $players[guid] is unset already, we have to trigger before
< $this->triggerEvent("playerQuit", $parts[0]);
< unset($this->players[$parts[0]]);
---
> if ($this->players[$parts[0]]->oldpid != $parts[1]) {
> //Can't trigger this event in destructor, because then $players[guid] is unset already, we have to trigger before
> $this->triggerEvent("playerQuit", $parts[0]);
> unset($this->players[$parts[0]]);
> } else {
> $this->players[$parts[0]]->oldpid = -1;
> }
Alles anzeigen
Das ist natürlich nur ein "Hack", besser wäre es die alten PIDs in ein Array zu legen (um den Fall auszuschließen, dass zwei alte Verbindungen existieren). Und natürlich wäre es gut, das evtl. in Funktionen zu kapseln, da ich die player::oldpid (Faulheit siegt) einfach PUBLIC gemacht hab
Verständlich was ich mein?