575 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
			
		
		
	
	
			575 lines
		
	
	
		
			57 KiB
		
	
	
	
		
			PHP
		
	
	
	
	
	
| <?php
 | |
| 
 | |
| namespace MCTeam\Dedimania;
 | |
| 
 | |
| 
 | |
| use ManiaControl\Callbacks\TimerListener;
 | |
| use ManiaControl\Files\AsyncHttpRequest;
 | |
| use ManiaControl\Logger;
 | |
| use ManiaControl\ManiaControl;
 | |
| use ManiaControl\Players\Player;
 | |
| 
 | |
| /**
 | |
|  * ManiaControl Dedimania Webhandler Class for Dedimania Plugin
 | |
|  *
 | |
|  * @author    ManiaControl Team <mail@maniacontrol.com>
 | |
|  * @copyright 2014-2017 ManiaControl Team
 | |
|  * @license   http://www.gnu.org/licenses/ GNU General Public License, Version 3
 | |
|  */
 | |
| class DedimaniaWebHandler implements TimerListener {
 | |
| 	const XMLRPC_MULTICALL                = 'system.multicall';
 | |
| 	const DEDIMANIA_URL                   = 'http://dedimania.net:8082/Dedimania';
 | |
| 	const DEDIMANIA_OPEN_SESSION          = 'dedimania.OpenSession';
 | |
| 	const DEDIMANIA_CHECK_SESSION         = 'dedimania.CheckSession';
 | |
| 	const DEDIMANIA_GET_RECORDS           = 'dedimania.GetChallengeRecords';
 | |
| 	const DEDIMANIA_PLAYERCONNECT         = 'dedimania.PlayerConnect';
 | |
| 	const DEDIMANIA_PLAYERDISCONNECT      = 'dedimania.PlayerDisconnect';
 | |
| 	const DEDIMANIA_UPDATE_SERVER_PLAYERS = 'dedimania.UpdateServerPlayers';
 | |
| 	const DEDIMANIA_SET_CHALLENGE_TIMES   = 'dedimania.SetChallengeTimes';
 | |
| 	const DEDIMANIA_WARNINGSANDTTR2       = 'dedimania.WarningsAndTTR2';
 | |
| 
 | |
| 	/** @var  ManiaControl $maniaControl */
 | |
| 	private $maniaControl;
 | |
| 	/** @var  \MCTeam\Dedimania\DedimaniaData $dedimaniaData */
 | |
| 	private $dedimaniaData;
 | |
| 
 | |
| 	private $requests             = array();
 | |
| 	private $requestIndex         = 0;
 | |
| 	private $maniaLinkNeedsUpdate = false;
 | |
| 
 | |
| 	public function __construct($maniaControl) {
 | |
| 		$this->maniaControl = $maniaControl;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Opens the Dedimania Session
 | |
| 	 *
 | |
| 	 * @param bool $updateRecords
 | |
| 	 */
 | |
| 	public function openDedimaniaSession($updateRecords = false) {
 | |
| 		//TODO updateRecords
 | |
| 		$content = $this->encodeRequest(self::DEDIMANIA_OPEN_SESSION, array($this->dedimaniaData->toArray()));
 | |
| 
 | |
| 		Logger::logInfo("Try to connect on Dedimania");
 | |
| 		$asyncHttpRequest = new AsyncHttpRequest($this->maniaControl, self::DEDIMANIA_URL);
 | |
| 		$asyncHttpRequest->setCallable(function ($data, $error) use ($updateRecords) {
 | |
| 			if (!$data || $error) {
 | |
| 				Logger::logError("Dedimania Error while opening session: '{$error}' Line 42");
 | |
| 			}
 | |
| 
 | |
| 
 | |
| 			$data = $this->decode($data);
 | |
| 			if (!is_array($data) || empty($data)) {
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			$methodResponse = $data[0];
 | |
| 			if (xmlrpc_is_fault($methodResponse)) {
 | |
| 				$this->handleXmlRpcFault($methodResponse, self::DEDIMANIA_OPEN_SESSION);
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			$responseData                   = $methodResponse[0];
 | |
| 			$this->dedimaniaData->sessionId = $responseData['SessionId'];
 | |
| 			if ($this->dedimaniaData->sessionId) {
 | |
| 				Logger::logInfo("Dedimania connection successfully established.");
 | |
| 
 | |
| 				if ($updateRecords) {
 | |
| 					$this->fetchDedimaniaRecords();
 | |
| 				}
 | |
| 
 | |
| 			} else {
 | |
| 				Logger::logError("Error while opening Dedimania Connection");
 | |
| 			}
 | |
| 		});
 | |
| 
 | |
| 		$asyncHttpRequest->setContent($content);
 | |
| 		$asyncHttpRequest->setCompression(true);
 | |
| 		$asyncHttpRequest->setTimeout(500);
 | |
| 		$asyncHttpRequest->postData();
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Fetch Dedimania Records
 | |
| 	 *
 | |
| 	 * @param bool $reset
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	public function fetchDedimaniaRecords($reset = true) {
 | |
| 		if (!isset($this->dedimaniaData) || !$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		// Reset records
 | |
| 		if ($reset) {
 | |
| 			$this->dedimaniaData->unsetRecords();
 | |
| 		}
 | |
| 
 | |
| 		$serverInfo = $this->getServerInfo();
 | |
| 		$playerInfo = $this->getPlayerList();
 | |
| 		$mapInfo    = $this->getMapInfo();
 | |
| 		$gameMode   = $this->getGameModeString();
 | |
| 
 | |
| 		if (!$serverInfo || !$playerInfo || !$mapInfo || !$gameMode) {
 | |
| 			$data = array($this->dedimaniaData->sessionId, $mapInfo, $gameMode, $serverInfo, $playerInfo);
 | |
| 			if ($serverInfo) { // No Players
 | |
| 				Logger::logError("Dedimania Records could not be fetched, debuginfo:" . json_encode($data));
 | |
| 			}
 | |
| 			return false;
 | |
| 		}
 | |
| 
 | |
| 		$data = array($this->dedimaniaData->sessionId, $mapInfo, $gameMode, $serverInfo, $playerInfo);
 | |
| 
 | |
| 		Logger::logInfo("Try to fetch Dedimania Records");
 | |
| 		$this->addRequest(self::DEDIMANIA_GET_RECORDS, $data);
 | |
| 
 | |
| 		return true;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Checks If a Dedimania Session exists, if not create a new oen
 | |
| 	 */
 | |
| 	public function checkDedimaniaSession() { //TODO complete check and refactor
 | |
| 		if (!$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		$this->addRequest(self::DEDIMANIA_CHECK_SESSION, array($this->dedimaniaData->sessionId));
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Handle EndMap Callback
 | |
| 	 */
 | |
| 	public function submitChallengeTimes() {
 | |
| 		if (!$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		if (!$this->getDedimaniaData()->recordsExisting()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		//Finish Counts as CP somehow
 | |
| 		if ($this->maniaControl->getMapManager()->getCurrentMap()->nbCheckpoints < 2) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Send dedimania records
 | |
| 		$gameMode = $this->getGameModeString();
 | |
| 		$times    = array();
 | |
| 		$replays  = array();
 | |
| 		foreach ($this->dedimaniaData->records as $record) {
 | |
| 			if ($record->rank > $this->dedimaniaData->serverMaxRank) {
 | |
| 				break;
 | |
| 			}
 | |
| 			if (!$record->newRecord) {
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			if ($record->vReplay == '' || !$record->vReplay) {
 | |
| 				Logger::logInfo("Dedimania Ignore time for " . $record->login . " no validation replay found");
 | |
| 				continue;
 | |
| 			}
 | |
| 
 | |
| 			//TODO check number of checkpoints
 | |
| 
 | |
| 			array_push($times, array('Login' => $record->login, 'Best' => $record->best, 'Checks' => $record->checkpoints));
 | |
| 			if (!isset($replays['VReplay'])) {
 | |
| 				$replays['VReplay'] = $record->vReplay;
 | |
| 			}
 | |
| 
 | |
| 			if (!isset($replays['VReplayChecks'])) {
 | |
| 				$replays['VReplayChecks'] = '';
 | |
| 				// TODO: VReplayChecks
 | |
| 			}
 | |
| 			if (!isset($replays['Top1GReplay'])) {
 | |
| 				$replays['Top1GReplay'] = $record->top1GReplay;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		xmlrpc_set_type($replays['VReplay'], 'base64');
 | |
| 		xmlrpc_set_type($replays['Top1GReplay'], 'base64');
 | |
| 
 | |
| 		$data = array($this->dedimaniaData->sessionId, $this->getMapInfo(), $gameMode, $times, $replays);
 | |
| 
 | |
| 		Logger::logInfo("Dedimania Submitting Map Times at End-Map Start");
 | |
| 		$this->addRequest(self::DEDIMANIA_SET_CHALLENGE_TIMES, $data);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Handle PlayerConnect callback
 | |
| 	 *
 | |
| 	 * @param Player $player
 | |
| 	 */
 | |
| 	public function handlePlayerConnect(Player $player) {
 | |
| 		if (!isset($this->dedimaniaData) || !$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Send Dedimania request
 | |
| 		$data = array($this->dedimaniaData->sessionId, $player->login, $player->rawNickname, $player->path, $player->isSpectator);
 | |
| 		$this->addRequest(self::DEDIMANIA_PLAYERCONNECT, $data);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Handle Player Disconnect Callback
 | |
| 	 *
 | |
| 	 * @param Player $player
 | |
| 	 */
 | |
| 	public function handlePlayerDisconnect(Player $player) { //TODO move into webhandler
 | |
| 		if (!isset($this->dedimaniaData) || !$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		$this->dedimaniaData->removePlayer($player->login);
 | |
| 
 | |
| 		// Send Dedimania request
 | |
| 		$data = array($this->dedimaniaData->sessionId, $player->login, '');
 | |
| 		$this->addRequest(self::DEDIMANIA_PLAYERDISCONNECT, $data);
 | |
| 	}
 | |
| 
 | |
| 
 | |
| 	/**
 | |
| 	 * Update the PlayerList every 3 Minutes
 | |
| 	 */
 | |
| 	public function updatePlayerList() {
 | |
| 		$serverInfo = $this->getServerInfo();
 | |
| 		$playerList = $this->getPlayerList();
 | |
| 		$votesInfo  = $this->getVotesInfo();
 | |
| 		if (!$serverInfo || !$votesInfo || !$playerList || !isset($this->dedimaniaData) || !$this->dedimaniaData->sessionIdSet()) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		// Send Dedimania request
 | |
| 		$data = array($this->dedimaniaData->sessionId, $serverInfo, $votesInfo, $playerList);
 | |
| 		$this->addRequest(self::DEDIMANIA_UPDATE_SERVER_PLAYERS, $data);
 | |
| 
 | |
| 	}
 | |
| 
 | |
| 	/** Adds a Request to the Dedimania Queue */
 | |
| 	private function addRequest($method, $params) {
 | |
| 		$this->requests[$this->requestIndex] = array('methodName' => $method, 'params' => $params);
 | |
| 		$this->requestIndex++;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Process Dedimania Calls
 | |
| 	 */
 | |
| 	public function callDedimania() {
 | |
| 		if (empty($this->requests)) {
 | |
| 			return;
 | |
| 		}
 | |
| 
 | |
| 		//var_dump($this->dedimaniaData->sessionId);
 | |
| 
 | |
| 		$this->addRequest(self::DEDIMANIA_WARNINGSANDTTR2, array());
 | |
| 
 | |
| 		$content = xmlrpc_encode_request(self::XMLRPC_MULTICALL, array($this->requests), array('encoding' => 'UTF-8', 'escaping' => 'cdata, non-ascii, non-print, markup', 'verbosity' => 'no_white_space'));
 | |
| 
 | |
| 
 | |
| 	/*	$content = "<?xml version=\"1.0\" encoding=\"UTF-8\"?><methodCall><methodName>system.multicall</methodName>
 | |
| <params>
 | |
| <param><value><array><data><value><struct><member><name>methodName</name><value>
 | |
| <string>dedimania.SetChallengeTimes</string></value></member>
 | |
| <member><name>params</name><value><array><data><value><string>".$this->dedimaniaData->sessionId."</string></value>
 | |
| <value><struct><member><name>UId</name><value><string>ymBMv4ra0y81UM58_E4qfUpfSOd</string></value></member>
 | |
| <member><name>Name</name><value><string>Sparkster's Canyon B12</string></value></member><member>
 | |
| <name>Environment</name><value><string>Canyon</string></value></member><member><name>Author</name>
 | |
| <value><string>sparkster</string></value></member><member><name>NbCheckpoints</name><value><int>3</int></value></member>
 | |
| <member><name>NbLaps</name><value><int>0</int></value></member></struct></value><value><string>TA</string></value><value><array>
 | |
| <data><value><struct><member><name>Login</name><value><string>kremsy</string></value></member><member><name>Best</name><value>
 | |
| <int>271954</int></value></member><member><name>Checks</name><value><string>9092,17778,271954</string></value></member></struct></value></data></array></value><value><struct><member><name>VReplay</name><value><base64>R0JYBgBCVUNSADAJAwcDAAADAAAAADAJA5IAAAABMAkD2QEAgAIwCQOAAAAACAAAAAMAAAAA
AABAGwAAAHltQk12NHJhMHk4MVVNNThfRTRxZlVwZlNPZAwAAAAAAABACQAAAHNwYXJrc3R
lclImBAAvAAAA77u/JHokcyRpJDA5Zs+BJDAwMMK7JGFhYW9tYm8gJGZmZkx1ayQwOWbDqS
DupaQGAAAAa3JlbXN5AQAAAEAIAAAAVE1DYW55b27VAQAAPGhlYWRlciB0eXBlPSJyZXBsY
XkiIGV4ZXZlcj0iMy4zLjAiIGV4ZWJ1aWxkPSIyMDE3LTA1LTE2XzE5XzAwIiB0aXRsZT0i
VE1DYW55b24iPjxtYXAgdWlkPSJ5bUJNdjRyYTB5ODFVTTU4X0U0cWZVcGZTT2QiIG5hbWU
9IlNwYXJrc3RlciZhcG9zO3MgQ2FueW9uIEIxMiIgYXV0aG9yPSJzcGFya3N0ZXIiIGF1dG
hvcnpvbmU9IldvcmxkfEV1cm9wZXxHZXJtYW55fFJoZWlubGFuZC1QZmFsenxLYWlzZXJzb
GF1dGVybiIvPjxkZXNjIGVudmlyPSJDYW55b24iIG1vb2Q9IiIgbWFwdHlwZT0iVHJhY2tt
YW5pYVxSYWNlIiBtYXBzdHlsZT0iIiBkaXNwbGF5Y29zdD0iMCIgbW9kPSIiIC8+PHBsYXl
lcm1vZGVsIGlkPSJDYW55b25DYXIiLz48dGltZXMgYmVzdD0iMjcxOTU0IiByZXNwYXducz
0iOSIgc3R1bnRzY29yZT0iNTIiIHZhbGlkYWJsZT0iMSIvPjxjaGVja3BvaW50cyBjdXI9I
jMiIG9uZWxhcD0iMyIvPjwvaGVhZGVyPgEAAAAAAAAADQAAAHBhcmFnb25jYW55b24wAAAA
JHckQURGUCQ5Q0ZhJDdCRnIkN0JGYSQ1QUZnJDJBRm8kMDlGbiRmZmYgQ2FueW9uKwAAAO+
7v1dvcmxkfEV1cm9wZXxGcmFuY2V8w45sZS1kZS1GcmFuY2V8UGFyaXMAAAAAAgAAAAAAAA
BpdQAAqmoAAAAIAjAJA/NZAABHQlgGAEJVQ1IAMAQDAAAAABxwAA0AAAAhawEA0lkAAAYNM
AQDZAMH/ykAAAkRMAQDAWQEAOOwAQOMAAUAAAAB3sr6AowCAwUDAbAFA2gBKgwADwSwBQOd
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
yJpWQEx7C54CGQnIyQ1A0JyaWRnZWgmCE5vUGlsbGFyAgYbLwmAMH2sBzBcAHQ/AQENFxou
XAp8AgEDDhcZLmQD3AIvbE/dAhd41XgT7FcjyGMokwMRFxwupQExe0MSFxwu7AZ9AgEx2NR
0C+woAkJ1c2hlKA0FASOgdCz9JDJiHw0XL4ybfAIBAw8XFC44AmDGAQEMDxYumAjdAhouoA
7dAhQumAhjLgEGGy/siZ0CBzBcAHgacCYipEAi6Foj9F50OgUxAQ0YDQCAACKKrUAHIshZA
ZAFAwJsAACDAAAAITQDyuqqln8LVKW6P6ZjSLEPa24yplLYM3kKwWNPcRv93Hk/AAAAU2tp
bnNcQW55XEFkdmVydGlzZW1lbnRcQnJpbGxpYW5jZSAnbicgTWV0YWxzXEVtZXJhbGRfVGl
0bGUuanBnOQAAAGh0dHA6Ly9kbC5kcm9wYm94LmNvbS9zL3lhZXl6dDRjZnI1MWFpby8v8A
AjXL54Fj4MABJAUzcWBDIBEiEGkLQgIuF2AGQgbAC0IAAQ9RH4GNU3Kz6517kqaUP2mWmc+
VkyMdjBhenMx0tdW8BFACAXFAQCTWlzY18kaG1sIXgpNiwEDTVlem96N3cwbXM4dDV1cS/s
IS0IASAQRAQi1EQvXQgyJFljASIgf9wiImCMIMtcBCLoZYygJjRJClNjcmVlbjJ4MQMZBhH
sZiIouvQibFAAEAOsmvq7MnKz3zvH/9+l+QIH6AV7H3/AE+sRHcFQp+/szzMSuVprNcQMCn
VkZGllYWRcQnVkZHkXyFtkQwE6AAAANmQIDWFzZnE5MHVneDV3M3Ziby8w9AAgDFEINSJaT
B0EJ4gDIkCV6BwirHcAEiE0A066RCY4+uvmQMCFVJtwIuiCk8bJfHXYg8ujm+hSlgYNRjqQ
AztYEAVTZXJpZXNfR2gtfR5AOdwDDDNpdHRrMXp2amV4YXp1aidEDC4MASAM9APwhCe0ByY
4xgJBAwkJEvg+EvRgLUwEAA5FcJWwWZpSC7araSAf1DnJjhAttQu1qk0uIoVb58NCYCAZkB
AIV2Fybl9EYW5nZXJoIjqQEAxvdGh4NDMwc3Z1bHFjeW0nSAQtCAEgDEUEN39BCQkQ7R8Nf
Fxwo2wAoKQguO0DNmwfAwYPEgCAAojkIkSELdwHABBKKvAex853mjshr/bVrH4kfTuvHxc+
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
YAFmAqaNxQLiYAFmAlahxQLEYAFmAvyqxgKIq9oZHK7NDZRgAW4EJLDsBGABZgKCsc0E5mA
BZgKgts4EmsHeCMLBzgTQws4WHsXOBCLGzgQwx84EUsjOBELJxgJ8y8YCYszGAjjOxgLizt
4IXtreCGjazgRC3dJETN3SBeXdx2Um3gMT154ADt/aNBzq3QiyYAF2GMDrxgIu7MYLDu7FA
nJgAW4EcPDFAqxgAWYC7PHGAkby1gbk9MYCevXGAmD2xQLEYAF2BiL4xQLCYAFmAjr51Rju
YAFmAsD6xgLi+9oZVP3FAvRgAW8EGgUEtaiSYAFnArIIBK+mxggExokJBLeWzgoEr68eCwS
tlG5gAWquoAvWBu4SzARgAZZgjhPLDPYUBKK1+hXCCtYW3ggMGNkHtmABexAsGwSmm5ob2Q
f0ZAJqAxIc3AhgASMCI6of0gV+I84W0iTKDJAlygzMJcMTsCYEtZ/5YAFiCqwn2gdaM9kQ0
mABagNiNcUC5GABZgLyNsYCYDfCCqo4xgIsOcUC4GABeiJYOsYCLjzVGJxgAX4Iqj3WBiI+
zQT+YAF2Bp4/xgJcQNYGHkLKHuZC1gaGQ84EikTGAoRFxgLURdYGPEfVBqBgAWYLOknGAl5
N1QbCYAF+EdpOxgJIT94IClHFAtJgAW4EhlLGArJTzgQMVM0NmGABbgQ4VcowsFXSBbpV7T
Fc1gaaXNIyDF7aB1BgwhOgYM4xAmPeCH5kzgSIZMoDDmbKAyJm1gYgaMoDcGjSDuxpzg0Ua
tIFcmveCIZr0gWUbMoDxmzeCNduz0MZbwS+fSJw0gW2fMYLOH3GC4J+xQL6YAFuH6R/xgIS
gM4EjoHFAvxgAW4EDIbFAt5gAWYCQofGAkaI1QbSYAF+NVSJxgKQidIXiorKFQyLxgJWjMY
CUI3eCA6O1Qb0YAF+CKiPxgJIkNUGymABdg+elNYGDJXOBBqWzQSIYAFuBEqYwiVymMkD4G
ABagNSmtI7fpvOOr6cxgLwnMYLNp3FC8JgAX4RMJ7GAjqe1gYMn9IFNJ/aB4yhzgTcoc4ED
qLOBCKizQTgYAF6EAij0gWEpM4EJKXGAkylxjiSpdIXUKbaGXimyiekp8IKqKjODUyq0QXY
YAFqDPaq3gi6vsoMRr/KDDTCxgLmxMYC4MXaByrHyQyEYAFuHwrJxQKWYAFmAoDLxgIMzN0
I1GABcg7Yzd4Ils7OFqDO0gVvz81VrmABcgWK0MYUPN3dCLRgAWoD9N7GAnbfxhQM4MUCrG
ABbgRC4cUCsGABZgKA6cYCKurWBqLq3hFq69oQ1u3OBDDuxhT879IFqPDFFONgAWIKoPHGF
Ej+1QbyYAFqA37/xQL2YAFnAswBBafRRAIFvs7AA8YCTATHAlQLBb3X9GABdgYWDccCTA4F
us1qDtcGkg4Fp9pkDwWyy5YP3QjIYAFuMe4RxgL4Ed4I1BLWBowUwgqgFMIKgBbeCGga1ga
aGtYG0CDSBRYh0gVsJd4IgCXSBbIl8gUlBabsSCbSBXom2AdgAZnotmgDYRz8aANqFVYn1w
bMKQW68f4p2gcIKtoHOirGFDwt1g9QLdYPgi3WD6ot3ggAN9YGBDjeCHY50gUmPsoMlD7CC
mBA2QfOYAFiEwRC1QauYAFmAlRHxQLCYAFmApJKxgIeS8YLok7GAvJOxhS6T94RyFDSDopS
0gWYU9IFQlTaELpUygPIVcoDQFbGAipYxRS2YAF2DzZbxQKuYAFmAipd1QaEYAFmAsJgxgI
cYd4IrmXWBiZm3iN4bs0EqmABdgYccMUCYmABZgLyccYCGnLeCMp2xgJgd8YCLHnFAqRgAX
YG4H7GAkR/zgTIh9YPGIjWDxaKxQJwYAF2BnSL1Qa6YAFmAkCNzQSQYAFmAvaQzgRgmsYLJ
J/GApChxgLgocow+KLaB46jzjF0pM4xTqfELwLyrAUAAHxQAAoRAAAATWFuaWFQbGFuZXQu
My4zLjAmvdB+DwAAhHAFLAAAADxpZD4QATDHCzwvaWQ+PGxhcHM+MTwvnAAIPGN0PjEzPC9
jdD54FWwAASYgCQMSscsQcAEtDQAnKWwAI+xKKXwAEmjN+AEHFTAJA/////8YMK0JjKIDQA
gSnMwETUNhbnlvbmgCCQ0AAABwYXJhZ29uY5ACAAMwAAAAJHckQURGUCQ5Q0ZhJDdCRnJwA
AADYSQ1QUZnJDJBRm8kMDlGbiRmZmYgoAkAEisAAADvu79Xb3JsZHxFdXJvcGV8RnJhbmNl
fMOObGUtZGUtRrgBAlBhcmlzfQ4a3RIUcAEpDABsFnkBG9wDfBV8AW0AHM0CEnABElDQbBk
HaW1lQXR0YWNrHdQDKsUAHswCZCmUicQHeQAfzAN8BSKUQmUPIM0CDBKg0nAEzQAh3AJsBc
oCACIxTQAjzAJ8B3wEbAp/ACQwCRMY1HwBbQAlKpwADAAAAAAAgL8AAAAAAd7K+hEAAA==
</base64></value></member><member><name>VReplayChecks</name><value><string/></value></member><member>
 | |
| <name>Top1GReplay</name><value><base64></base64></value></member>
 | |
| </struct></value></data></array></value></member></struct></value><value><struct><member><name>methodName</name><value><string>dedimania.WarningsAndTTR2</string></value></member><member><name>params</name><value><array><data/></array></value></member></struct></value></data></array></value></param></params></methodCall>";
 | |
| */ //TODO remove debug code later
 | |
| 
 | |
| 		$asyncHttpRequest = new AsyncHttpRequest($this->maniaControl, self::DEDIMANIA_URL);
 | |
| 		$asyncHttpRequest->setCallable(function ($answerData, $error) {
 | |
| 			if ($error) {
 | |
| 				Logger::logError("Dedimania Error while Request: " . $error);
 | |
| 				$this->checkDedimaniaSession();
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			//var_dump($error);
 | |
| 			//var_dump($answerData);
 | |
| 
 | |
| 			$data = $this->decode($answerData);
 | |
| 			if(!$data){
 | |
| 				//TODO just Temporary
 | |
| 				var_dump("Dedimania Debug:");
 | |
| 				var_dump($answerData);
 | |
| 			}
 | |
| 
 | |
| 			if (!is_array($data) || empty($data) || !isset($data[0]) || !isset($data[0][0])) {
 | |
| 				return;
 | |
| 			}
 | |
| 
 | |
| 			//Get the Errors and Warnings to get the Method Order
 | |
| 			$errorsAndWarnings = $data[count($data) - 1][0];
 | |
| 			$methods           = $errorsAndWarnings['methods'];
 | |
| 
 | |
| 			foreach ($data as $key => $methodResponse) {
 | |
| 				$methodName = $methods[$key]['methodName'];
 | |
| 
 | |
| 				if (xmlrpc_is_fault($methodResponse)) {
 | |
| 					$this->handleXmlRpcFault($methodResponse, $methodName);
 | |
| 				}
 | |
| 
 | |
| 				$responseParameters = $methodResponse[0];
 | |
| 
 | |
| 				switch ($methodName) {
 | |
| 					case self::DEDIMANIA_UPDATE_SERVER_PLAYERS:
 | |
| 						Logger::logInfo("Dedimania Playerlist Updated");
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_GET_RECORDS:
 | |
| 						if (!isset($responseParameters['Players']) || !isset($responseParameters['Records'])) {
 | |
| 							$this->maniaControl->getErrorHandler()->triggerDebugNotice('Invalid Dedimania response! ' . json_encode($responseParameters));
 | |
| 							return;
 | |
| 						}
 | |
| 
 | |
| 						$this->dedimaniaData->serverMaxRank = $responseParameters['ServerMaxRank'];
 | |
| 
 | |
| 						foreach ($responseParameters['Players'] as $player) {
 | |
| 							$dediPlayer = new DedimaniaPlayer($player);
 | |
| 							$this->dedimaniaData->addPlayer($dediPlayer);
 | |
| 						}
 | |
| 						foreach ($responseParameters['Records'] as $recordKey => $record) {
 | |
| 							$this->dedimaniaData->records[$recordKey] = new RecordData($record);
 | |
| 						}
 | |
| 
 | |
| 						Logger::logInfo(count($this->dedimaniaData->records) . " Dedimania Records Fetched succesfully!");
 | |
| 
 | |
| 						$this->maniaLinkNeedsUpdate = true;
 | |
| 						$this->maniaControl->getCallbackManager()->triggerCallback(DedimaniaPlugin::CB_DEDIMANIA_UPDATED, $this->dedimaniaData->records); //TODO
 | |
| 
 | |
| 						//3 Minutes
 | |
| 						$this->maniaControl->getTimerManager()->registerOneTimeListening($this, function () {
 | |
| 							$this->updatePlayerList();
 | |
| 						}, 1000 * 60 * 3);
 | |
| 
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_CHECK_SESSION:
 | |
| 						//TODO Check and reopen if needed
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_SET_CHALLENGE_TIMES:
 | |
| 						//TODO Proper Checks
 | |
| 						Logger::logInfo("Dedimania Times succesfully submitted");
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_PLAYERCONNECT:
 | |
| 						$dediPlayer = new DedimaniaPlayer($responseParameters);
 | |
| 						$this->dedimaniaData->addPlayer($dediPlayer);
 | |
| 
 | |
| 						// Fetch records if he is the first who joined the server
 | |
| 						if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) === 1) {
 | |
| 							$this->fetchDedimaniaRecords(true);
 | |
| 						}
 | |
| 
 | |
| 						Logger::logInfo("Dedimania Player added " . $dediPlayer->login);
 | |
| 
 | |
| 						$this->maniaLinkNeedsUpdate = true; //TODO handle update for only one player instead of everyone as soon splitted
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_PLAYERDISCONNECT:
 | |
| 						Logger::logInfo("Debug: Dedimania Player removed");
 | |
| 						break;
 | |
| 					case self::DEDIMANIA_WARNINGSANDTTR2:
 | |
| 						foreach ($responseParameters['methods'] as $method) {
 | |
| 							if ($method['errors']) {
 | |
| 								Logger::log('Dedimania Warning or Error: ' . $method['methodName'] . ': ' . json_encode($method['errors']));
 | |
| 							}
 | |
| 						}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			//exit();
 | |
| 		});
 | |
| 
 | |
| 		$asyncHttpRequest->setContent($content);
 | |
| 		//$asyncHttpRequest->setCompression(true);
 | |
| 		//FIXME setChallengeTime Compressed gives Dedimania Error 400
 | |
| 		$asyncHttpRequest->setTimeout(500);
 | |
| 		$asyncHttpRequest->postData();
 | |
| 
 | |
| 		$this->requests = array();
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Encode the given xml rpc method and params
 | |
| 	 *
 | |
| 	 * @param string $method
 | |
| 	 * @param array  $params
 | |
| 	 * @return string
 | |
| 	 */
 | |
| 	private function encodeRequest($method, $params) {
 | |
| 		$paramArray = array(array('methodName' => $method, 'params' => $params), array('methodName' => self::DEDIMANIA_WARNINGSANDTTR2, 'params' => array()));
 | |
| 		return xmlrpc_encode_request(self::XMLRPC_MULTICALL, array($paramArray), array('encoding' => 'UTF-8', 'escaping' => 'markup'));
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Decodes xml rpc response
 | |
| 	 *
 | |
| 	 * @param string $response
 | |
| 	 * @return mixed
 | |
| 	 */
 | |
| 	private function decode($response) {
 | |
| 		return xmlrpc_decode($response, 'utf-8');
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Build Votes Info Array for Callbacks
 | |
| 	 */
 | |
| 	private function getVotesInfo() {
 | |
| 		$map = $this->maniaControl->getMapManager()->getCurrentMap();
 | |
| 		if (!$map) {
 | |
| 			return null;
 | |
| 		}
 | |
| 		$gameMode = $this->getGameModeString();
 | |
| 		if (!$gameMode) {
 | |
| 			return null;
 | |
| 		}
 | |
| 		return array('UId' => $map->uid, 'GameMode' => $gameMode);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Build server info Structure for callbacks
 | |
| 	 */
 | |
| 	private function getServerInfo() {
 | |
| 		$server = $this->maniaControl->getClient()->getServerOptions();
 | |
| 		if (!$server) {
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		if ($this->maniaControl->getPlayerManager()->getPlayerCount(false) <= 0) {
 | |
| 			return null;
 | |
| 		}
 | |
| 
 | |
| 		$playerCount    = $this->maniaControl->getPlayerManager()->getPlayerCount();
 | |
| 		$spectatorCount = $this->maniaControl->getPlayerManager()->getSpectatorCount();
 | |
| 
 | |
| 		return array('SrvName'  => $server->name, 'Comment' => $server->comment, 'Private' => (strlen($server->password) > 0), 'NumPlayers' => $playerCount, 'MaxPlayers' => $server->currentMaxPlayers,
 | |
| 		             'NumSpecs' => $spectatorCount, 'MaxSpecs' => $server->currentMaxSpectators);
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Build simple player list for callbacks
 | |
| 	 */
 | |
| 	private function getPlayerList() {
 | |
| 		$players = $this->maniaControl->getPlayerManager()->getPlayers();
 | |
| 
 | |
| 		if (empty($players)) {
 | |
| 			return null;
 | |
| 		}
 | |
| 		$playerInfo = array();
 | |
| 		foreach ($players as $player) {
 | |
| 			array_push($playerInfo, array('Login' => $player->login, 'IsSpec' => $player->isSpectator));
 | |
| 		}
 | |
| 		return $playerInfo;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Build Map Info Array for Dedimania Requests
 | |
| 	 *
 | |
| 	 * @return array
 | |
| 	 */
 | |
| 	private function getMapInfo() {
 | |
| 		$map = $this->maniaControl->getMapManager()->getCurrentMap();
 | |
| 		if (!$map) {
 | |
| 			return null;
 | |
| 		}
 | |
| 		$mapInfo                  = array();
 | |
| 		$mapInfo['UId']           = $map->uid;
 | |
| 		$mapInfo['Name']          = $map->rawName;
 | |
| 		$mapInfo['Environment']   = $map->environment;
 | |
| 		$mapInfo['Author']        = $map->authorLogin;
 | |
| 		$mapInfo['NbCheckpoints'] = $map->nbCheckpoints;
 | |
| 		$mapInfo['NbLaps']        = $map->nbLaps;
 | |
| 		return $mapInfo;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Get Dedimania String Representation of the current Game Mode
 | |
| 	 *
 | |
| 	 * @return String
 | |
| 	 */
 | |
| 	private function getGameModeString() {
 | |
| 		$gameMode = $this->maniaControl->getServer()->getGameMode();
 | |
| 		if ($gameMode === null) {
 | |
| 			Logger::logError("Couldn't retrieve game mode.");
 | |
| 			return null;
 | |
| 		}
 | |
| 		switch ($gameMode) {
 | |
| 			case 0: {
 | |
| 				$scriptNameResponse = $this->maniaControl->getClient()->getScriptName();
 | |
| 				$scriptName         = str_replace('.Script.txt', '', $scriptNameResponse['CurrentValue']);
 | |
| 				switch ($scriptName) {
 | |
| 					case 'Rounds':
 | |
| 					case 'Cup':
 | |
| 					case 'Team':
 | |
| 						return 'Rounds';
 | |
| 					case 'TimeAttack':
 | |
| 					case 'Laps':
 | |
| 					case 'TeamAttack':
 | |
| 					case 'TimeAttackPlus':
 | |
| 						return 'TA';
 | |
| 				}
 | |
| 				break;
 | |
| 			}
 | |
| 			case 1:
 | |
| 			case 3:
 | |
| 			case 5: {
 | |
| 				return 'Rounds';
 | |
| 			}
 | |
| 			case 2:
 | |
| 			case 4: {
 | |
| 				return 'TA';
 | |
| 			}
 | |
| 		}
 | |
| 		return null;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Handle xml rpc fault
 | |
| 	 *
 | |
| 	 * @param array  $fault
 | |
| 	 * @param string $method
 | |
| 	 */
 | |
| 	private function handleXmlRpcFault(array $fault, $method) {
 | |
| 		trigger_error("XmlRpc Fault on '{$method}': '{$fault['faultString']} ({$fault['faultCode']})!");
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @return \MCTeam\Dedimania\DedimaniaData
 | |
| 	 */
 | |
| 	public function getDedimaniaData() {
 | |
| 		return $this->dedimaniaData;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @param \MCTeam\Dedimania\DedimaniaData $dedimaniaData
 | |
| 	 */
 | |
| 	public function setDedimaniaData($dedimaniaData) {
 | |
| 		$this->dedimaniaData = $dedimaniaData;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * @return bool
 | |
| 	 */
 | |
| 	public function doesManiaLinkNeedUpdate() {
 | |
| 		return $this->maniaLinkNeedsUpdate;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Call if ManiaLink got Updated
 | |
| 	 */
 | |
| 	public function maniaLinkUpdated() {
 | |
| 		$this->maniaLinkNeedsUpdate = false;
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Call if You want a ManiaLink Update
 | |
| 	 */
 | |
| 	public function maniaLinkUpdateNeeded() {
 | |
| 		$this->maniaLinkNeedsUpdate = true;
 | |
| 	}
 | |
| } |