diff --git a/system/compat/config.php b/system/compat/config.php index 4fc3004a..5476c52e 100644 --- a/system/compat/config.php +++ b/system/compat/config.php @@ -5,8 +5,6 @@ $deprecatedConfig = [ 'genders', 'template', 'template_allow_change', - 'vocations_amount', - 'vocations', 'client', 'session_prefix', 'friendly_urls', diff --git a/system/init.php b/system/init.php index 862b5370..d5767eb8 100644 --- a/system/init.php +++ b/system/init.php @@ -14,6 +14,7 @@ use MyAAC\CsrfToken; use MyAAC\Hooks; use MyAAC\Plugins; use MyAAC\Models\Town; +use MyAAC\Server\XML\Vocations; use MyAAC\Settings; defined('MYAAC') or die('Direct access not allowed!'); @@ -214,3 +215,5 @@ if (count($towns) <= 0) { config(['towns', $towns]); unset($towns); + +new Vocations(); diff --git a/system/libs/pot/OTS_Player.php b/system/libs/pot/OTS_Player.php index 099f5db1..fbd77aac 100644 --- a/system/libs/pot/OTS_Player.php +++ b/system/libs/pot/OTS_Player.php @@ -852,13 +852,7 @@ class OTS_Player extends OTS_Row_DAO throw new E_OTS_NotLoaded(); } - if(isset($this->data['promotion'])) { - global $config; - if((int)$this->data['promotion'] > 0) - return ($this->data['vocation'] + ($this->data['promotion'] * $config['vocations_amount'])); - } - - return $this->data['vocation']; + return \OTS_Toolbox::getVocationFromPromotion($this->data['vocation'], $this->data['promotion'] ?? 0); } diff --git a/system/libs/pot/OTS_Toolbox.php b/system/libs/pot/OTS_Toolbox.php index 575dba6f..2b587ca1 100644 --- a/system/libs/pot/OTS_Toolbox.php +++ b/system/libs/pot/OTS_Toolbox.php @@ -13,6 +13,8 @@ * @license http://www.gnu.org/licenses/lgpl-3.0.txt GNU Lesser General Public License, Version 3 */ +use MyAAC\Server\XML\Vocations; + /** * Toolbox for common operations. * @@ -110,14 +112,21 @@ class OTS_Toolbox $list->setFilter($filter); return $list; } - - public static function getVocationName($id, $promotion = 0): string + public static function getVocationFromPromotion($id, $promotion = 0): int { if($promotion > 0) { - $id = ($id + ($promotion * config('vocations_amount'))); + for ($i = 0; $i < $promotion; $i++) { + if ($_id = Vocations::getPromoted($id)) { + $id = $_id; + } + } } - return config('vocations')[$id] ?? 'Unknown'; + return $id; + } + + public static function getVocationName($id, $promotion = 0): string { + return config('vocations')[self::getVocationFromPromotion($id, $promotion)] ?? 'Unknown'; } } diff --git a/system/pages/characters.php b/system/pages/characters.php index b88368ff..2f03884b 100644 --- a/system/pages/characters.php +++ b/system/pages/characters.php @@ -452,10 +452,8 @@ WHERE killers.death_id = '".$death['id']."' ORDER BY killers.final_hit DESC, kil if($query->rowCount() > 0) { echo 'Did you mean:'; diff --git a/system/pages/highscores.php b/system/pages/highscores.php index 79d4feee..cf8e6cb7 100644 --- a/system/pages/highscores.php +++ b/system/pages/highscores.php @@ -13,6 +13,7 @@ use MyAAC\Cache\Cache; use MyAAC\Models\Player; use MyAAC\Models\PlayerDeath; use MyAAC\Models\PlayerKillers; +use MyAAC\Server\XML\Vocations; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Highscores'; @@ -35,24 +36,20 @@ if(!is_numeric($page) || $page < 1 || $page > PHP_INT_MAX) { $query = Player::query(); $configVocations = config('vocations'); -$configVocationsAmount = config('vocations_amount'); $vocationId = null; if($vocation !== 'all') { foreach($configVocations as $id => $name) { if(strtolower($name) == $vocation) { $vocationId = $id; - $add_vocs = [$id]; + $filterVocations = [$id]; - if ($id !== 0) { - $i = $id + $configVocationsAmount; - while (isset($configVocations[$i])) { - $add_vocs[] = $i; - $i += $configVocationsAmount; - } + while($tmpVoc = Vocations::getPromoted($id)) { + $id = $tmpVoc; + $filterVocations[] = $tmpVoc; } - $query->whereIn('players.vocation', $add_vocs); + $query->whereIn('players.vocation', $filterVocations); break; } } @@ -325,4 +322,5 @@ $twig->display('highscores.html.twig', [ 'page' => $page, 'baseLink' => $baseLink, 'updatedAt' => $updatedAt, + 'baseVocations' => Vocations::getBase(true), ]); diff --git a/system/pages/online.php b/system/pages/online.php index 21f2ee0d..c68fd619 100644 --- a/system/pages/online.php +++ b/system/pages/online.php @@ -12,6 +12,7 @@ use MyAAC\Cache\Cache; use MyAAC\Models\ServerConfig; use MyAAC\Models\ServerRecord; +use MyAAC\Server\XML\Vocations; defined('MYAAC') or die('Direct access not allowed!'); $title = 'Who is online?'; @@ -56,15 +57,14 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60 $vocations = array_map(function ($name) { return 0; - }, setting('core.vocations')); + }, config('vocations')); if($db->hasTable('players_online')) // tfs 1.0 $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players`, `players_online` WHERE `players`.`id` = `players_online`.`player_id` AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); else $playersOnline = $db->query('SELECT `accounts`.`country`, `players`.`name`, `players`.`level`, `players`.`vocation`' . $outfit . ', ' . $promotion . ' `' . $skull_time . '` as `skulltime`, `' . $skull_type . '` as `skull` FROM `accounts`, `players` WHERE `players`.`online` > 0 AND `accounts`.`id` = `players`.`account_id` ORDER BY ' . $orderSql); - $settingVocations = setting('core.vocations'); - $settingVocationsAmount = setting('core.vocations_amount'); + $configVocations = config('vocations'); $players = []; foreach($playersOnline as $player) { @@ -81,22 +81,19 @@ $cached = Cache::remember("online_$order", setting('core.online_cache_ttl') * 60 } } - if(isset($player['promotion'])) { - if((int)$player['promotion'] > 0) - $player['vocation'] += ($player['promotion'] * $settingVocationsAmount); - } + $player['vocation'] = OTS_Toolbox::getVocationFromPromotion($player['vocation'], $player['promotion'] ?? 0); $players[] = array( 'name' => getPlayerLink($player['name']), 'player' => $player, 'level' => $player['level'], - 'vocation' => $settingVocations[$player['vocation']], + 'vocation' => $configVocations[$player['vocation']], 'skull' => $skull, 'country_image' => getFlagImage($player['country']), 'outfit' => setting('core.outfit_images_url') . '?id=' . $player['looktype'] . ($outfit_addons ? '&addons=' . $player['lookaddons'] : '') . '&head=' . $player['lookhead'] . '&body=' . $player['lookbody'] . '&legs=' . $player['looklegs'] . '&feet=' . $player['lookfeet'], ); - $vocations[($player['vocation'] > $settingVocationsAmount ? $player['vocation'] - $settingVocationsAmount : $player['vocation'])]++; + $vocations[Vocations::getOriginal($player['vocation'])]++; } $record = ''; @@ -142,6 +139,7 @@ $twig->display('online.html.twig', array( 'vocations' => $cached['vocations'], 'vocs' => $cached['vocations'], // deprecated, to be removed 'order' => $order, + 'baseVocations' => Vocations::getBase(false), )); // search bar diff --git a/system/settings.php b/system/settings.php index 6de908ce..614b07ac 100644 --- a/system/settings.php +++ b/system/settings.php @@ -319,23 +319,6 @@ return [ }, ], ], - 'vocations_amount' => [ - 'name' => 'Vocations Amount', - 'type' => 'number', - 'desc' => 'How much basic vocations your server got (without promotion)', - 'default' => 4, - ], - 'vocations' => [ - 'name' => 'Vocation Names', - 'type' => 'textarea', - 'desc' => 'Separated by comma. Must be in the same order as in vocations.xml, starting with id: 0.', - 'default' => 'None, Sorcerer, Druid, Paladin, Knight, Master Sorcerer, Elder Druid,Royal Paladin, Elite Knight', - 'callbacks' => [ - 'get' => function ($value) { - return array_map('trim', explode(',', $value)); - }, - ], - ], [ 'type' => 'category', 'title' => 'Database', diff --git a/system/src/Models/Player.php b/system/src/Models/Player.php index 77fe4504..479967c8 100644 --- a/system/src/Models/Player.php +++ b/system/src/Models/Player.php @@ -46,14 +46,8 @@ class Player extends Model { }); } - public function getVocationNameAttribute() - { - $vocation = $this->vocation; - if (isset($this->promotion) && $this->promotion > 0) { - $vocation += ($this->promotion * setting('core.vocations_amount')); - } - - return config('vocations')[$vocation] ?? 'Unknown'; + public function getVocationNameAttribute() { + return \OTS_Toolbox::getVocationName($this->vocation, $this->promotion ?? 0); } public function getIsDeletedAttribute() diff --git a/system/src/Server/XML/Vocations.php b/system/src/Server/XML/Vocations.php new file mode 100644 index 00000000..6bd8f357 --- /dev/null +++ b/system/src/Server/XML/Vocations.php @@ -0,0 +1,93 @@ +load(); + $from = $this->getFrom(); + + $amount = 0; + foreach ($from as $vocId => $fromVocation) { + if ($vocId != 0 && $vocId == $fromVocation) { + $amount++; + } + } + + return ['vocations' => $this->get(), 'vocationsFrom' => $from, 'amount' => $amount]; + }); + + self::$vocations = $cached['vocations']; + self::$vocationsFrom = $cached['vocationsFrom']; + + config(['vocations', self::$vocations]); + config(['vocations_amount', $cached['amount']]); + } + + public function load(): void + { + if(!class_exists('DOMDocument')) { + throw new \RuntimeException('Please install PHP xml extension. MyAAC will not work without it.'); + } + + $vocationsXML = new \DOMDocument(); + $file = config('data_path') . 'XML/vocations.xml'; + if(!@file_exists($file)) { + $file = config('data_path') . 'vocations.xml'; + } + + if(!$vocationsXML->load($file)) { + throw new \RuntimeException('ERROR: Cannot load vocations.xml - the file is malformed. Check the file with xml syntax validator.'); + } + + foreach($vocationsXML->getElementsByTagName('vocation') as $vocation) { + $id = $vocation->getAttribute('id'); + + self::$vocations[$id] = $vocation->getAttribute('name'); + + $fromVocation = (int) $vocation->getAttribute('fromvoc'); + self::$vocationsFrom[$id] = $fromVocation; + } + } + + public static function get(): array { + return self::$vocations; + } + + public static function getFrom(): array { + return self::$vocationsFrom; + } + + public static function getPromoted(int $id): ?int { + foreach (self::$vocationsFrom as $vocId => $fromVocation) { + if ($id == $fromVocation && $vocId != $id) { + return $vocId; + } + } + + return null; + } + + public static function getOriginal(int $id): ?int { + return self::$vocationsFrom[$id] ?? null; + } + + public static function getBase($includingRook = true): array { + $vocations = []; + foreach (self::$vocationsFrom as $vocId => $fromVoc) { + if ($vocId == $fromVoc && ($vocId != 0 || $includingRook)) { + $vocations[] = $vocId; + } + } + + return $vocations; + } +} diff --git a/system/templates/highscores.html.twig b/system/templates/highscores.html.twig index 88bf579b..a22cacb0 100644 --- a/system/templates/highscores.html.twig +++ b/system/templates/highscores.html.twig @@ -18,7 +18,7 @@ @@ -120,7 +120,7 @@ [ALL]
- {% for i in 0..config.vocations_amount %} + {% for i in baseVocations %} {{ config.vocations[i]}}
{% endfor %} diff --git a/system/templates/online.html.twig b/system/templates/online.html.twig index 6f798740..71dfa4f2 100644 --- a/system/templates/online.html.twig +++ b/system/templates/online.html.twig @@ -10,22 +10,19 @@ {% if setting('core.online_vocations_images') %} - - - - + {% for vocationId in baseVocations %} + + {% endfor %} - - - - + {% for vocationId in baseVocations %} + + {% endfor %} - - - - + {% for vocationId in baseVocations %} + + {% endfor %}
SorcerersDruidsPaladinsKnights{{ config('vocations')[vocationId] }}s
{{ vocs[1] }}{{ vocs[2] }}{{ vocs[3] }}{{ vocs[4] }}{{ vocs[vocationId] }}
 
@@ -35,11 +32,14 @@ Vocation statistics - {% for i in 1..config.vocations_amount %} - - {{ config.vocations[i] }} - {{ vocs[i] }} - + {% set i = 0 %} + {% for vocationId in baseVocations %} + + {{ config.vocations[vocationId] }} + {{ vocs[vocationId] }} + + + {% set i = i + 1 %} {% endfor %}