/** Connects the bot to the server. * This function connects the bot to the server, i.e. opens the log, send resume commands to the server and simulate events for the plugins to synchronize. * If the server cannot be synchronized, it is reloaded. * * \return TRUE if server config connected correctly, FALSE otherwise. */ public function connect() { //First, we test connectivity to the server Leelabot::message('Connecting to server...'); $this->_rcon->setServer($this->_addr, $this->_port); $this->_rcon->setRConPassword($this->_rconpassword); $this->_rcon->setWaiting($this->_rconWaiting); if (!RCon::test()) { $reply = FALSE; if ($this->_rcon->lastError() == Quake3RCon::E_BADRCON && !empty($this->_recoverPassword)) { Leelabot::message('Bad RCon password, trying to recover', array(), E_WARNING); $this->_rcon->send('rconRecovery ' . $this->_recoverPassword, FALSE); $data = $this->_rcon->getReply(2); if (strpos($data, 'rconPassword') === 0) { $split = explode(' ', $data, 2); $this->_rconpassword = $split[1]; $this->_rcon->setRConPassword($this->_rconpassword); Leelabot::message('Updated RCon password.', array(), E_NOTICE); if (RCon::test()) { $reply = TRUE; } } } if ($reply == FALSE) { Leelabot::message('Can\'t connect : $0', array(RCon::getErrorString(RCon::lastError())), E_WARNING); return FALSE; } } //Sending startup Event for plugins $this->_leelabot->plugins->callServerEvent('StartupGame', $this->_name); Leelabot::message('Gathering server info...'); $this->serverInfo = RCon::serverInfo(); if (!$this->serverInfo) { Leelabot::message('Can\'t gather server info: ', array($this->_rcon->getErrorString($this->_rcon->lastError())), E_WARNING); return FALSE; } Leelabot::message('Gathering server players...'); $status = RCon::status(); if (!$status) { Leelabot::message('Can\'t gather server players.', array(), E_WARNING); return FALSE; } $this->players = array(); foreach ($status['players'] as $id => $player) { Leelabot::message('Gathering info for player $0 (Slot $1)...', array($player['name'], $id)); $playerData = array(); if (!($dump = RCon::dumpUser($id))) { Leelabot::message('Cannot retrieve info for player $0.', array($player['name']), E_WARNING); continue; } //The characterfile argument is unique to bots, so we use it to know if a player is a bot or not if (isset($dump['characterfile'])) { $playerData['isBot'] = TRUE; } else { $playerData['isBot'] = FALSE; $address = explode(':', $player['address']); $playerData['addr'] = $address[0]; $playerData['port'] = $address[1]; $playerData['guid'] = $dump['cl_guid']; } $playerData['name'] = preg_replace('#^[0-9]#', '', $dump['name']); $playerData['id'] = $id; $playerData['level'] = $this->_defaultLevel; $playerData['time'] = time(); $playerData['team'] = Server::TEAM_SPEC; $playerData['begin'] = FALSE; $playerData['uuid'] = Leelabot::UUID(); $this->players[$id] = new Storage($playerData); $this->players[$id]->other = $dump; $this->players[$id]->ip =& $this->players[$id]->addr; $data = array_merge($dump, $player); $this->_leelabot->plugins->callServerEvent('ClientConnect', $id); $this->_leelabot->plugins->callServerEvent('ClientUserinfo', array($id, $data)); } //Getting team repartition for players if (count($this->players) > 0) { // TODO : g_redteamlist and g_blueteamlist doesn't work in LMS and FFA. // TODO : If the team of player is Server::TEAM_FREE, what's happend ? Leelabot::message('Gathering teams...'); //Red team if (!($redteam = RCon::redTeamList())) { Leelabot::message('Cannot retrieve red team list'); } else { foreach ($redteam as $id) { $this->players[$id]->team = Server::TEAM_RED; $this->players[$id]->begin = TRUE; $playerData = array('team' => 'red', 't' => Server::TEAM_RED, 'n' => $this->players[$id]->name); $this->_leelabot->plugins->callServerEvent('ClientUserInfoChanged', array($id, $playerData)); $this->_leelabot->plugins->callServerEvent('ClientBegin', $id); } } //Blue team if (!($blueteam = RCon::blueTeamList())) { Leelabot::message('Cannot retrieve blue team list'); } else { foreach ($blueteam as $id) { if (empty($this->players[$id])) { $this->players[$id] = new Storage(); } $this->players[$id]->team = Server::TEAM_BLUE; $this->players[$id]->begin = TRUE; $playerData = array('team' => 'blue', 't' => Server::TEAM_BLUE, 'n' => $this->players[$id]->name); $this->_leelabot->plugins->callServerEvent('ClientUserInfoChanged', array($id, $playerData)); $this->_leelabot->plugins->callServerEvent('ClientBegin', $id); } } //We call ClientBegin for spectators foreach ($this->players as $id => $player) { if ($player->team == Server::TEAM_SPEC) { $this->_leelabot->plugins->callServerEvent('ClientBegin', $id); } } } //We init scoreboard and virtually start a game (for the plugins). $this->scores = array(1 => 0, 2 => 0); $this->_leelabot->plugins->callServerEvent('InitGame', $this->serverInfo); //Finally, we open the game log file if (!$this->openLogFile()) { return FALSE; } //Showing current server status Leelabot::message('Current server status :'); Leelabot::message(' Server name : $0', array($this->serverInfo['sv_hostname'])); Leelabot::message(' Gametype : $0', array(Server::getGametype())); Leelabot::message(' Map : $0', array($this->serverInfo['mapname'])); Leelabot::message(' Number of players : $0', array(count($this->players))); Leelabot::message(' Server version : $0', array($this->serverInfo['version'])); Leelabot::message(' Matchmode : $0', array($this->_leelabot->intl->translate($this->serverInfo['g_matchmode'] ? 'On' : 'Off'))); return TRUE; }