This repository has been archived on 2024-07-18. You can view files and clone it, but cannot push or open issues or pull requests.
lwb5/scripts/lib/xml_config.inc

376 lines
11 KiB
PHP

<?php
/****************************************************************************
* XML CONFIGURATION PARSER
****************************************************************************/
class xml_config {
private static $mVersion = null;
private static $mGame = null;
private static $versions = null;
private static $games = null;
private static $defGame = null;
private function parseMainParams($root) {
$node = $root->firstChild;
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE && $node->nodeName == 'Param') {
$aName = $node->getAttribute('name');
$aValue = $node->getAttribute('value');
if ($aName == "") {
l::warn("CONFIG: a main parameter is missing a 'name' attribute");
} elseif (is_null(xml_config::$mGame->params[$aName])) {
xml_config::$mGame->params[$aName] = $aValue;
} else {
l::notice("CONFIG: duplicate main parameter '$aName'");
}
} elseif ($node->nodeType == XML_ELEMENT_NODE) {
l::notice("CONFIG: found unexpected tag '{$node->nodeName}' in MainParams section");
}
$node = $node->nextSibling;
}
}
private function parseMainTicks($root) {
$node = $root->firstChild;
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE && $node->nodeName == 'Tick') {
$tScript = $node->getAttribute('script');
$tFirst = $node->getAttribute('first');
$tInterval = $node->getAttribute('interval');
$tLast = $node->getAttribute('last');
if ($tScript == "" || $tFirst == "" || $tInterval == "") {
l::warn("CONFIG: a main tick declaration is missing a mandatory attribute");
} elseif ((int)$tInterval == 0) {
l::warn("CONFIG: invalid interval for main tick '$tScript'");
} elseif (is_null(xml_config::$mVersion->getTickDefinition($tScript))) {
new tick_definition(xml_config::$mVersion, $tScript, false);
new tick_instance(xml_config::$mGame, $tScript, (int)$tFirst,
(int)$tInterval, $tLast ? (int)$tLast : null);
} else {
l::notice("CONFIG: duplicate main tick '$tScript'");
}
} elseif ($node->nodeType == XML_ELEMENT_NODE) {
l::notice("CONFIG: found unexpected tag '{$node->nodeName}' in MainTicks section");
}
$node = $node->nextSibling;
}
}
private function parseTickDefinition($version, $root) {
$script = $root->getAttribute('script');
$public = ($root->getAttribute('public') == 1);
if ($script == "") {
l::warn("CONFIG: invalid tick definition for version {$version->id}");
return;
}
if (!is_null($version->getTickDefinition($script))) {
l::notice("CONFIG: duplicate tick definition '$script' for version {$version->id}");
return;
}
$def = new tick_definition($version, $script, $public);
if (!$public) {
return;
}
$names = array();
$descs = array();
$node = $root->firstChild;
while ($node) {
if ($node->nodeType != XML_ELEMENT_NODE) {
$node = $node->nextSibling;
continue;
}
if ($node->nodeName != "Name" && $node->nodeName != 'Description') {
l::warn("CONFIG: unexpected tag '{$node->nodeName}' found in tick definition "
. "'{$script}' for version '{$version->id}'");
$node = $node->nextSibling;
continue;
}
$lang = $node->getAttribute('lang');
if ($lang == '') {
l::warn("CONFIG: missing language for {$node->nodeName} in tick definition "
. "'{$script}' for version '{$version->id}'");
$node = $node->nextSibling;
continue;
}
$contents = trim($node->textContent);
if ($contents == '') {
l::warn("CONFIG: missing contents for {$node->nodeName} in tick definition "
. "'{$script}' for version '{$version->id}'");
$node = $node->nextSibling;
continue;
}
if ($node->nodeName == 'Name') {
$names[$lang] = $contents;
} else {
$descs[$lang] = $contents;
}
$node = $node->nextSibling;
}
foreach ($names as $lang => $name) {
$def->addText($lang, $name, $descs[$lang]);
}
}
private function parseVersion($root) {
$id = $root->getAttribute("id");
$cp = ($root->getAttribute("playable") == 1);
$tx = $root->getAttribute("text");
if ($id == "" || $tx == "") {
l::warn("CONFIG: invalid version definition (missing identifier or text)");
return null;
} elseif ($id == 'main') {
l::warn("CONFIG: invalid version definition (using 'main' identifier)");
return null;
}
$version = new version($id, $cp, $tx);
$node = $root->firstChild;
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE && $node->nodeName == 'Tick') {
xml_config::parseTickDefinition($version, $node);
} elseif ($node->nodeType == XML_ELEMENT_NODE) {
l::warn("CONFIG: found unexpected tag '{$node->nodeName}' in MainTicks section");
}
$node = $node->nextSibling;
}
return $version;
}
private function parseVersions($root) {
$node = $root->firstChild;
$versions = array();
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE && $node->nodeName == 'Version') {
$v = xml_config::parseVersion($node);
if (!is_null($v)) {
if (is_null($versions[$v->id])) {
$versions[$v->id] = $v;
} else {
l::notice("CONFIG: found duplicate definition for version '{$v->id}'");
}
}
} elseif ($node->nodeType == XML_ELEMENT_NODE) {
l::notice("CONFIG: found unexpected tag '{$node->nodeName}' in Versions section");
}
$node = $node->nextSibling;
}
return $versions;
}
private function parseGame($root) {
$id = $root->getAttribute('id');
if ($id == '') {
l::warn("CONFIG: game definition is missing an identifier");
return null;
}
if ($id == 'main') {
l::warn("CONFIG: game definition with 'main' identifier ignored");
return null;
}
$version = $root->getAttribute('version');
if (is_null(xml_config::$versions[$version])) {
l::warn("CONFIG: game '$id' has unknown version '$version'");
return null;
}
$namespace = $root->getAttribute('namespace');
if ($namespace == '') {
l::warn("CONFIG: no namespace defined for game '$id'");
return null;
}
$text = $root->getAttribute('text');
if ($namespace == '') {
l::warn("CONFIG: no text for game '$id'");
return null;
}
$public = ($root->getAttribute('public') == 1);
$canJoin = ($root->getAttribute('canjoin') == 1);
$game = new game(xml_config::$versions[$version], $id, $namespace, $public, $canJoin, $text);
$node = $root->firstChild;
while ($node) {
if ($node->nodeType != XML_ELEMENT_NODE) {
$node = $node->nextSibling;
continue;
}
if ($node->nodeName == 'Param') {
$aName = $node->getAttribute('name');
$aValue = $node->getAttribute('value');
if ($aName == "") {
l::warn("CONFIG: a parameter is missing a 'name' attribute for game '$id'");
} elseif (is_null($game->params[$aName])) {
$game->params[$aName] = $aValue;
} else {
l::notice("CONFIG: duplicate parameter '$aName'");
}
} elseif ($node->nodeName == 'Description') {
$lang = $node->getAttribute('lang');
$contents = trim($node->textContent);
if ($lang == "") {
l::warn("CONFIG: a description is missing the 'lang' attribute for game '$id'");
} elseif ($contents == "") {
l::warn("CONFIG: description in language '$lang' has no contents for game '$id'");
} elseif (!is_null($game->descriptions[$lang])) {
l::notice("CONFIG: description in language '$lang' appears twice for game '$id'");
} else {
$game->descriptions[$lang] = $contents;
}
} elseif ($node->nodeName == 'Tick') {
$tScript = $node->getAttribute('script');
$tFirst = $node->getAttribute('first');
$tInterval = $node->getAttribute('interval');
$tLast = $node->getAttribute('last');
if ($tScript == "" || $tFirst == "" || $tInterval == "") {
l::warn("CONFIG: a tick declaration is missing a mandatory attribute "
. "for game '$id'");
} elseif ((int)$tInterval == 0) {
l::warn("CONFIG: invalid interval for tick '$tScript' in game '$id'");
} elseif (is_null($game->version->getTickDefinition($tScript))) {
l::warn("CONFIG: no definition for tick '$tScript' in game '$id' "
. "(version '$version')");
} elseif (is_null($game->ticks[$tScript])) {
new tick_instance($game, $tScript, (int)$tFirst, (int)$tInterval,
$tLast ? (int)$tLast : null);
} else {
l::notice("CONFIG: duplicate tick initialiser for tick '$tScript' in game '$id'");
}
} else {
l::notice("CONFIG: found unexpected tag '{$node->nodeName}' in game '$id' definition");
}
$node = $node->nextSibling;
}
return $game;
}
private function parseGames($root) {
$defaultId = $root->getAttribute('default');
$games = array();
$node = $root->firstChild;
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE && $node->nodeName == 'Game') {
$g = xml_config::parseGame($node);
if (!is_null($g)) {
if (is_null($games[$g->name])) {
$games[$g->name] = $g;
} else {
l::notice("CONFIG: found duplicate definition for game '{$v->name}'");
}
}
} elseif ($node->nodeType == XML_ELEMENT_NODE) {
l::notice("CONFIG: found unexpected tag '{$node->nodeName}' in Games section");
}
$node = $node->nextSibling;
}
if (count($games) && ($defaultId == '' || is_null($games[$defaultId]))) {
$defaultId = $games[0]->name;
l::notice("CONFIG: no default game, using '$defaultId'");
}
xml_config::$defGame = $defaultId;
return $games;
}
function parse($xmlData) {
$doc = new DOMDocument();
if (!$doc->loadXML($xmlData)) {
l::error("CONFIG: error while parsing XML configuration");
return false;
}
xml_config::$mVersion = new version('main', false, 'Legacy Worlds');
xml_config::$mGame = new game(xml_config::$mVersion, 'main', '', false, false, 'Legacy Worlds');
xml_config::$versions = null;
xml_config::$games = null;
xml_config::$defGame = null;
$root = $doc->documentElement;
$node = $root->firstChild;
while ($node) {
if ($node->nodeType == XML_ELEMENT_NODE) {
switch ($node->nodeName) :
case 'MainParams':
xml_config::parseMainParams($node);
break;
case 'MainTicks':
xml_config::parseMainTicks($node);
break;
case 'Versions':
if (is_array(xml_config::$versions)) {
l::notice("CONFIG: found duplicate set of version definitions");
} else {
xml_config::$versions = xml_config::parseVersions($node);
}
break;
case 'Games':
if (is_array(xml_config::$games)) {
l::notice("CONFIG: found duplicate set of game definitions");
} elseif (is_array(xml_config::$versions)) {
xml_config::$games = xml_config::parseGames($node);
} else {
l::notice("CONFIG: game definitions found before version "
. "definitions, ignored");
}
break;
default:
l::notice("CONFIG: found unknown tag '{$node->nodeName}' at toplevel");
break;
endswitch;
}
$node = $node->nextSibling;
}
if (!is_array(xml_config::$versions) || count(xml_config::$versions) == 0) {
l::error("CONFIG: no versions have been defined!");
return false;
}
if (!is_array(xml_config::$games) || count(xml_config::$games) == 0) {
l::error("CONFIG: no games have been defined!");
return false;
}
xml_config::$versions['main'] = xml_config::$mVersion;
xml_config::$games['main'] = xml_config::$mGame;
return new config(xml_config::$versions, xml_config::$games, xml_config::$defGame);
}
}
?>