changed names, some other minor things

This commit is contained in:
kremsy 2013-11-09 13:29:18 +01:00
parent 4a0ed1836d
commit 99a754034a
19 changed files with 156 additions and 5171 deletions

View File

@ -23,10 +23,46 @@
</component>
<component name="FileEditorManager">
<leaf>
<file leaf-file-name="plugin.php" pinned="false" current="false" current-in-tab="false">
<file leaf-file-name="plugin.php" pinned="false" current="true" current-in-tab="true">
<entry file="file://$PROJECT_DIR$/core/plugin.php">
<provider selected="true" editor-type-id="text-editor">
<state line="31" column="0" selection-start="501" selection-end="501" vertical-scroll-proportion="-20.26923" vertical-offset="0" max-vertical-offset="1972">
<state line="21" column="20" selection-start="307" selection-end="307" vertical-scroll-proportion="0.47536618" vertical-offset="0" max-vertical-offset="2380">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="plugins.ManiaControl.xml" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/configs/plugins.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="11" column="0" selection-start="363" selection-end="363" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="323">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="core.ManiaControl.xml" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/configs/core.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="357">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="database.ManiaControl.xml" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/configs/database.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="374">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="ManiaControl.php" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/ManiaControl.php">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-0.0" vertical-offset="0" max-vertical-offset="544">
<folding />
</state>
</provider>
@ -35,34 +71,16 @@
<file leaf-file-name="pluginHandler.php" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/pluginHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="3" selection-start="108" selection-end="108" vertical-scroll-proportion="-5.230769" vertical-offset="0" max-vertical-offset="357">
<state line="28" column="2" selection-start="439" selection-end="439" vertical-scroll-proportion="-18.307692" vertical-offset="0" max-vertical-offset="578">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="karma.plugin.php" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/plugins/karma.plugin.php">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="-0.0" vertical-offset="0" max-vertical-offset="5287">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="manialinkIdHandler.php" pinned="false" current="true" current-in-tab="true">
<file leaf-file-name="manialinkIdHandler.php" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/manialinkIdHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state line="2" column="23" selection-start="30" selection-end="30" vertical-scroll-proportion="0.04527297" vertical-offset="0" max-vertical-offset="751">
<folding />
</state>
</provider>
</entry>
</file>
<file leaf-file-name="database.ManiaControl.php" pinned="false" current="false" current-in-tab="false">
<entry file="file://$PROJECT_DIR$/core/database.ManiaControl.php">
<provider selected="true" editor-type-id="text-editor">
<state line="29" column="0" selection-start="380" selection-end="380" vertical-scroll-proportion="-6.486842" vertical-offset="0" max-vertical-offset="6919">
<state line="19" column="5" selection-start="306" selection-end="306" vertical-scroll-proportion="-12.423077" vertical-offset="0" max-vertical-offset="748">
<folding />
</state>
</provider>
@ -80,9 +98,12 @@
<list>
<option value="$PROJECT_DIR$/plugins/chatlog.plugin.php" />
<option value="$PROJECT_DIR$/core/database.ManiaControl.php" />
<option value="$PROJECT_DIR$/core/pluginHandler.php" />
<option value="$PROJECT_DIR$/core/manialinkIdHandler.php" />
<option value="$PROJECT_DIR$/core/core.ManiaControl.php" />
<option value="$PROJECT_DIR$/core/pluginHandler.php" />
<option value="$PROJECT_DIR$/core/plugin.php" />
<option value="$PROJECT_DIR$/core/core.php" />
<option value="$PROJECT_DIR$/configs/plugins.ManiaControl.xml" />
</list>
</option>
</component>
@ -119,7 +140,18 @@
<sortByType />
</navigator>
<panes>
<pane id="Scope" />
<pane id="Scope">
<subPane subId="Problems" />
<subPane subId="Tests" />
<subPane subId="Project Files">
<PATH>
<PATH_ELEMENT USER_OBJECT="Root">
<option name="myItemId" value="" />
<option name="myItemType" value="" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
<pane id="ProjectPane">
<subPane>
<PATH>
@ -166,6 +198,20 @@
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
<PATH>
<PATH_ELEMENT>
<option name="myItemId" value="application" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.ProjectViewProjectNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="application" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
<PATH_ELEMENT>
<option name="myItemId" value="configs" />
<option name="myItemType" value="com.intellij.ide.projectView.impl.nodes.PsiDirectoryNode" />
</PATH_ELEMENT>
</PATH>
</subPane>
</pane>
</panes>
@ -240,24 +286,24 @@
<servers />
</component>
<component name="ToolWindowManager">
<frame x="-8" y="-8" width="1936" height="1056" extended-state="6" />
<frame x="-8" y="-8" width="1936" height="1056" extended-state="7" />
<editor active="true" />
<layout>
<window_info id="Changes" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Terminal" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Database" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Remote Host" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.12540022" sideWeight="0.8942093" order="0" side_tool="false" content_ui="combo" />
<window_info id="Debug" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="3" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Event Log" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.105790645" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Favorites" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="true" content_ui="tabs" />
<window_info id="Version Control" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="-1" side_tool="false" content_ui="tabs" />
<window_info id="TODO" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="6" side_tool="false" content_ui="tabs" />
<window_info id="Structure" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Project" active="false" anchor="left" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="true" weight="0.12540022" sideWeight="0.8942093" order="0" side_tool="false" content_ui="combo" />
<window_info id="Run" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="2" side_tool="false" content_ui="tabs" />
<window_info id="Cvs" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="4" side_tool="false" content_ui="tabs" />
<window_info id="Message" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Find" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.33" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Ant Build" active="false" anchor="right" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.25" sideWeight="0.5" order="1" side_tool="false" content_ui="tabs" />
<window_info id="Commander" active="false" anchor="right" auto_hide="false" internal_type="SLIDING" type="SLIDING" visible="false" weight="0.4" sideWeight="0.5" order="0" side_tool="false" content_ui="tabs" />
<window_info id="Inspection" active="false" anchor="bottom" auto_hide="false" internal_type="DOCKED" type="DOCKED" visible="false" weight="0.4" sideWeight="0.5" order="5" side_tool="false" content_ui="tabs" />
@ -276,51 +322,65 @@
<breakpoint-manager />
</component>
<component name="editorHistoryManager">
<entry file="file://$PROJECT_DIR$/plugins/chatlog.plugin.php">
<entry file="file://$PROJECT_DIR$/core/manialinkIdHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state line="7" column="20" selection-start="90" selection-end="90" vertical-scroll-proportion="0.14066194" vertical-offset="0" max-vertical-offset="1547">
<state line="19" column="5" selection-start="306" selection-end="306" vertical-scroll-proportion="-12.423077" vertical-offset="0" max-vertical-offset="748">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/core/pluginHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="3" selection-start="108" selection-end="108" vertical-scroll-proportion="-5.230769" vertical-offset="0" max-vertical-offset="357">
<state line="28" column="2" selection-start="439" selection-end="439" vertical-scroll-proportion="-18.307692" vertical-offset="0" max-vertical-offset="578">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/plugins/plugin.ManiaControl.php">
<entry file="file://$PROJECT_DIR$/core/authentication.php">
<provider selected="true" editor-type-id="text-editor">
<state line="8" column="7" selection-start="111" selection-end="111" vertical-scroll-proportion="0.1607565" vertical-offset="0" max-vertical-offset="846">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="1853">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/core/database.ManiaControl.php">
<entry file="file://$PROJECT_DIR$/ManiaControl.php">
<provider selected="true" editor-type-id="text-editor">
<state line="29" column="0" selection-start="380" selection-end="380" vertical-scroll-proportion="-6.486842" vertical-offset="0" max-vertical-offset="6919">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="777">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/plugins/karma.plugin.php">
<entry file="file://$PROJECT_DIR$/core/core.php">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="5287">
<state line="158" column="10" selection-start="3332" selection-end="3335" vertical-scroll-proportion="-35.342106" vertical-offset="0" max-vertical-offset="6596">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/configs/database.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="777">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/configs/core.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="0" column="0" selection-start="0" selection-end="0" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="777">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/configs/plugins.ManiaControl.xml">
<provider selected="true" editor-type-id="text-editor">
<state line="11" column="0" selection-start="363" selection-end="363" vertical-scroll-proportion="0.0" vertical-offset="0" max-vertical-offset="323">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/core/plugin.php">
<provider selected="true" editor-type-id="text-editor">
<state line="31" column="0" selection-start="501" selection-end="501" vertical-scroll-proportion="-20.26923" vertical-offset="0" max-vertical-offset="1972">
<folding />
</state>
</provider>
</entry>
<entry file="file://$PROJECT_DIR$/core/manialinkIdHandler.php">
<provider selected="true" editor-type-id="text-editor">
<state line="2" column="23" selection-start="30" selection-end="30" vertical-scroll-proportion="0.04527297" vertical-offset="0" max-vertical-offset="751">
<state line="21" column="20" selection-start="307" selection-end="307" vertical-scroll-proportion="0.47536618" vertical-offset="0" max-vertical-offset="2380">
<folding />
</state>
</provider>

View File

@ -1,12 +1,12 @@
<?xml version="1.0" encoding="UTF-8"?>
<!-- Configure which plugins should be loaded -->
<plugins-config>
<!-- <plugin>FILENAME1</plugin> <plugin>FILENAME2</plugin> -->
<!-- <plugin>FILENAME1</plugin> <plugin>FILENAME2</plugin>
<plugin>chatlog.plugin.php</plugin>
<plugin>karma.plugin.php</plugin>
<plugin>records.plugin.php</plugin>
<plugin>united.plugin.php</plugin>
<plugin>united.plugin.php</plugin>-->
<!-- <plugin>obstacle.plugin.php</plugin> -->

View File

@ -1,103 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class handling authentication levels
*
* @author steeffeen
*/
class Authentication {
/**
* Constants
*/
public $RIGHTS_LEVELS = array(-1 => 'none', 0 => 'superadmin', 1 => 'admin', 2 => 'operator', 3 => 'all');
/**
* Private properties
*/
private $mControl = null;
private $config = null;
/**
* Construct authentication manager
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('authentication.ManiaControl.xml');
}
/**
* Check if the player has enough rights
*
* @param string $login
* @param string $defaultRight
* @param string $neededRight
* @return bool
*/
public function checkRight($login, $neededRight) {
$right = $this->getRights($login);
return $this->compareRights($right, $neededRight);
}
/**
* Compare if the rights are enough
*
* @param string $hasRight
* @param string $neededRight
* @return bool
*/
public function compareRights($hasRight, $neededRight) {
if (!in_array($hasRight, $this->RIGHTS_LEVELS) || !in_array($neededRight, $this->RIGHTS_LEVELS)) {
return false;
}
$hasLevel = array_search($hasRight, $this->RIGHTS_LEVELS);
$neededLevel = array_search($neededRight, $this->RIGHTS_LEVELS);
if ($hasLevel > $neededLevel) {
return false;
}
else {
return true;
}
}
/**
* Get rights of the given login
*
* @param string $login
* @param string $defaultRights
* @return string
*/
public function getRights($login, $defaultRight = 'all') {
$groups = $this->config->xpath('//login[text()="' . $login . '"]/..');
if (empty($groups)) return $defaultRight;
$right = $defaultRight;
$rightLevel = array_search($right, $this->RIGHTS_LEVELS);
foreach ($groups as $group) {
$level = array_search($group->getName(), $this->RIGHTS_LEVELS);
if ($level === false) continue;
if ($level < $rightLevel || $rightLevel === false) {
$right = $group->getName();
$rightLevel = $level;
}
}
return $right;
}
/**
* Sends an error message to the login
*
* @param string $login
*/
public function sendNotAllowed($login) {
if (!$this->iControl->chat->sendError('You do not have the required rights to perform this command!', $login)) {
trigger_error("Couldn't send forbidden message to login '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
}
?>

View File

@ -1,191 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class for handling server callbacks
*
* @author steeffeen
*/
class Callbacks {
/**
* Constants
*/
// ManiaControl callbacks
const CB_IC_1_SECOND = 'ManiaControl.1Second';
const CB_IC_5_SECOND = 'ManiaControl.5Second';
const CB_IC_1_MINUTE = 'ManiaControl.1Minute';
const CB_IC_3_MINUTE = 'ManiaControl.3Minute';
const CB_IC_ONINIT = 'ManiaControl.OnInit';
const CB_IC_CLIENTUPDATED = 'ManiaControl.ClientUpdated';
const CB_IC_BEGINMAP = 'ManiaControl.BeginMap';
const CB_IC_ENDMAP = 'ManiaControl.EndMap';
// ManiaPlanet callbacks
const CB_MP_SERVERSTART = 'ManiaPlanet.ServerStart';
const CB_MP_SERVERSTOP = 'ManiaPlanet.ServerStop';
const CB_MP_BEGINMAP = 'ManiaPlanet.BeginMap';
const CB_MP_BEGINMATCH = 'ManiaPlanet.BeginMatch';
const CB_MP_ENDMATCH = 'ManiaPlanet.EndMatch';
const CB_MP_ENDMAP = 'ManiaPlanet.EndMap';
const CB_MP_MAPLISTMODIFIED = 'ManiaPlanet.MapListModified';
const CB_MP_ECHO = 'ManiaPlanet.Echo';
const CB_MP_BILLUPDATED = 'ManiaPlanet.BillUpdated';
const CB_MP_PLAYERCHAT = 'ManiaPlanet.PlayerChat';
const CB_MP_PLAYERCONNECT = 'ManiaPlanet.PlayerConnect';
const CB_MP_PLAYERDISCONNECT = 'ManiaPlanet.PlayerDisconnect';
const CB_MP_PLAYERMANIALINKPAGEANSWER = 'ManiaPlanet.PlayerManialinkPageAnswer';
const CB_MP_PLAYERINFOCHANGED = 'ManiaPlanet.PlayerInfoChanged';
const CB_MP_PLAYERALLIESCHANGED = 'ManiaPlanet.PlayerAlliesChanged';
const CB_MP_VOTEUPDATED = 'ManiaPlanet.VoteUpdated';
const CB_MP_STATUSCHANGED = 'ManiaPlanet.StatusChanged';
const CB_MP_MODESCRIPTCALLBACK = 'ManiaPlanet.ModeScriptCallback';
const CB_MP_MODESCRIPTCALLBACKARRAY = 'ManiaPlanet.ModeScriptCallbackArray';
const CB_MP_TUNNELDATARECEIVED = 'ManiaPlanet.TunnelDataReceived';
// TrackMania callbacks
const CB_TM_PLAYERCHECKPOINT = 'TrackMania.PlayerCheckpoint';
const CB_TM_PLAYERFINISH = 'TrackMania.PlayerFinish';
const CB_TM_PLAYERINCOHERENCE = 'TrackMania.PlayerIncoherence';
/**
* Private properties
*/
private $mControl = null;
private $callbackHandlers = array();
private $last1Second = -1;
private $last5Second = -1;
private $last1Minute = -1;
private $last3Minute = -1;
/**
* Construct callbacks handler
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Init values
$this->last1Second = time();
$this->last5Second = time();
$this->last1Minute = time();
$this->last3Minute = time();
}
/**
* Perform OnInit callback
*/
public function onInit() {
// On init callback
$this->triggerCallback(self::CB_IC_ONINIT, array(self::CB_IC_ONINIT));
// Simulate begin map
$map = $this->iControl->server->getMap();
if ($map) {
$this->triggerCallback(self::CB_IC_BEGINMAP, array(self::CB_IC_BEGINMAP, array($map)));
}
}
/**
* Handles the given array of callbacks
*/
public function handleCallbacks() {
// Perform ManiaControl callbacks
if ($this->last1Second <= time() - 1) {
$this->last1Second = time();
// 1 second
$this->triggerCallback(self::CB_IC_1_SECOND, array(self::CB_IC_1_SECOND));
if ($this->last5Second <= time() - 5) {
$this->last5Second = time();
// 5 second
$this->triggerCallback(self::CB_IC_5_SECOND, array(self::CB_IC_5_SECOND));
if ($this->last1Minute <= time() - 60) {
$this->last1Minute = time();
// 1 minute
$this->triggerCallback(self::CB_IC_1_MINUTE, array(self::CB_IC_1_MINUTE));
if ($this->last3Minute <= time() - 180) {
$this->last3Minute = time();
// 3 minute
$this->triggerCallback(self::CB_IC_3_MINUTE, array(self::CB_IC_3_MINUTE));
}
}
}
}
// Get server callbacks
if (!$this->iControl->client) return;
$this->iControl->client->resetError();
$this->iControl->client->readCB();
$callbacks = $this->iControl->client->getCBResponses();
if (!is_array($callbacks) || $this->iControl->client->isError()) {
trigger_error("Error reading server callbacks. " . $this->iControl->getClientErrorText());
return;
}
// Handle callbacks
foreach ($callbacks as $index => $callback) {
$callbackName = $callback[0];
switch ($callbackName) {
case self::CB_MP_BEGINMAP:
{
// Map begin
$this->triggerCallback($callbackName, $callback);
$this->triggerCallback(self::CB_IC_BEGINMAP, $callback);
break;
}
case self::CB_MP_ENDMAP:
{
// Map end
$this->triggerCallback($callbackName, $callback);
$this->triggerCallback(self::CB_IC_ENDMAP, $callback);
break;
}
default:
{
$this->triggerCallback($callbackName, $callback);
break;
}
}
}
}
/**
* Trigger a specific callback
*
* @param string $callbackName
* @param mixed $data
*/
public function triggerCallback($callbackName, $data) {
if (!array_key_exists($callbackName, $this->callbackHandlers) || !is_array($this->callbackHandlers[$callbackName])) return;
foreach ($this->callbackHandlers[$callbackName] as $handler) {
call_user_func(array($handler[0], $handler[1]), $data);
}
}
/**
* Add a new callback handler
*/
public function registerCallbackHandler($callback, $handler, $method) {
if (!is_object($handler) || !method_exists($handler, $method)) {
trigger_error("Given handler can't handle callback '" . $callback . "' (no method '" . $method . "')!");
return;
}
if (!array_key_exists($callback, $this->callbackHandlers) || !is_array($this->callbackHandlers[$callback])) {
// Init callback handler array
$this->callbackHandlers[$callback] = array();
}
// Register callback handler
array_push($this->callbackHandlers[$callback], array($handler, $method));
}
}
?>

View File

@ -1,85 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class for chat methods
*
* @author steeffeen
*/
class Chat {
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $prefix = 'ManiaControl>';
/**
* Construct ManiaControl chat
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('chat.ManiaControl.xml');
}
/**
* Send a chat message to the given login
*
* @param string $login
* @param string $message
* @param bool $prefix
*/
public function sendChat($message, $login = null, $prefix = false) {
if (!$this->iControl->client) return false;
if ($login === null) {
return $this->iControl->client->query('ChatSendServerMessage', ($prefix ? $this->prefix : '') . $message);
}
else {
return $this->iControl->client->query('ChatSendServerMessageToLogin', ($prefix ? $this->prefix : '') . $message, $login);
}
}
/**
* Send an information message to the given login
*
* @param string $login
* @param string $message
* @param bool $prefix
*/
public function sendInformation($message, $login = null, $prefix = false) {
$format = (string) $this->config->messages->information;
return $this->sendChat($format . $message, $login);
}
/**
* Send a success message to the given login
*
* @param string $message
* @param string $login
* @param bool $prefix
*/
public function sendSuccess($message, $login = null, $prefix = false) {
$format = (string) $this->config->messages->success;
return $this->sendChat($format . $message, $login);
}
/**
* Send an error message to the given login
*
* @param string $login
* @param string $message
* @param bool $prefix
*/
public function sendError($message, $login = null, $prefix = false) {
$format = (string) $this->config->messages->error;
return $this->sendChat($format . $message, $login);
}
}
?>

View File

@ -1,684 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class for handling chat commands
*
* @author steeffeen
*/
class Commands {
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $commandHandlers = array();
private $openBills = array();
private $serverShutdownTime = -1;
private $serverShutdownEmpty = false;
/**
* Construct commands handler
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('commands.ManiaControl.xml');
// Register for callbacks
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'each5Seconds');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_BILLUPDATED, $this, 'handleBillUpdated');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCHAT, $this, 'handleChatCallback');
// Register basic commands
$commands = array('help', 'version', 'shutdown', 'shutdownserver', 'networkstats', 'systeminfo', 'getservername',
'setservername', 'getplanets', 'donate', 'pay', 'kick', 'nextmap', 'restartmap', 'addmap', 'removemap', 'startwarmup',
'stopwarmup');
foreach ($commands as $command) {
$this->registerCommandHandler($command, $this, 'command_' . $command);
}
}
/**
* Register a command handler
*
* @param string $commandName
* @param object $handler
* @param string $method
*/
public function registerCommandHandler($commandName, $handler, $method) {
$command = strtolower($commandName);
if (!is_object($handler) || !method_exists($handler, $method)) {
trigger_error("Given handler can't handle command '" . $command . "' (no method '" . $method . "')!");
return;
}
if (!array_key_exists($command, $this->commandHandlers) || !is_array($this->commandHandlers[$command])) {
// Init handlers array
$this->commandHandlers[$command] = array();
}
// Register command handler
array_push($this->commandHandlers[$command], array($handler, $method));
}
/**
* Handle chat callback
*/
public function handleChatCallback($callback) {
$chat = $callback[1];
// Check for command
if (!$chat[3]) return;
// Check for valid player
if ($chat[0] <= 0 || strlen($chat[1]) <= 0) return;
// Handle command
$command = explode(" ", substr($chat[2], 1));
$command = strtolower($command[0]);
if (!array_key_exists($command, $this->commandHandlers) || !is_array($this->commandHandlers[$command])) {
// No command handler registered
return;
}
// Inform command handlers
foreach ($this->commandHandlers[$command] as $handler) {
call_user_func(array($handler[0], $handler[1]), $callback);
}
}
/**
* Handle bill updated callback
*/
public function handleBillUpdated($callback) {
$bill = $callback[1];
if (!array_key_exists($bill[0], $this->openBills)) return;
$login = $this->openBills[$bill[0]];
switch ($bill[1]) {
case 4:
{
// Payed
$message = 'Success! Thanks.';
$this->iControl->chat->sendSuccess($message, $login);
unset($this->openBills[$bill[0]]);
break;
}
case 5:
{
// Refused
$message = 'Transaction cancelled.';
$this->iControl->chat->sendError($message, $login);
unset($this->openBills[$bill[0]]);
break;
}
case 6:
{
// Error
$this->iControl->chat->sendError($bill[2], $login);
unset($this->openBills[$bill[0]]);
break;
}
}
}
/**
* Retrieve the needed rights level to perform the given command
*
* @param string $commandName
* @param string $defaultLevel
* @return string
*/
private function getRightsLevel($commandName, $defaultLevel) {
$command_rights = $this->config->xpath('//' . strtolower($commandName) . '/..');
if (empty($command_rights)) return $defaultLevel;
$rights = $this->iControl->authentication->RIGHTS_LEVELS;
$highest_level = null;
foreach ($command_rights as $right) {
$levelName = $right->getName();
$levelInt = array_search($levelName, $rights);
if ($levelInt !== false && ($highest_level === null || $highest_level < $levelInt)) {
$highest_level = $levelInt;
}
}
if ($highest_level === null || !array_key_exists($highest_level, $rights)) return $defaultLevel;
return $rights[$highest_level];
}
/**
* Send ManiaControl version
*/
private function command_version($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('version', 'all'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->chat->sendInformation('This server is using ManiaControl v' . ManiaControl::VERSION . '!', $login)) {
trigger_error("Couldn't send version to '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
/**
* Send help list
*/
private function command_help($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('help', 'all'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
// TODO: improve help command
// TODO: enable help for specific commands
$list = 'Available commands: ';
$commands = array_keys($this->commandHandlers);
$count = count($commands);
for ($index = 0; $index < $count; $index++) {
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel($commands[$index], 'superadmin'))) {
unset($commands[$index]);
}
}
$count = count($commands);
$index = 0;
foreach ($commands as $command) {
$list .= $command;
if ($index < $count - 1) {
$list .= ', ';
}
$index++;
}
if (!$this->iControl->chat->sendInformation($list, $login)) {
trigger_error("Couldn't send help list to '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
/**
* Handle getplanets command
*/
private function command_getplanets($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('getplanets', 'admin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->client->query('GetServerPlanets')) {
trigger_error("Couldn't retrieve server planets. " . $this->iControl->getClientErrorText());
}
else {
$planets = $this->iControl->client->getResponse();
if (!$this->iControl->chat->sendInformation('This Server has ' . $planets . ' Planets!', $login)) {
trigger_error("Couldn't send server planets to '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
}
/**
* Handle donate command
*/
private function command_donate($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('donate', 'all'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$params = explode(' ', $chat[1][2]);
if (count($params) < 2) {
// TODO: send usage information
return;
}
$amount = (int) $params[1];
if (!$amount || $amount <= 0) {
// TODO: send usage information
return;
}
if (count($params) >= 3) {
$receiver = $params[2];
$receiverPlayer = $this->iControl->database->getPlayer($receiver);
$receiverName = ($receiverPlayer ? $receiverPlayer['NickName'] : $receiver);
}
else {
$receiver = '';
$receiverName = $this->iControl->server->getName();
}
$message = 'Donate ' . $amount . ' Planets to $<' . $receiverName . '$>?';
if (!$this->iControl->client->query('SendBill', $login, $amount, $message, $receiver)) {
trigger_error(
"Couldn't create donation of " . $amount . " planets from '" . $login . "' for '" . $receiver . "'. " .
$this->iControl->getClientErrorText());
$this->iControl->chat->sendError("Creating donation failed.", $login);
}
else {
$bill = $this->iControl->client->getResponse();
$this->openBills[$bill] = $login;
}
}
/**
* Handle pay command
*/
private function command_pay($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('pay', 'superadmin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$params = explode(' ', $chat[1][2]);
if (count($params) < 2) {
// TODO: send usage information
return;
}
$amount = (int) $params[1];
if (!$amount || $amount <= 0) {
// TODO: send usage information
return;
}
if (count($params) >= 3) {
$receiver = $params[2];
}
else {
$receiver = $login;
}
$message = 'Payout from $<' . $this->iControl->server->getName() . '$>.';
if (!$this->iControl->client->query('Pay', $receiver, $amount, $message)) {
trigger_error(
"Couldn't create payout of" . $amount . " planets by '" . $login . "' for '" . $receiver . "'. " .
$this->iControl->getClientErrorText());
$this->iControl->chat->sendError("Creating payout failed.", $login);
}
else {
$bill = $this->iControl->client->getResponse();
$this->openBills[$bill] = $login;
}
}
/**
* Handle networkstats command
*/
private function command_networkstats($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('networkstats', 'superadmin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$networkStats = $this->iControl->server->getNetworkStats();
$message = 'NetworkStats: ' . 'uptime=' . $networkStats['Uptime'] . ', ' . 'nbConn=' . $networkStats['NbrConnection'] . ', ' .
'recvRate=' . $networkStats['RecvNetRate'] . ', ' . 'sendRate=' . $networkStats['SendNetRate'] . ', ' . 'recvTotal=' .
$networkStats['SendNetRate'] . ', ' . 'sentTotal=' . $networkStats['SendNetRate'];
if (!$this->iControl->chat->sendInformation($message, $login)) {
trigger_error("Couldn't send network stats to '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
/**
* Handle systeminfo command
*/
private function command_systeminfo($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('systeminfo', 'superadmin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$systemInfo = $this->iControl->server->getSystemInfo();
$message = 'SystemInfo: ' . 'ip=' . $systemInfo['PublishedIp'] . ', ' . 'port=' . $systemInfo['Port'] . ', ' . 'p2pPort=' .
$systemInfo['P2PPort'] . ', ' . 'title=' . $systemInfo['TitleId'] . ', ' . 'login=' . $systemInfo['ServerLogin'] . ', ';
if (!$this->iControl->chat->sendInformation($message, $login)) {
trigger_error("Couldn't send system info to '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
/**
* Handle shutdown command
*/
private function command_shutdown($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('shutdown', 'superadmin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$this->iControl->quit("ManiaControl shutdown requested by '" . $login . "'");
}
/**
* Handle startwarmup command
*/
private function command_startwarmup($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('startwarmup', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->client->query("SetWarmUp", true)) {
trigger_error("Couldn't start warmup. " . $this->iControl->getClientErrorText());
$player = $this->iControl->database->getPlayer($login);
$this->iControl->chat->sendInformation('$<' . ($player ? $player['NickName'] : $login) . '$> started WarmUp!');
}
}
/**
* Handle stopwarmup command
*/
private function command_stopwarmup($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('stopwarmup', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->client->query("SetWarmUp", false)) {
trigger_error("Couldn't stop warmup. " . $this->iControl->getClientErrorText());
}
else {
$player = $this->iControl->database->getPlayer($login);
$this->iControl->chat->sendInformation('$<' . ($player ? $player['NickName'] : $login) . '$> stopped WarmUp!');
}
}
/**
* Handle server shutdown command
*/
private function command_shutdownserver($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('shutdownserver', 'superadmin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
// Check for delayed shutdown
$params = explode(' ', $chat[1][2]);
if (count($params) >= 2) {
$param = $params[1];
if ($param == 'empty') {
$this->serverShutdownEmpty = !$this->serverShutdownEmpty;
if ($this->serverShutdownEmpty) {
$this->iControl->chat->sendInformation("The server will shutdown as soon as it's empty!", $login);
}
else {
$this->iControl->chat->sendInformation("Empty-shutdown cancelled!", $login);
}
}
else {
$delay = (int) $param;
if ($delay <= 0) {
// Cancel shutdown
$this->serverShutdownTime = -1;
$this->iControl->chat->sendInformation("Delayed shutdown cancelled!", $login);
}
else {
// Trigger delayed shutdown
$this->serverShutdownTime = time() + $delay * 60.;
$this->iControl->chat->sendInformation("The server will shut down in " . $delay . " minutes!", $login);
}
}
}
else {
$this->shutdownServer($login);
}
}
/**
* Handle kick command
*/
private function command_kick($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('kick', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$params = explode(' ', $chat[1][2], 3);
if (count($params) < 2) {
// TODO: show usage
return;
}
$target = $params[1];
$players = $this->iControl->server->getPlayers();
foreach ($players as $player) {
if ($player['Login'] != $target) continue;
// Kick player
if (isset($params[2])) {
$message = $params[2];
}
else {
$message = "";
}
if (!$this->iControl->client->query('Kick', $target, $message)) {
trigger_error("Couldn't kick player '" . $target . "'! " . $this->iControl->getClientErrorText());
}
return;
}
$this->iControl->chat->sendError("Invalid player login.", $login);
}
/**
* Handle removemap command
*/
private function command_removemap($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('kick', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
// TODO: allow params
// Get map name
$map = $this->iControl->server->getMap();
if (!$map) {
$this->iControl->chat->sendError("Couldn't remove map.", $login);
}
else {
$mapName = $map['FileName'];
// Remove map
if (!$this->iControl->client->query('RemoveMap', $mapName)) {
trigger_error("Couldn't remove current map. " . $this->iControl->getClientErrorText());
}
else {
$this->iControl->chat->sendSuccess('Map removed.', $login);
}
}
}
/**
* Handle addmap command
*/
private function command_addmap($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('addmap', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$params = explode(' ', $chat[1][2], 2);
if (count($params) < 2) {
// TODO: show usage
return;
}
// Check if ManiaControl can even write to the maps dir
if (!$this->iControl->client->query('GetMapsDirectory')) {
trigger_error("Couldn't get map directory. " . $this->iControl->getClientErrorText());
$this->iControl->chat->sendError("ManiaControl couldn't retrieve the maps directory.", $login);
return;
}
else {
$mapDir = $this->iControl->client->getResponse();
if (!is_dir($mapDir)) {
trigger_error("ManiaControl doesn't have have access to the maps directory in '" . $mapDir . "'.");
$this->iControl->chat->sendError("ManiaControl doesn't have access to the maps directory.", $login);
return;
}
$dlDir = (string) $this->iControl->config->maps_dir;
// Create mx directory if necessary
if (!is_dir($mapDir . $dlDir) && !mkdir($mapDir . $dlDir)) {
trigger_error("ManiaControl doesn't have to rights to save maps in'" . $mapDir . $dlDir, "'.");
$this->iControl->chat->sendError("ManiaControl doesn't have to rights to save maps.", $login);
return;
}
$mapDir .= $dlDir . '/';
// Download the map
if (is_numeric($params[1])) {
$serverInfo = $this->iControl->server->getSystemInfo();
$title = strtolower(substr($serverInfo['TitleId'], 0, 2));
// Check if map exists
$url = 'http://' . $title . '.mania-exchange.com/api/tracks/get_track_info/id/' . $params[1] . '?format=json';
$mapInfo = Tools::loadFile($url);
if (!$mapInfo || strlen($mapInfo) <= 0) {
// Invalid id
$this->iControl->chat->sendError('Invalid MX-Id!', $login);
return;
}
$mapInfo = json_decode($mapInfo, true);
$url = 'http://' . $title . '.mania-exchange.com/tracks/download/' . $params[1];
$file = Tools::loadFile($url);
if (!$file) {
// Download error
$this->iControl->chat->sendError('Download failed!', $login);
return;
}
// Save map
$fileName = $mapDir . $mapInfo['TrackID'] . '_' . $mapInfo['Name'] . '.Map.Gbx';
if (!file_put_contents($fileName, $file)) {
// Save error
$this->iControl->chat->sendError('Saving map failed!', $login);
return;
}
// Check for valid map
if (!$this->iControl->client->query('CheckMapForCurrentServerParams', $fileName)) {
trigger_error("Couldn't check if map is valid. " . $this->iControl->getClientErrorText());
}
else {
$response = $this->iControl->client->getResponse();
if (!$response) {
// Inalid map type
$this->iControl->chat->sendError("Invalid map type.", $login);
return;
}
}
// Add map to map list
if (!$this->iControl->client->query('InsertMap', $fileName)) {
$this->iControl->chat->sendError("Couldn't add map to match settings!", $login);
return;
}
$this->iControl->chat->sendSuccess('Map $<' . $mapInfo['Name'] . '$> successfully added!');
}
else {
// TODO: check if map exists locally
// TODO: load map from direct url
}
}
}
/**
* Handle nextmap command
*/
private function command_nextmap($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('nextmap', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->client->query('NextMap')) {
trigger_error("Couldn't skip map. " . $this->iControl->getClientErrorText());
}
}
/**
* Handle retartmap command
*/
private function command_restartmap($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('restartmap', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
if (!$this->iControl->client->query('RestartMap')) {
trigger_error("Couldn't restart map. " . $this->iControl->getClientErrorText());
}
}
/**
* Handle getservername command
*/
private function command_getservername($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('getservername', 'operator'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$serverName = $this->iControl->server->getName();
$this->iControl->chat->sendInformation("Server Name: " . $serverName, $login);
}
/**
* Handle setservername command
*/
private function command_setservername($chat) {
$login = $chat[1][1];
if (!$this->iControl->authentication->checkRight($login, $this->getRightsLevel('setservername', 'admin'))) {
// Not allowed!
$this->iControl->authentication->sendNotAllowed($login);
return;
}
$params = explode(' ', $chat[1][2], 2);
if (count($params) < 2) {
// TODO: show usage
return;
}
$serverName = $params[1];
if (!$this->iControl->client->query('SetServerName', $serverName)) {
trigger_error("Couldn't set server name. " . $this->iControl->getClientErrorText());
$this->iControl->chat->sendError("Error!");
}
else {
$serverName = $this->iControl->server->getName();
$this->iControl->chat->sendInformation("New Name: " . $serverName);
}
}
/**
* Check stuff each 5 seconds
*/
public function each5Seconds() {
// Empty shutdown
if ($this->serverShutdownEmpty) {
$players = $this->iControl->server->getPlayers();
if (count($players) <= 0) {
$this->shutdownServer('empty');
}
}
// Delayed shutdown
if ($this->serverShutdownTime > 0) {
if (time() >= $this->serverShutdownTime) {
$this->shutdownServer('delayed');
}
}
}
/**
* Perform server shutdown
*/
private function shutdownServer($login = '#') {
$this->iControl->client->resetError();
if (!$this->iControl->client->query('StopServer') || $this->iControl->client->isError()) {
trigger_error("Server shutdown command from '" . $login . "' failed. " . $this->iControl->getClientErrorText());
return;
}
$this->iControl->quit("Server shutdown requested by '" . $login . "'");
}
}
?>

View File

@ -1,348 +0,0 @@
<?php
namespace ManiaControl;
/**
* Needed includes
*/
require_once __DIR__ . '/authentication.ManiaControl.php';
require_once __DIR__ . '/callbacks.ManiaControl.php';
require_once __DIR__ . '/chat.ManiaControl.php';
require_once __DIR__ . '/commands.ManiaControl.php';
require_once __DIR__ . '/database.ManiaControl.php';
require_once __DIR__ . '/server.ManiaControl.php';
require_once __DIR__ . '/stats.ManiaControl.php';
require_once __DIR__ . '/tools.ManiaControl.php';
list($endiantest) = array_values(unpack('L1L', pack('V', 1)));
if ($endiantest == 1) {
require_once __DIR__ . '/PhpRemote/GbxRemote.inc.php';
}
else {
require_once __DIR__ . '/PhpRemote/GbxRemote.bem.php';
}
/**
* ManiaControl Server Controller for ManiaPlanet Server
*
* @author steeffeen
*/
class ManiaControl {
/**
* Constants
*/
const VERSION = '0.1';
const API_VERSION = '2013-04-16';
const DATE = 'd-m-y h:i:sa T';
/**
* Public properties
*/
public $authentication = null;
public $callbacks = null;
public $client = null;
public $chat = null;
public $config = null;
public $commands = null;
public $database = null;
public $debug = false;
public $server = null;
public $startTime = -1;
public $stats = null;
/**
* Private properties
*/
private $plugins = array();
private $shutdownRequested = false;
/**
* Construct ManiaControl
*/
public function __construct() {
// Load core
$this->config = Tools::loadConfig('core.ManiaControl.xml');
$this->startTime = time();
// Load chat tool
$this->chat = new Chat($this);
// Load callbacks handler
$this->callbacks = new Callbacks($this);
// Load database
$this->database = new Database($this);
// Load server
$this->server = new Server($this);
// Load authentication
$this->authentication = new Authentication($this);
// Load commands handler
$this->commands = new Commands($this);
// Load stats manager
$this->stats = new Stats($this);
// Register for core callbacks
$this->callbacks->registerCallbackHandler(Callbacks::CB_MP_ENDMAP, $this, 'handleEndMap');
}
/**
* Return message composed of client error message and error code
*
* @param object $client
* @return string
*/
public function getClientErrorText($client = null) {
if (is_object($client)) {
return $client->getErrorMessage() . ' (' . $client->getErrorCode() . ')';
}
return $this->client->getErrorMessage() . ' (' . $this->client->getErrorCode() . ')';
}
/**
* Quit ManiaControl and log the given message
*/
public function quit($message = false) {
if ($this->shutdownRequested) return;
if ($this->client) {
// Announce quit
$this->chat->sendInformation('ManiaControl shutting down.');
// Hide manialinks
$this->client->query('SendHideManialinkPage');
}
// Log quit reason
if ($message) {
error_log($message);
}
// Shutdown
if ($this->client) $this->client->Terminate();
error_log("Quitting ManiaControl!");
exit();
}
/**
* Run ManiaControl
*/
public function run($debug = false) {
error_log('Starting ManiaControl v' . self::VERSION . '!');
$this->debug = (bool) $debug;
// Load plugins
$this->loadPlugins();
// Connect to server
$this->connect();
// Loading finished
error_log("Loading completed!");
// Announce ManiaControl
if (!$this->chat->sendInformation('ManiaControl v' . self::VERSION . ' successfully started!')) {
trigger_error("Couldn't announce ManiaControl. " . $this->iControl->getClientErrorText());
}
// OnInit
$this->callbacks->onInit();
// Main loop
while (!$this->shutdownRequested) {
$loopStart = microtime(true);
// Disable script timeout
set_time_limit(30);
// Handle server callbacks
$this->callbacks->handleCallbacks();
// Loop plugins
foreach ($this->plugins as $plugin) {
if (!method_exists($plugin, 'loop')) {
continue;
}
$plugin->loop();
}
// Yield for next tick
$loopEnd = microtime(true);
$sleepTime = 300000 - $loopEnd + $loopStart;
if ($sleepTime > 0) {
usleep($sleepTime);
}
}
// Shutdown
$this->client->Terminate();
}
/**
* Connect to ManiaPlanet server
*/
private function connect() {
$enable = $this->server->config->xpath('enable');
$enable = Tools::toBool($enable[0]);
if (!$enable) return;
// Load remote client
$this->client = new \IXR_ClientMulticall_Gbx();
$host = $this->server->config->xpath('host');
if (!$host) trigger_error("Invalid server configuration (host).", E_USER_ERROR);
$host = (string) $host[0];
$port = $this->server->config->xpath('port');
if (!$host) trigger_error("Invalid server configuration (port).", E_USER_ERROR);
$port = (string) $port[0];
$timeout = $this->config->xpath('timeout');
if (!$timeout) trigger_error("Invalid core configuration (timeout).", E_USER_ERROR);
$timeout = (int) $timeout[0];
error_log("Connecting to server at " . $host . ":" . $port . "...");
// Connect
if (!$this->client->InitWithIp($host, $port, $timeout)) {
trigger_error(
"Couldn't connect to server! " . $this->client->getErrorMessage() . "(" . $this->client->getErrorCode() . ")",
E_USER_ERROR);
}
$login = $this->server->config->xpath('login');
if (!$login) trigger_error("Invalid server configuration (login).", E_USER_ERROR);
$login = (string) $login[0];
$pass = $this->server->config->xpath('pass');
if (!$pass) trigger_error("Invalid server configuration (password).", E_USER_ERROR);
$pass = (string) $pass[0];
// Authenticate
if (!$this->client->query('Authenticate', $login, $pass)) {
trigger_error(
"Couldn't authenticate on server with user '" . $login . "'! " . $this->client->getErrorMessage() . "(" .
$this->client->getErrorCode() . ")", E_USER_ERROR);
}
// Enable callback system
if (!$this->client->query('EnableCallbacks', true)) {
trigger_error("Couldn't enable callbacks! " . $this->client->getErrorMessage() . "(" . $this->client->getErrorCode() . ")",
E_USER_ERROR);
}
// Wait for server to be ready
if (!$this->server->waitForStatus($this->client, 4)) {
trigger_error("Server couldn't get ready!", E_USER_ERROR);
}
// Set api version
if (!$this->client->query('SetApiVersion', self::API_VERSION)) {
trigger_error(
"Couldn't set API version '" . self::API_VERSION . "'! This might cause problems. " .
$this->iControl->getClientErrorText());
}
// Connect finished
error_log("Server connection succesfully established!");
// Enable service announces
if (!$this->client->query("DisableServiceAnnounces", false)) {
trigger_error("Couldn't enable service announces. " . $this->iControl->getClientErrorText());
}
// Enable script callbacks if needed
if ($this->server->getGameMode() === 0) {
if (!$this->client->query('GetModeScriptSettings')) {
trigger_error("Couldn't get mode script settings. " . $this->iControl->getClientErrorText());
}
else {
$scriptSettings = $this->client->getResponse();
if (array_key_exists('S_UseScriptCallbacks', $scriptSettings)) {
$scriptSettings['S_UseScriptCallbacks'] = true;
if (!$this->client->query('SetModeScriptSettings', $scriptSettings)) {
trigger_error(
"Couldn't set mode script settings to enable script callbacks. " . $this->iControl->getClientErrorText());
}
else {
error_log("Script callbacks successfully enabled.");
}
}
}
}
}
/**
* Load ManiaControl plugins
*/
private function loadPlugins() {
$pluginsConfig = Tools::loadConfig('plugins.ManiaControl.xml');
if (!$pluginsConfig || !isset($pluginsConfig->plugin)) {
trigger_error('Invalid plugins config.');
return;
}
// Load plugin classes
$classes = get_declared_classes();
foreach ($pluginsConfig->xpath('plugin') as $plugin) {
$fileName = ManiaControlDir . '/plugins/' . $plugin;
if (!file_exists($fileName)) {
trigger_error("Couldn't load plugin '" . $plugin . "'! File doesn't exist. (/plugins/" . $plugin . ")");
}
else {
require_once $fileName;
error_log("Loading plugin: " . $plugin);
}
}
$plugins = array_diff(get_declared_classes(), $classes);
// Create plugins
foreach ($plugins as $plugin) {
$nameIndex = stripos($plugin, 'plugin');
if ($nameIndex === false) continue;
array_push($this->plugins, new $plugin($this));
}
}
/**
* Handle EndMap callback
*/
public function handleEndMap($callback) {
// Autosave match settings
$autosaveMatchsettings = $this->config->xpath('autosave_matchsettings');
if ($autosaveMatchsettings) {
$autosaveMatchsettings = (string) $autosaveMatchsettings[0];
if ($autosaveMatchsettings) {
if (!$this->client->query('SaveMatchSettings', 'MatchSettings/' . $autosaveMatchsettings)) {
trigger_error("Couldn't autosave match settings. " . $this->iControl->getClientErrorText());
}
}
}
}
/**
* Check config settings
*/
public function checkConfig($config, $settings, $name = 'Config XML') {
if (!is_array($settings)) $settings = array($settings);
foreach ($settings as $setting) {
$settingTags = $config->xpath('//' . $setting);
if (empty($settingTags)) {
trigger_error("Missing property '" . $setting . "' in config '" . $name . "'!", E_USER_ERROR);
}
}
}
}
?>

View File

@ -1,401 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class for database connection
*
* @author steeffeen
*/
class Database {
/**
* Constants
*/
const TABLE_PLAYERS = 'ic_players';
const TABLE_MAPS = 'ic_maps';
/**
* Public properties
*/
public $mysqli = null;
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $multiQueries = '';
/**
* Construct database connection
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('database.ManiaControl.xml');
$this->mControl->checkConfig($this->config, array("host", "user"), 'database.ManiaControl.xml');
// Get mysql server information
$host = $this->config->xpath('host');
if (!$host) trigger_error("Invalid database configuration (host).", E_USER_ERROR);
$host = (string) $host[0];
$port = $this->config->xpath('port');
if (!$port) trigger_error("Invalid database configuration (port).", E_USER_ERROR);
$port = (int) $port[0];
$user = $this->config->xpath('user');
if (!$user) trigger_error("Invalid database configuration (user).", E_USER_ERROR);
$user = (string) $user[0];
$pass = $this->config->xpath('pass');
if (!$pass) trigger_error("Invalid database configuration (pass).", E_USER_ERROR);
$pass = (string) $pass[0];
// Open database connection
$this->mysqli = new \mysqli($host, $user, $pass, null, $port);
if ($this->mysqli->connect_error) {
// Connection error
throw new \Exception(
"Error on connecting to mysql server. " . $this->mysqli->connect_error . " (" . $this->mysqli->connect_errno . ")");
}
// Set charset
$this->mysqli->set_charset("utf8");
// Create/Connect database
$this->initDatabase();
// Init tables
$this->initTables();
// Register for callbacks
$this->mControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'handle5Second');
$this->mControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleBeginMap');
}
/**
* Destruct database connection
*/
public function __destruct() {
$this->mysqli->close();
}
/**
* Connect to the defined database (create it if needed)
*/
private function initDatabase() {
$dbname = $this->config->xpath('database');
if (!$dbname) trigger_error("Invalid database configuration (database).", E_USER_ERROR);
$dbname = (string) $dbname[0];
// Try to connect
$result = $this->mysqli->select_db($dbname);
if (!$result) {
// Create database
$query = "CREATE DATABASE `" . $this->escape($dbname) . "`;";
$result = $this->mysqli->query($query);
if (!$result) {
trigger_error(
"Couldn't create database '" . $dbname . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')',
E_USER_ERROR);
}
else {
// Connect to database
$result = $this->mysqli->select_db($dbname);
if (!$result) {
trigger_error(
"Couldn't select database '" . $dbname . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')',
E_USER_ERROR);
}
}
}
}
/**
* Create the needed tables
*/
private function initTables() {
$query = "";
// Players table
$query .= "CREATE TABLE IF NOT EXISTS `" . self::TABLE_PLAYERS . "` (
`index` int(11) NOT NULL AUTO_INCREMENT,
`Login` varchar(100) NOT NULL,
`NickName` varchar(250) NOT NULL,
`PlayerId` int(11) NOT NULL,
`LadderRanking` int(11) NOT NULL,
`Flags` varchar(50) NOT NULL,
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`index`),
UNIQUE KEY `Login` (`Login`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Store player metadata' AUTO_INCREMENT=1;";
// Maps table
$query .= "CREATE TABLE IF NOT EXISTS `ic_maps` (
`index` int(11) NOT NULL AUTO_INCREMENT,
`UId` varchar(100) NOT NULL,
`Name` varchar(100) NOT NULL,
`FileName` varchar(200) NOT NULL,
`Author` varchar(150) NOT NULL,
`Environnement` varchar(50) NOT NULL,
`Mood` varchar(50) NOT NULL,
`BronzeTime` int(11) NOT NULL DEFAULT '-1',
`SilverTime` int(11) NOT NULL DEFAULT '-1',
`GoldTime` int(11) NOT NULL DEFAULT '-1',
`AuthorTime` int(11) NOT NULL DEFAULT '-1',
`CopperPrice` int(11) NOT NULL DEFAULT '-1',
`LapRace` tinyint(1) NOT NULL,
`NbLaps` int(11) NOT NULL DEFAULT '-1',
`NbCheckpoints` int(11) NOT NULL DEFAULT '-1',
`MapType` varchar(100) NOT NULL,
`MapStyle` varchar(100) NOT NULL,
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`index`),
UNIQUE KEY `UId` (`UId`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Store map metadata' AUTO_INCREMENT=1;";
// Perform queries
if (!$this->multiQuery($query)) {
trigger_error("Creating basic tables failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')', E_USER_ERROR);
}
// Optimize all existing tables
$query = "SHOW TABLES;";
$result = $this->query($query);
if (!$result || !is_object($result)) {
trigger_error("Couldn't select tables. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
}
else {
$query = "OPTIMIZE TABLE ";
$count = $result->num_rows;
$index = 0;
while ($row = $result->fetch_row()) {
$query .= "`" . $row[0] . "`";
if ($index < $count - 1) $query .= ", ";
$index++;
}
$query .= ";";
if (!$this->query($query)) {
trigger_error("Couldn't optimize tables. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
}
}
}
/**
* Wrapper for performing a simple query
*
* @param string $query
* @return mixed query result
*/
public function query($query) {
if (!is_string($query)) return false;
if (strlen($query) <= 0) return true;
return $this->mysqli->query($query);
}
/**
* Perform multi query
*
* @param
* string multi_query
* @return bool whether no error occured during executing the multi query
*/
public function multiQuery($query) {
if (!is_string($query)) return false;
if (strlen($query) <= 0) return true;
$noError = true;
$this->mysqli->multi_query($query);
if ($this->mysqli->error) {
trigger_error("Executing multi query failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
$noError = false;
}
while ($this->mysqli->more_results() && $this->mysqli->next_result()) {
if ($this->mysqli->error) {
trigger_error("Executing multi query failed. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
$noError = false;
}
}
return $noError;
}
/**
* Handle 5Second callback
*/
public function handle5Second($callback = null) {
// Save current players in database
$players = $this->mControl->server->getPlayers();
if ($players) {
$query = "";
foreach ($players as $player) {
if (!Tools::isPlayer($player)) continue;
$query .= $this->composeInsertPlayer($player);
}
$this->multiQuery($query);
}
}
/**
* Handle BeginMap callback
*/
public function handleBeginMap($callback) {
$map = $callback[1][0];
$query = $this->composeInsertMap($map);
$result = $this->query($query);
if ($this->mysqli->error) {
trigger_error("Couldn't save map. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
}
}
/**
* Get the player index for the given login
*
* @param string $login
* @return int null
*/
public function getPlayerIndex($login) {
$query = "SELECT `index` FROM `" . self::TABLE_PLAYERS . "` WHERE `Login` = '" . $this->escape($login) . "';";
$result = $this->query($query);
$result = $result->fetch_assoc();
if ($result) {
return $result['index'];
}
return null;
}
/**
* Get the map index for the given UId
*
* @param string $uid
* @return int null
*/
public function getMapIndex($uid) {
$query = "SELECT `index` FROM `" . self::TABLE_MAPS . "` WHERE `UId` = '" . $this->escape($uid) . "';";
$result = $this->query($query);
$result = $result->fetch_assoc();
if ($result) {
return $result['index'];
}
return null;
}
/**
* Compose a query string for inserting the given player
*
* @param array $player
*/
private function composeInsertPlayer($player) {
if (!Tools::isPlayer($player)) return "";
return "INSERT INTO `" . self::TABLE_PLAYERS . "` (
`Login`,
`NickName`,
`PlayerId`,
`LadderRanking`,
`Flags`
) VALUES (
'" . $this->escape($player['Login']) . "',
'" . $this->escape($player['NickName']) . "',
" . $player['PlayerId'] . ",
" . $player['LadderRanking'] . ",
'" . $this->escape($player['Flags']) . "'
) ON DUPLICATE KEY UPDATE
`NickName` = VALUES(`NickName`),
`PlayerId` = VALUES(`PlayerId`),
`LadderRanking` = VALUES(`LadderRanking`),
`Flags` = VALUES(`Flags`);";
}
/**
* Compose a query string for inserting the given map
*
* @param array $map
*/
private function composeInsertMap($map) {
if (!$map) return "";
return "INSERT INTO `" . self::TABLE_MAPS . "` (
`UId`,
`Name`,
`FileName`,
`Author`,
`Environnement`,
`Mood`,
`BronzeTime`,
`SilverTime`,
`GoldTime`,
`AuthorTime`,
`CopperPrice`,
`LapRace`,
`NbLaps`,
`NbCheckpoints`,
`MapType`,
`MapStyle`
) VALUES (
'" . $this->escape($map['UId']) . "',
'" . $this->escape($map['Name']) . "',
'" . $this->escape($map['FileName']) . "',
'" . $this->escape($map['Author']) . "',
'" . $this->escape($map['Environnement']) . "',
'" . $this->escape($map['Mood']) . "',
" . $map['BronzeTime'] . ",
" . $map['SilverTime'] . ",
" . $map['GoldTime'] . ",
" . $map['AuthorTime'] . ",
" . $map['CopperPrice'] . ",
" . Tools::boolToInt($map['LapRace']) . ",
" . $map['NbLaps'] . ",
" . $map['NbCheckpoints'] . ",
'" . $this->escape($map['MapType']) . "',
'" . $this->escape($map['MapStyle']) . "'
) ON DUPLICATE KEY UPDATE
`Name` = VALUES(`Name`),
`FileName` = VALUES(`FileName`),
`Author` = VALUES(`Author`),
`Environnement` = VALUES(`Environnement`),
`Mood` = VALUES(`Mood`),
`BronzeTime` = VALUES(`BronzeTime`),
`SilverTime` = VALUES(`SilverTime`),
`GoldTime` = VALUES(`GoldTime`),
`AuthorTime` = VALUES(`AuthorTime`),
`CopperPrice` = VALUES(`CopperPrice`),
`LapRace` = VALUES(`LapRace`),
`NbLaps` = VALUES(`NbLaps`),
`NbCheckpoints` = VALUES(`NbCheckpoints`),
`MapType` = VALUES(`MapType`),
`MapStyle` = VALUES(`MapStyle`);";
}
/**
* Retrieve all information about the player with the given login
*/
public function getPlayer($login) {
if (!$login) return null;
$query = "SELECT * FROM `" . self::TABLE_PLAYERS . "` WHERE `Login` = '" . $this->escape($login) . "';";
$result = $this->mysqli->query($query);
if ($this->mysqli->error || !$result) {
trigger_error(
"Couldn't select player with login '" . $login . "'. " . $this->mysqli->error . ' (' . $this->mysqli->errno . ')');
return null;
}
else {
while ($player = $result->fetch_assoc()) {
return $player;
}
return null;
}
}
/**
* Escapes the given string for a mysql query
*
* @param string $string
* @return string
*/
public function escape($string) {
return $this->mysqli->escape_string($string);
}
}
?>

View File

@ -14,20 +14,21 @@ namespace ManiaControl;
/**
* Private properties
*/
private $mControl;
private $mc;
private $version;
private $author;
private $updateUrl;
private $name;
private $active;
public function __construct($mControl, $name, $version = 0, $author = '', $updateUrl = ''){
$this->mControl = $mControl;
public function __construct($mc, $name, $version = 0, $author = '', $updateUrl = ''){
$this->mc = $mc;
$this->name = $name;
$this->version = $version;
$this->author = $author;
$this->updateUrl = $updateUrl;
$this->mc->pluginHandler->registerPlugin($this);
}
/**
@ -37,13 +38,37 @@ namespace ManiaControl;
* @return array with manialink Ids
*/
public function reserveManialinkIds($count){
return $this->mControl->manialinkIdHandler->reserveManialikIds($count);
return $this->mc->manialinkIdHandler->reserveManialikIds($count);
}
public function checkUpdate(){
}
/**
* Enables the Plugin
*/
public function enablePlugin()
{
$this->active = true;
}
/**
* Disable the Plugin
*/
public function disablePlugin()
{
$this->active = true;
}
/**
* @return mixed
*/
public function isActive()
{
return $this->active;
}
/**
* @param mixed $author
*/

View File

@ -11,6 +11,19 @@ namespace ManiaControl;
class PluginHandler {
/**
* Private properties
*/
private $mc;
private $plugins;
public function __construct($mc){
$this->mControl = $mc;
$this->plugins = array();
}
public function registerPlugin($plugin){
array_push($this->plugins, $plugin);
}
}
?>

View File

@ -1,381 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class providing information and commands for the connected maniaplanet server
*
* @author steeffeen
*/
class Server {
/**
* Constants
*/
const VALIDATIONREPLAYDIR = 'ValidationReplays/';
const GHOSTREPLAYDIR = 'GhostReplays/';
/**
* Public properties
*/
public $config = null;
/**
* Private properties
*/
private $mControl = null;
/**
* Construct server
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('server.ManiaControl.xml');
$this->iControl->checkConfig($this->config, array('host', 'port', 'login', 'pass'), 'server');
// Register for callbacks
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_1_SECOND, $this, 'eachSecond');
}
/**
* Perform actions every second
*/
public function eachSecond() {
// Delete cached information
$this->players = null;
}
/**
* Fetch game directory of the server
*
* @return string
*/
public function getDataDirectory() {
if (!$this->iControl->client->query('GameDataDirectory')) {
trigger_error("Couldn't get data directory. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
/**
* Checks if ManiaControl has access to the given directory (server data directory if no param)
*
* @param string $directory
* @return bool
*/
public function checkAccess($directory = null) {
if (!$directory) {
$directory = $this->getDataDirectory();
}
return is_dir($directory) && is_writable($directory);
}
/**
* Fetch server login
*/
public function getLogin($client = null) {
$systemInfo = $this->getSystemInfo(false, $client);
if (!$systemInfo) return null;
return $systemInfo['ServerLogin'];
}
/**
* Get detailed server info
*/
public function getInfo($detailed = false) {
if ($detailed) {
$login = $this->getLogin();
if (!$this->iControl->client->query('GetDetailedPlayerInfo', $login)) {
trigger_error("Couldn't fetch detailed server player info. " . $this->iControl->getClientErrorText());
return null;
}
}
else {
if (!$this->iControl->client->query('GetMainServerPlayerInfo')) {
trigger_error("Couldn't fetch server player info. " . $this->iControl->getClientErrorText());
return null;
}
}
return $this->iControl->client->getResponse();
}
/**
* Get server options
*/
public function getOptions() {
if (!$this->iControl->client->query('GetServerOptions')) {
trigger_error("Couldn't fetch server options. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
/**
* Fetch server name
*/
public function getName() {
if (!$this->iControl->client->query('GetServerName')) {
trigger_error("Couldn't fetch server name. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
/**
* Fetch server version
*/
public function getVersion($forceRefresh = false) {
if (isset($this->iControl->client->version) && !$forceRefresh) return $this->iControl->client->version;
if (!$this->iControl->client->query('GetVersion')) {
trigger_error("Couldn't fetch server version. " . $this->iControl->getClientErrorText());
return null;
}
else {
$this->iControl->client->version = $this->iControl->client->getResponse();
return $this->iControl->client->version;
}
}
/**
* Fetch server system info
*/
public function getSystemInfo($forceRefresh = false, &$client = null) {
if (!$this->iControl->client && !$client) return null;
if (!$client) $client = $this->iControl->client;
if (isset($client->systemInfo) && !$forceRefresh) return $client->systemInfo;
if (!$client->query('GetSystemInfo')) {
trigger_error("Couldn't fetch server system info. " . $this->iControl->getClientErrorText($client));
return null;
}
else {
$client->systemInfo = $client->getResponse();
return $client->systemInfo;
}
}
/**
* Fetch network status
*/
public function getNetworkStats($forceRefresh = false) {
if (isset($this->iControl->client->networkStats) && !$forceRefresh) return $this->iControl->client->networkStats;
if (!$this->iControl->client->query('GetNetworkStats')) {
trigger_error("Couldn't fetch network stats. " . $this->iControl->getClientErrorText());
return null;
}
else {
$this->iControl->client->networkStats = $this->iControl->client->getResponse();
return $this->iControl->client->networkStats;
}
}
/**
* Fetch current game mode
*
* @param bool $stringValue
* @param int $parseValue
* @return int | string
*/
public function getGameMode($stringValue = false, $parseValue = null) {
if (is_int($parseValue)) {
$gameMode = $parseValue;
}
else {
if (!$this->iControl->client->query('GetGameMode')) {
trigger_error("Couldn't fetch current game mode. " . $this->iControl->getClientErrorText());
return null;
}
$gameMode = $this->iControl->client->getResponse();
}
if ($stringValue) {
switch ($gameMode) {
case 0:
{
return 'Script';
}
case 1:
{
return 'Rounds';
}
case 2:
{
return 'TimeAttack';
}
case 3:
{
return 'Team';
}
case 4:
{
return 'Laps';
}
case 5:
{
return 'Cup';
}
case 6:
{
return 'Stunts';
}
default:
{
return 'Unknown';
}
}
}
return $gameMode;
}
/**
* Fetch player info
*
* @param string $login
* @return struct
*/
public function getPlayer($login, $detailed = false) {
if (!$login) return null;
$command = ($detailed ? 'GetDetailedPlayerInfo' : 'GetPlayerInfo');
if (!$this->iControl->client->query($command, $login)) {
trigger_error("Couldn't player info for '" . $login . "'. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
/**
* Fetch all players
*/
public function getPlayers(&$client = null, &$purePlayers = null, &$pureSpectators = null) {
if (!$this->iControl->client && !$client) return null;
if (!$client) $client = $this->iControl->client;
$fetchLength = 30;
$offset = 0;
$players = array();
if (!is_array($purePlayers)) $purePlayers = array();
if (!is_array($pureSpectators)) $pureSpectators = array();
$tries = 0;
while ($tries < 10) {
if (!$client->query('GetPlayerList', $fetchLength, $offset)) {
trigger_error("Couldn't get player list. " . $this->iControl->getClientErrorText($client));
$tries++;
}
else {
$chunk = $client->getResponse();
$count = count($chunk);
$serverLogin = $this->getLogin($client);
for ($index = 0; $index < $count; $index++) {
$login = $chunk[$index]['Login'];
if ($login === $serverLogin) {
// Ignore server
unset($chunk[$index]);
}
else {
if ($chunk[$index]['SpectatorStatus'] > 0) {
// Pure spectator
array_push($pureSpectators, $chunk[$index]);
}
else {
// Pure player
array_push($purePlayers, $chunk[$index]);
}
}
}
$players = array_merge($players, $chunk);
$offset += $count;
if ($count < $fetchLength) break;
}
}
return $players;
}
/**
* Retrieve validation replay for given login
*
* @param string $login
* @return string
*/
public function getValidationReplay($login) {
if (!$login) return null;
if (!$this->iControl->client->query('GetValidationReplay', $login)) {
trigger_error("Couldn't get validation replay of '" . $login . "'. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
public function getGhostReplay($login) {
$dataDir = $this->getDataDirectory();
if (!$this->checkAccess($dataDir)) {
return null;
}
// Build file name
$map = $this->getMap();
$gameMode = $this->getGameMode();
$time = time();
$fileName = 'Ghost.' . $login . '.' . $gameMode . '.' . $time . '.' . $map['UId'] . '.Replay.Gbx';
// Save ghost replay
if (!$this->iControl->client->query('SaveBestGhostsReplay', $login, self::GHOSTREPLAYDIR . $fileName)) {
trigger_error("Couldn't save ghost replay. " . $this->iControl->getClientErrorText());
return null;
}
// Load replay file
$ghostReplay = file_get_contents($dataDir . 'Replays/' . self::GHOSTREPLAYDIR . $fileName);
if (!$ghostReplay) {
trigger_error("Couldn't retrieve saved ghost replay.");
return null;
}
return $ghostReplay;
}
/**
* Fetch current map
*/
public function getMap() {
if (!$this->iControl->client) return null;
if (!$this->iControl->client->query('GetCurrentMapInfo')) {
trigger_error("Couldn't fetch map info. " . $this->iControl->getClientErrorText());
return null;
}
return $this->iControl->client->getResponse();
}
/**
* Waits for the server to have the given status
*/
public function waitForStatus($client, $statusCode = 4) {
$client->query('GetStatus');
$response = $client->getResponse();
// Check if server reached given status
if ($response['Code'] === 4) return true;
// Server not yet in given status -> Wait for it...
$waitBegin = time();
$timeoutTags = $this->iControl->config->xpath('timeout');
$maxWaitTime = (!empty($timeoutTags) ? (int) $timeoutTags[0] : 20);
$lastStatus = $response['Name'];
error_log("Waiting for server to reach status " . $statusCode . "...");
error_log("Current Status: " . $lastStatus);
while ($response['Code'] !== 4) {
sleep(1);
$client->query('GetStatus');
$response = $client->getResponse();
if ($lastStatus !== $response['Name']) {
error_log("New Status: " . $response['Name']);
$lastStatus = $response['Name'];
}
if (time() - $maxWaitTime > $waitBegin) {
// It took too long to reach the status
trigger_error(
"Server couldn't reach status " . $statusCode . " after " . $maxWaitTime . " seconds! " .
$this->iControl->getClientErrorText());
return false;
}
}
return true;
}
}
?>

View File

@ -1,297 +0,0 @@
<?php
namespace ManiaControl;
/**
* Stats class
*
* @author steeffeen
*/
class Stats {
/**
* Constants
*/
const TABLE_STATS_SERVER = 'ic_stats_server';
const TABLE_STATS_PLAYERS = 'ic_stats_players';
/**
* Private properties
*/
private $mControl = null;
private $config = null;
/**
* Constuct stats manager
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('stats.ManiaControl.xml');
$this->loadSettings();
// Init database tables
$this->initTables();
// Register for needed callbacks
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_ENDMAP, $this, 'handleEndMap');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCHAT, $this, 'handlePlayerChat');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnect');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERDISCONNECT, $this, 'handlePlayerDisconnect');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_TM_PLAYERFINISH, $this, 'handlePlayerFinish');
}
/**
* Create the database tables
*/
private function initTables() {
$query = "";
// Server stats
$query .= "CREATE TABLE IF NOT EXISTS `" . self::TABLE_STATS_SERVER . "` (
`index` int(11) NOT NULL AUTO_INCREMENT,
`day` date NOT NULL,
`connectCount` int(11) NOT NULL DEFAULT '0',
`maxPlayerCount` int(11) NOT NULL DEFAULT '0',
`playedMaps` int(11) NOT NULL DEFAULT '0',
`finishCount` int(11) NOT NULL DEFAULT '0',
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`index`),
UNIQUE KEY `day` (`day`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Stores server stats' AUTO_INCREMENT=1;";
// Player stats
$query .= "CREATE TABLE IF NOT EXISTS `" . self::TABLE_STATS_PLAYERS . "` (
`index` int(11) NOT NULL AUTO_INCREMENT,
`Login` varchar(100) NOT NULL,
`playTime` int(11) NOT NULL DEFAULT '0',
`connectCount` int(11) NOT NULL DEFAULT '0',
`chatCount` int(11) NOT NULL DEFAULT '0',
`finishCount` int(11) NOT NULL DEFAULT '0',
`hitCount` int(11) NOT NULL DEFAULT '0',
`eliminationCount` int(11) NOT NULL DEFAULT '0',
`lastJoin` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00',
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`index`),
UNIQUE KEY `Login` (`Login`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Tracks player stats' AUTO_INCREMENT=1;";
// Perform queries
if (!$this->iControl->database->multiQuery($query)) {
trigger_error("Creating stats tables failed.");
}
}
/**
* Load settings from config
*/
private function loadSettings() {
$this->settings = new \stdClass();
$this->settings->track_server_connects = Tools::checkSetting($this->config, 'track_server_connects');
$this->settings->track_server_max_players = Tools::checkSetting($this->config, 'track_server_max_players');
$this->settings->track_server_played_maps = Tools::checkSetting($this->config, 'track_server_played_maps');
$this->settings->track_server_finishes = Tools::checkSetting($this->config, 'track_server_finishes');
$this->settings->track_player_connects = Tools::checkSetting($this->config, 'track_player_connects');
$this->settings->track_player_playtime = Tools::checkSetting($this->config, 'track_player_playtime');
$this->settings->track_player_chats = Tools::checkSetting($this->config, 'track_player_chats');
$this->settings->track_player_finishes = Tools::checkSetting($this->config, 'track_player_finishes');
}
/**
* Handle EndMap callback
*/
public function handleEndMap($callback) {
$multiquery = "";
// Track played server maps
if ($this->settings->track_server_played_maps) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_SERVER . "` (
`day`,
`playedMaps`
) VALUES (
CURDATE(),
1
) ON DUPLICATE KEY UPDATE
`playedMaps` = `playedMaps` + VALUES(`playedMaps`)
;";
}
// Perform query
if (!$this->iControl->database->multiQuery($multiquery)) {
trigger_error("Perform queries on end map failed.");
}
}
/**
* Handle PlayerChat callback
*/
public function handlePlayerChat($callback) {
if ($callback[1][0] <= 0) return;
$multiquery = "";
$login = $callback[1][1];
// Track chats
if ($this->settings->track_player_chats) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_PLAYERS . "` (
`Login`,
`chatCount`
) VALUES (
'" . $this->iControl->database->escape($login) . "',
1
) ON DUPLICATE KEY UPDATE
`chatCount` = `chatCount` + VALUES(`chatCount`)
;";
}
// Perform query
if (!$this->iControl->database->multiQuery($multiquery)) {
trigger_error("Perform queries on player chat failed.");
}
}
/**
* Handle PlayerConnect callback
*/
public function handlePlayerConnect($callback) {
$multiquery = "";
$login = $callback[1][0];
// Track server connect
if ($this->settings->track_server_connects) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_SERVER . "` (
`day`,
`connectCount`
) VALUES (
CURDATE(),
1
) ON DUPLICATE KEY UPDATE
`connectCount` = `connectCount` + VALUES(`connectCount`)
;";
}
// Track server max players
if ($this->settings->track_server_max_players) {
$players = $this->iControl->server->getPlayers();
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_SERVER . "` (
`day`,
`maxPlayerCount`
) VALUES (
CURDATE(),
" . count($players) . "
) ON DUPLICATE KEY UPDATE
`maxPlayerCount` = GREATEST(`maxPlayerCount`, VALUES(`maxPlayerCount`))
;";
}
// Track player connect
if ($this->settings->track_player_connects) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_PLAYERS . "` (
`Login`,
`lastJoin`,
`connectCount`
) VALUES (
'" . $this->iControl->database->escape($login) . "',
NOW(),
1
) ON DUPLICATE KEY UPDATE
`lastJoin` = VALUES(`lastJoin`),
`connectCount` = `connectCount` + VALUES(`connectCount`)
;";
}
// Perform query
if (!$this->iControl->database->multiQuery($multiquery)) {
trigger_error("Perform queries on player connect failed.");
}
}
/**
* Handle PlayerDisconnect callback
*/
public function handlePlayerDisconnect($callback) {
$multiquery = "";
$login = $callback[1][0];
// Track player playtime
if ($this->settings->track_player_playtime) {
$query = "SELECT `lastJoin` FROM `" . self::TABLE_STATS_PLAYERS . "`
WHERE `Login` = '" . $this->iControl->database->escape($login) . "'
;";
$result = $this->iControl->database->query($query);
if (!$result) {
// Error
trigger_error("Error selecting player join time from '" . $login . "'.");
}
else {
// Add play time
while ($row = $result->fetch_object()) {
if (!property_exists($row, 'lastJoin')) continue;
$lastJoin = strtotime($row->lastJoin);
$lastJoin = ($lastJoin > $this->iControl->startTime ? $lastJoin : $this->iControl->startTime);
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_PLAYERS . "` (
`Login`,
`playTime`
) VALUES (
'" . $this->iControl->database->escape($login) . "',
TIMESTAMPDIFF(SECOND, '" . Tools::timeToTimestamp($lastJoin) . "', NOW())
) ON DUPLICATE KEY UPDATE
`playTime` = `playTime` + VALUES(`playTime`)
;";
break;
}
}
}
// Perform query
if (!$this->iControl->database->multiQuery($multiquery)) {
trigger_error("Perform queries on player connect failed.");
}
}
/**
* Handle the PlayerFinish callback
*/
public function handlePlayerFinish($callback) {
if ($callback[1][0] <= 0) return;
if ($callback[1][2] <= 0) return;
$multiquery = "";
$login = $callback[1][1];
// Track server finishes
if ($this->settings->track_server_finishes) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_SERVER . "` (
`day`,
`finishCount`
) VALUES (
CURDATE(),
1
) ON DUPLICATE KEY UPDATE
`finishCount` = `finishCount` + VALUES(`finishCount`)
;";
}
// Track player finishes
if ($this->settings->track_player_finishes) {
$multiquery .= "INSERT INTO `" . self::TABLE_STATS_PLAYERS . "` (
`Login`,
`finishCount`
) VALUES (
'" . $this->iControl->database->escape($login) . "',
1
) ON DUPLICATE KEY UPDATE
`finishCount` = `finishCount` + VALUES(`finishCount`)
;";
}
// Perform query
if (!$this->iControl->database->multiQuery($multiquery)) {
trigger_error("Perform queries on player finish failed.");
}
}
}
?>

View File

@ -1,240 +0,0 @@
<?php
namespace ManiaControl;
/**
* Class for basic tools
*
* @author steeffeen
*/
class Tools {
/**
* Check if the given setting is enabled
*
* @param simple_xml_element $config
* @param string $setting
*/
public static function checkSetting($config, $setting) {
$settings = $config->xpath('//' . $setting);
if (empty($settings)) {
return false;
}
else {
foreach ($settings as $setting) {
return self::toBool((string) $setting[0]);
}
}
}
/**
* Check if the given data describes a player
*
* @param array $player
* @return bool
*/
public static function isPlayer($player) {
if (!$player || !is_array($player)) return false;
if (!array_key_exists('PlayerId', $player) || !is_int($player['PlayerId']) || $player['PlayerId'] <= 0) return false;
return true;
}
/**
* Convert the given time int to mysql timestamp
*
* @param int $time
* @return string
*/
public static function timeToTimestamp($time) {
return date("Y-m-d H:i:s", $time);
}
/**
* Add alignment attributes to an xml element
*
* @param simple_xml_element $xml
* @param string $halign
* @param string $valign
*/
public static function addAlignment($xml, $halign = 'center', $valign = 'center2') {
if (!is_object($xml) || !method_exists($xml, 'addAttribute')) return;
if (!property_exists($xml, 'halign')) $xml->addAttribute('halign', $halign);
if (!property_exists($xml, 'valign')) $xml->addAttribute('valign', $valign);
}
/**
* Add translate attribute to an xml element
*
* @param simple_xml_element $xml
* @param bool $translate
*/
public static function addTranslate($xml, $translate = true) {
if (!is_object($xml) || !method_exists($xml, 'addAttribute')) return;
if (!property_exists($xml, 'translate')) $xml->addAttribute('translate', ($translate ? 1 : 0));
}
/**
* Load a remote file
*
* @param string $url
* @return string || null
*/
public static function loadFile($url) {
if (!$url) return false;
$urlData = parse_url($url);
$port = (isset($urlData['port']) ? $urlData['port'] : 80);
$fsock = fsockopen($urlData['host'], $port);
stream_set_timeout($fsock, 3);
$query = 'GET ' . $urlData['path'] . ' HTTP/1.0' . PHP_EOL;
$query .= 'Host: ' . $urlData['host'] . PHP_EOL;
$query .= 'Content-Type: UTF-8' . PHP_EOL;
$query .= 'User-Agent: ManiaControl v' . ManiaControl::VERSION . PHP_EOL;
$query .= PHP_EOL;
fwrite($fsock, $query);
$buffer = '';
$info = array('timed_out' => false);
while (!feof($fsock) && !$info['timed_out']) {
$buffer .= fread($fsock, 1024);
$info = stream_get_meta_data($fsock);
}
fclose($fsock);
if ($info['timed_out'] || !$buffer) {
return null;
}
if (substr($buffer, 9, 3) != "200") {
return null;
}
$result = explode("\r\n\r\n", $buffer, 2);
if (count($result) < 2) {
return null;
}
return $result[1];
}
/**
* Formats the given time (milliseconds)
*
* @param int $time
* @return string
*/
public static function formatTime($time) {
if (!is_int($time)) $time = (int) $time;
$milliseconds = $time % 1000;
$seconds = floor($time / 1000);
$minutes = floor($seconds / 60);
$hours = floor($minutes / 60);
$minutes -= $hours * 60;
$seconds -= $hours * 60 + $minutes * 60;
$format = ($hours > 0 ? $hours . ':' : '');
$format .= ($hours > 0 && $minutes < 10 ? '0' : '') . $minutes . ':';
$format .= ($seconds < 10 ? '0' : '') . $seconds . ':';
$format .= ($milliseconds < 100 ? '0' : '') . ($milliseconds < 10 ? '0' : '') . $milliseconds;
return $format;
}
/**
* Convert given data to real boolean
*
* @param
* mixed data
*/
public static function toBool($var) {
if ($var === true) return true;
if ($var === false) return false;
if ($var === null) return false;
if (is_object($var)) {
$var = (string) $var;
}
if (is_int($var)) {
return ($var > 0);
}
else if (is_string($var)) {
$text = strtolower($var);
if ($text === 'true' || $text === 'yes') {
return true;
}
else if ($text === 'false' || $text === 'no') {
return false;
}
else {
return ((int) $text > 0);
}
}
else {
return (bool) $var;
}
}
/**
* Converts the given boolean to an int representation
*
* @param bool $bool
* @return int
*/
public static function boolToInt($bool) {
return ($bool ? 1 : 0);
}
/**
* Build new simple xml element
*
* @param string $name
* @param string $id
* @return \SimpleXMLElement
*/
public static function newManialinkXml($id = null) {
$xml = new \SimpleXMLElement('<?xml version="1.0" encoding="UTF-8" standalone="yes"?><manialink/>');
$xml->addAttribute('version', '1');
if ($id) $xml->addAttribute('id', $id);
return $xml;
}
/**
* Load config xml-file
*
* @param string $fileName
* @return \SimpleXMLElement
*/
public static function loadConfig($fileName) {
// Load config file from configs folder
$fileLocation = ManiaControlDir . '/configs/' . $fileName;
if (!file_exists($fileLocation)) {
trigger_error("Config file doesn't exist! (" . $fileName . ")", E_USER_ERROR);
}
return simplexml_load_file($fileLocation);
}
/**
* Send the given manialink to players
*
* @param string $manialink
* @param array $logins
*/
public static function sendManialinkPage($client, $manialink, $logins = null, $timeout = 0, $hideOnClick = false) {
if (!$client || !$manialink) return;
if (!$logins) {
// Send manialink to all players
$client->query('SendDisplayManialinkPage', $manialink, $timeout, $hideOnClick);
}
else if (is_array($logins)) {
// Send manialink to players
foreach ($logins as $login) {
$client->query('SendDisplayManialinkPageToLogin', $login, $manialink, $timeout, $hideOnClick);
}
}
else if (is_string($logins)) {
// Send manialink to player
$client->query('SendDisplayManialinkPageToLogin', $logins, $manialink, $timeout, $hideOnClick);
}
}
}
?>

View File

@ -1,85 +0,0 @@
<?php
namespace ManiaControl;
/**
* ManiaControl Chatlog Plugin
*
* @author steeffeen
*/
class Plugin_Chatlog extends Plugin{
/**
* Constants
*/
const VERSION = '1.0';
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $settings = null;
/**
* Constuct chatlog plugin
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('chatlog.plugin.xml');
// Check for enabled setting
if (!Tools::toBool($this->config->enabled)) return;
// Load settings
$this->loadSettings();
// Register for callbacksc
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCHAT, $this, 'handlePlayerChatCallback');
error_log('Chatlog Pugin v' . self::VERSION . ' ready!');
}
/**
* Load settings from config
*/
private function loadSettings() {
$this->settings = new \stdClass();
// File name
$fileName = (string) $this->config->filename;
$this->settings->fileName = ManiaControlDir . '/' . $fileName;
// log_server_messages
$log_server_messages = $this->config->xpath('log_server_messages');
$this->settings->log_server_messages = ($log_server_messages ? (Tools::toBool($log_server_messages[0])) : false);
}
/**
* Handle PlayerChat callback
*/
public function handlePlayerChatCallback($callback) {
$data = $callback[1];
if ($data[0] <= 0 && !$this->settings->log_server_messages) {
// Skip server message
return;
}
$this->logText($data[2], $data[1]);
}
/**
* Log the given message
*
* @param string $message
* @param string $login
*/
private function logText($text, $login = null) {
$message = date(ManiaControl::DATE) . '>> ' . ($login ? $login . ': ' : '') . $text . PHP_EOL;
file_put_contents($this->settings->fileName, $message, FILE_APPEND);
}
}
?>

View File

@ -1,305 +0,0 @@
<?php
namespace ManiaControl;
/**
* ManiaControl Karma Plugin
*
* @author : steeffeen
*/
class Plugin_Karma {
/**
* Constants
*/
const VERSION = '1.0';
const MLID_KARMA = 'KarmaPlugin.MLID';
const TABLE_KARMA = 'ic_karma';
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $sendManialinkRequested = -1;
/**
* Construct plugin
*
* @param object $mControl
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('karma.plugin.xml');
if (!Tools::toBool($this->config->enabled)) return;
// Init database
$this->initDatabase();
// Register for callbacks
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInitCallback');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_BEGINMAP, $this, 'handleBeginMapCallback');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnectCallback');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERMANIALINKPAGEANSWER, $this,
'handleManialinkPageAnswerCallback');
error_log('Karma Pugin v' . self::VERSION . ' ready!');
}
/**
* Repetitive actions
*/
public function loop() {
if ($this->sendManialinkRequested > 0 && $this->sendManialinkRequested <= time()) {
$this->sendManialinkRequested = -1;
// Send manialink to all players
$players = $this->iControl->server->getPlayers();
foreach ($players as $player) {
$login = $player['Login'];
$manialink = $this->buildManialink($login);
if (!$manialink) {
// Skip and retry
$this->sendManialinkRequested = time() + 5;
continue;
}
Tools::sendManialinkPage($this->iControl->client, $manialink->asXml(), $login);
}
}
}
/**
* Handle OnInit ManiaControl callback
*
* @param array $callback
*/
public function handleOnInitCallback($callback) {
// Send manialink to all players once
$this->sendManialinkRequested = time() + 3;
}
/**
* Handle ManiaControl BeginMap callback
*
* @param array $callback
*/
public function handleBeginMapCallback($callback) {
// Send manialink to all players once
$this->sendManialinkRequested = time() + 2;
}
/**
* Handle PlayerConnect callback
*
* @param array $callback
*/
public function handlePlayerConnectCallback($callback) {
$login = $callback[1][0];
$manialink = $this->buildManialink($login);
if (!$manialink) return;
Tools::sendManialinkPage($this->iControl->client, $manialink->asXml(), $login);
}
/**
* Create necessary tables
*/
private function initDatabase() {
$query = "CREATE TABLE IF NOT EXISTS `" . self::TABLE_KARMA . "` (
`index` int(11) NOT NULL AUTO_INCREMENT,
`mapIndex` int(11) NOT NULL,
`playerIndex` int(11) NOT NULL,
`vote` tinyint(1) NOT NULL,
`changed` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
PRIMARY KEY (`index`),
UNIQUE KEY `player_map_vote` (`mapIndex`, `playerIndex`)
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COMMENT='Save players map votes' AUTO_INCREMENT=1;";
$result = $this->iControl->database->query($query);
if ($this->iControl->database->mysqli->error) {
trigger_error('MySQL Error on creating karma table. ' . $this->iControl->database->mysqli->error, E_USER_ERROR);
}
}
/**
* Handle ManialinkPageAnswer callback
*
* @param array $callback
*/
public function handleManialinkPageAnswerCallback($callback) {
$action = $callback[1][2];
if (substr($action, 0, strlen(self::MLID_KARMA)) !== self::MLID_KARMA) return;
// Get vote
$action = substr($action, -4);
$vote = null;
switch ($action) {
case '.pos':
{
$vote = 1;
break;
}
case '.neu':
{
$vote = 0;
break;
}
case '.neg':
{
$vote = -1;
break;
}
default:
{
return;
}
}
// Save vote
$login = $callback[1][1];
$playerIndex = $this->iControl->database->getPlayerIndex($login);
$map = $this->iControl->server->getMap();
$mapIndex = $this->iControl->database->getMapIndex($map['UId']);
$query = "INSERT INTO `" . self::TABLE_KARMA . "` (
`mapIndex`,
`playerIndex`,
`vote`
) VALUES (
" . $mapIndex . ",
" . $playerIndex . ",
" . $vote . "
) ON DUPLICATE KEY UPDATE
`vote` = VALUES(`vote`);";
$result = $this->iControl->database->query($query);
if (!$result) return;
// Send success message
$this->iControl->chat->sendSuccess('Vote successfully updated!', $login);
// Send updated manialink
$this->sendManialinkRequested = time() + 1;
}
/**
* Build karma voting manialink xml for the given login
*/
private function buildManialink($login) {
// Get config
$title = (string) $this->config->title;
$pos_x = (float) $this->config->pos_x;
$pos_y = (float) $this->config->pos_y;
$mysqli = $this->iControl->database->mysqli;
// Get indezes
$playerIndex = $this->iControl->database->getPlayerIndex($login);
if ($playerIndex === null) return null;
$map = $this->iControl->server->getMap();
if (!$map) return null;
$mapIndex = $this->iControl->database->getMapIndex($map['UId']);
if ($mapIndex === null) return null;
// Get votings
$query = "SELECT
(SELECT `vote` FROM `" .
self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `playerIndex` = " . $playerIndex . ") as `playerVote`,
(SELECT COUNT(`vote`) FROM `" .
self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = 1) AS `positiveVotes`,
(SELECT COUNT(`vote`) FROM `" .
self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = 0) AS `neutralVotes`,
(SELECT COUNT(`vote`) FROM `" .
self::TABLE_KARMA . "` WHERE `mapIndex` = " . $mapIndex . " AND `vote` = -1) AS `negativeVotes`
FROM `" . self::TABLE_KARMA . "`;";
$result = $mysqli->query($query);
if ($mysqli->error) {
trigger_error('MySQL ERROR: ' . $mysqli->error);
}
$votes = $result->fetch_assoc();
if (!$votes) {
$votes = array('playerVote' => null, 'positiveVotes' => 0, 'neutralVotes' => 0, 'negativeVotes' => 0);
}
// Build manialink
$xml = Tools::newManialinkXml(self::MLID_KARMA);
$frameXml = $xml->addChild('frame');
$frameXml->addAttribute('posn', $pos_x . ' ' . $pos_y);
// Title
$labelXml = $frameXml->addChild('label');
Tools::addAlignment($labelXml);
$labelXml->addAttribute('posn', '0 4.5 -1');
$labelXml->addAttribute('sizen', '22 0');
$labelXml->addAttribute('style', 'TextTitle1');
$labelXml->addAttribute('textsize', '1');
$labelXml->addAttribute('text', $title);
// Background
$quadXml = $frameXml->addChild('quad');
Tools::addAlignment($quadXml);
$quadXml->addAttribute('sizen', '23 15 -2');
$quadXml->addAttribute('style', 'Bgs1InRace');
$quadXml->addAttribute('substyle', 'BgTitleShadow');
// Votes
for ($i = 1; $i >= -1; $i--) {
$x = $i * 7.;
// Vote button
$quadXml = $frameXml->addChild('quad');
Tools::addAlignment($quadXml);
$quadXml->addAttribute('posn', $x . ' 0 0');
$quadXml->addAttribute('sizen', '6 6');
$quadXml->addAttribute('style', 'Icons64x64_1');
// Vote count
$labelXml = $frameXml->addChild('label');
Tools::addAlignment($labelXml);
$labelXml->addAttribute('posn', $x . ' -4.5 0');
$labelXml->addAttribute('style', 'TextTitle1');
$labelXml->addAttribute('textsize', '2');
if ((string) $i === $votes['playerVote']) {
// Player vote X
$voteQuadXml = $frameXml->addChild('quad');
Tools::addAlignment($voteQuadXml);
$voteQuadXml->addAttribute('posn', $x . ' 0 1');
$voteQuadXml->addAttribute('sizen', '6 6');
$voteQuadXml->addAttribute('style', 'Icons64x64_1');
$voteQuadXml->addAttribute('substyle', 'Close');
}
switch ($i) {
case 1:
{
// Positive
$quadXml->addAttribute('substyle', 'LvlGreen');
$quadXml->addAttribute('action', self::MLID_KARMA . '.pos');
$labelXml->addAttribute('text', $votes['positiveVotes']);
break;
}
case 0:
{
// Neutral
$quadXml->addAttribute('substyle', 'LvlYellow');
$quadXml->addAttribute('action', self::MLID_KARMA . '.neu');
$labelXml->addAttribute('text', $votes['neutralVotes']);
break;
}
case -1:
{
// Negative
$quadXml->addAttribute('substyle', 'LvlRed');
$quadXml->addAttribute('action', self::MLID_KARMA . '.neg');
$labelXml->addAttribute('text', $votes['negativeVotes']);
break;
}
}
}
return $xml;
}
}
?>

View File

@ -1,63 +0,0 @@
<?php
namespace ManiaControl;
/**
* ManiaControl Obstacle Plugin
*
* @author steeffeen
*/
class Plugin_Obstacle extends Plugin {
/**
* Constants
*/
const CB_JUMPTO = 'Obstacle.JumpTo';
const VERSION = '1.0';
/**
* Private properties
*/
private $mControl = null;
private $config = null;
/**
* Constuct obstacle plugin
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('obstacle.plugin.xml');
// Check for enabled setting
if (!Tools::toBool($this->config->enabled)) return;
// Register for jump command
$this->iControl->commands->registerCommandHandler('jumpto', $this, 'command_jumpto');
error_log('Obstacle Pugin v' . self::VERSION . ' ready!');
}
/**
* Handle jumpto command
*/
public function command_jumpto($chat) {
$login = $chat[1][1];
$rightLevel = (string) $this->config->jumps_rightlevel;
if (!$this->iControl->authentication->checkRight($login, $rightLevel)) {
// Not allowed
$this->iControl->authentication->sendNotAllowed($login);
}
else {
// Send jump callback
$params = explode(' ', $chat[1][2], 2);
$param = $login . ";" . $params[1] . ";";
if (!$this->iControl->client->query('TriggerModeScriptEvent', self::CB_JUMPTO, $param)) {
trigger_error("Couldn't send jump callback for '" . $login . "'. " . $this->iControl->getClientErrorText());
}
}
}
}
?>

View File

@ -1,37 +0,0 @@
<?php
namespace ManiaControl;
/**
* Abstract ManiaControl plugin class
*/
abstract class Plugin_Name {
/**
* Constants
*/
const VERSION = '0.1';
/**
* Private properties
*/
private $mControl = null;
/**
* Construct plugin
*
* @param object $mControl
*/
public function __construct($mControl) {
$this->mControl = $mControl;
error_log('Pugin v' . self::VERSION . ' ready!');
}
/**
* Perform actions during each loop
*/
public function loop() {
}
}
?>

File diff suppressed because it is too large Load Diff

View File

@ -1,677 +0,0 @@
<?php
namespace ManiaControl;
// TODO: Jump message "now playing stadium"
// TODO: put inactive server in idle (keeping same map)
// TODO: let next server wait for the first player
// TODO: check compatibility with other modes (laps, ...)
// TODO: max players setting
/**
* ManiaControl United Plugin
*
* @author steeffeen
*/
class Plugin_United {
/**
* Constants
*/
const VERSION = '1.0';
const ML_ADDFAVORITE = 'MLID_UnitedPlugin.AddFavorite';
/**
* Private properties
*/
private $mControl = null;
private $config = null;
private $settings = null;
private $gameServer = array();
private $lobbies = array();
private $currentClientIndex = 0;
private $lastStatusCheck = 0;
private $finishedBegin = -1;
private $switchServerRequested = -1;
private $manialinks = array();
/**
* Constuct plugin
*/
public function __construct($mControl) {
$this->mControl = $mControl;
// Load config
$this->config = Tools::loadConfig('united.plugin.xml');
$this->loadSettings();
// Check for enabled setting
if (!$this->settings->enabled) return;
// Load clients
$this->loadClients();
// Register for callbacks
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_ONINIT, $this, 'handleOnInitCallback');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_IC_5_SECOND, $this, 'handle5Seconds');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERCONNECT, $this, 'handlePlayerConnect');
$this->iControl->callbacks->registerCallbackHandler(Callbacks::CB_MP_PLAYERMANIALINKPAGEANSWER, $this,
'handleManialinkPageAnswer');
// Register for commands
$this->iControl->commands->registerCommandHandler('nextserver', $this, 'handleNextServerCommand');
if ($this->settings->widgets_enabled) {
// Build addfavorite manialink
$this->buildFavoriteManialink();
}
error_log('United Pugin v' . self::VERSION . ' ready!');
}
/**
* Handle ManiaControl OnInit callback
*
* @param array $callback
*/
public function handleOnInitCallback($callback) {
if ($this->settings->widgets_enabled) {
// Send widgets to all players
if (Tools::toBool($this->config->widgets->addfavorite->enabled)) {
// Send favorite widget
if (!$this->iControl->client->query('SendDisplayManialinkPage', $this->manialinks[self::ML_ADDFAVORITE]->asXml(), 0,
false)) {
trigger_error("Couldn't send favorite widget! " . $this->iControl->getClientErrorText());
}
}
}
}
/**
* Load settings from config
*/
private function loadSettings() {
$this->settings = new \stdClass();
// Enabled
$this->settings->enabled = Tools::toBool($this->config->enabled);
// Timeout
$timeout = $this->iControl->server->config->xpath('timeout');
if ($timeout) {
$this->settings->timeout = (int) $timeout[0];
}
else {
$this->settings->timeout = 30;
}
// Game mode
$mode = $this->config->xpath('mode');
if ($mode) {
$mode = (int) $mode[0];
if ($mode < 1 || $mode > 6) {
$this->settings->gamemode = 2;
}
else {
$this->settings->gamemode = $mode;
}
}
// Server status
$hide_game_server = $this->config->xpath('hide_game_server');
if ($hide_game_server) {
$this->settings->hide_game_server = Tools::toBool($hide_game_server[0]);
}
else {
$this->settings->hide_game_server = true;
}
// Passwords
$lobbyPassword = $this->config->xpath('lobbies/password');
if ($lobbyPassword) {
$this->settings->lobbyPassword = (string) $lobbyPassword[0];
}
else {
$this->settings->lobbyPassword = '';
}
$gamePassword = $this->config->xpath('gameserver/password');
if ($gamePassword) {
$this->settings->gamePassword = (string) $gamePassword[0];
}
else {
$this->settings->gamePassword = '';
}
// Widgets
$this->settings->widgets_enabled = Tools::toBool($this->config->widgets->enabled);
}
/**
* Loop events on clients
*/
public function loop() {
if (!$this->settings->enabled) return;
// Check callbacks all clients
$clients = array_merge($this->gameServer, $this->lobbies);
$currentServer = $this->gameServer[$this->currentClientIndex];
foreach ($clients as $index => $client) {
$client->resetError();
$client->readCB();
$callbacks = $client->getCBResponses();
if (!is_array($callbacks) || $client->isError()) {
trigger_error("Error reading server callbacks! " . $this->iControl->getClientErrorText($client));
}
else {
if ($client == $currentServer) {
// Currently active game server
foreach ($callbacks as $index => $callback) {
$callbackName = $callback[0];
switch ($callbackName) {
case Callbacks::CB_MP_ENDMAP:
{
$this->switchToNextServer(false);
break;
}
}
}
if ($this->lastStatusCheck + 2 > time()) continue;
$this->lastStatusCheck = time();
if (!$client->query('CheckEndMatchCondition')) {
trigger_error("Couldn't get game server status. " . $this->iControl->getClientErrorText($client));
}
else {
$response = $client->getResponse();
switch ($response) {
case 'Finished':
{
if ($this->finishedBegin < 0) {
$this->finishedBegin = time();
}
else if ($this->finishedBegin + 13 <= time()) {
$this->switchToNextServer(true);
}
break;
}
default:
{
$this->finishedBegin = -1;
break;
}
}
}
}
else {
// Lobby or inactive game server -> Redirect players
foreach ($callbacks as $callback) {
switch ($callback[0]) {
case Callbacks::CB_MP_PLAYERCONNECT:
{
$this->playerJoinedLobby($client, $callback);
break;
}
}
}
}
}
}
// Check for switch server request
if ($this->switchServerRequested > 0 && $this->switchServerRequested <= time()) {
$this->switchServerRequested = -1;
// Switch server
$this->switchToNextServer(true);
}
}
/**
* Handle 5 seconds callback
*/
public function handle5Seconds($callback = null) {
// Update lobby infos
$players = $this->iControl->server->getPlayers();
if (is_array($players)) {
$playerCount = count($players);
$playerLevel = 0.;
if ($playerCount > 0) {
foreach ($players as $player) {
$playerLevel += $player['LadderRanking'];
}
$playerLevel /= $playerCount;
}
foreach ($this->lobbies as $lobby) {
if (!$lobby->query('SetLobbyInfo', true, $playerCount, 255, $playerLevel)) {
trigger_error("Couldn't update lobby info. " . $this->iControl->getClientErrorText($lobby));
}
}
}
// Check for not-redirected players
$clients = array_merge($this->gameServer, $this->lobbies);
$joinLink = $this->getJoinLink();
foreach ($clients as $client) {
if ($client == $this->gameServer[$this->currentClientIndex]) continue;
$players = $this->iControl->server->getPlayers($client);
if (!is_array($players)) continue;
foreach ($players as $player) {
$login = $player['Login'];
if (!$client->query('SendOpenLinkToLogin', $login, $joinLink, 1)) {
trigger_error(
"Couldn't redirect player '" . $login . "' to active game server. " .
$this->iControl->getClientErrorText($client));
}
}
}
}
/**
* Handle player manialink page answer callback
*/
public function handleManialinkPageAnswer($callback) {
$login = $callback[1][1];
$action = $callback[1][2];
switch ($action) {
case self::ML_ADDFAVORITE:
{
// Open manialink to add server logins to favorite
$serverLogins = array();
$add_all = Tools::toBool($this->config->widgets->addfavorite->add_all);
if ($add_all) {
// Add all server
foreach ($this->gameServer as $serverClient) {
array_push($serverLogins, $this->iControl->server->getLogin($serverClient));
}
foreach ($this->lobbies as $serverClient) {
array_push($serverLogins, $this->iControl->server->getLogin($serverClient));
}
}
else {
// Add only current server
array_push($serverLogins, $this->iControl->server->getLogin());
}
// Build manialink url
$manialink = 'iControl?favorite';
foreach ($serverLogins as $serverLogin) {
$manialink .= '&' . $serverLogin;
}
// Send url to player
if (!$this->iControl->client->query('SendOpenLinkToLogin', $login, $manialink, 1)) {
trigger_error(
"Couldn't open manialink to add server to favorite for '" . $login . "'! " .
$this->iControl->getClientErrorText());
}
break;
}
}
}
/**
* Switch to the next server
*
* @param bool $simulateMapEnd
* Simulate end of the map by sending callbacks
*/
private function switchToNextServer($simulateMapEnd) {
$this->finishedBegin = -1;
$oldClient = $this->gameServer[$this->currentClientIndex];
$random_order = Tools::toBool($this->config->random_order);
if ($random_order) {
// Random next server
$this->currentClientIndex = rand(0, count($this->gameServer) - 1);
}
else {
// Next server in list
$this->currentClientIndex++;
}
if ($this->currentClientIndex >= count($this->gameServer)) $this->currentClientIndex = 0;
$newClient = $this->gameServer[$this->currentClientIndex];
if ($newClient == $oldClient) return;
// Restart map on next game server
if (!$newClient->query('RestartMap')) {
trigger_error("Couldn't restart map on next game server. " . $this->iControl->getClientErrorText($newClient));
}
if ($simulateMapEnd) {
// Simulate EndMap on old client
$this->iControl->callbacks->triggerCallback(Callbacks::CB_IC_ENDMAP, array(Callbacks::CB_IC_ENDMAP));
}
// Transfer players to next server
$joinLink = $this->getJoinLink($newClient);
if (!$oldClient->query('GetPlayerList', 255, 0)) {
trigger_error("Couldn't get player list. " . $this->iControl->getClientErrorText($oldClient));
}
else {
$playerList = $oldClient->getResponse();
foreach ($playerList as $player) {
$login = $player['Login'];
if (!$oldClient->query('SendOpenLinkToLogin', $login, $joinLink, 1)) {
trigger_error("Couldn't redirect player to next game server. " . $this->iControl->getClientErrorText($oldClient));
}
}
$this->iControl->client = $newClient;
}
// Trigger client updated callback
$this->iControl->callbacks->triggerCallback(Callbacks::CB_IC_CLIENTUPDATED, "Plugin_United.SwitchedServer");
if ($simulateMapEnd) {
// Simulate BeginMap on new client
$map = $this->iControl->server->getMap();
if ($map) {
$this->iControl->callbacks->triggerCallback(Callbacks::CB_IC_BEGINMAP, array(Callbacks::CB_IC_BEGINMAP, array($map)));
}
}
}
/**
* Handle nextserver command
*
* @param mixed $command
*/
public function handleNextServerCommand($command) {
if (!$command) return;
$login = $command[1][1];
if (!$this->iControl->authentication->checkRight($login, 'operator')) {
// Not allowed
$this->iControl->authentication->sendNotAllowed($login);
return;
}
// Request skip to next server
$this->switchServerRequested = time() + 3;
// Send chat message
$this->iControl->chat->sendInformation("Switching to next server in 3 seconds...");
}
/**
* Handle PlayerConnect callback
*/
public function playerJoinedLobby($client, $callback) {
if (!$client) return;
$data = $callback[1];
$login = $data[0];
// Redirect player to current game server
$gameserver = $this->gameServer[$this->currentClientIndex];
$joinLink = $this->getJoinLink($gameserver, !$data[1]);
if (!$client->query('SendOpenLinkToLogin', $login, $joinLink, 1)) {
trigger_error(
"United Plugin: Couldn't redirect player to current game server. " . $this->iControl->getClientErrorText($client));
}
}
/**
* Connect to the game server defined in the config
*/
private function loadClients() {
$gameserver = $this->config->xpath('gameserver/server');
$lobbies = $this->config->xpath('lobbies/server');
$clientsConfig = array_merge($gameserver, $lobbies);
foreach ($clientsConfig as $index => $serv) {
$isGameServer = (in_array($serv, $gameserver));
$host = $serv->xpath('host');
$port = $serv->xpath('port');
if (!$host || !$port) {
trigger_error("Invalid configuration!", E_USER_ERROR);
}
$host = (string) $host[0];
$port = (string) $port[0];
error_log("Connecting to united " . ($isGameServer ? 'game' : 'lobby') . " server at " . $host . ":" . $port . "...");
$client = new \IXR_ClientMulticall_Gbx();
// Connect
if (!$client->InitWithIp($host, $port, $this->settings->timeout)) {
trigger_error(
"Couldn't connect to united " . ($isGameServer ? 'game' : lobby) . " server! " . $client->getErrorMessage() .
"(" . $client->getErrorCode() . ")", E_USER_ERROR);
}
$login = $serv->xpath('login');
$pass = $serv->xpath('pass');
if (!$login || !$pass) {
trigger_error("Invalid configuration!", E_USER_ERROR);
}
$login = (string) $login[0];
$pass = (string) $pass[0];
// Authenticate
if (!$client->query('Authenticate', $login, $pass)) {
trigger_error(
"Couldn't authenticate on united " . ($isGameServer ? 'game' : 'lobby') . " server with user '" . $login . "'! " .
$client->getErrorMessage() . "(" . $client->getErrorCode() . ")", E_USER_ERROR);
}
// Enable callback system
if (!$client->query('EnableCallbacks', true)) {
trigger_error("Couldn't enable callbacks! " . $client->getErrorMessage() . "(" . $client->getErrorCode() . ")",
E_USER_ERROR);
}
// Wait for server to be ready
if (!$this->iControl->server->waitForStatus($client, 4)) {
trigger_error("Server couldn't get ready!", E_USER_ERROR);
}
// Set api version
if (!$client->query('SetApiVersion', ManiaControl::API_VERSION)) {
trigger_error(
"Couldn't set API version '" . ManiaControl::API_VERSION . "'! This might cause problems. " .
$this->iControl->getClientErrorText($client));
}
// Set server settings
$password = ($isGameServer ? $this->settings->gamePassword : $this->settings->lobbyPassword);
$hideServer = ($isGameServer && $this->settings->hide_game_server ? 1 : 0);
// Passwords
if (!$client->query('SetServerPassword', $password)) {
trigger_error("Couldn't set server join password. " . $this->iControl->getClientErrorText($client));
}
if (!$client->query('SetServerPasswordForSpectator', $password)) {
trigger_error("Couldn't set server spec password. " . $this->iControl->getClientErrorText($client));
}
// Show/Hide server
if (!$client->query('SetHideServer', $hideServer)) {
trigger_error(
"Couldn't set server '" . ($hideServer == 0 ? 'shown' : 'hidden') . "'. " .
$this->iControl->getClientErrorText($client));
}
// Enable service announces
if (!$client->query("DisableServiceAnnounces", false)) {
trigger_error("Couldn't enable service announces. " . $this->iControl->getClientErrorText($client));
}
// Set game mode
if (!$client->query('SetGameMode', $this->settings->gamemode)) {
trigger_error(
"Couldn't set game mode (" . $this->settings->gamemode . "). " . $this->iControl->getClientErrorText($client));
}
else if (!$client->query('RestartMap')) {
trigger_error("Couldn't restart map to change game mode. " . $this->iControl->getClientErrorText($client));
}
// Save client
$client->index = $index;
if ($isGameServer) {
array_push($this->gameServer, $client);
if (count($this->gameServer) === 1) {
$this->iControl->client = $client;
}
}
else {
array_push($this->lobbies, $client);
}
}
error_log("United Plugin: Connected to all game and lobby server!");
}
/**
* Handle PlayerConnect callback
*
* @param array $callback
*/
public function handlePlayerConnect($callback) {
if ($this->settings->widgets_enabled) {
// Send manialinks to the client
$login = $callback[1][0];
if (Tools::toBool($this->config->widgets->addfavorite->enabled)) {
// Send favorite widget
if (!$this->iControl->client->query('SendDisplayManialinkPageToLogin', $login,
$this->manialinks[self::ML_ADDFAVORITE]->asXml(), 0, false)) {
trigger_error("Couldn't send favorite widget to player '" . $login . "'! " . $this->iControl->getClientErrorText());
}
}
}
}
/**
* Build join link for the given client
*/
private function getJoinLink(&$client = null, $play = true) {
if (!$client) {
$client = $this->gameServer[$this->currentClientIndex];
}
if (!$client->query('GetSystemInfo')) {
trigger_error("Couldn't fetch server system info. " . $this->iControl->getClientErrorText($client));
return null;
}
else {
$systemInfo = $client->getResponse();
$password = '';
if (!$client->query('GetServerPassword')) {
trigger_error("Couldn't get server password. " . $this->iControl->getClientErrorText($client));
}
else {
$password = $client->getResponse();
}
return '#q' . ($play ? 'join' : 'spectate') . '=' . $systemInfo['ServerLogin'] .
(strlen($password) > 0 ? ':' . $password : '') . '@' . $systemInfo['TitleId'];
}
}
/**
* Build manialink for addfavorite button
*/
private function buildFavoriteManialink() {
// Load configs
$config = $this->config->widgets->addfavorite;
if (!Tools::toBool($config->enabled)) return;
$pos_x = (float) $config->pos_x;
$pos_y = (float) $config->pos_y;
$height = (float) $config->height;
$width = (float) $config->width;
$add_all = Tools::toBool($config->add_all);
// Build manialink
$xml = Tools::newManialinkXml(self::ML_ADDFAVORITE);
$frameXml = $xml->addChild('frame');
$frameXml->addAttribute('posn', $pos_x . ' ' . $pos_y);
// Background
$quadXml = $frameXml->addChild('quad');
Tools::addAlignment($quadXml);
$quadXml->addAttribute('posn', '0 0 0');
$quadXml->addAttribute('sizen', $width . ' ' . $height);
$quadXml->addAttribute('style', 'Bgs1InRace');
$quadXml->addAttribute('substyle', 'BgTitleShadow');
$quadXml->addAttribute('action', self::ML_ADDFAVORITE);
// Heart
$quadXml = $frameXml->addChild('quad');
Tools::addAlignment($quadXml);
$quadXml->addAttribute('id', 'Quad_AddFavorite');
$quadXml->addAttribute('posn', '0 0 1');
$quadXml->addAttribute('sizen', ($width - 1.) . ' ' . ($height - 0.8));
$quadXml->addAttribute('style', 'Icons64x64_1');
$quadXml->addAttribute('substyle', 'StateFavourite');
$quadXml->addAttribute('scriptevents', '1');
// Tooltip
$tooltipFrameXml = $frameXml->addChild('frame');
$tooltipFrameXml->addAttribute('id', 'Frame_FavoriteTooltip');
$tooltipFrameXml->addAttribute('posn', '0 ' . ($pos_y >= 0 ? '-' : '') . '13');
$tooltipFrameXml->addAttribute('hidden', '1');
$quadXml = $tooltipFrameXml->addChild('quad');
Tools::addAlignment($quadXml);
$quadXml->addAttribute('posn', '0 0 2');
$quadXml->addAttribute('sizen', '28 16');
$quadXml->addAttribute('style', 'Bgs1InRace');
$quadXml->addAttribute('substyle', 'BgTitleShadow');
$labelXml = $tooltipFrameXml->addChild('label');
Tools::addAlignment($labelXml);
Tools::addTranslate($labelXml);
$labelXml->addAttribute('posn', '0 0 3');
$labelXml->addAttribute('sizen', '26 0');
$labelXml->addAttribute('style', 'TextTitle1');
$labelXml->addAttribute('textsize', '2');
$labelXml->addAttribute('autonewline', '1');
$countText = '';
if ($add_all) {
$count = count($this->gameServer) + count($this->lobbies);
$countText = 'all ' . $count . ' ';
}
$labelXml->addAttribute('text', 'Add ' . $countText . 'server to Favorite!');
// Script for tooltip
$script = '
declare Frame_FavoriteTooltip <=> (Page.GetFirstChild("Frame_FavoriteTooltip") as CMlFrame);
while (True) {
yield;
foreach (Event in PendingEvents) {
switch (Event.Type) {
case CMlEvent::Type::MouseOver: {
switch (Event.ControlId) {
case "Quad_AddFavorite": {
Frame_FavoriteTooltip.Visible = True;
}
}
}
case CMlEvent::Type::MouseOut: {
switch (Event.ControlId) {
case "Quad_AddFavorite": {
Frame_FavoriteTooltip.Visible = False;
}
}
}
}
}
}';
$xml->addChild('script', $script);
$this->manialinks[self::ML_ADDFAVORITE] = $xml;
}
}
?>