* detatch from User and Util and move to its own enum class
 * added definitions for all locales the 12340 client could in theory have
 * this is incompatble with the Intl extension
 * version bump and php requirement bump
This commit is contained in:
Sarjuuk
2025-01-27 07:47:19 +01:00
parent 40c2c63d1b
commit 398b93e9a7
72 changed files with 1007 additions and 924 deletions

View File

@@ -18,7 +18,7 @@ Also, this project is not meant to be used for commercial puposes of any kind!
## Requirements
+ Webserver running PHP ≥ 8.0 including extensions:
+ Webserver running PHP ≥ 8.2 including extensions:
+ [SimpleXML](https://www.php.net/manual/en/book.simplexml.php)
+ [GD](https://www.php.net/manual/en/book.image)
+ [MySQL Improved](https://www.php.net/manual/en/book.mysqli.php)

View File

@@ -20,17 +20,11 @@ class AjaxAccount extends AjaxHandler
'remove' => ['filter' => FILTER_SANITIZE_NUMBER_INT],
// 'sessionKey' => ['filter' => FILTER_SANITIZE_NUMBER_INT]
);
protected $_get = array(
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
);
public function __construct(array $params)
{
parent::__construct($params);
if (is_numeric($this->_get['locale']))
User::useLocale($this->_get['locale']);
if (!$this->params || !User::$id)
return;
@@ -60,12 +54,12 @@ class AjaxAccount extends AjaxHandler
// we don't get signaled whether an id should be added to or removed from either includes or excludes
// so we throw everything into one table and toggle the mode if its already in here
$includes = DB::Aowow()->selectCol('SELECT typeId FROM ?_profiler_excludes WHERE type = ?d AND typeId IN (?a)', $type, $ids);
$includes = DB::Aowow()->selectCol('SELECT `typeId` FROM ?_profiler_excludes WHERE `type` = ?d AND `typeId` IN (?a)', $type, $ids);
foreach ($ids as $typeId)
DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE mode = (mode ^ 0x3)', array(
User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1
));
DB::Aowow()->query('INSERT INTO ?_account_excludes (`userId`, `type`, `typeId`, `mode`) VALUES (?a) ON DUPLICATE KEY UPDATE `mode` = (`mode` ^ 0x3)',
[User::$id, $type, $typeId, in_array($typeId, $includes) ? 2 : 1]
);
return;
}

View File

@@ -248,7 +248,7 @@ class AjaxComment extends AjaxHandler
if ($this->_get['rating'] < 0)
$val *= -1;
if (User::getCurDailyVotes() <= 0)
if (User::getCurrentDailyVotes() <= 0)
return Util::toJSON(['error' => 1, 'message' => Lang::main('tooManyVotes')]);
else if (!$target || $val != $this->_get['rating'])
return Util::toJSON(['error' => 1, 'message' => Lang::main('genericError')]);

View File

@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
class AjaxData extends AjaxHandler
{
protected $_get = array(
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale' ],
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom' ],
't' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkTextLine'],
'catg' => ['filter' => FILTER_SANITIZE_NUMBER_INT ],
'skill' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxData::checkSkill' ],
@@ -18,8 +18,8 @@ class AjaxData extends AjaxHandler
{
parent::__construct($params);
if (is_numeric($this->_get['locale']))
User::useLocale($this->_get['locale']);
if ($this->_get['locale']?->validate())
Lang::load($this->_get['locale']);
// always this one
$this->handler = 'handleData';
@@ -103,7 +103,7 @@ class AjaxData extends AjaxHandler
case 'pets':
case 'zones':
if (!Util::loadStaticFile($set, $result, true) && Cfg::get('DEBUG'))
$result .= "alert('could not fetch static data: ".$set." for locale: ".User::$localeString."');";
$result .= "alert('could not fetch static data: ".$set." for locale: ".Lang::getLocale()->json()."');";
$result .= "\n\n";
break;
@@ -118,7 +118,7 @@ class AjaxData extends AjaxHandler
protected static function checkSkill(string $val) : array
{
return array_intersect([171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356], explode(',', $val));
return array_intersect(array_merge(SKILLS_TRADE_PRIMARY, [SKILL_FIRST_AID, SKILL_COOKING, SKILL_FISHING]), explode(',', $val));
}
protected static function checkCallback(string $val) : bool

View File

@@ -6,7 +6,7 @@ if (!defined('AOWOW_REVISION'))
class AjaxLocale extends AjaxHandler
{
protected $_get = array(
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'AjaxHandler::checkLocale']
'locale' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFrom']
);
public function __construct(array $params)
@@ -23,8 +23,11 @@ class AjaxLocale extends AjaxHandler
*/
protected function handleLocale() : string
{
User::setLocale($this->_get['locale']);
User::save();
if ($this->_get['locale']?->validate())
{
User::$preferedLoc = $this->_get['locale'];
User::save(true);
}
return isset($_SERVER['HTTP_REFERER']) ? $_SERVER['HTTP_REFERER'] : '.';
}

View File

@@ -654,10 +654,10 @@ class AjaxProfile extends AjaxHandler
{
// get and apply inventory
$gItems[$iId] = array(
'name_'.User::$localeString => $phItems->getField('name', true),
'quality' => $phItems->getField('quality'),
'icon' => $phItems->getField('iconString'),
'jsonequip' => $data[$iId]
'name_'.Lang::getLocale()->json() => $phItems->getField('name', true),
'quality' => $phItems->getField('quality'),
'icon' => $phItems->getField('iconString'),
'jsonequip' => $data[$iId]
);
$profile['inventory'][$slot] = [$iId, 0, 0, 0, 0, 0, 0, 0];
@@ -682,10 +682,10 @@ class AjaxProfile extends AjaxHandler
{
// get and apply inventory
$gItems[$i['item']] = array(
'name_'.User::$localeString => $itemz->getField('name', true),
'quality' => $itemz->getField('quality'),
'icon' => $itemz->getField('iconString'),
'jsonequip' => $data[$i['item']]
'name_'.Lang::getLocale()->json() => $itemz->getField('name', true),
'quality' => $itemz->getField('quality'),
'icon' => $itemz->getField('iconString'),
'jsonequip' => $data[$i['item']]
);
$profile['inventory'][$i['slot']] = [$i['item'], $i['subItem'], $i['permEnchant'], $i['tempEnchant'], $i['gem1'], $i['gem2'], $i['gem3'], $i['gem4']];
}
@@ -719,7 +719,7 @@ class AjaxProfile extends AjaxHandler
// }
// }
// $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', modifier:".Util::toJSON($mods)."});\n";
// $buff .= 'g_spells.add('.$id.", {id:".$id.", name:'".Util::jsEscape(mb_substr($data['name'], 1))."', icon:'".$data['icon']."', callback:".Util::toJSON($mods)."});\n";
// }
// $buff .= "\n";
// }

View File

@@ -1479,7 +1479,7 @@ abstract class Filter
private function genericString($field, $value, $strFlags)
{
if ($strFlags & STR_LOCALIZED)
$field .= '_loc'.User::$localeId;
$field .= '_loc'.Lang::getLocale()->value;
return $this->modularizeString([$field], (string)$value, $strFlags & STR_MATCH_EXACT, $strFlags & STR_ALLOW_SHORT);
}

View File

@@ -139,21 +139,6 @@ define('U_GROUP_MODERATOR', (U_GROUP_ADMIN|U_GROUP_MOD|U_GROUP_B
define('U_GROUP_COMMENTS_MODERATOR', (U_GROUP_MODERATOR|U_GROUP_LOCALIZER));
define('U_GROUP_PREMIUM_PERMISSIONS', (U_GROUP_PREMIUM|U_GROUP_STAFF|U_GROUP_VIP));
// Locales
define('LOCALE_EN', 0); // enGB, enUS
define('LOCALE_KR', 1); // koKR [aowwo unused]
define('LOCALE_FR', 2); // frFR
define('LOCALE_DE', 3); // deDE
define('LOCALE_CN', 4); // zhCN, enCN
define('LOCALE_TW', 5); // zhTW, enTW [aowow unused]
define('LOCALE_ES', 6); // esES
define('LOCALE_MX', 7); // esMX [aowow unused]
define('LOCALE_RU', 8); // ruRU
define('LOCALE_JP', 9); // jaJP [aowow & 335 unused]
define('LOCALE_PT', 10); // ptPT, ptBR [aowow unused]
define('LOCALE_IT', 11); // itIT [aowow & 335 unused]
define('LOCALE_MASK_ALL', 0b000101011101);
// red buttons on the top of the page
define('BUTTON_WOWHEAD', 0);
define('BUTTON_UPGRADE', 1);
@@ -330,7 +315,6 @@ define('GUIDE_CU_NO_RATING', 0x200);
define('MAX_LEVEL', 80);
define('MAX_SKILL', 450);
define('MAX_LOCALES', 16); // technical limitation, 6 in use here
define('WOW_BUILD', 12340);
// Loot handles

View File

@@ -220,7 +220,7 @@ class Game
$pages = [];
while ($ptId)
{
if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', User::$localeId, User::$localeString, $ptId))
if ($row = DB::World()->selectRow('SELECT ptl.Text AS Text_loc?d, pt.* FROM page_text pt LEFT JOIN page_text_locale ptl ON pt.ID = ptl.ID AND locale = ? WHERE pt.ID = ?d', Lang::getLocale()->value, Lang::getLocale()->json(), $ptId))
{
$ptId = $row['NextPageID'];
$pages[] = Util::parseHtmlText(Util::localizedString($row, 'Text'));
@@ -392,28 +392,20 @@ class Game
$quotes = [];
$soundIds = [];
$quoteSrc = DB::World()->select('
SELECT
ct.GroupID AS ARRAY_KEY, ct.ID as ARRAY_KEY2,
ct.`Type` AS `talkType`,
ct.TextRange AS `range`,
IFNULL(bct.`LanguageID`, ct.`Language`) AS lang,
IFNULL(NULLIF(bct.Text, ""), IFNULL(NULLIF(bct.Text1, ""), IFNULL(ct.`Text`, ""))) AS text_loc0,
{IFNULL(NULLIF(bctl.Text, ""), IFNULL(NULLIF(bctl.Text1, ""), IFNULL(ctl.Text, ""))) AS text_loc?d,}
IF(bct.SoundEntriesID > 0, bct.SoundEntriesID, ct.Sound) AS soundId
FROM
creature_text ct
{LEFT JOIN
creature_text_locale ctl ON ct.CreatureID = ctl.CreatureID AND ct.GroupID = ctl.GroupID AND ct.ID = ctl.ID AND ctl.Locale = ?}
LEFT JOIN
broadcast_text bct ON ct.BroadcastTextId = bct.ID
{LEFT JOIN
broadcast_text_locale bctl ON ct.BroadcastTextId = bctl.ID AND bctl.locale = ?}
WHERE
ct.CreatureID = ?d',
User::$localeId ?: DBSIMPLE_SKIP,
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
$quoteSrc = DB::World()->select(
'SELECT ct.`GroupID` AS ARRAY_KEY, ct.`ID` AS ARRAY_KEY2, ct.`Type` AS "talkType", ct.TextRange AS "range",
IFNULL(bct.`LanguageID`, ct.`Language`) AS "lang",
IFNULL(NULLIF(bct.`Text`, ""), IFNULL(NULLIF(bct.`Text1`, ""), IFNULL(ct.`Text`, ""))) AS "text_loc0",
{ IFNULL(NULLIF(bctl.`Text`, ""), IFNULL(NULLIF(bctl.`Text1`, ""), IFNULL(ctl.`Text`, ""))) AS text_loc?d, }
IF(bct.`SoundEntriesID` > 0, bct.`SoundEntriesID`, ct.`Sound`) AS "soundId"
FROM creature_text ct
{ LEFT JOIN creature_text_locale ctl ON ct.`CreatureID` = ctl.`CreatureID` AND ct.`GroupID` = ctl.`GroupID` AND ct.`ID` = ctl.`ID` AND ctl.`Locale` = ? }
LEFT JOIN broadcast_text bct ON ct.`BroadcastTextId` = bct.`ID`
{ LEFT JOIN broadcast_text_locale bctl ON ct.`BroadcastTextId` = bctl.`ID` AND bctl.`locale` = ? }
WHERE ct.`CreatureID` = ?d',
Lang::getLocale()->value ?: DBSIMPLE_SKIP,
Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
Lang::getLocale()->value ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
$creatureId
);

View File

@@ -3,7 +3,7 @@
mb_internal_encoding('UTF-8');
mysqli_report(MYSQLI_REPORT_ERROR);
define('AOWOW_REVISION', 39);
define('AOWOW_REVISION', 40);
define('OS_WIN', substr(PHP_OS, 0, 3) == 'WIN'); // OS_WIN as per compile info of php
define('CLI', PHP_SAPI === 'cli');
define('CLI_HAS_E', CLI && // WIN10 and later usually support ANSI escape sequences
@@ -11,25 +11,30 @@ define('CLI_HAS_E', CLI && // WIN10 and later u
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'fileinfo'/*, 'gmp'*/];
$badExt = ['Intl']; // Intl contains its own class Locale. What? Namespaces? Never heard of those!
$error = '';
if ($ext = array_filter($reqExt, function($x) { return !extension_loaded($x); }))
if ($ext = array_filter($reqExt, fn($x) => !extension_loaded($x)))
$error .= 'Required Extension <b>'.implode(', ', $ext)."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
if (version_compare(PHP_VERSION, '8.0.0') < 0)
$error .= 'PHP Version <b>8.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
if ($ext = array_filter($badExt, fn($x) => extension_loaded($x)))
$error .= 'Loaded Extension <b>'.implode(', ', $ext)."</b> is incompatible and must be disabled.\n\n";
if (version_compare(PHP_VERSION, '8.2.0') < 0)
$error .= 'PHP Version <b>8.2</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
if ($error)
die(CLI ? strip_tags($error) : $error);
require_once 'includes/defines.php';
require_once 'includes/locale.class.php';
require_once 'includes/stats.class.php'; // Game entity statistics conversion
require_once 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master)
require_once 'includes/utilities.php'; // helper functions
require_once 'includes/config.class.php'; // Config holder
require_once 'includes/game.php'; // game related data & functions
require_once 'includes/profiler.class.php';
require_once 'includes/user.class.php';
require_once 'includes/profiler.class.php'; // Profiler feature
require_once 'includes/user.class.php'; // Session handling
require_once 'includes/markup.class.php'; // manipulate markup text
require_once 'includes/database.class.php'; // wrap DBSimple
require_once 'includes/community.class.php'; // handle comments, screenshots and videos
@@ -213,6 +218,12 @@ if (!CLI)
if (User::init())
User::save(); // save user-variables in session
// hard override locale for this call (should this be here..?)
if (isset($_GET['locale']) && ($loc = Locale::tryFrom($_GET['locale'])))
Lang::load($loc);
else
Lang::load(User::$preferedLoc);
// set up some logging (~10 queries will execute before we init the user and load the config)
if (Cfg::get('DEBUG') >= CLI::LOG_INFO && User::isInGroup(U_GROUP_DEV | U_GROUP_ADMIN))
{
@@ -227,17 +238,6 @@ if (!CLI)
DB::Characters($idx)->setLogger(['DB', 'profiler']);
}
// hard-override locale for this call (should this be here..?)
// all strings attached..
if (isset($_GET['locale']))
{
$loc = intVal($_GET['locale']);
if ($loc <= MAX_LOCALES && $loc >= 0 && (Cfg::get('LOCALES') & (1 << $loc)))
User::useLocale($loc);
}
Lang::load(User::$localeId);
// parse page-parameters .. sanitize before use!
$str = explode('&', $_SERVER['QUERY_STRING'] ?? '', 2)[0];
$_ = explode('=', $str, 2);
@@ -245,6 +245,6 @@ if (!CLI)
$pageParam = $_[1] ?? '';
}
else if (DB::isConnected(DB_AOWOW))
Lang::load(LOCALE_EN);
Lang::load(Locale::EN);
?>

209
includes/locale.class.php Normal file
View File

@@ -0,0 +1,209 @@
<?php
if (!defined('AOWOW_REVISION'))
die('illegal access');
enum Locale : int
{ // unused by TC WoW self
case EN = 0; // enGB, enUS
case KR = 1; // koKR ?
case FR = 2; // frFR
case DE = 3; // deDE
case CN = 4; // zhCN, enCN
case TW = 5; // zhTW, enTW x
case ES = 6; // esES
case MX = 7; // esMX x
case RU = 8; // ruRU
case JP = 9; // jaJP x x x
case PT = 10; // ptPT, ptBR x ?
case IT = 11; // itIT x x x
private const MASK_ALL = 0b000101011101; // technically supported locales
public function domain() : string // our subdomain / locale in web context
{
return match ($this)
{
self::EN => 'en',
self::KR => 'kt',
self::FR => 'fr',
self::DE => 'de',
self::CN => 'cn',
self::TW => 'tw',
self::ES => 'es',
self::MX => 'mx',
self::RU => 'ru',
self::JP => 'jp',
self::PT => 'pt',
self::IT => 'it'
};
}
public function json() : string // internal usage / json string
{
return match ($this)
{
self::EN => 'enus',
self::KR => 'kokr',
self::FR => 'frfr',
self::DE => 'dede',
self::CN => 'zhcn',
self::TW => 'zhtw',
self::ES => 'eses',
self::MX => 'esmx',
self::RU => 'ruru',
self::JP => 'jajp',
self::PT => 'ptpt',
self::IT => 'itit'
};
}
public function title() : string // localized language name
{
return match ($this)
{
self::EN => 'English',
self::KR => '한국어',
self::FR => 'Français',
self::DE => 'Deutsch',
self::CN => '简体中文',
self::TW => '繁體中文',
self::ES => 'Español',
self::MX => 'Mexicano',
self::RU => 'Русский',
self::JP => '日本語',
self::PT => 'Português',
self::IT => 'Italiano'
};
}
public function gameDirs() : array // setup data source / wow client locale code
{
return match ($this)
{
self::EN => ['enGB', 'enUS', ''],
self::KR => ['koKR'],
self::FR => ['frFR'],
self::DE => ['deDE'],
self::CN => ['zhCN', 'enCN'],
self::TW => ['zhTW', 'enTW'],
self::ES => ['esES'],
self::MX => ['esMX'],
self::RU => ['ruRU'],
self::JP => ['jaJP'],
self::PT => ['ptPT', 'ptBR'],
self::IT => ['itIT']
};
}
public function httpCode() : array // HTTP_ACCEPT_LANGUAGE
{
return match ($this)
{
self::EN => ['en', 'en-au', 'en-bz', 'en-ca', 'en-ie', 'en-jm', 'en-nz', 'en-ph', 'en-za', 'en-tt', 'en-gb', 'en-us', 'en-zw'],
self::KR => ['ko', 'ko-kp', 'ko-kr'],
self::FR => ['fr', 'fr-be', 'fr-ca', 'fr-fr', 'fr-lu', 'fr-mc', 'fr-ch'],
self::DE => ['de', 'de-at', 'de-de', 'de-li', 'de-lu', 'de-ch'],
self::CN => ['zh', 'zh-hk', 'zh-cn', 'zh-sg'],
self::TW => ['tw', 'zh-tw'],
self::ES => ['es', 'es-ar', 'es-bo', 'es-cl', 'es-co', 'es-cr', 'es-do', 'es-ec', 'es-sv', 'es-gt', 'es-hn', 'es-ni', 'es-pa', 'es-py', 'es-pe', 'es-pr', 'es-es', 'es-uy', 'es-ve'],
self::MX => ['mx', 'es-mx'],
self::RU => ['ru', 'ru-mo'],
self::JP => ['ja'],
self::PT => ['pt', 'pt-br'],
self::IT => ['it', 'it-ch']
};
}
public function isLogographic() : bool
{
return $this == Locale::CN || $this == Locale::TW || $this == Locale::KR;
}
public function validate() : ?self
{
return ($this->maskBit() & self::MASK_ALL & (Cfg::get('LOCALES') ?: 0xFFFF)) ? $this : null;
}
public function maskBit() : int
{
return (1 << $this->value);
}
public static function tryFromDomain(string $str) : ?self
{
foreach (self::cases() as $l)
if ($l->validate() && $str == $l->domain())
return $l;
return null;
}
public static function tryFromHttpAcceptLanguage(string $httpAccept) : ?self
{
if (!$httpAccept)
return null;
$available = [];
// e.g.: de,de-DE;q=0.9,en;q=0.8,en-GB;q=0.7,en-US;q=0.6
foreach (explode(',', $_SERVER['HTTP_ACCEPT_LANGUAGE']) as $loc)
if (preg_match('/([a-z\-]+)(?:\s*;\s*q\s*=\s*([\.\d]+))?/ui', $loc, $m, PREG_UNMATCHED_AS_NULL))
$available[Util::lower($m[1])] = floatVal($m[2] ?? 1); // no quality set: assume 100%
arsort($available, SORT_NUMERIC); // highest quality on top
foreach ($available as $code => $_)
foreach (self::cases() as $l)
if ($l->validate() && in_array($code, $l->httpCode()))
return $l;
return null;
}
public static function getFallback() : self
{
foreach (Locale::cases() as $l)
if ($l->validate())
return $l;
// wow, you really fucked up your config mate!
trigger_error('Locale::getFallback - there are no valid locales', E_USER_ERROR);
return self::EN;
}
}
/* The shape of things to come */
class LocString
{
private WeakMap $store;
public function __construct(array $data, string $key = 'name', ?callable $callback = null)
{
$this->store = new WeakMap();
$callback ??= fn($x) => $x;
if (!array_filter($data, fn($v, $k) => $v && strstr($k, $key.'_loc'), ARRAY_FILTER_USE_BOTH))
trigger_error('LocString - is entrirely empty', E_USER_WARNING);
foreach (Locale::cases() as $l)
$this->store[$l] = (string)$callback($data[$key.'_loc'.$l->value] ?? '');
}
public function __toString() : string
{
if ($str = $this->store[Lang::getLocale()])
return $str;
foreach (Locale::cases() as $l) // desired loc not set, use any other
if ($str = $this->store[$l])
return Cfg::get('DEBUG') ? '['.$str.']' : $str;
return Cfg::get('DEBUG') ? '[LOCSTRING]' : '';
}
}
?>

View File

@@ -918,16 +918,18 @@ class SmartAI
$this->jsGlobals[Type::NPC][] = $e['param'][1];
break;
case SAI_EVENT_LINK: // 61 - Used to link together multiple events as a chain of events.
$e['param'][10] = LANG::concat(DB::World()->selectCol('SELECT CONCAT("#[b]", id, "[/b]") FROM smart_scripts WHERE link = ?d AND entryorguid = ?d AND source_type = ?d', $this->itr['id'], $this->entry, $this->srcType), false);
if ($links = DB::World()->selectCol('SELECT `id` FROM smart_scripts WHERE `link` = ?d AND `entryorguid` = ?d AND `source_type` = ?d', $this->itr['id'], $this->entry, $this->srcType))
$e['param'][10] = LANG::concat($links, false, fn($x) => "#[b]".$x."[/b]");
break;
case SAI_EVENT_GOSSIP_SELECT: // 62 - On gossip clicked (gossip_menu_option335).
$gmo = DB::World()->selectRow('SELECT gmo.OptionText AS text_loc0 {, gmol.OptionText AS text_loc?d}
FROM gossip_menu_option gmo LEFT JOIN gossip_menu_option_locale gmol ON gmo.MenuID = gmol.MenuID AND gmo.OptionID = gmol.OptionID AND gmol.Locale = ?d
WHERE gmo.MenuId = ?d AND gmo.OptionID = ?d',
User::$localeId ? Util::$localeStrings[User::$localeId] : DBSIMPLE_SKIP,
User::$localeId,
$e['param'][0],
$e['param'][1]
$gmo = DB::World()->selectRow(
'SELECT gmo.`OptionText` AS "text_loc0" {, gmol.`OptionText` AS text_loc?d }
FROM gossip_menu_option gmo
LEFT JOIN gossip_menu_option_locale gmol ON gmo.`MenuID` = gmol.`MenuID` AND gmo.`OptionID` = gmol.`OptionID` AND gmol.`Locale` = ?d
WHERE gmo.`MenuId` = ?d AND gmo.`OptionID` = ?d',
Lang::getLocale() != Locale::EN ? Lang::getLocale()->json() : DBSIMPLE_SKIP,
Lang::getLocale()->value,
$e['param'][0], $e['param'][1]
);
if ($gmo)
@@ -941,11 +943,11 @@ class SmartAI
break;
case SAI_EVENT_DISTANCE_CREATURE: // 75 - On creature guid OR any instance of creature entry is within distance.
if ($e['param'][0])
$e['param'][10] = DB::World()->selectCell('SELECT id FROM creature WHERE guid = ?d', $e['param'][0]);
$e['param'][10] = DB::World()->selectCell('SELECT `id` FROM creature WHERE `guid` = ?d', $e['param'][0]);
// do not break;
case SAI_EVENT_DISTANCE_GAMEOBJECT: // 76 - On gameobject guid OR any instance of gameobject entry is within distance.
if ($e['param'][0] && !$e['param'][10])
$e['param'][10] = DB::World()->selectCell('SELECT id FROM gameobject WHERE guid = ?d', $e['param'][0]);
$e['param'][10] = DB::World()->selectCell('SELECT `id` FROM gameobject WHERE `guid` = ?d', $e['param'][0]);
else if ($e['param'][1])
$e['param'][10] = $e['param'][1];
else if (!$e['param'][10])
@@ -1244,7 +1246,7 @@ class SmartAI
JOIN ?_taxinodes tn1 ON tp.startNodeId = tn1.id
JOIN ?_taxinodes tn2 ON tp.endNodeId = tn2.id
WHERE tp.id = ?d',
User::$localeId, User::$localeId, User::$localeId, User::$localeId, $a['param'][0]
Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $a['param'][0]
);
$a['param'][6] = Util::localizedString($nodes, 'start');
$a['param'][7] = Util::localizedString($nodes, 'end');

View File

@@ -343,9 +343,9 @@ class AchievementListFilter extends Filter
{
$_ = [];
if (isset($_v['ex']) && $_v['ex'] == 'on')
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'reward_loc'.User::$localeId, 'description_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'reward_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]);
else
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
if ($_)
$parts[] = $_;

View File

@@ -353,9 +353,9 @@ class CreatureListFilter extends Filter
{
$_ = [];
if (isset($_v['ex']) && $_v['ex'] == 'on')
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'subname_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'subname_loc'.Lang::getLocale()->value]);
else
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
if ($_)
$parts[] = $_;

View File

@@ -13,7 +13,7 @@ class EnchantmentList extends BaseType
public static $dataTable = '?_itemenchantment';
private $jsonStats = [];
private $relSpells = [];
private SpellList $relSpells;
private $triggerIds = [];
protected $queryBase = 'SELECT ie.*, ie.id AS ARRAY_KEY FROM ?_itemenchantment ie';
@@ -26,6 +26,8 @@ class EnchantmentList extends BaseType
{
parent::__construct($conditions, $miscData);
$relSpells = [];
// post processing
foreach ($this->iterate() as &$curTpl)
{
@@ -40,15 +42,15 @@ class EnchantmentList extends BaseType
case ENCHANTMENT_TYPE_COMBAT_SPELL:
$proc = -$this->getField('ppmRate') ?: ($this->getField('procChance') ?: $this->getField('amount'.$i));
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_HIT, $curTpl['charges'], $proc];
$this->relSpells[] = $curTpl['object'.$i];
$relSpells[] = $curTpl['object'.$i];
break;
case ENCHANTMENT_TYPE_EQUIP_SPELL:
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_EQUIP, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
$relSpells[] = $curTpl['object'.$i];
break;
case ENCHANTMENT_TYPE_USE_SPELL:
$curTpl['spells'][$i] = [$curTpl['object'.$i], SPELL_TRIGGER_USE, $curTpl['charges'], 0];
$this->relSpells[] = $curTpl['object'.$i];
$relSpells[] = $curTpl['object'.$i];
break;
}
}
@@ -56,8 +58,8 @@ class EnchantmentList extends BaseType
$this->jsonStats[$this->id] = (new StatsContainer)->fromJson($curTpl, true);
}
if ($this->relSpells)
$this->relSpells = new SpellList(array(['id', $this->relSpells]));
if ($relSpells)
$this->relSpells = new SpellList(array(['id', $relSpells]));
}
// use if you JUST need the name
@@ -241,7 +243,7 @@ class EnchantmentListFilter extends Filter
//string
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
$parts[] = $_;
// type

View File

@@ -180,7 +180,7 @@ class GameObjectListFilter extends Filter
// name
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
$parts[] = $_;
return $parts;

View File

@@ -1935,7 +1935,7 @@ class ItemListFilter extends Filter
104 => [FILTER_CR_STRING, 'description', STR_LOCALIZED ], // flavortext
105 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 1 ], // dropsinnormal [heroicdungeon-any]
106 => [FILTER_CR_CALLBACK, 'cbDropsInInstance', SRC_FLAG_DUNGEON_DROP, 2 ], // dropsinheroic [heroicdungeon-any]
107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.User::$localeId, $cr[2]]
107 => [FILTER_CR_NYI_PH, null, 1, ], // effecttext [str] not yet parsed ['effectsParsed_loc'.Lang::getLocale()->value, $cr[2]]
109 => [FILTER_CR_CALLBACK, 'cbArmorBonus', null, null ], // armorbonus [op] [int]
111 => [FILTER_CR_NUMERIC, 'requiredSkillRank', NUM_CAST_INT, true ], // reqskillrank
113 => [FILTER_CR_FLAG, 'cuFlags', CUSTOM_HAS_SCREENSHOT ], // hasscreenshots
@@ -2122,7 +2122,7 @@ class ItemListFilter extends Filter
// name
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
$parts[] = $_;
// usable-by (not excluded by requiredClass && armor or weapons match mask from ?_classes)
@@ -2277,7 +2277,7 @@ class ItemListFilter extends Filter
$n = preg_replace(Filter::PATTERN_NAME, '', $cr[2]);
$n = $this->transformString($n, false);
$randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', User::$localeId, User::$localeId, $n);
$randIds = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, ABS(`id`) AS `id`, name_loc?d, `name_loc0` FROM ?_itemrandomenchant WHERE name_loc?d LIKE ?', Lang::getLocale()->value, Lang::getLocale()->value, $n);
$tplIds = $randIds ? DB::World()->select('SELECT `entry`, `ench` FROM item_enchantment_template WHERE `ench` IN (?a)', array_column($randIds, 'id')) : [];
foreach ($tplIds as &$set)
{

View File

@@ -211,7 +211,7 @@ class ItemsetListFilter extends Filter
// name [str]
if (isset($_v['na']))
if ($_ = $this->modularizeString(['name_loc'.User::$localeId]))
if ($_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]))
$parts[] = $_;
// quality [enum]

View File

@@ -498,9 +498,9 @@ class QuestListFilter extends Filter
{
$_ = [];
if (isset($_v['ex']) && $_v['ex'] == 'on')
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'objectives_loc'.User::$localeId, 'details_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'objectives_loc'.Lang::getLocale()->value, 'details_loc'.Lang::getLocale()->value]);
else
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
if ($_)
$parts[] = $_;

View File

@@ -1436,8 +1436,8 @@ class SpellList extends BaseType
$this->charLevel = $level;
// step -1: already handled?
if (isset($this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive]))
return $this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive];
if (isset($this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive]))
return $this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive];
// step 0: get text
$data = $this->getField($type, true);
@@ -1543,7 +1543,7 @@ class SpellList extends BaseType
$data = strtr($data, ["\r" => '', "\n" => '<br />']);
// cache result
$this->parsedText[$this->id][$type][User::$localeId][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]];
$this->parsedText[$this->id][$type][Lang::getLocale()->value][$this->charLevel][(int)$this->interactive] = [$data, $relSpells, $this->scaling[$this->id]];
return [$data, $relSpells, $this->scaling[$this->id]];
}
@@ -2451,9 +2451,9 @@ class SpellListFilter extends Filter
{
$_ = [];
if (isset($_v['ex']) && $_v['ex'] == 'on')
$_ = $this->modularizeString(['name_loc'.User::$localeId, 'buff_loc'.User::$localeId, 'description_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value, 'buff_loc'.Lang::getLocale()->value, 'description_loc'.Lang::getLocale()->value]);
else
$_ = $this->modularizeString(['name_loc'.User::$localeId]);
$_ = $this->modularizeString(['name_loc'.Lang::getLocale()->value]);
if ($_)
$parts[] = $_;

View File

@@ -45,9 +45,13 @@ class TitleList extends BaseType
unset($_curTpl['src3']);
// shorthand for more generic access
foreach (Util::$localeStrings as $i => $str)
if ($str)
$_curTpl['name_loc'.$i] = trim(str_replace('%s', '', $_curTpl['male_loc'.$i]));
// i don't see it being used anywhere..?
/*
foreach (Locale::cases() as $loc)
if ($loc->validate())
$_curTpl['name'] = new LocString($_curTpl, 'male', fn($x) => trim(str_replace('%s', '', $x)));
// $_curTpl['name_loc'.$loc->value] = trim(str_replace('%s', '', $_curTpl['male_loc'.$loc->value]));
*/
}
}

View File

@@ -6,28 +6,34 @@ if (!defined('AOWOW_REVISION'))
class User
{
public static $id = 0;
public static $displayName = '';
public static $banStatus = 0x0; // see ACC_BAN_* defines
public static $groups = 0x0;
public static $perms = 0;
public static $localeId = 0;
public static $localeString = 'enus';
public static $avatar = 'inv_misc_questionmark';
public static $dailyVotes = 0;
public static int $id = 0;
public static string $displayName = '';
public static int $banStatus = 0x0; // see ACC_BAN_* defines
public static int $groups = 0x0;
public static int $perms = 0;
public static string $avatar = 'inv_misc_questionmark';
public static int $dailyVotes = 0;
public static $ip = null;
private static $reputation = 0;
private static $dataKey = '';
private static $expires = false;
private static $passHash = '';
private static $excludeGroups = 1;
private static $profiles = null;
private static int $reputation = 0;
private static string $dataKey = '';
private static bool $expires = false;
private static string $passHash = '';
private static int $excludeGroups = 1;
public static Locale $preferedLoc;
private static LocalProfileList $profiles;
public static function init()
{
self::setIP();
self::setLocale();
if (isset($_SESSION['locale']) && $_SESSION['locale'] instanceof Locale)
self::$preferedLoc = $_SESSION['locale']->validate() ?? Locale::getFallback();
else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]) && ($loc = Locale::tryFromHttpAcceptLanguage($_SERVER["HTTP_ACCEPT_LANGUAGE"])))
self::$preferedLoc = $loc;
else
self::$preferedLoc = Locale::getFallback();
// session have a dataKey to access the JScripts (yes, also the anons)
if (empty($_SESSION['dataKey']))
@@ -39,12 +45,12 @@ class User
return false;
// check IP bans
if ($ipBan = DB::Aowow()->selectRow('SELECT count, unbanDate FROM ?_account_bannedips WHERE ip = ? AND type = 0', self::$ip))
if ($ipBan = DB::Aowow()->selectRow('SELECT `count`, `unbanDate` FROM ?_account_bannedips WHERE `ip` = ? AND `type` = 0', self::$ip))
{
if ($ipBan['count'] > Cfg::get('ACC_FAILED_AUTH_COUNT') && $ipBan['unbanDate'] > time())
return false;
else if ($ipBan['unbanDate'] <= time())
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE ip = ?', self::$ip);
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `ip` = ?', self::$ip);
}
// try to restore session
@@ -55,36 +61,39 @@ class User
if (!empty($_SESSION['timeout']) && $_SESSION['timeout'] <= time())
return false;
$query = DB::Aowow()->SelectRow('
SELECT a.id, a.passHash, a.displayName, a.locale, a.userGroups, a.userPerms, a.allowExpire, BIT_OR(ab.typeMask) AS bans, IFNULL(SUM(r.amount), 0) as reputation, a.avatar, a.dailyVotes, a.excludeGroups
$uData = DB::Aowow()->SelectRow(
'SELECT a.`id`, a.`passHash`, a.`displayName`, a.`locale`, a.`userGroups`, a.`userPerms`, a.`allowExpire`, BIT_OR(ab.`typeMask`) AS "bans", IFNULL(SUM(r.`amount`), 0) AS "reputation", a.`avatar`, a.`dailyVotes`, a.`excludeGroups`
FROM ?_account a
LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
LEFT JOIN ?_account_reputation r ON a.id = r.userId
WHERE a.id = ?d
GROUP BY a.id',
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
LEFT JOIN ?_account_reputation r ON a.`id` = r.`userId`
WHERE a.`id` = ?d
GROUP BY a.`id`',
$_SESSION['user']
);
if (!$query)
if (!$uData)
return false;
if ($loc = Locale::tryFrom($uData['locale']))
self::$preferedLoc = $loc;
// password changed, terminate session
if (AUTH_MODE_SELF && $query['passHash'] != $_SESSION['hash'])
if (AUTH_MODE_SELF && $uData['passHash'] != $_SESSION['hash'])
{
self::destroy();
return false;
}
self::$id = intval($query['id']);
self::$displayName = $query['displayName'];
self::$passHash = $query['passHash'];
self::$expires = (bool)$query['allowExpire'];
self::$reputation = $query['reputation'];
self::$banStatus = $query['bans'];
self::$groups = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userGroups']);
self::$perms = $query['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($query['userPerms']);
self::$dailyVotes = $query['dailyVotes'];
self::$excludeGroups = $query['excludeGroups'];
self::$id = intVal($uData['id']);
self::$displayName = $uData['displayName'];
self::$passHash = $uData['passHash'];
self::$expires = (bool)$uData['allowExpire'];
self::$reputation = $uData['reputation'];
self::$banStatus = $uData['bans'];
self::$groups = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userGroups']);
self::$perms = $uData['bans'] & (ACC_BAN_TEMP | ACC_BAN_PERM) ? 0 : intval($uData['userPerms']);
self::$dailyVotes = $uData['dailyVotes'];
self::$excludeGroups = $uData['excludeGroups'];
$conditions = array(
[['cuFlags', PROFILER_CU_DELETED, '&'], 0],
@@ -96,11 +105,8 @@ class User
self::$profiles = (new LocalProfileList($conditions));
if ($query['avatar'])
self::$avatar = $query['avatar'];
if (self::$localeId != $query['locale']) // reset, if changed
self::setLocale(intVal($query['locale']));
if ($uData['avatar'])
self::$avatar = $uData['avatar'];
// stuff, that updates on a daily basis goes here (if you keep you session alive indefinitly, the signin-handler doesn't do very much)
// - conscutive visits
@@ -115,10 +121,10 @@ class User
// daily votes (we need to reset this one)
self::$dailyVotes = self::getMaxDailyVotes();
DB::Aowow()->query('
UPDATE ?_account
SET dailyVotes = ?d, prevLogin = curLogin, curLogin = UNIX_TIMESTAMP(), prevIP = curIP, curIP = ?
WHERE id = ?d',
DB::Aowow()->query(
'UPDATE ?_account
SET `dailyVotes` = ?d, `prevLogin` = `curLogin`, `curLogin` = UNIX_TIMESTAMP(), `prevIP` = `curIP`, `curIP` = ?
WHERE `id` = ?d',
self::$dailyVotes,
self::$ip,
self::$id
@@ -131,16 +137,16 @@ class User
// increment consecutive visits (next day or first of new month and not more than 48h)
// i bet my ass i forgott a corner case
if ((date('j', $lastLogin) + 1 == date('j') || (date('j') == 1 && date('n', $lastLogin) != date('n'))) && (time() - $lastLogin) < 2 * DAY)
DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = consecutiveVisits + 1 WHERE id = ?d', self::$id);
DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = `consecutiveVisits` + 1 WHERE `id` = ?d', self::$id);
else
DB::Aowow()->query('UPDATE ?_account SET consecutiveVisits = 0 WHERE id = ?d', self::$id);
DB::Aowow()->query('UPDATE ?_account SET `consecutiveVisits` = 0 WHERE `id` = ?d', self::$id);
}
}
return true;
}
private static function setIP()
private static function setIP() : void
{
$ipAddr = '';
$method = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
@@ -165,68 +171,32 @@ class User
self::$ip = $ipAddr ?: null;
}
/****************/
/* set language */
/****************/
// set and save
public static function setLocale($set = -1)
public static function save(bool $toDB = false)
{
$loc = LOCALE_EN;
$_SESSION['user'] = self::$id;
$_SESSION['hash'] = self::$passHash;
$_SESSION['locale'] = self::$preferedLoc;
$_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0;
// $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
// get
if ($set != -1 && isset(Util::$localeStrings[$set]))
$loc = $set;
else if (isset($_SESSION['locale']) && isset(Util::$localeStrings[$_SESSION['locale']]))
$loc = $_SESSION['locale'];
else if (!empty($_SERVER["HTTP_ACCEPT_LANGUAGE"]))
{
$loc = strtolower(substr($_SERVER["HTTP_ACCEPT_LANGUAGE"], 0, 2));
switch ($loc) {
case 'fr': $loc = LOCALE_FR; break;
case 'de': $loc = LOCALE_DE; break;
case 'zh': $loc = LOCALE_CN; break; // may cause issues in future with zh-tw
case 'es': $loc = LOCALE_ES; break;
case 'ru': $loc = LOCALE_RU; break;
default: $loc = LOCALE_EN;
}
}
// check; pick first viable if failed
$allowedLoc = Cfg::get('LOCALES');
if ($allowedLoc && !($allowedLoc & (1 << $loc)))
{
foreach (Util::$localeStrings as $idx => $__)
{
if ($allowedLoc & (1 << $idx))
{
$loc = $idx;
break;
}
}
}
// set
if (self::$id)
DB::Aowow()->query('UPDATE ?_account SET locale = ? WHERE id = ?', $loc, self::$id);
self::useLocale($loc);
if (self::$id && $toDB)
DB::Aowow()->query('UPDATE ?_account SET `locale` = ? WHERE `id` = ?', self::$preferedLoc->value, self::$id);
}
// only use once
public static function useLocale($use)
public static function destroy()
{
self::$localeId = isset(Util::$localeStrings[$use]) ? $use : LOCALE_EN;
self::$localeString = self::localeString(self::$localeId);
session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id
session_unset();
$_SESSION['locale'] = self::$preferedLoc; // keep locale
$_SESSION['dataKey'] = self::$dataKey; // keep dataKey
self::$id = 0;
self::$displayName = '';
self::$perms = 0;
self::$groups = U_GROUP_NONE;
}
private static function localeString($loc = -1)
{
if (!isset(Util::$localeStrings[$loc]))
$loc = 0;
return Util::$localeStrings[$loc];
}
/*******************/
/* auth mechanisms */
@@ -245,21 +215,21 @@ class User
return AUTH_INTERNAL_ERR;
// handle login try limitation
$ip = DB::Aowow()->selectRow('SELECT ip, count, unbanDate FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
$ip = DB::Aowow()->selectRow('SELECT `ip`, `count`, `unbanDate` FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip);
if (!$ip || $ip['unbanDate'] < time()) // no entry exists or time expired; set count to 1
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (ip, type, count, unbanDate) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK'));
DB::Aowow()->query('REPLACE INTO ?_account_bannedips (`ip`, `type`, `count`, `unbanDate`) VALUES (?, 0, 1, UNIX_TIMESTAMP() + ?d)', self::$ip, Cfg::get('ACC_FAILED_AUTH_BLOCK'));
else // entry already exists; increment count
DB::Aowow()->query('UPDATE ?_account_bannedips SET count = count + 1, unbanDate = UNIX_TIMESTAMP() + ?d WHERE ip = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip);
DB::Aowow()->query('UPDATE ?_account_bannedips SET `count` = `count` + 1, `unbanDate` = UNIX_TIMESTAMP() + ?d WHERE `ip` = ?', Cfg::get('ACC_FAILED_AUTH_BLOCK'), self::$ip);
if ($ip && $ip['count'] >= Cfg::get('ACC_FAILED_AUTH_COUNT') && $ip['unbanDate'] >= time())
return AUTH_IPBANNED;
$query = DB::Aowow()->SelectRow('
SELECT a.id, a.passHash, BIT_OR(ab.typeMask) AS bans, a.status
$query = DB::Aowow()->SelectRow(
'SELECT a.`id`, a.`passHash`, BIT_OR(ab.`typeMask`) AS "bans", a.`status`
FROM ?_account a
LEFT JOIN ?_account_banned ab ON a.id = ab.userId AND ab.end > UNIX_TIMESTAMP()
WHERE a.user = ?
GROUP BY a.id',
LEFT JOIN ?_account_banned ab ON a.`id` = ab.`userId` AND ab.`end` > UNIX_TIMESTAMP()
WHERE a.`user` = ?
GROUP BY a.`id`',
$name
);
if (!$query)
@@ -270,7 +240,7 @@ class User
return AUTH_WRONGPASS;
// successfull auth; clear bans for this IP
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE type = 0 AND ip = ?', self::$ip);
DB::Aowow()->query('DELETE FROM ?_account_bannedips WHERE `type` = 0 AND `ip` = ?', self::$ip);
if ($query['bans'] & (ACC_BAN_PERM | ACC_BAN_TEMP))
return AUTH_BANNED;
@@ -304,10 +274,19 @@ class User
case AUTH_MODE_EXTERNAL:
{
if (!file_exists('config/extAuth.php'))
{
trigger_error('config/extAuth.php not found');
return AUTH_INTERNAL_ERR;
}
require 'config/extAuth.php';
if (!function_exists('extAuth'))
{
trigger_error('external auth function extAuth() not defined in config/extAuth.php');
return AUTH_INTERNAL_ERR;
}
$extGroup = -1;
$result = extAuth($name, $pass, $extId, $extGroup);
@@ -335,27 +314,22 @@ class User
return AUTH_OK;
}
// create a linked account for our settings if nessecary
private static function checkOrCreateInDB($extId, $name, $userGroup = -1)
// create a linked account for our settings if necessary
private static function checkOrCreateInDB(int $extId, string $name, int $userGroup = -1) : int
{
if (!intVal($extId))
return 0;
$userGroup = intVal($userGroup);
if ($_ = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE extId = ?d', $extId))
if ($_ = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `extId` = ?d', $extId))
{
if ($userGroup >= U_GROUP_NONE)
DB::Aowow()->query('UPDATE ?_account SET userGroups = ?d WHERE extId = ?d', $userGroup, $extId);
DB::Aowow()->query('UPDATE ?_account SET `userGroups` = ?d WHERE `extId` = ?d', $userGroup, $extId);
return $_;
}
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (extId, user, displayName, joinDate, prevIP, prevLogin, locale, status, userGroups) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
$newId = DB::Aowow()->query('INSERT IGNORE INTO ?_account (`extId`, `user`, `displayName`, `joinDate`, `prevIP`, `prevLogin`, `locale`, `status`, `userGroups`) VALUES (?d, ?, ?, UNIX_TIMESTAMP(), ?, UNIX_TIMESTAMP(), ?d, ?d, ?d)',
$extId,
$name,
Util::ucFirst($name),
isset($_SERVER["REMOTE_ADDR"]) ? $_SERVER["REMOTE_ADDR"] : '',
User::$localeId,
$_SERVER["REMOTE_ADDR"] ?? '',
self::$preferedLoc->value,
ACC_STATUS_OK,
$userGroup >= U_GROUP_NONE ? $userGroup : U_GROUP_NONE
);
@@ -439,39 +413,17 @@ class User
return $errCode == 0;
}
public static function save()
{
$_SESSION['user'] = self::$id;
$_SESSION['hash'] = self::$passHash;
$_SESSION['locale'] = self::$localeId;
$_SESSION['timeout'] = self::$expires ? time() + Cfg::get('SESSION_TIMEOUT_DELAY') : 0;
// $_SESSION['dataKey'] does not depend on user login status and is set in User::init()
}
public static function destroy()
{
session_regenerate_id(true); // session itself is not destroyed; status changed => regenerate id
session_unset();
$_SESSION['locale'] = self::$localeId; // keep locale
$_SESSION['dataKey'] = self::$dataKey; // keep dataKey
self::$id = 0;
self::$displayName = '';
self::$perms = 0;
self::$groups = U_GROUP_NONE;
}
/*********************/
/* access management */
/*********************/
public static function isInGroup($group)
public static function isInGroup($group) : bool
{
return (self::$groups & $group) != 0;
}
public static function canComment()
public static function canComment() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -479,7 +431,7 @@ class User
return self::$perms || self::$reputation >= Cfg::get('REP_REQ_COMMENT');
}
public static function canReply()
public static function canReply() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -487,7 +439,7 @@ class User
return self::$perms || self::$reputation >= Cfg::get('REP_REQ_REPLY');
}
public static function canUpvote()
public static function canUpvote() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_COMMENT | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -495,7 +447,7 @@ class User
return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_UPVOTE') && self::$dailyVotes > 0);
}
public static function canDownvote()
public static function canDownvote() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -503,7 +455,7 @@ class User
return self::$perms || (self::$reputation >= Cfg::get('REP_REQ_DOWNVOTE') && self::$dailyVotes > 0);
}
public static function canSupervote()
public static function canSupervote() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_RATE | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -511,7 +463,7 @@ class User
return self::$reputation >= Cfg::get('REP_REQ_SUPERVOTE');
}
public static function canUploadScreenshot()
public static function canUploadScreenshot() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_SCREENSHOT | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -519,7 +471,7 @@ class User
return true;
}
public static function canWriteGuide()
public static function canWriteGuide() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_GUIDE | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -527,7 +479,7 @@ class User
return true;
}
public static function canSuggestVideo()
public static function canSuggestVideo() : bool
{
if (!self::$id || self::$banStatus & (ACC_BAN_VIDEO | ACC_BAN_PERM | ACC_BAN_TEMP))
return false;
@@ -535,27 +487,28 @@ class User
return true;
}
public static function isPremium()
public static function isPremium() : bool
{
return self::isInGroup(U_GROUP_PREMIUM) || self::$reputation >= Cfg::get('REP_REQ_PREMIUM');
}
/**************/
/* js-related */
/**************/
public static function decrementDailyVotes()
public static function decrementDailyVotes() : void
{
self::$dailyVotes--;
DB::Aowow()->query('UPDATE ?_account SET dailyVotes = ?d WHERE id = ?d', self::$dailyVotes, self::$id);
DB::Aowow()->query('UPDATE ?_account SET `dailyVotes` = ?d WHERE `id` = ?d', self::$dailyVotes, self::$id);
}
public static function getCurDailyVotes()
public static function getCurrentDailyVotes() : int
{
return self::$dailyVotes;
}
public static function getMaxDailyVotes()
public static function getMaxDailyVotes() : int
{
if (!self::$id || self::$banStatus & (ACC_BAN_PERM | ACC_BAN_TEMP))
return 0;
@@ -563,12 +516,12 @@ class User
return Cfg::get('USER_MAX_VOTES') + (self::$reputation >= Cfg::get('REP_REQ_VOTEMORE_BASE') ? 1 + intVal((self::$reputation - Cfg::get('REP_REQ_VOTEMORE_BASE')) / Cfg::get('REP_REQ_VOTEMORE_ADD')) : 0);
}
public static function getReputation()
public static function getReputation() : int
{
return self::$reputation;
}
public static function getUserGlobals()
public static function getUserGlobals() : array
{
$gUser = array(
'id' => self::$id,
@@ -613,34 +566,34 @@ class User
return $gUser;
}
public static function getWeightScales()
public static function getWeightScales() : array
{
$result = [];
$res = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, name FROM ?_account_weightscales WHERE userId = ?d', self::$id);
$res = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `name` FROM ?_account_weightscales WHERE `userId` = ?d', self::$id);
if (!$res)
return $result;
$weights = DB::Aowow()->selectCol('SELECT id AS ARRAY_KEY, `field` AS ARRAY_KEY2, val FROM ?_account_weightscale_data WHERE id IN (?a)', array_keys($res));
$weights = DB::Aowow()->selectCol('SELECT `id` AS ARRAY_KEY, `field` AS ARRAY_KEY2, `val` FROM ?_account_weightscale_data WHERE `id` IN (?a)', array_keys($res));
foreach ($weights as $id => $data)
$result[] = array_merge(['name' => $res[$id], 'id' => $id], $data);
return $result;
}
public static function getProfilerExclusions()
public static function getProfilerExclusions() : array
{
$result = [];
$modes = [1 => 'excludes', 2 => 'includes'];
foreach ($modes as $mode => $field)
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, typeId AS ARRAY_KEY2, typeId FROM ?_account_excludes WHERE mode = ?d AND userId = ?d', $mode, self::$id))
if ($ex = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `typeId` FROM ?_account_excludes WHERE `mode` = ?d AND `userId` = ?d', $mode, self::$id))
foreach ($ex as $type => $ids)
$result[$field][$type] = array_values($ids);
return $result;
}
public static function getCharacters()
public static function getCharacters() : array
{
if (!self::$profiles)
return [];
@@ -648,7 +601,7 @@ class User
return self::$profiles->getJSGlobals(PROFILEINFO_CHARACTER);
}
public static function getProfiles()
public static function getProfiles() : array
{
if (!self::$profiles)
return [];
@@ -675,7 +628,7 @@ class User
return [];
}
public static function getGuides()
public static function getGuides() : array
{
$result = [];
@@ -689,17 +642,17 @@ class User
return $result;
}
public static function getCookies()
public static function getCookies() : array
{
$data = [];
if (self::$id)
$data = DB::Aowow()->selectCol('SELECT name AS ARRAY_KEY, data FROM ?_account_cookies WHERE userId = ?d', self::$id);
$data = DB::Aowow()->selectCol('SELECT `name` AS ARRAY_KEY, `data` FROM ?_account_cookies WHERE `userId` = ?d', self::$id);
return $data;
}
public static function getFavorites()
public static function getFavorites() : array
{
if (!self::$id)
return [];

View File

@@ -77,22 +77,6 @@ trait TrRequestData
return 0;
}
private static function checkLocale(string $val) : int
{
if (preg_match('/^'.implode('|', array_keys(array_filter(Util::$localeStrings))).'$/', $val))
return intVal($val);
return -1;
}
private static function checkDomain(string $val) : string
{
if (preg_match('/^'.implode('|', array_filter(Util::$subDomains)).'$/i', $val))
return strtolower($val);
return '';
}
private static function checkIdList(string $val) : array
{
if (preg_match('/^-?\d+(,-?\d+)*$/', $val))
@@ -538,14 +522,6 @@ abstract class Util
private static $perfectGems = null;
public static $localeStrings = array( // zero-indexed
'enus', null, 'frfr', 'dede', 'zhcn', null, 'eses', null, 'ruru'
);
public static $subDomains = array(
'en', null, 'fr', 'de', 'cn', null, 'es', null, 'ru'
);
public static $regions = array(
'us', 'eu', 'kr', 'tw', 'cn', 'dev'
);
@@ -919,19 +895,19 @@ abstract class Util
$silent = true;
// default case: selected locale available
if (!empty($data[$field.'_loc'.User::$localeId]))
return $data[$field.'_loc'.User::$localeId];
if (!empty($data[$field.'_loc'.Lang::getLocale()->value]))
return $data[$field.'_loc'.Lang::getLocale()->value];
// locale not enUS; aowow-type localization available; add brackets if not silent
else if (User::$localeId != LOCALE_EN && !empty($data[$field.'_loc0']))
else if (Lang::getLocale() != Locale::EN && !empty($data[$field.'_loc0']))
return $silent ? $data[$field.'_loc0'] : '['.$data[$field.'_loc0'].']';
// locale not enUS; TC localization; add brackets if not silent
else if (User::$localeId != LOCALE_EN && !empty($data[$field]))
else if (Lang::getLocale() != Locale::EN && !empty($data[$field]))
return $silent ? $data[$field] : '['.$data[$field].']';
// locale enUS; TC localization; return normal
else if (User::$localeId == LOCALE_EN && !empty($data[$field]))
else if (Lang::getLocale() == Locale::EN && !empty($data[$field]))
return $data[$field];
// nothing to find; be empty
@@ -969,22 +945,6 @@ abstract class Util
return Lang::item('ratingString', [$statId, $result, $level]);
}
public static function powerUseLocale(string $domain = 'en') : void
{
foreach (Util::$subDomains as $k => $v)
{
if ($domain != $v)
continue;
User::useLocale($k);
Lang::load($k);
return;
}
User::useLocale(LOCALE_EN);
Lang::load(LOCALE_EN);
}
// default ucFirst doesn't convert UTF-8 chars
public static function ucFirst($str)
{
@@ -1097,8 +1057,8 @@ abstract class Util
$success = true;
if ($localized)
{
if (file_exists('datasets/'.User::$localeString.'/'.$file))
$result .= file_get_contents('datasets/'.User::$localeString.'/'.$file);
if (file_exists('datasets/'.Lang::getLocale()->json().'/'.$file))
$result .= file_get_contents('datasets/'.Lang::getLocale()->json().'/'.$file);
else if (file_exists('datasets/enus/'.$file))
$result .= file_get_contents('datasets/enus/'.$file);
else

View File

@@ -121,7 +121,7 @@ switch ($pageCall)
if (is_callable([$classInstance, 'display']))
$classInstance->display();
else if (isset($_GET['power']))
die('$WowheadPower.register(0, '.User::$localeId.', {})');
die('$WowheadPower.register(0, '.Lang::getLocale()->value.', {})');
else // in conjunction with a proper rewriteRule in .htaccess...
(new GenericPage($pageCall))->error();
}
@@ -153,7 +153,7 @@ switch ($pageCall)
break;
default: // unk parameter given -> ErrorPage
if (isset($_GET['power']))
die('$WowheadPower.register(0, '.User::$localeId.', {})');
die('$WowheadPower.register(0, '.Lang::getLocale()->value.', {})');
else // in conjunction with a proper rewriteRule in .htaccess...
(new GenericPage($pageCall))->error();
break;

View File

@@ -44,28 +44,21 @@ class Lang
private static $emote;
private static $enchantment;
private static $locId;
private static $locales = array(
LOCALE_EN => 'English',
LOCALE_FR => 'Français',
LOCALE_DE => 'Deutsch',
LOCALE_CN => '简体中文',
LOCALE_ES => 'Español',
LOCALE_RU => 'Русский'
);
private static ?Locale $locale = null;
public const FMT_RAW = 0;
public const FMT_HTML = 1;
public const FMT_MARKUP = 2;
public static function load(int $locale) : void
public static function load(Locale $loc) : void
{
if (!isset(Util::$localeStrings[$locale]))
die($locale.' is not a known locale!');
if (!file_exists('localization/locale_'.Util::$localeStrings[$locale].'.php'))
die('File for locale '.$locale.' not found.');
if (self::$locale == $loc)
return;
if (!file_exists('localization/locale_'.$loc->json().'.php'))
die('File for locale '.$loc->name.' not found.');
else
require 'localization/locale_'.Util::$localeStrings[$locale].'.php';
require 'localization/locale_'.$loc->json().'.php';
foreach ($lang as $k => $v)
self::$$k = $v;
@@ -75,10 +68,15 @@ class Lang
self::$item['cat'][2][1][14] .= ' ('.self::$item['cat'][2][0].')';
self::$main['moreTitles']['privilege'] = self::$privileges['_privileges'];
self::$locId = $locale;
self::$locale = $loc;
}
public static function __callStatic(string $prop, array $args) // : ?string|array
public static function getLocale() : Locale
{
return self::$locale;
}
public static function __callStatic(string $prop, ?array $args = []) : string|array|null
{
$vspfArgs = [];
foreach ($args as $i => $arg)
@@ -96,9 +94,11 @@ class Lang
$dbt = debug_backtrace()[0];
$file = explode(DIRECTORY_SEPARATOR, $dbt['file']);
trigger_error('Lang - undefined property Lang::$'.$prop.'[\''.implode('\'][\'', $args).'\'], called in '.array_pop($file).':'.$dbt['line'], E_USER_WARNING);
return null;
}
public static function exist(string $prop, ...$args)
public static function exist(string $prop, string ...$args) : string|array|null
{
if (!isset(self::$$prop))
return null;
@@ -120,12 +120,12 @@ class Lang
$b = '';
$i = 0;
$n = count($args);
$callback ??= fn($x) => $x;
foreach ($args as $k => $arg)
{
if (is_callable($callback))
$b .= $callback($arg, $k);
else
$b .= $arg;
$b .= $callback($arg, $k);
if ($n > 1 && $i < ($n - 2))
$b .= ', ';
@@ -192,13 +192,13 @@ class Lang
foreach ($row as &$r)
$r = implode(' ', $r);
switch ($fmt)
$separator = match ($fmt)
{
case self::FMT_HTML: $separator = '<br />'; break;
case self::FMT_MARKUP: $separator = '[br]'; break;
case self::FMT_RAW:
default: $separator = "\n"; break;
}
self::FMT_HTML => '<br />',
self::FMT_MARKUP => '[br]',
self::FMT_RAW => "\n",
default => "\n"
};
return implode($separator, $row);
}
@@ -223,20 +223,20 @@ class Lang
}
// todo: expand
public static function getInfoBoxForFlags(int $flags) : array
public static function getInfoBoxForFlags(int $cuFlags) : array
{
$tmp = [];
if ($flags & CUSTOM_DISABLED)
if ($cuFlags & CUSTOM_DISABLED)
$tmp[] = '[tooltip name=disabledHint]'.Util::jsEscape(self::main('disabledHint')).'[/tooltip][span class=tip tooltip=disabledHint]'.Util::jsEscape(self::main('disabled')).'[/span]';
if ($flags & CUSTOM_SERVERSIDE)
if ($cuFlags & CUSTOM_SERVERSIDE)
$tmp[] = '[tooltip name=serversideHint]'.Util::jsEscape(self::main('serversideHint')).'[/tooltip][span class=tip tooltip=serversideHint]'.Util::jsEscape(self::main('serverside')).'[/span]';
if ($flags & CUSTOM_UNAVAILABLE)
if ($cuFlags & CUSTOM_UNAVAILABLE)
$tmp[] = self::main('unavailable');
if ($flags & CUSTOM_EXCLUDE_FOR_LISTVIEW && User::isInGroup(U_GROUP_STAFF))
if ($cuFlags & CUSTOM_EXCLUDE_FOR_LISTVIEW && User::isInGroup(U_GROUP_STAFF))
$tmp[] = '[tooltip name=excludedHint]This entry is excluded from lists and is not searchable.[/tooltip][span tooltip=excludedHint class="tip q10"]Hidden[/span]';
return $tmp;
@@ -246,7 +246,7 @@ class Lang
{
$locks = [];
$ids = [];
$lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE id = ?d', $lockId);
$lock = DB::Aowow()->selectRow('SELECT * FROM ?_lock WHERE `id` = ?d', $lockId);
if (!$lock)
return $locks;
@@ -518,13 +518,13 @@ class Lang
{
$tmp = self::game('difficulty').self::main('colon');
switch ($fmt)
$base = match ($fmt)
{
case self::FMT_HTML: $base = '<span class="r%1$d">%2$s</span> '; break;
case self::FMT_MARKUP: $base = '[color=r%1$d]%2$s[/color] '; break;
case self::FMT_RAW:
default: $base = '%2$s '; break;
}
self::FMT_HTML => '<span class="r%1$d">%2$s</span> ',
self::FMT_MARKUP => '[color=r%1$d]%2$s[/color] ',
self::FMT_RAW => '%2$s ',
default => '%2$s '
};
for ($i = 0; $i < 4; $i++)
if (!empty($bp[$i]))
@@ -594,7 +594,7 @@ class Lang
return '';
}
private static function vspf(/* array|string */ $var, array $args = []) // : array|string
private static function vspf(null|array|string $var, array $args = []) : null|array|string
{
if (is_array($var))
{
@@ -775,7 +775,7 @@ class Lang
switch (strtolower($word[1]))
{
case 'h':
if (self::$locId != LOCALE_FR)
if (self::$locale != Locale::FR)
return 'de ' . $word;
case 'a':
case 'e':
@@ -810,7 +810,7 @@ class Lang
{
[$_, $num, $pad, $singular, $plural1, $plural2] = array_pad($m, 6, null);
if (self::$locId != LOCALE_RU || !$plural2)
if (self::$locale != Locale::RU || !$plural2)
return $num . $pad . ($num == 1 ? $singular : $plural1);
// singular - ends in 1, but not teen number

View File

@@ -437,7 +437,7 @@ Markup.printHtml("description text here", "description-generic", { allow: Markup
$this->_post['email'],
User::$ip,
$this->_post['remember_me'] != 'yes',
User::$localeId,
Lang::getLocale()->value,
U_GROUP_PENDING,
ACC_STATUS_NEW,
Cfg::get('ACC_CREATE_SAVE_DECAY'),

View File

@@ -38,7 +38,7 @@ class AchievementPage extends GenericPage
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerAchievement(%d, %d, %s);';
@@ -48,7 +48,7 @@ class AchievementPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -233,7 +233,7 @@ class AchievementPage extends GenericPage
// tab: see also
$conditions = array(
['name_loc'.User::$localeId, $this->subject->getField('name', true)],
['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)],
['id', $this->typeId, '!']
);
$saList = new AchievementList($conditions);
@@ -551,12 +551,12 @@ class AchievementPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
private function createMail(&$reqCss = false)

View File

@@ -87,10 +87,10 @@ class ComparePage extends GenericPage
$si['enchantment'] = implode(', ', $si['enchantment']);
$this->cmpItems[$itemId] = [
'name_'.User::$localeString => $iList->getField('name', true),
'quality' => $iList->getField('quality'),
'icon' => $iList->getField('iconString'),
'jsonequip' => $data[$itemId]
'name_'.Lang::getLocale()->json() => $iList->getField('name', true),
'quality' => $iList->getField('quality'),
'icon' => $iList->getField('iconString'),
'jsonequip' => $data[$itemId]
];
}
}

View File

@@ -17,7 +17,7 @@ class CurrencyPage extends GenericPage
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerCurrency(%d, %d, %s);';
@@ -27,7 +27,7 @@ class CurrencyPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -231,12 +231,12 @@ class CurrencyPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
}

View File

@@ -89,7 +89,7 @@ class EmotePage extends GenericPage
if ($this->subject->getField('cuFlags') & EMOTE_CU_MISSING_CMD)
$text .= Lang::emote('noCommand').'[br][br]';
else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << User::$localeId))
else if ($aliasses = DB::Aowow()->selectCol('SELECT command FROM ?_emotes_aliasses WHERE id = ?d AND locales & ?d', $this->typeId, 1 << Lang::getLocale()->value))
{
$text .= '[h3]'.Lang::emote('aliases').'[/h3][ul]';
foreach ($aliasses as $a)

View File

@@ -19,7 +19,7 @@ class EventPage extends GenericPage
protected $tabId = 0;
protected $mode = CACHE_TYPE_PAGE;
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerHoliday(%d, %d, %s);';
private $hId = 0;
@@ -31,7 +31,7 @@ class EventPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -283,15 +283,15 @@ class EventPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
if ($this->subject->getField('iconString') != 'trade_engineering')
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
protected function postCache()
@@ -309,7 +309,7 @@ class EventPage extends GenericPage
else
{
if ($this->hId)
$this->wowheadLink = sprintf(WOWHEAD_LINK, Util::$subDomains[User::$localeId], 'event', $this->hId);
$this->wowheadLink = sprintf(WOWHEAD_LINK, Lang::getLocale()->domain(), 'event', $this->hId);
/********************/
/* finalize infobox */

View File

@@ -30,7 +30,7 @@ trait TrDetailPage
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
// mode, type, typeId, employee-flag, localeId, category, filter
$key = [$this->mode, $this->type, $this->typeId, $staff, User::$localeId, '-1', '-1'];
$key = [$this->mode, $this->type, $this->typeId, $staff, Lang::getLocale()->value, '-1', '-1'];
// item special: can modify tooltips
if (isset($this->enhancedTT))
@@ -70,7 +70,7 @@ trait TrListPage
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
// mode, type, typeId, employee-flag, localeId,
$key = [$this->mode, $this->type, '-1', $staff, User::$localeId];
$key = [$this->mode, $this->type, '-1', $staff, Lang::getLocale()->value];
//category
$key[] = $this->category ? implode('.', $this->category) : '-1';
@@ -100,7 +100,7 @@ trait TrProfiler
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
// mode, type, typeId, employee-flag, localeId, category, filter
$key = [$this->mode, $this->type, $this->subject->getField('id'), $staff, User::$localeId, '-1', '-1'];
$key = [$this->mode, $this->type, $this->subject->getField('id'), $staff, Lang::getLocale()->value, '-1', '-1'];
return implode('_', $key);
}
@@ -141,7 +141,7 @@ trait TrProfiler
}
}
protected function initialSync() : void
protected function initialSync() : never
{
$this->prepareContent();
@@ -320,7 +320,7 @@ class GenericPage
$this->gFavorites = User::getFavorites();
$this->pageTemplate['pageName'] = strtolower($pageCall);
$this->wowheadLink = sprintf(WOWHEAD_LINK, Util::$subDomains[User::$localeId], $pageCall, $pageParam);
$this->wowheadLink = sprintf(WOWHEAD_LINK,Lang::getLocale()->domain(), $pageCall, $pageParam);
if (!$this->isValidPage())
$this->error();
@@ -495,15 +495,15 @@ class GenericPage
// insert locale string
if ($flags & SC_FLAG_LOCALIZED)
$str = sprintf($str, User::$localeString);
$str = sprintf($str, Lang::getLocale()->json());
if ($dynData)
{
$app[] = 'locale='.User::$localeId;
$app[] = 'locale='.Lang::getLocale()->value;
$app[] = 't='.$_SESSION['dataKey'];
}
else if (($flags & SC_FLAG_APPEND_LOCALE) && User::$localeId)
$app[] = 'lang='.Util::$subDomains[User::$localeId];
else if (($flags & SC_FLAG_APPEND_LOCALE) && Lang::getLocale() != Locale::EN)
$app[] = 'lang='.Lang::getLocale()->domain();
// append anti-cache timestamp
if (!($flags & SC_FLAG_NO_TIMESTAMP) && !$dynData)
@@ -549,10 +549,10 @@ class GenericPage
Type::GUIDE, $this->typeId, $this->guideRevision);
else if (!empty($this->articleUrl))
$article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `url` = ? AND `locale` IN (?a) ORDER BY `locale` DESC, `rev` DESC LIMIT 1',
$this->articleUrl, [User::$localeId, LOCALE_EN]);
$this->articleUrl, [Lang::getLocale()->value, Locale::EN->value]);
else if (!empty($this->type) && isset($this->typeId))
$article = DB::Aowow()->selectRow('SELECT `article`, `quickInfo`, `locale`, `editAccess` FROM ?_articles WHERE `type` = ?d AND `typeId` = ?d AND `locale` IN (?a) ORDER BY `locale` DESC, `rev` DESC LIMIT 1',
$this->type, $this->typeId, [User::$localeId, LOCALE_EN]);
$this->type, $this->typeId, [Lang::getLocale()->value, Locale::EN->value]);
if ($article)
{
@@ -586,7 +586,7 @@ class GenericPage
if (empty($this->infobox) && !empty($article['quickInfo']))
$this->infobox = $article['quickInfo'];
if ($article['locale'] != User::$localeId)
if ($article['locale'] != Lang::getLocale()->value)
$this->article['params']['prepend'] = '<div class="notice-box"><span class="icon-bubble">'.Lang::main('langOnly', [Lang::lang($article['locale'])]).'</span></div>';
if (method_exists($this, 'postArticle')) // e.g. update variables in article
@@ -676,7 +676,7 @@ class GenericPage
/*******************/
// unknown entry
public function notFound(string $title = '', string $msg = '') : void
public function notFound(string $title = '', string $msg = '') : never
{
if ($this->mode == CACHE_TYPE_TOOLTIP && method_exists($this, 'generateTooltip'))
{
@@ -713,7 +713,7 @@ class GenericPage
}
// unknown page
public function error() : void
public function error() : never
{
// $this->path = null;
// $this->tabId = null;
@@ -733,7 +733,7 @@ class GenericPage
}
// display brb gnomes
public function maintenance() : void
public function maintenance() : never
{
header('HTTP/1.0 503 Service Temporarily Unavailable', true, 503);
header('Retry-After: '.(3 * HOUR));
@@ -748,7 +748,7 @@ class GenericPage
/*******************/
// load given template string or GenericPage::$tpl
public function display(string $override = '') : void
public function display(string $override = '') : never
{
// Heisenbug: IE11 and FF32 will sometimes (under unknown circumstances) cache 302 redirects and stop
// re-requesting them from the server but load them from local cache, thus breaking menu features.
@@ -797,7 +797,7 @@ class GenericPage
}
// generate and cache
public function displayExtra(callable $generator, string $mime = MIME_TYPE_JSON) : void
public function displayExtra(callable $generator, string $mime = MIME_TYPE_JSON) : never
{
$outString = '';
if (!$this->loadCache($outString))
@@ -833,7 +833,7 @@ class GenericPage
// localizes expected fields .. except for icons .. icons are special
if (in_array($k, ['name', 'namefemale']) && $struct[0] != Type::getJSGlobalString(Type::ICON))
{
$data[$k.'_'.User::$localeString] = $v;
$data[$k.'_'.Lang::getLocale()->json()] = $v;
unset($data[$k]);
}
}
@@ -849,13 +849,13 @@ class GenericPage
// spell
if (!empty($x['tooltip'])) // spell + item
$buff .= "\n _[".$x['id'].'].tooltip_'.User::$localeString.' = '.Util::toJSON($x['tooltip']).";\n";
$buff .= "\n _[".$x['id'].'].tooltip_'.Lang::getLocale()->json().' = '.Util::toJSON($x['tooltip']).";\n";
if (!empty($x['buff'])) // spell
$buff .= " _[".$x['id'].'].buff_'.User::$localeString.' = '.Util::toJSON($x['buff']).";\n";
$buff .= " _[".$x['id'].'].buff_'.Lang::getLocale()->json().' = '.Util::toJSON($x['buff']).";\n";
if (!empty($x['spells'])) // spell + item
$buff .= " _[".$x['id'].'].spells_'.User::$localeString.' = '.Util::toJSON($x['spells']).";\n";
$buff .= " _[".$x['id'].'].spells_'.Lang::getLocale()->json().' = '.Util::toJSON($x['spells']).";\n";
if (!empty($x['buffspells'])) // spell
$buff .= " _[".$x['id'].'].buffspells_'.User::$localeString.' = '.Util::toJSON($x['buffspells']).";\n";
$buff .= " _[".$x['id'].'].buffspells_'.Lang::getLocale()->json().' = '.Util::toJSON($x['buffspells']).";\n";
$buff .= "\n";
}
@@ -922,17 +922,17 @@ class GenericPage
}
// load brick with more text then vars
protected function localizedBrick(string $file, int $loc = LOCALE_EN) : void
protected function localizedBrick(string $file, Locale $loc = Locale::EN) : void
{
if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc))
if (!$this->isSaneInclude('template/localized/', $file.'_'.$loc->value))
{
if ($loc == LOCALE_EN || !$this->isSaneInclude('template/localized/', $file.'_'.LOCALE_EN))
trigger_error('Nonexistant template requested: template/localized/'.$file.'_'.$loc.'.tpl.php', E_USER_ERROR);
if ($loc == Locale::EN || !$this->isSaneInclude('template/localized/', $file.'_'.Locale::EN->value))
trigger_error('Nonexistant template requested: template/localized/'.$file.'_'.$loc->value.'.tpl.php', E_USER_ERROR);
else
include('template/localized/'.$file.'_'.LOCALE_EN.'.tpl.php');
include('template/localized/'.$file.'_'.Locale::EN->value.'.tpl.php');
}
else
include('template/localized/'.$file.'_'.$loc.'.tpl.php');
include('template/localized/'.$file.'_'.$loc->value.'.tpl.php');
}

View File

@@ -180,7 +180,7 @@ class GuidePage extends GenericPage
{
// init required template vars
$this->editorFields = array(
'locale' => User::$localeId,
'locale' => Lang::getLocale()->value,
'status' => GUIDE_STATUS_DRAFT
);
}
@@ -522,11 +522,11 @@ class GuidePage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = strip_tags($this->name);
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = strip_tags($this->name);
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
}
return sprintf($this->powerTpl, Util::toJSON($this->articleUrl ?: $this->typeId), User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, Util::toJSON($this->articleUrl ?: $this->typeId), Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
protected function generatePath() : void

View File

@@ -52,7 +52,7 @@ class GuidesPage extends GenericPage
else
{
$conditions = array(
['locale', User::$localeId],
['locale', Lang::getLocale()->value],
['status', GUIDE_STATUS_ARCHIVED, '!'], // never archived guides
[
'OR',

View File

@@ -41,7 +41,7 @@ class HomePage extends GenericPage
$this->extendGlobalData($_);
if (empty($this->featuredBox['boxBG']))
$this->featuredBox['boxBG'] = Cfg::get('STATIC_URL').'/images/'.User::$localeString.'/mainpage-bg-news.jpg';
$this->featuredBox['boxBG'] = Cfg::get('STATIC_URL').'/images/'.Lang::getLocale()->json().'/mainpage-bg-news.jpg';
// load overlay links
$this->featuredBox['overlays'] = DB::Aowow()->select('SELECT * FROM ?_home_featuredbox_overlay WHERE featureId = ?d', $this->featuredBox['id']);
@@ -54,7 +54,7 @@ class HomePage extends GenericPage
protected function generateTitle()
{
if ($_ = DB::Aowow()->selectCell('SELECT title FROM ?_home_titles WHERE active = 1 AND locale = ?d ORDER BY RAND() LIMIT 1', User::$localeId))
if ($_ = DB::Aowow()->selectCell('SELECT title FROM ?_home_titles WHERE active = 1 AND locale = ?d ORDER BY RAND() LIMIT 1', Lang::getLocale()->value))
$this->homeTitle = Cfg::get('NAME').Lang::main('colon').$_;
}

View File

@@ -29,7 +29,7 @@ class ItemPage extends genericPage
);
protected $_get = array(
'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'],
'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain'],
'rand' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
'ench' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkInt'],
'gems' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkIntArray'],
@@ -50,7 +50,7 @@ class ItemPage extends genericPage
{
// temp locale
if ($this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
if ($this->_get['rand'])
$this->enhancedTT['r'] = $this->_get['rand'];
@@ -65,11 +65,11 @@ class ItemPage extends genericPage
{
// temp locale
if ($this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
// allow lookup by name for xml
if (!is_numeric($param))
$conditions = [['name_loc'.User::$localeId, urldecode($param)]];
$conditions = [['name_loc'.Lang::getLocale()->value, urldecode($param)]];
}
$this->subject = new ItemList($conditions);
@@ -672,7 +672,7 @@ class ItemPage extends genericPage
['id', $this->typeId, '!'],
[
'OR',
['name_loc'.User::$localeId, $this->subject->getField('name', true)],
['name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)],
[
'AND',
['class', $_class],
@@ -1030,10 +1030,10 @@ class ItemPage extends genericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW);
$power->quality = $this->subject->getField('quality');
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip(false, 0, $this->enhancedTT);
$power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true, false, $this->enhancedTT), Lang::FMT_RAW);
$power->quality = $this->subject->getField('quality');
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip(false, 0, $this->enhancedTT);
}
$itemString = $this->typeId;
@@ -1044,7 +1044,7 @@ class ItemPage extends genericPage
$itemString = "'".$itemString."'";
}
return sprintf($this->powerTpl, $itemString, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $itemString,Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
protected function generateXML()

View File

@@ -25,7 +25,7 @@ class ItemsetPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_JS_FILE, 'js/Summary.js']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerItemSet(%d, %d, %s);';
@@ -35,7 +35,7 @@ class ItemsetPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -149,7 +149,7 @@ class ItemsetPage extends GenericPage
$compare[] = $itemId;
$pieces[$itemId] = array(
'name_'.User::$localeString => $iList->getField('name', true),
'name_'.Lang::getLocale()->json() => $iList->getField('name', true),
'quality' => $iList->getField('quality'),
'icon' => $iList->getField('iconString'),
'jsonequip' => $data[$itemId]
@@ -244,11 +244,11 @@ class ItemsetPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
}

View File

@@ -24,7 +24,7 @@ class NpcPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $scripts = [[SC_JS_FILE, 'js/swfobject.js'], [SC_CSS_FILE, 'css/Profiler.css']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $soundIds = [];
private $powerTpl = '$WowheadPower.registerNpc(%d, %d, %s);';
@@ -35,7 +35,7 @@ class NpcPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -902,12 +902,12 @@ class NpcPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->map = $this->subject->getSpawns(SPAWNINFO_SHORT);
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
$power->map = $this->subject->getSpawns(SPAWNINFO_SHORT);
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
private function getRepForId(array $entries, array &$spillover) : array

View File

@@ -21,7 +21,7 @@ class ObjectPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerObject(%d, %d, %s);';
@@ -31,7 +31,7 @@ class ObjectPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -488,12 +488,12 @@ class ObjectPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW);
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW);
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
$power->map = $this->subject->getSpawns(SPAWNINFO_SHORT);
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
}

View File

@@ -30,7 +30,7 @@ class ProfilePage extends GenericPage
);
protected $_get = array(
'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain'],
'domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain'],
'new' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkEmptySet']
);
@@ -55,7 +55,7 @@ class ProfilePage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
if (count($params) == 1 && intval($params[0]))
{
@@ -170,7 +170,7 @@ class ProfilePage extends GenericPage
// dummy title from dungeon encounter
foreach (Lang::profiler('encounterNames') as $id => $name)
$this->extendGlobalData([Type::NPC => [$id => ['name_'.User::$localeString => $name]]]);
$this->extendGlobalData([Type::NPC => [$id => ['name_'.Lang::getLocale()->json() => $name]]]);
}
protected function generatePath()
@@ -204,15 +204,15 @@ class ProfilePage extends GenericPage
if ($title = (new TitleList(array(['id', $_])))->getField($g ? 'female' : 'male', true))
$n = sprintf($title, $n);
$power->{'name_'.User::$localeString} = $n;
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->icon = '$$WH.g_getProfileIcon('.$r.', '.$c.', '.$g.', '.$l.', \''.$this->subject->getIcon().'\')';
$power->{'name_'.Lang::getLocale()->json()} = $n;
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
$power->icon = '$$WH.g_getProfileIcon('.$r.', '.$c.', '.$g.', '.$l.', \''.$this->subject->getIcon().'\')';
}
return sprintf($this->powerTpl, $id, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $id, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
public function display(string $override = ''): void
public function display(string $override = ''): never
{
if ($this->mode != CACHE_TYPE_TOOLTIP)
parent::display($override);
@@ -222,7 +222,7 @@ class ProfilePage extends GenericPage
die($this->generateTooltip());
}
public function notFound(string $title = '', string $msg = '') : void
public function notFound(string $title = '', string $msg = '') : never
{
parent::notFound($title ?: Util::ucFirst(Lang::profiler('profiler')), $msg ?: Lang::profiler('notFound', 'profile'));
}

View File

@@ -33,7 +33,7 @@ class QuestPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $scripts = [[SC_JS_FILE, 'js/ShowOnMap.js'], [SC_CSS_FILE, 'css/Book.css']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $powerTpl = '$WowheadPower.registerQuest(%d, %d, %s);';
@@ -43,7 +43,7 @@ class QuestPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -981,7 +981,7 @@ class QuestPage extends GenericPage
/**************/
// tab: see also
$seeAlso = new QuestList(array(['name_loc'.User::$localeId, '%'.Util::htmlEscape($this->subject->getField('name', true)).'%'], ['id', $this->typeId, '!']));
$seeAlso = new QuestList(array(['name_loc'.Lang::getLocale()->value, '%'.Util::htmlEscape($this->subject->getField('name', true)).'%'], ['id', $this->typeId, '!']));
if (!$seeAlso->error)
{
$this->extendGlobalData($seeAlso->getJSGlobals());
@@ -1045,13 +1045,13 @@ class QuestPage extends GenericPage
$power = new StdClass();
if (!$this->subject->error)
{
$power->{'name_'.User::$localeString} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW);
$power->{'tooltip_'.User::$localeString} = $this->subject->renderTooltip();
$power->{'name_'.Lang::getLocale()->json()} = Lang::unescapeUISequences($this->subject->getField('name', true), Lang::FMT_RAW);
$power->{'tooltip_'.Lang::getLocale()->json()} = $this->subject->renderTooltip();
if ($this->subject->isDaily())
$power->daily = 1;
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
private function createRewards($side)

View File

@@ -138,14 +138,14 @@ class SearchPage extends GenericPage
continue;
else if ($clean[0] == '-')
{
if (mb_strlen($clean) < 4 && !Util::isLogographic(User::$localeId))
if (mb_strlen($clean) < 4 && !Util::isLogographic(Lang::getLocale()->value))
$this->invalid[] = mb_substr($raw, 1);
else
$this->excluded[] = mb_substr(str_replace('_', '\\_', $clean), 1);
}
else if ($clean !== '')
{
if (mb_strlen($clean) < 3 && !Util::isLogographic(User::$localeId))
if (mb_strlen($clean) < 3 && !Util::isLogographic(Lang::getLocale()->value))
$this->invalid[] = $raw;
else
$this->included[] = str_replace('_', '\\_', $clean);
@@ -157,7 +157,7 @@ class SearchPage extends GenericPage
{
$staff = intVal($withStaff && User::isInGroup(U_GROUP_EMPLOYEE));
$key = [$this->mode, $this->searchMask, md5($this->query), $staff, User::$localeId];
$key = [$this->mode, $this->searchMask, md5($this->query), $staff, Lang::getLocale()->value];
return implode('_', $key);
}
@@ -212,7 +212,7 @@ class SearchPage extends GenericPage
$this->performSearch();
}
public function notFound(string $title = '', string $msg = '') : void
public function notFound(string $title = '', string $msg = '') : never
{
if ($this->searchMask & SEARCH_TYPE_REGULAR)
{
@@ -237,7 +237,7 @@ class SearchPage extends GenericPage
}
}
public function display(string $override = '') : void
public function display(string $override = '') : never
{
if ($override || ($this->searchMask & SEARCH_TYPE_REGULAR))
parent::display($override);
@@ -330,7 +330,7 @@ class SearchPage extends GenericPage
{
// default to name-field
if (!$fields)
$fields[] = 'name_loc'.User::$localeId;
$fields[] = 'name_loc'.Lang::getLocale()->value;
$qry = [];
foreach ($fields as $f)
@@ -429,7 +429,7 @@ class SearchPage extends GenericPage
private function _searchTitle($cndBase) // 2 Titles: $searchMask & 0x00000004
{
$cnd = array_merge($cndBase, [$this->createLookup(['male_loc'.User::$localeId, 'female_loc'.User::$localeId])]);
$cnd = array_merge($cndBase, [$this->createLookup(['male_loc'.Lang::getLocale()->value, 'female_loc'.Lang::getLocale()->value])]);
$titles = new TitleList($cnd, ['calcTotal' => true]);
if ($data = $titles->getListviewData())
@@ -458,7 +458,7 @@ class SearchPage extends GenericPage
$cnd = array_merge($cndBase, array(
array(
'OR',
$this->createLookup(['h.name_loc'.User::$localeId]),
$this->createLookup(['h.name_loc'.Lang::getLocale()->value]),
['AND', $this->createLookup(['e.description']), ['e.holidayId', 0]]
)
));
@@ -1321,7 +1321,7 @@ class SearchPage extends GenericPage
private function _searchEmote($cndBase) // 25 Emotes $searchMask & 0x2000000
{
$cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.User::$localeId, 'meToNone_loc'.User::$localeId, 'extToMe_loc'.User::$localeId, 'extToExt_loc'.User::$localeId, 'extToNone_loc'.User::$localeId])]);
$cnd = array_merge($cndBase, [$this->createLookup(['cmd', 'meToExt_loc'.Lang::getLocale()->value, 'meToNone_loc'.Lang::getLocale()->value, 'extToMe_loc'.Lang::getLocale()->value, 'extToExt_loc'.Lang::getLocale()->value, 'extToNone_loc'.Lang::getLocale()->value])]);
$emote = new EmoteList($cnd, ['calcTotal' => true]);
if ($data = $emote->getListviewData())
@@ -1340,7 +1340,7 @@ class SearchPage extends GenericPage
private function _searchEnchantment($cndBase) // 26 Enchantments $searchMask & 0x4000000
{
$cnd = array_merge($cndBase, [$this->createLookup(['name_loc'.User::$localeId])]);
$cnd = array_merge($cndBase, [$this->createLookup(['name_loc'.Lang::getLocale()->value])]);
$enchantment = new EnchantmentList($cnd, ['calcTotal' => true]);
if ($data = $enchantment->getListviewData())

View File

@@ -38,7 +38,7 @@ class SpellPage extends GenericPage
protected $mode = CACHE_TYPE_PAGE;
protected $scripts = [[SC_JS_FILE, 'js/swfobject.js']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'GenericPage::checkDomain']];
protected $_get = ['domain' => ['filter' => FILTER_CALLBACK, 'options' => 'Locale::tryFromDomain']];
private $difficulties = [];
private $firstRank = 0;
@@ -56,7 +56,7 @@ class SpellPage extends GenericPage
// temp locale
if ($this->mode == CACHE_TYPE_TOOLTIP && $this->_get['domain'])
Util::powerUseLocale($this->_get['domain']);
Lang::load($this->_get['domain']);
$this->typeId = intVal($id);
@@ -541,7 +541,7 @@ class SpellPage extends GenericPage
['s.effect2Id', $this->subject->getField('effect2Id')],
['s.effect3Id', $this->subject->getField('effect3Id')],
['s.id', $this->subject->id, '!'],
['s.name_loc'.User::$localeId, $this->subject->getField('name', true)]
['s.name_loc'.Lang::getLocale()->value, $this->subject->getField('name', true)]
);
$saSpells = new SpellList($conditions);
@@ -1283,15 +1283,15 @@ class SpellPage extends GenericPage
[$tooltip, $ttSpells] = $this->subject->renderTooltip();
[$buff, $bfSpells] = $this->subject->renderBuff();
$power->{'name_'.User::$localeString} = $this->subject->getField('name', true);
$power->{'name_'.Lang::getLocale()->json()} = $this->subject->getField('name', true);
$power->icon = rawurlencode($this->subject->getField('iconString', true, true));
$power->{'tooltip_'.User::$localeString} = $tooltip;
$power->{'spells_'.User::$localeString} = $ttSpells;
$power->{'buff_'.User::$localeString} = $buff;
$power->{'buffspells_'.User::$localeString} = $bfSpells;
$power->{'tooltip_'.Lang::getLocale()->json()} = $tooltip;
$power->{'spells_'.Lang::getLocale()->json()} = $ttSpells;
$power->{'buff_'.Lang::getLocale()->json()} = $buff;
$power->{'buffspells_'.Lang::getLocale()->json()} = $bfSpells;
}
return sprintf($this->powerTpl, $this->typeId, User::$localeId, Util::toJSON($power, JSON_AOWOW_POWER));
return sprintf($this->powerTpl, $this->typeId, Lang::getLocale()->value, Util::toJSON($power, JSON_AOWOW_POWER));
}
private function buildPctStack(float $baseChance, int $maxStack) : string
@@ -1907,7 +1907,7 @@ class SpellPage extends GenericPage
JOIN ?_taxinodes tn1 ON tp.`startNodeId` = tn1.`id`
JOIN ?_taxinodes tn2 ON tp.`endNodeId` = tn2.`id`
WHERE tp.`id` = ?d',
User::$localeId, User::$localeId, User::$localeId, User::$localeId, $effMV
Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, Lang::getLocale()->value, $effMV
);
if ($_)
$_nameMV = $this->fmtStaffTip('<span class="breadcrumb-arrow">'.Util::localizedString($_, 'start').'</span>'.Util::localizedString($_, 'end'), 'MiscValue: '.$effMV);

View File

@@ -48,7 +48,7 @@ class UtilityPage extends GenericPage
}
}
public function display(string $override = '') : void
public function display(string $override = '') : never
{
if ($this->rss) // this should not be cached
{
@@ -275,7 +275,7 @@ class UtilityPage extends GenericPage
$channel->addChild('title', Cfg::get('NAME_SHORT').' - '.$this->name);
$channel->addChild('link', Cfg::get('HOST_URL').'/?'.$this->page . ($this->category ? '='.$this->category[0] : null));
$channel->addChild('description', Cfg::get('NAME'));
$channel->addChild('language', implode('-', str_split(User::$localeString, 2)));
$channel->addChild('language', implode('-', str_split(Lang::getLocale()->json(), 2)));
$channel->addChild('ttl', Cfg::get('TTL_RSS'));
$channel->addChild('lastBuildDate', date(DATE_RSS));

View File

@@ -195,9 +195,9 @@ class ZonePage extends GenericPage
}
// see if we can actually display a map
$hasMap = file_exists('static/images/wow/maps/'.Util::$localeStrings[User::$localeId].'/normal/'.$this->typeId.'.jpg');
$hasMap = file_exists('static/images/wow/maps/'.Lang::getLocale()->json().'/normal/'.$this->typeId.'.jpg');
if (!$hasMap) // try multilayered
$hasMap = file_exists('static/images/wow/maps/'.Util::$localeStrings[User::$localeId].'/normal/'.$this->typeId.'-1.jpg');
$hasMap = file_exists('static/images/wow/maps/'.Lang::getLocale()->json().'/normal/'.$this->typeId.'-1.jpg');
if (!$hasMap) // try english fallback
$hasMap = file_exists('static/images/wow/maps/enus/normal/'.$this->typeId.'.jpg');
if (!$hasMap) // try english fallback, multilayered

View File

@@ -14,14 +14,6 @@ class CLISetup
public static $srcDir = 'setup/mpqdata/';
private static $mpqFiles = [];
public static $expectedPaths = array( // update paths [yes, you can have en empty string as key]
'' => LOCALE_EN, 'enGB' => LOCALE_EN, 'enUS' => LOCALE_EN,
'frFR' => LOCALE_FR,
'deDE' => LOCALE_DE,
'zhCN' => LOCALE_CN, 'enCN' => LOCALE_CN,
'esES' => LOCALE_ES,
'ruRU' => LOCALE_RU
);
public const SQL_BATCH = 1000; // max. n items per sql insert
@@ -175,21 +167,15 @@ class CLISetup
// optional limit handled locales
if (isset(self::$opts['locales']))
{
// engb and enus are identical for all intents and purposes
$from = ['engb', 'encn'];
$to = ['enus', 'zhcn'];
self::$opts['locales'] = str_ireplace($from, $to, self::$opts['locales']);
self::$locales = array_intersect(Util::$localeStrings, array_map('strtolower', self::$opts['locales']));
$opt = array_map('strtolower', self::$opts['locales']);
foreach (Locale::cases() as $loc)
if ($loc->validate() && array_intersect(array_map('strtolower', $loc->gameDirs()), $opt))
self::$locales[$loc->value] = $loc;
}
if (!self::$locales)
self::$locales = array_filter(Util::$localeStrings);
// restrict actual locales
foreach (self::$locales as $idx => $_)
if (($l = Cfg::get('LOCALES')) && !($l & (1 << $idx)))
unset(self::$locales[$idx]);
foreach (Locale::cases() as $loc)
if ($loc->validate())
self::$locales[$loc->value] = $loc;
return !!self::$locales;
}
@@ -557,22 +543,19 @@ class CLISetup
{
$result = [];
foreach (self::$expectedPaths as $xp => $locId)
foreach (self::$locales as $locId => $loc)
{
if (!in_array($locId, array_keys(self::$locales)))
continue;
if (isset($result[$locId]))
continue;
if ($xp) // if in subDir add trailing slash
$xp .= DIRECTORY_SEPARATOR;
$path = sprintf($pathPattern, $xp);
if (self::fileExists($path))
foreach ($loc->gameDirs() as $gDir)
{
$result[$locId] = $path;
continue;
if ($gDir) // if in subDir add trailing slash
$gDir .= DIRECTORY_SEPARATOR;
$path = sprintf($pathPattern, $gDir);
if (self::fileExists($path))
{
$result[$locId] = $path;
break;
}
}
}
@@ -590,17 +573,23 @@ class CLISetup
CLI::write('loading required GlobalStrings', CLI::LOG_INFO);
// try to load globalstrings for all selected locales
foreach (self::$expectedPaths as $xp => $lId)
foreach (self::$locales as $locId => $loc)
{
if (isset(self::$gsFiles[$lId]))
if (isset(self::$gsFiles[$locId]))
continue;
if ($xp)
$xp .= DIRECTORY_SEPARATOR;
foreach ($loc->gameDirs() as $gDir)
{
if ($gDir)
$gDir .= DIRECTORY_SEPARATOR;
$gsFile = sprintf(self::GLOBALSTRINGS_LUA, self::$srcDir, $xp);
if (self::fileExists($gsFile))
self::$gsFiles[$lId] = file($gsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
$gsFile = sprintf(self::GLOBALSTRINGS_LUA, self::$srcDir, $gDir);
if (self::fileExists($gsFile))
{
self::$gsFiles[$locId] = file($gsFile, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
break;
}
}
}
if ($missing = array_diff_key(self::$locales, self::$gsFiles))
@@ -612,7 +601,7 @@ class CLISetup
return true;
}
public static function searchGlobalStrings(string $pattern) : generator
public static function searchGlobalStrings(string $pattern) : Generator
{
if (!self::$gsFiles)
return;

View File

@@ -38,8 +38,7 @@ CLISetup::registerUtility(new class extends UtilityScript
// args: username, password, email, null // iiin
public function run(&$args) : bool
{
User::useLocale(LOCALE_EN);
Lang::load(LOCALE_EN);
Lang::load(Locale::EN);
$name = $args[0] ?? '';
$passw = $args[1] ?? '';
@@ -67,21 +66,21 @@ CLISetup::registerUtility(new class extends UtilityScript
{
CLI::write();
if (!$name && !User::isValidName($uiAccount['name'], $e))
if (!$name && !User::isValidName($uiAccount['name'] ?? '', $e))
CLI::write(Lang::account($e == 1 ? 'errNameLength' : 'errNameChars'), CLI::LOG_ERROR);
else if (!$name)
$name = $uiAccount['name'];
if (!$passw && !User::isValidPass($uiAccount['pass1'], $e))
if (!$passw && !User::isValidPass($uiAccount['pass1'] ?? '', $e))
CLI::write(Lang::account($e == 1 ? 'errPassLength' : 'errPassChars'), CLI::LOG_ERROR);
else if (!$passw && $uiAccount['pass1'] != $uiAccount['pass2'])
CLI::write(Lang::account('passMismatch'), CLI::LOG_ERROR);
else if (!$passw)
$passw = $uiAccount['pass1'];
if (!$email && Util::isValidEmail($uiAccount['email']))
if (!$email && Util::isValidEmail($uiAccount['email'] ?? ''))
$email = $uiAccount['email'];
else if (!$email && $uiAccount['email'])
else if (!$email && $uiAccount && $uiAccount['email'])
CLI::write('[account] email invalid ... using default: ' . Cfg::get('CONTACT_EMAIL'), CLI::LOG_INFO);
}
else if ($this->fields)
@@ -92,7 +91,7 @@ CLISetup::registerUtility(new class extends UtilityScript
return true;
}
if (DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE user = ? AND (status <> ?d OR (status = ?d AND statusTimer > UNIX_TIMESTAMP()))', $name, ACC_STATUS_NEW, ACC_STATUS_NEW))
if (DB::Aowow()->SelectCell('SELECT 1 FROM ?_account WHERE `user` = ? AND (`status` <> ?d OR (`status` = ?d AND `statusTimer` > UNIX_TIMESTAMP()))', $name, ACC_STATUS_NEW, ACC_STATUS_NEW))
{
CLI::write('[account] ' . Lang::account('nameInUse'), CLI::LOG_ERROR);
CLI::write();
@@ -102,10 +101,10 @@ CLISetup::registerUtility(new class extends UtilityScript
if (!$name || !$passw)
return false;
if (DB::Aowow()->query('REPLACE INTO ?_account (user, passHash, displayName, joindate, email, allowExpire, userGroups, userPerms) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)',
if (DB::Aowow()->query('REPLACE INTO ?_account (`user`, `passHash`, `displayName`, `joindate`, `email`, `allowExpire`, `userGroups`, `userPerms`) VALUES (?, ?, ?, UNIX_TIMESTAMP(), ?, 0, ?d, 1)',
$name, User::hashCrypt($passw), Util::ucFirst($name), $email ?: Cfg::get('CONTACT_EMAIL'), U_GROUP_ADMIN))
{
$newId = DB::Aowow()->selectCell('SELECT id FROM ?_account WHERE user = ?', $name);
$newId = DB::Aowow()->selectCell('SELECT `id` FROM ?_account WHERE `user` = ?', $name);
Util::gainSiteReputation($newId, SITEREP_ACTION_REGISTER);
CLI::write("[account] admin ".$name." created successfully", CLI::LOG_OK);

View File

@@ -84,7 +84,7 @@ CLISetup::registerUtility(new class extends UtilityScript
CLI::write();
if (!DB::isConnectable(DB_AUTH) || !$this->test())
CLI::write('[db] auth server not yet set up.', CLI::LOG_ERROR);
else if ($realms = DB::Auth()->select('SELECT id AS "0", name AS "1", icon AS "2", timezone AS "3", isRestricted AS "4" FROM realmlist'))
else if ($realms = DB::Auth()->select('SELECT `id` AS "0", `name` AS "1", `icon` AS "2", `timezone` AS "3", `allowedSecurityLevel` AS "4" FROM realmlist'))
{
$tbl = [['Realm Id', 'Name', 'Type', 'Region', 'GMLevel', 'Status']];
foreach ($realms as [$id, $name, $icon, $region, $level])

View File

@@ -110,21 +110,27 @@ class DBC
$this->isGameTable = array_values($this->format) == ['f'] && substr($file, 0, 2) == 'gt';
$foundMask = 0x0;
foreach (CLISetup::$expectedPaths as $locStr => $locId)
foreach (Locale::cases() as $loc)
{
if (!in_array($locId, array_keys(CLISetup::$locales)))
if (!in_array($loc, CLISetup::$locales))
continue;
if ($foundMask & (1 << $locId))
if ($foundMask & (1 << $loc->value))
continue;
$fullPath = CLI::nicePath($this->file.'.dbc', CLISetup::$srcDir, $locStr, 'DBFilesClient');
if (!CLISetup::fileExists($fullPath))
continue;
foreach ($loc->gameDirs() as $dir)
{
$fullPath = CLI::nicePath($this->file.'.dbc', CLISetup::$srcDir, $dir, 'DBFilesClient');
if (!CLISetup::fileExists($fullPath))
continue;
$this->curFile = $fullPath;
if ($this->validateFile($locId))
$foundMask |= (1 << $locId);
$this->curFile = $fullPath;
if ($this->validateFile($loc))
{
$foundMask |= (1 << $loc->value);
break;
}
}
}
if (!$this->fileRefs)
@@ -138,7 +144,7 @@ class DBC
$x = array_unique(array_column($headers, 'recordCount'));
if (count($x) != 1)
{
CLI::write('some DBCs have differenct record counts ('.implode(', ', $x).' respectively). cannot merge!', CLI::LOG_ERROR);
CLI::write('some DBCs have different record counts ('.implode(', ', $x).' respectively). cannot merge!', CLI::LOG_ERROR);
return;
}
$x = array_unique(array_column($headers, 'fieldCount'));
@@ -165,7 +171,7 @@ class DBC
$this->createTable();
if ($this->localized)
CLI::write(' - DBC: reading and merging '.$this->file.'.dbc for locales '.Lang::concat(array_intersect_key(Util::$localeStrings, $this->fileRefs), true, 'CLI::bold'));
CLI::write(' - DBC: reading and merging '.$this->file.'.dbc for locales '.Lang::concat(array_keys($this->fileRefs), callback: fn($x) => CLI::bold(Locale::from($x)->name)));
else
CLI::write(' - DBC: reading '.$this->file.'.dbc');
@@ -212,25 +218,25 @@ class DBC
$this->dataBuffer = null;
}
private function readHeader(&$handle = null)
private function readHeader(&$handle = null) : array
{
if (!is_resource($handle))
$handle = fopen($this->curFile, 'rb');
if (!$handle)
return false;
return [];
if (fread($handle, 4) != 'WDBC')
{
CLI::write('file '.$this->curFile.' has incorrect magic bytes', CLI::LOG_ERROR);
fclose($handle);
return false;
return [];
}
return unpack('VrecordCount/VfieldCount/VrecordSize/VstringSize', fread($handle, 16));
}
private function validateFile($locId)
private function validateFile(Locale $loc) : bool
{
$filesize = filesize($this->curFile);
if ($filesize < 20)
@@ -266,7 +272,7 @@ class DBC
return false;
}
$this->fileRefs[$locId] = [$handle, $this->curFile, $header];
$this->fileRefs[$loc->value] = [$handle, $this->curFile, $header];
return true;
}

View File

@@ -66,16 +66,16 @@ CLISetup::registerSetup("build", new class extends SetupScript
$castItems = [];
$enchantSpells = DB::Aowow()->select(
'SELECT s.id AS ARRAY_KEY,
effect1MiscValue,
equippedItemClass, equippedItemInventoryTypeMask, equippedItemSubClassMask,
skillLine1,
IFNULL(i.name, ?) AS iconString,
name_loc0, name_loc2, name_loc3, name_loc4, name_loc6, name_loc8
'SELECT s.`id` AS ARRAY_KEY,
`effect1MiscValue`,
`equippedItemClass`, `equippedItemInventoryTypeMask`, `equippedItemSubClassMask`,
`skillLine1`,
IFNULL(i.`name`, ?) AS "iconString",
`name_loc0`, `name_loc2`, `name_loc3`, `name_loc4`, `name_loc6`, `name_loc8`
FROM ?_spell s
LEFT JOIN ?_icons i ON i.id = s.iconId
WHERE effect1Id = ?d AND
name_loc0 NOT LIKE "QA%"',
LEFT JOIN ?_icons i ON i.`id` = s.`iconId`
WHERE `effect1Id` = ?d AND
`name_loc0` NOT LIKE "QA%"',
DEFAULT_ICON, SPELL_EFFECT_ENCHANT_ITEM
);
@@ -97,10 +97,9 @@ CLISetup::registerSetup("build", new class extends SetupScript
return false;
}
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
$enchantsOut = [];
foreach ($enchantSpells as $esId => $es)
@@ -121,7 +120,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if ($invType = $es['equippedItemInventoryTypeMask'])
$slot = $invType >> 1;
else /* if (equippedItemSubClassMask == 64) */ // shields have it their own way <_<
$slot = (1 << (14 - 1));
$slot = (1 << (INVTYPE_SHIELD - 1));
}
else if ($es['equippedItemClass'] == ITEM_CLASS_WEAPON)
{
@@ -133,7 +132,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if ((1 << $i) & $es['equippedItemSubClassMask'])
{
if ($sp == 13) // also mainHand & offHand *siiigh*
$slot |= ((1 << (21 - 1)) | (1 << (22 - 1)));
$slot |= ((1 << (INVTYPE_WEAPONMAINHAND - 1)) | (1 << (INVTYPE_WEAPONOFFHAND - 1)));
$slot |= (1 << ($sp - 1));
}
@@ -185,7 +184,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if ($cI->getField('spellId1') != $esId)
continue;
$isScroll = substr($cI->getField('name_loc0'), 0, 17) == 'Scroll of Enchant';
$isScroll = $cI->getField('class') == ITEM_CLASS_CONSUMABLE && $cI->getField('subClass') == ITEM_SUBCLASS_ITEM_ENHANCEMENT && $cI->getField('pickUpSoundId') == 1192;
if ($s = Util::getEnchantmentScore($cI->getField('itemLevel'), $isScroll ? -1 : $cI->getField('quality'), !!$enchantments->getField('skillLevel'), $eId))
if ($s > $ench['gearscore'])
@@ -254,7 +253,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$ench[$k] = $v[0];
$toFile = "var g_enchants = ".Util::toJSON($enchantsOut).";";
$file = 'datasets/'.$jsonStr.'/enchants';
$file = 'datasets/'.$loc->json().'/enchants';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;

View File

@@ -35,19 +35,19 @@ CLISetup::registerSetup("build", new class extends SetupScript
// sketchy, but should work
// id < 36'000 || ilevel < 70 ? BC : WOTLK
$gems = DB::Aowow()->select(
'SELECT i.id AS itemId,
i.name_loc0, i.name_loc2, i.name_loc3, i.name_loc4, i.name_loc6, i.name_loc8,
IF (i.id < 36000 OR i.itemLevel < 70, ?d, ?d) AS expansion,
i.quality,
ic.name AS icon,
i.gemEnchantmentId AS enchId,
i.gemColorMask AS colors,
i.requiredSkill,
i.itemLevel
'SELECT i.`id` AS "itemId",
i.`name_loc0`, i.`name_loc2`, i.`name_loc3`, i.`name_loc4`, i.`name_loc6`, i.`name_loc8`,
IF (i.`id` < 36000 OR i.`itemLevel` < 70, ?d, ?d) AS "expansion",
i.`quality`,
ic.`name` AS "icon",
i.`gemEnchantmentId` AS "enchId",
i.`gemColorMask` AS "colors",
i.`requiredSkill`,
i.`itemLevel`
FROM ?_items i
JOIN ?_icons ic ON ic.id = i.iconId
WHERE i.gemEnchantmentId <> 0
ORDER BY i.id DESC',
JOIN ?_icons ic ON ic.`id` = i.`iconId`
WHERE i.`gemEnchantmentId` <> 0
ORDER BY i.`id` DESC',
EXP_BC, EXP_WOTLK
);
@@ -59,12 +59,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
return false;
}
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
$gemsOut = [];
foreach ($gems as $g)
@@ -88,7 +87,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
$toFile = "var g_gems = ".Util::toJSON($gemsOut).";";
$file = 'datasets/'.$jsonStr.'/gems';
$file = 'datasets/'.$loc->json().'/gems';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;

View File

@@ -32,32 +32,31 @@ CLISetup::registerSetup("build", new class extends SetupScript
public function generate() : bool
{
$glyphList = DB::Aowow()->Select(
'SELECT i.id AS itemId,
'SELECT i.`id` AS "itemId",
i.*,
IF (g.typeFlags & 0x1, 2, 1) AS type,
i.subclass AS classs,
i.requiredLevel AS level,
s1.id AS glyphSpell,
ic.name AS icon,
s1.skillLine1 AS skillId,
s2.id AS glyphEffect,
s2.id AS ARRAY_KEY
IF (g.`typeFlags` & 0x1, 2, 1) AS "type",
i.`subclass` AS "classs",
i.`requiredLevel` AS "level",
s1.`id` AS "glyphSpell",
ic.`name` AS "icon",
s1.`skillLine1` AS "skillId",
s2.`id` AS "glyphEffect",
s2.`id` AS ARRAY_KEY
FROM ?_items i
JOIN ?_spell s1 ON s1.id = i.spellid1
JOIN ?_glyphproperties g ON g.id = s1.effect1MiscValue
JOIN ?_spell s2 ON s2.id = g.spellId
JOIN ?_icons ic ON ic.id = s1.iconIdAlt
JOIN ?_spell s1 ON s1.`id` = i.`spellid1`
JOIN ?_glyphproperties g ON g.`id` = s1.`effect1MiscValue`
JOIN ?_spell s2 ON s2.`id` = g.`spellId`
JOIN ?_icons ic ON ic.`id` = s1.`iconIdAlt`
WHERE i.classBak = ?d',
ITEM_CLASS_GLYPH);
$glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], Cfg::get('SQL_LIMIT_NONE')));
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(30);
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
$glyphsOut = [];
foreach ($glyphSpells->iterate() as $__)
@@ -67,7 +66,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!$pop['glyphEffect'])
continue;
if ($glyphSpells->getField('effect1Id') != 6 && $glyphSpells->getField('effect2Id') != 6 && $glyphSpells->getField('effect3Id') != 6)
if ($glyphSpells->getField('effect1Id') != SPELL_EFFECT_APPLY_AURA && $glyphSpells->getField('effect2Id') != SPELL_EFFECT_APPLY_AURA && $glyphSpells->getField('effect3Id') != SPELL_EFFECT_APPLY_AURA)
continue;
$glyphsOut[$pop['itemId']] = array(
@@ -82,7 +81,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
$toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";";
$file = 'datasets/'.$jsonStr.'/glyphs';
$file = 'datasets/'.$loc->json().'/glyphs';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;

View File

@@ -42,7 +42,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$this->imgPath = CLISetup::$srcDir.$this->imgPath;
$this->maxExecTime = ini_get('max_execution_time');
foreach ($this->genSteps[0][self::$GEN_IDX_DEST_INFO] as $dir)
foreach ($this->genSteps[0][self::GEN_IDX_DEST_INFO] as $dir)
$this->requiredDirs[] = $dir[0];
}

View File

@@ -84,8 +84,8 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (strpos($dir[0], '%s') === false)
$this->requiredDirs[] = $dir[0];
else
foreach (CLISetup::$locales as $l => $locJsonStr)
$this->requiredDirs[] = sprintf($dir[0], $locJsonStr.'/');
foreach (CLISetup::$locales as $loc)
$this->requiredDirs[] = sprintf($dir[0], $loc->json().DIRECTORY_SEPARATOR);
}
}
}
@@ -145,7 +145,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$sumAreas = count($this->wmAreas);
$sumMaps = count(CLISetup::$locales) * ($sumAreas + $sumFloors);
CLI::write('Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, CLISetup::$locales)));
CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(CLISetup::$locales, callback: fn($x) => $x->name));
/* todo: retrain brain and generate maps by given files and GlobalStrings. Then assign dbc data to them not the other way round like it is now.
foreach ($this->mapFiles as $name => [$floors, $isMultilevel])
@@ -188,7 +188,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
// create spawn-maps if wanted
if ($resOverlay && $this->modeMask & self::M_SPAWNS)
{
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
$outFile = $this->genSteps[self::M_SPAWNS][self::GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
if (!$this->buildSpawnMap($resOverlay, $outFile))
$this->success = false;
}
@@ -237,7 +237,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
*/
$progressLoc = -1;
foreach (CLISetup::$locales as $l => $locJsonStr)
foreach (CLISetup::$locales as $l => $loc)
{
$progressLoc++;
@@ -279,11 +279,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
str_pad('Dungeon Maps: '.($nFloors + ((($flags ?? 0) & self::AREA_FLAG_DEFAULT_FLOOR_TERRAIN) ? 1 : 0)), 18)
);
$srcPath = $mapSrcDir.'/'.$textureStr;
$srcPath = $mapSrcDir.DIRECTORY_SEPARATOR.$textureStr;
if (!CLISetup::fileExists($srcPath))
{
$this->success = false;
CLI::write('worldmap file '.$srcPath.' missing for selected locale '.$locJsonStr, CLI::LOG_ERROR);
CLI::write('worldmap file '.$srcPath.' missing for selected locale '.$loc->name, CLI::LOG_ERROR);
continue;
}
@@ -316,7 +316,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
{
ini_set('max_execution_time', $this->maxExecTime);
$file = $srcPath.'/'.$textureStr;
$file = $srcPath.DIRECTORY_SEPARATOR.$textureStr;
// todo: Dalaran [4395] has no level 0 but is not skipped here
if (!$floorIdx && !($flags & self::AREA_FLAG_DEFAULT_FLOOR_TERRAIN) && !in_array($mapId, self::CONTINENTS))
@@ -333,7 +333,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
foreach (self::DEST_DIRS as $sizeIdx => [$path, $width, $height])
{
$outFile[$sizeIdx] = sprintf($path, $locJsonStr.'/') . $zoneId;
$outFile[$sizeIdx] = sprintf($path, $loc->json().DIRECTORY_SEPARATOR) . $zoneId;
/* dataset 'zones' requires that ...
* 3959 - Black Temple: starts with empty floor suffix
@@ -386,7 +386,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
// also create subzone-maps
if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
$this->buildSubZones($resMap, $wmaId, $l);
$this->buildSubZones($resMap, $wmaId, $loc);
if ($resMap)
imagedestroy($resMap);
@@ -508,9 +508,9 @@ CLISetup::registerSetup("build", new class extends SetupScript
$sumAreas = count($this->wmAreas);
$sumMaps = count(CLISetup::$locales) * ($sumAreas + $sumFloors);
CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(array_intersect_key(Util::$localeStrings, CLISetup::$locales)));
CLI::write('[img-maps] Processing '.$sumAreas.' zone maps and '.$sumFloors.' dungeon maps from Interface/WorldMap/ for locale: '.Lang::concat(CLISetup::$locales, callback: fn($x) => CLI::bold($x->name)));
foreach (CLISetup::$locales as $l => $locJsonStr)
foreach (CLISetup::$locales as $l => $loc)
{
// source for mapFiles
$mapSrcDir = '';
@@ -522,7 +522,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$mapSrcDir = $this->genSteps[self::M_MAPS][1][$l] ?? '';
if (!$mapSrcDir)
{
CLI::write('[img-maps] - No suitable localized map files found for locale ['.$l.': '.$locJsonStr.'].', CLI::LOG_ERROR);
CLI::write('[img-maps] - No suitable localized map files found for locale '.CLI::bold($loc->name).'.', CLI::LOG_ERROR);
$this->success = false;
continue;
}
@@ -551,28 +551,28 @@ CLISetup::registerSetup("build", new class extends SetupScript
// .. which is not set in dbc 0 => 1, 1 => 2, etc.
if ($flags & self::AREA_FLAG_NO_DEFAULT_FLOOR)
$dmFloors = array_combine($dmFloors, array_map(function ($x) { return ++$x; }, $dmFloors));
$dmFloors = array_combine($dmFloors, array_map(fn($x) => ++$x, $dmFloors));
}
else if ($dmFloors != [0]) // 1 => 1, 2 => 2, etc.
$dmFloors = array_combine($dmFloors, $dmFloors);
CLI::write(
'['.$locJsonStr.'] ' .
'['.$loc->json().'] ' .
str_pad('['.$areaEntry['areaId'].']', 7) .
str_pad($areaEntry['nameINT'], 22) .
str_pad('Overlays: '.count($this->wmOverlays[$areaEntry['id']] ?? []), 14) .
str_pad('Dungeon Maps: '.$nFloors, 18)
);
$srcPath = $mapSrcDir.'/'.$textureStr;
$srcPath = $mapSrcDir.DIRECTORY_SEPARATOR.$textureStr;
if (!CLISetup::fileExists($srcPath))
{
CLI::write('[img-maps] - WorldMap file path '.$srcPath.' missing for selected locale '.$locJsonStr, CLI::LOG_ERROR);
CLI::write('[img-maps] - WorldMap file path '.$srcPath.' missing for selected locale '.CLI::bold($loc->name), CLI::LOG_ERROR);
$this->success = false;
continue;
}
$srcPath .= '/';
$srcPath .= DIRECTORY_SEPARATOR;
// zone has overlays (is in open world; is not multilevel)
if (isset($this->wmOverlays[$wmaId]) && ($this->modeMask & (self::M_MAPS | self::M_SPAWNS | self::M_SUBZONES)))
@@ -619,7 +619,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
foreach (self::DEST_DIRS as $sizeIdx => [$path, $width, $height])
{
$outPaths[$sizeIdx] = sprintf($path, strtolower($locJsonStr).'/') . $outFile . '.jpg';
$outPaths[$sizeIdx] = sprintf($path, strtolower($loc->json()).DIRECTORY_SEPARATOR) . $outFile . '.jpg';
if (!CLISetup::getOpt('force') && file_exists($outPaths[$sizeIdx]))
{
@@ -662,7 +662,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
// also create subzone-maps
if ($resMap && isset($this->wmOverlays[$wmaId]) && $this->modeMask & self::M_SUBZONES)
$this->buildSubZones($resMap, $wmaId, $l);
$this->buildSubZones($resMap, $wmaId, $loc);
if ($resMap)
imagedestroy($resMap);
@@ -677,7 +677,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
{
$areaNames = array_combine(
array_column($this->wmAreas, 'areaId'),
array_map(function ($x) { return strtoupper($x); }, array_column($this->wmAreas, 'nameINT'))
array_map(fn($x) => strtoupper($x), array_column($this->wmAreas, 'nameINT'))
);
if ($this->multiLevelZones)
@@ -708,7 +708,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
foreach (CLISetup::$locales as $lId => $loc)
{
Lang::load($lId);
Lang::load($loc);
// "custom" - show second level of Ahn'Kahet not shown but present in-game
if (isset($zoneAreas[$lId][4494]))
@@ -722,7 +722,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
continue;
// todo: just note for now, try to compensate later?
CLI::write('[img-maps] ['.$loc.'] '.str_pad('['.$zoneId.']', 7).'floor count mismatch between GlobalStrings: '.$nStrings.' and image files: '.$nFloors, CLI::LOG_WARN);
CLI::write('[img-maps] ['.$loc->json().'] '.str_pad('['.$zoneId.']', 7).'floor count mismatch between GlobalStrings: '.$nStrings.' and image files: '.$nFloors, CLI::LOG_WARN);
}
ksort($zoneAreas[$lId]);
@@ -732,24 +732,16 @@ CLISetup::registerSetup("build", new class extends SetupScript
// don't convert numbers to int in json
$toFile = "Mapper.multiLevelZones = ".Util::toJSON($this->multiLevelZones, 0x0).";\n\n";
$toFile .= "var g_zone_areas = ".Util::toJSON($zoneAreas[$lId]).";";
$file = 'datasets/'.$loc.'/zones';
$file = 'datasets/'.$loc->json().'/zones';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;
}
}
private function buildSpawnMap(/*GdImage*/ $resOverlay, int $zoneId) : void
private function buildSpawnMap(GdImage $resOverlay, int $zoneId) : void
{
// GdImage: < 8.0 resource; >= 8.0 object
if (gettype($resOverlay) != 'resource' && gettype($resOverlay) != 'object')
{
CLI::write('[img-maps] - no GdImage passed to buildSpawnMap', CLI::LOG_ERROR);
$this->success = false;
return;
}
$outFile = $this->genSteps[self::M_SPAWNS][self::$GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
$outFile = $this->genSteps[self::M_SPAWNS][self::GEN_IDX_DEST_INFO][0][0] . $zoneId . '.png';
if (!CLISetup::getOpt('force') && file_exists($outFile))
{
@@ -777,16 +769,8 @@ CLISetup::registerSetup("build", new class extends SetupScript
$this->success = false;
}
private function buildSubZones(/*GdImage*/ $resMap, int $wmaId, int $locId) : void
private function buildSubZones(GdImage $resMap, int $wmaId, Locale $loc) : void
{
// GdImage: < 8.0 resource; >= 8.0 object
if (gettype($resMap) != 'resource' && gettype($resMap) != 'object')
{
CLI::write('[img-maps] - no GdImage passed to buildSubZones()', CLI::LOG_ERROR);
$this->success = false;
return;
}
foreach ($this->wmOverlays[$wmaId] as &$row)
{
$doSkip = 0x0;
@@ -794,7 +778,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
foreach (self::DEST_DIRS as $sizeIdx => [$path, , ])
{
$outFile[$sizeIdx] = sprintf($path, strtolower(Util::$localeStrings[$locId]).'/') . $row['areaTableId'].'.jpg';
$outFile[$sizeIdx] = sprintf($path, $loc->json() . DIRECTORY_SEPARATOR) . $row['areaTableId'].'.jpg';
if (!CLISetup::getOpt('force') && file_exists($outFile[$sizeIdx]))
{
CLI::write($this->status.' - file '.$outFile[$sizeIdx].' was already processed', CLI::LOG_BLANK, true, true);
@@ -822,7 +806,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
}
private function generateOverlay(int $wmaId, string $basePath) // : ?GdImage
private function generateOverlay(int $wmaId, string $basePath) : ?GdImage
{
if (!isset($this->wmOverlays[$wmaId]))
return null;

View File

@@ -41,13 +41,12 @@ CLISetup::registerSetup("build", new class extends SetupScript
public function generate() : bool
{
$setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY refSetId DESC');
$setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY `refSetId` DESC');
$jsonBonus = [];
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
$itemsetOut = [];
foreach ($setList as $set)
@@ -120,7 +119,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
$toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";";
$file = 'datasets/'.$jsonStr.'/itemsets';
$file = 'datasets/'.$loc->json().'/itemsets';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;

View File

@@ -8,7 +8,45 @@ if (!CLI)
// Create 'locale.js'-file in static/js
// available locales have to be set in aowow.aowow_config
/*
0: { // English
id: LOCALE_ENUS,
name: 'enus',
domain: 'en',
description: 'English'
},
2: { // French
id: LOCALE_FRFR,
name: 'frfr',
domain: 'fr',
description: 'Fran' + String.fromCharCode(231) + 'ais'
},
3: { // German
id: LOCALE_DEDE,
name: 'dede',
domain: 'de',
description: 'Deutsch'
},
4:{ // Chinese
id: LOCALE_ZHCN,
name: 'zhcn',
domain: 'cn',
description: String.fromCharCode(31616, 20307, 20013, 25991)
},
6: { // Spanish
id: LOCALE_ESES,
name: 'eses',
domain: 'es',
description: 'Espa' + String.fromCharCode(241) + 'ol'
},
8: { // Russian
id: LOCALE_RURU,
name: 'ruru',
domain: 'ru',
description: String.fromCharCode(1056, 1091, 1089, 1089, 1082, 1080, 1081)
}
*/
CLISetup::registerSetup("build", new class extends SetupScript
{
@@ -23,51 +61,17 @@ CLISetup::registerSetup("build", new class extends SetupScript
private function locales() : string
{
$available = array(
LOCALE_EN => " 0: { // English\r\n" .
" id: LOCALE_ENUS,\r\n" .
" name: 'enus',\r\n" .
" domain: 'en',\r\n" .
" description: 'English'\r\n" .
" }",
LOCALE_FR => " 2: { // French\r\n" .
" id: LOCALE_FRFR,\r\n" .
" name: 'frfr',\r\n" .
" domain: 'fr',\r\n" .
" description: 'Fran' + String.fromCharCode(231) + 'ais'\r\n" .
" }",
LOCALE_DE => " 3: { // German\r\n" .
" id: LOCALE_DEDE,\r\n" .
" name: 'dede',\r\n" .
" domain: 'de',\r\n" .
" description: 'Deutsch'\r\n" .
" }",
LOCALE_CN => " 4:{ // Chinese\r\n" .
" id: LOCALE_ZHCN,\r\n" .
" name: 'zhcn',\r\n" .
" domain: 'cn',\r\n" .
" description: String.fromCharCode(31616, 20307, 20013, 25991)\r\n" .
" }",
LOCALE_ES => " 6: { // Spanish\r\n" .
" id: LOCALE_ESES,\r\n" .
" name: 'eses',\r\n" .
" domain: 'es',\r\n" .
" description: 'Espa' + String.fromCharCode(241) + 'ol'\r\n" .
" }",
LOCALE_RU => " 8: { // Russian\r\n" .
" id: LOCALE_RURU,\r\n" .
" name: 'ruru',\r\n" .
" domain: 'ru',\r\n" .
" description: String.fromCharCode(1056, 1091, 1089, 1089, 1082, 1080, 1081)\r\n" .
" }",
);
$result = [];
foreach (CLISetup::$locales as $l => $_)
if (isset($available[$l]))
$result[] = $available[$l];
return implode(",\r\n", $result);
foreach (CLISetup::$locales as $loc)
$result[$loc->value] = array(
'id' => '$LOCALE_' . strtoupper($loc->json()),
'name' => $loc->json(),
'domain' => $loc->domain(),
'description' => $loc->title()
);
return Util::toJSON($result);
}
});

View File

@@ -39,28 +39,29 @@ CLISetup::registerSetup("build", new class extends SetupScript
public function generate() : bool
{
$petList = DB::Aowow()->Select(
'SELECT cr.id,
cr.name_loc0, cr.name_loc2, cr.name_loc3, cr.name_loc4, cr.name_loc6, cr.name_loc8,
cr.minLevel, cr.maxLevel,
ft.A, ft.H,
cr.rank AS classification,
cr.family,
cr.displayId1 AS displayId,
cr.textureString AS skin,
LOWER(SUBSTRING_INDEX(cf.iconString, "\\\\", -1)) AS icon,
cf.petTalentType AS type
FROM ?_creature cr
JOIN ?_factiontemplate ft ON ft.id = cr.faction
JOIN dbc_creaturefamily cf ON cf.id = cr.family
WHERE cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
ORDER BY cr.id ASC');
'SELECT cr.`id`,
cr.`name_loc0`, cr.`name_loc2`, cr.`name_loc3`, cr.`name_loc4`, cr.`name_loc6`, cr.`name_loc8`,
cr.`minLevel`, cr.`maxLevel`,
ft.`A`, ft.`H`,
cr.`rank` AS "classification",
cr.`family`,
cr.`displayId1` AS "displayId",
cr.`textureString` AS "skin",
LOWER(SUBSTRING_INDEX(cf.`iconString`, "\\\\", -1)) AS "icon",
cf.`petTalentType` AS "type"
FROM ?_creature cr
JOIN ?_factiontemplate ft ON ft.`id` = cr.`faction`
JOIN dbc_creaturefamily cf ON cf.`id` = cr.`family`
WHERE cr.`typeFlags` & 0x1 AND (cr.`cuFlags` & ?d) = 0
ORDER BY cr.`id` ASC',
NPC_CU_DIFFICULTY_DUMMY
);
$locations = DB::Aowow()->selectCol('SELECT `typeId` AS ARRAY_KEY, `areaId` AS ARRAY_KEY2, `areaId` FROM ?_spawns WHERE `type` = ?d AND `typeId` IN (?a) GROUP BY `typeId`, `areaId`', Type::NPC, array_column($petList, 'id'));
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
$petsOut = [];
foreach ($petList as $pet)
@@ -82,7 +83,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
$toFile = "var g_pets = ".Util::toJSON($petsOut).";";
$file = 'datasets/'.$jsonStr.'/pets';
$file = 'datasets/'.$loc->json().'/pets';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;

View File

@@ -90,12 +90,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
$relCurr = new CurrencyList(array(['id', $_]));
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(20);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
if (!$relCurr->error)
{
@@ -108,7 +107,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
foreach ($questz->getListviewData() as $id => $data)
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-quests-'.$cat2, $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-quests-'.$cat2, $buff))
$this->success = false;
}
}
@@ -132,15 +131,14 @@ CLISetup::registerSetup("build", new class extends SetupScript
// get titles for exclusion
foreach ($titlez->iterate() as $id => $__)
if (empty($titlez->sources[$id][4]) && empty($titlez->sources[$id][12]))
if (empty($titlez->sources[$id][SRC_QUEST]) && empty($titlez->sources[$id][SRC_ACHIEVEMENT]))
$this->addExclusion(Type::TITLE, $id, PR_EXCLUDE_GROUP_UNAVAILABLE);
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
foreach ([GENDER_MALE, GENDER_FEMALE] as $g)
{
@@ -152,7 +150,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
}
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-titles-'.$g, $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-titles-'.$g, $buff))
$this->success = false;
}
}
@@ -168,7 +166,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
);
$mountz = new SpellList($condition);
$conditionSet = DB::World()->selectCol('SELECT SourceEntry AS ARRAY_KEY, ConditionValue1 FROM conditions WHERE SourceTypeOrReferenceId = ?d AND ConditionTypeOrReference = ?d AND SourceEntry IN (?a)', Conditions::SRC_SPELL, Conditions::SKILL, $mountz->getFoundIDs());
$conditionSet = DB::World()->selectCol('SELECT `SourceEntry` AS ARRAY_KEY, `ConditionValue1` FROM conditions WHERE `SourceTypeOrReferenceId` = ?d AND `ConditionTypeOrReference` = ?d AND `SourceEntry` IN (?a)', Conditions::SRC_SPELL, Conditions::SKILL, $mountz->getFoundIDs());
// get mounts for exclusion
foreach ($conditionSet as $mount => $skill)
@@ -179,12 +177,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!$mountz->getSources())
$this->addExclusion(Type::SPELL, $id, PR_EXCLUDE_GROUP_UNAVAILABLE);
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
$buff = "var _ = g_spells;\n";
foreach ($mountz->getListviewData(ITEMINFO_MODEL) as $id => $data)
@@ -203,7 +200,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
}
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-mounts', $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-mounts', $buff))
$this->success = false;
}
}
@@ -222,12 +219,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!$companionz->getSources())
$this->addExclusion(Type::SPELL, $id, PR_EXCLUDE_GROUP_UNAVAILABLE);
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
$buff = "var _ = g_spells;\n";
foreach ($companionz->getListviewData(ITEMINFO_MODEL) as $id => $data)
@@ -241,7 +237,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
}
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-companions', $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-companions', $buff))
$this->success = false;
}
}
@@ -254,12 +250,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
);
$factionz = new FactionList($condition);
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
$buff = "var _ = g_factions;\n";
foreach ($factionz->getListviewData() as $id => $data)
@@ -267,7 +262,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
$buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n";
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-factions', $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-factions', $buff))
$this->success = false;
}
}
@@ -284,8 +279,10 @@ CLISetup::registerSetup("build", new class extends SetupScript
$baseCnd = array(
Cfg::get('SQL_LIMIT_NONE'),
[['cuFlags', CUSTOM_EXCLUDE_FOR_LISTVIEW, '&'], 0],
['effect1Id', [6, 45, 57, 127, 33, 158, 99, 28, 95], '!'], // aura, tradeSkill, Tracking, Prospecting, Decipher, Milling, Disenchant, Summon (Engineering), Skinning
['effect2Id', [118, 60], '!'], // not the skill itself
// Inscryption Engineering
['effect1Id', [SPELL_EFFECT_APPLY_AURA, SPELL_EFFECT_TRADE_SKILL, SPELL_EFFECT_PROSPECTING, SPELL_EFFECT_OPEN_LOCK, SPELL_EFFECT_MILLING, SPELL_EFFECT_DISENCHANT, SPELL_EFFECT_SUMMON, SPELL_EFFECT_SKINNING], '!'],
// not the skill itself
['effect2Id', [SPELL_EFFECT_SKILL, SPELL_EFFECT_PROFICIENCY], '!'],
['OR', ['typeCat', 9], ['typeCat', 11]]
);
@@ -307,12 +304,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
}
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(10);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
$buff = '';
foreach ($recipez->getListviewData() as $id => $data)
@@ -324,7 +320,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!$buff)
{
// this behaviour is intended, do not create an error
CLI::write('[profiler] - file datasets/'.$jsonStr.'/p-recipes-'.$file.' has no content => skipping', CLI::LOG_INFO);
CLI::write('[profiler] - file datasets/'.$loc->json().'/p-recipes-'.$file.' has no content => skipping', CLI::LOG_INFO);
continue;
}
@@ -333,7 +329,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (is_array($s))
$buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n";
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/p-recipes-'.$file, $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/p-recipes-'.$file, $buff))
$this->success = false;
}
}
@@ -348,12 +344,11 @@ CLISetup::registerSetup("build", new class extends SetupScript
);
$achievez = new AchievementList($condition);
foreach (CLISetup::$locales as $l => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
set_time_limit(5);
User::useLocale($l);
Lang::load($l);
Lang::load($loc);
$sumPoints = 0;
$buff = "var _ = g_achievements;\n";
@@ -368,7 +363,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
// sum points
$buff .= "\ng_achievement_points = [".$sumPoints."];\n";
if (!CLISetup::writeFile('datasets/'.$jsonStr.'/achievements', $buff))
if (!CLISetup::writeFile('datasets/'.$loc->json().'/achievements', $buff))
$this->success = false;
}
}
@@ -378,7 +373,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
set_time_limit(2);
CLI::write('[profiler] applying '.count($this->exclusions).' baseline exclusions');
DB::Aowow()->query('DELETE FROM ?_profiler_excludes WHERE comment = ""');
DB::Aowow()->query('DELETE FROM ?_profiler_excludes WHERE `comment` = ""');
foreach ($this->exclusions as $ex)
DB::Aowow()->query('REPLACE INTO ?_profiler_excludes (?#) VALUES (?a)', array_keys($ex), array_values($ex));
@@ -389,10 +384,10 @@ CLISetup::registerSetup("build", new class extends SetupScript
$exData = DB::Aowow()->selectCol('SELECT `type` AS ARRAY_KEY, `typeId` AS ARRAY_KEY2, `groups` FROM ?_profiler_excludes');
for ($i = 0; (1 << $i) < PR_EXCLUDE_GROUP_ANY; $i++)
foreach ($exData as $type => $data)
if ($ids = array_keys(array_filter($data, function ($x) use ($i) { return $x & (1 << $i); } )))
if ($ids = array_keys(array_filter($data, fn($x) => $x & (1 << $i))))
$excludes[$type][$i + 1] = $ids;
$buff = "g_excludes = ".Util::toJSON($excludes ?: (new Stdclass)).";\n";
$buff = "g_excludes = ".Util::toJSON($excludes ?: (new StdClass)).";\n";
if (!CLISetup::writeFile('datasets/quick-excludes', $buff))
$this->success = false;
@@ -400,13 +395,13 @@ CLISetup::registerSetup("build", new class extends SetupScript
private function getExcludeForSkill(int $skillId) : int
{
switch ($skillId)
return match ($skillId)
{
case SKILL_FISHING: return PR_EXCLUDE_GROUP_REQ_FISHING;
case SKILL_ENGINEERING: return PR_EXCLUDE_GROUP_REQ_ENGINEERING;
case SKILL_TAILORING: return PR_EXCLUDE_GROUP_REQ_TAILORING;
default: return 0;
}
SKILL_FISHING => PR_EXCLUDE_GROUP_REQ_FISHING,
SKILL_ENGINEERING => PR_EXCLUDE_GROUP_REQ_ENGINEERING,
SKILL_TAILORING => PR_EXCLUDE_GROUP_REQ_TAILORING,
default => 0
};
}
private function addExclusion(int $type, int $typeId, int $groups, string $comment = '') : void
@@ -423,7 +418,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
}
}
private function sumTotal (array &$sumArr, int $raceMask = -1, int $classMask= -1) : void
private function sumTotal(array &$sumArr, int $raceMask = -1, int $classMask= -1) : void
{
for ($i = 0; $i < RACE_MASK_ALL; $i++)
{

View File

@@ -74,8 +74,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
CLI::write('[realmmenu] no viable realms found .. realm menu will be empty', CLI::LOG_WARN);
// why is this file not localized!?
User::useLocale(LOCALE_EN);
Lang::load(LOCALE_EN);
Lang::load(Locale::EN);
foreach (Util::$regions as $idx => $n)
if ($set & (1 << $idx))

View File

@@ -118,18 +118,18 @@ CLISetup::registerSetup("build", new class extends SetupScript
$this->maxExecTime = ini_get('max_execution_time');
// init directories to be checked when registered
foreach (array_column($this->genSteps, self::$GEN_IDX_DEST_INFO) as $subDirs)
foreach (array_column($this->genSteps, self::GEN_IDX_DEST_INFO) as $subDirs)
foreach ($subDirs as $sd)
$this->requiredDirs[] = $sd[0];
// fix genSteps 2 [icons] - no tiny inventory backgrounds
$this->genSteps[2][self::$GEN_IDX_DEST_INFO] = array_slice($this->genSteps[2][self::$GEN_IDX_DEST_INFO], 0, 3);
$this->genSteps[2][self::GEN_IDX_DEST_INFO] = array_slice($this->genSteps[2][self::GEN_IDX_DEST_INFO], 0, 3);
// fix genSteps 12 [pvp money icons] - smaller border offset for pvp currency icons
array_walk($this->genSteps[12][self::$GEN_IDX_DEST_INFO], function(&$x) { $x[4] = 2; });
array_walk($this->genSteps[12][self::GEN_IDX_DEST_INFO], function(&$x) { $x[4] = 2; });
// fix genSteps 10 [holoday icons] - img src size is 90px
array_walk($this->genSteps[10][self::$GEN_IDX_DEST_INFO], function(&$x) { $x[2] = 90; });
array_walk($this->genSteps[10][self::GEN_IDX_DEST_INFO], function(&$x) { $x[2] = 90; });
}
public function generate() : bool
@@ -154,7 +154,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
if (!in_array($idx, $groups))
unset($this->genSteps[$idx]);
else
$this->genSteps[$idx][self::$GEN_IDX_SRC_REAL] = null;
$this->genSteps[$idx][self::GEN_IDX_SRC_REAL] = null;
}
if (!$this->checkSourceDirs())
@@ -340,24 +340,24 @@ CLISetup::registerSetup("build", new class extends SetupScript
{
if ($siRows = DB::Aowow()->selectCol('SELECT `iconPath` FROM dbc_spellicon WHERE `iconPath` NOT LIKE "%glyph-rune%"'))
foreach ($siRows as $icon)
if (stristr($icon, $this->genSteps[0][self::$GEN_IDX_SRC_PATH])) // Icons/
$dbcEntries[] = strtolower($this->genSteps[0][self::$GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1));
if (stristr($icon, $this->genSteps[0][self::GEN_IDX_SRC_PATH])) // Icons/
$dbcEntries[] = strtolower($this->genSteps[0][self::GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1));
if ($itemIcons = DB::Aowow()->selectCol('SELECT `inventoryIcon1` FROM dbc_itemdisplayinfo WHERE `inventoryIcon1` <> ""'))
foreach ($itemIcons as $icon)
$dbcEntries[] = strtolower($this->genSteps[0][self::$GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon);
$dbcEntries[] = strtolower($this->genSteps[0][self::GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon);
}
if (in_array(1, $gens)) // generates glyphs
if ($siRows = DB::Aowow()->selectCol('SELECT `iconPath` FROM dbc_spellicon WHERE `iconPath` LIKE "%glyph-rune%"'))
foreach ($siRows as $icon)
if (stristr($icon, $this->genSteps[1][self::$GEN_IDX_SRC_PATH])) // Spellbook/
$dbcEntries[] = strtolower($this->genSteps[1][self::$GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1));
if (stristr($icon, $this->genSteps[1][self::GEN_IDX_SRC_PATH])) // Spellbook/
$dbcEntries[] = strtolower($this->genSteps[1][self::GEN_IDX_SRC_REAL].substr(strrchr($icon, '\\'), 1));
if (in_array(10, $gens)) // generates holiday icons
if ($eventIcons = DB::Aowow()->selectCol('SELECT `textureString` FROM dbc_holidays WHERE `textureString` <> ""'))
foreach ($eventIcons as $icon)
$dbcEntries[] = strtolower($this->genSteps[10][self::$GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon.'start');
$dbcEntries[] = strtolower($this->genSteps[10][self::GEN_IDX_SRC_REAL].DIRECTORY_SEPARATOR.$icon.'start');
// case-insensitive array_unique *vomits silently into a corner*
$dbcEntries = array_intersect_key($dbcEntries, array_unique($dbcEntries));

View File

@@ -19,7 +19,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
public function generate() : bool
{
// ALL files
$files = DB::Aowow()->selectCol('SELECT ABS(id) AS ARRAY_KEY, CONCAT(path, "/", `file`) FROM ?_sounds_files');
$files = DB::Aowow()->selectCol('SELECT ABS(`id`) AS ARRAY_KEY, CONCAT(`path`, "/", `file`) FROM ?_sounds_files');
$nFiles = count($files);
$qtLen = strlen($nFiles);
$sum = 0;
@@ -37,31 +37,31 @@ CLISetup::registerSetup("build", new class extends SetupScript
// expect converted files as file.wav_ or file.mp3_
$filePath .= '_';
// just use the first locale available .. there is no support for multiple audio files anyway
foreach (CLISetup::$expectedPaths as $locStr => $__)
// just use the first locale available .. there is no support for multiple audio files for now
foreach (CLISetup::$locales as $loc)
{
// get your paths straight!
$p = CLI::nicePath($filePath, CLISetup::$srcDir, $locStr);
if (CLISetup::fileExists($p))
foreach ($loc->gameDirs() as $dir)
{
// copy over to static/wowsounds/
if (!copy($p, 'static/wowsounds/'.$fileId))
{
$this->success = false;
CLI::write('[soundfiles] - could not copy '.CLI::bold($p).' into '.CLI::bold('static/wowsounds/'.$fileId), CLI::LOG_ERROR);
$time->reset();
break 2;
}
// get your paths straight!
$p = CLI::nicePath($filePath, CLISetup::$srcDir, $dir);
continue 2;
if (!CLISetup::fileExists($p))
continue;
// copy over to static/wowsounds/
if (copy($p, 'static/wowsounds/'.$fileId))
continue 3;
$this->success = false;
CLI::write('[soundfiles] - could not copy '.CLI::bold($p).' into '.CLI::bold('static/wowsounds/'.$fileId), CLI::LOG_ERROR);
$time->reset();
}
}
CLI::write('[soundfiles] - did not find file: '.CLI::bold(CLI::nicePath($filePath, CLISetup::$srcDir, '['.implode(',', CLISetup::$locales).']')), CLI::LOG_WARN);
CLI::write('[soundfiles] - did not find file: '.CLI::bold(CLI::nicePath($filePath, CLISetup::$srcDir, '['.implode(',', array_map(fn($x) => $x->json(), CLISetup::$locales)).']')), CLI::LOG_WARN);
$time->reset();
// flag as unusable in DB
DB::Aowow()->query('UPDATE ?_sounds_files SET id = ?d WHERE ABS(id) = ?d', -$fileId, $fileId);
DB::Aowow()->query('UPDATE ?_sounds_files SET `id` = ?d WHERE ABS(`id`) = ?d', -$fileId, $fileId);
}
return $this->success;

View File

@@ -49,15 +49,14 @@ CLISetup::registerSetup("build", new class extends SetupScript
$this->petFamIcons = ['Ability_Druid_KingoftheJungle', 'Ability_Druid_DemoralizingRoar', 'Ability_EyeOfTheOwl']; // .. i've no idea where to fetch these from
$this->spellMods = (new SpellList(array(['typeCat', -2], Cfg::get('SQL_LIMIT_NONE'))))->getProfilerMods();
$petIcons = Util::toJSON(DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(iconString, "\\\\", -1)) AS iconString FROM dbc_creaturefamily WHERE petTalentType IN (0, 1, 2)'));
$petIcons = Util::toJSON(DB::Aowow()->SelectCol('SELECT `id` AS ARRAY_KEY, LOWER(SUBSTRING_INDEX(`iconString`, "\\\\", -1)) AS "iconString" FROM dbc_creaturefamily WHERE `petTalentType` IN (0, 1, 2)'));
$tSpellIds = DB::Aowow()->selectCol('SELECT rank1 FROM dbc_talent UNION SELECT rank2 FROM dbc_talent UNION SELECT rank3 FROM dbc_talent UNION SELECT rank4 FROM dbc_talent UNION SELECT rank5 FROM dbc_talent');
$tSpellIds = DB::Aowow()->selectCol('SELECT `rank1` FROM dbc_talent UNION SELECT `rank2` FROM dbc_talent UNION SELECT `rank3` FROM dbc_talent UNION SELECT `rank4` FROM dbc_talent UNION SELECT `rank5` FROM dbc_talent');
$this->tSpells = new SpellList(array(['s.id', $tSpellIds], Cfg::get('SQL_LIMIT_NONE')));
foreach (CLISetup::$locales as $lId => $jsonStr)
foreach (CLISetup::$locales as $loc)
{
User::useLocale($lId);
Lang::load($lId);
Lang::load($loc);
// TalentCalc
for ($i = 1; (1 << ($i - 1)) < CLASS_MASK_ALL; $i++ )
@@ -67,7 +66,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
set_time_limit(20);
$file = 'datasets/'.$jsonStr.'/talents-'.$i;
$file = 'datasets/'.$loc->json().'/talents-'.$i;
$toFile = '$WowheadTalentCalculator.registerClass('.$i.', '.Util::toJSON($this->buildTree(1 << ($i - 1))).')';
if (!CLISetup::writeFile($file, $toFile))
@@ -77,7 +76,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
// PetCalc
$toFile = "var g_pet_icons = ".$petIcons.";\n\n";
$toFile .= 'var g_pet_talents = '.Util::toJSON($this->buildTree(0)).';';
$file = 'datasets/'.$jsonStr.'/pet-talents';
$file = 'datasets/'.$loc->json().'/pet-talents';
if (!CLISetup::writeFile($file, $toFile))
$this->success = false;
@@ -91,12 +90,21 @@ CLISetup::registerSetup("build", new class extends SetupScript
$petCategories = [];
// All "tabs" of a given class talent
$tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $classMask);
$tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE `classMask` = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $classMask);
$result = [];
for ($tabIdx = 0; $tabIdx < count($tabs); $tabIdx++)
{
$talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, IF(t.rank5, 5, IF(t.rank4, 4, IF(t.rank3, 3, IF(t.rank2, 2, 1)))) AS maxRank, s.name_loc0, s.name_loc2, s.name_loc3, s.name_loc4, s.name_loc6, s.name_loc8, LOWER(SUBSTRING_INDEX(si.iconPath, "\\\\", -1)) AS iconString FROM dbc_talent t, dbc_spell s, dbc_spellicon si WHERE si.`id` = s.`iconId` AND t.`tabId`= ?d AND s.`id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$tabIdx]['id']);
$talents = DB::Aowow()->select(
'SELECT t.id AS "tId", t.*, IF(t.rank5, 5, IF(t.rank4, 4, IF(t.rank3, 3, IF(t.rank2, 2, 1)))) AS "maxRank",
s.`name_loc0`, s.`name_loc2`, s.`name_loc3`, s.`name_loc4`, s.`name_loc6`, s.`name_loc8`,
LOWER(SUBSTRING_INDEX(si.`iconPath`, "\\\\", -1)) AS "iconString"
FROM dbc_talent t, dbc_spell s, dbc_spellicon si
WHERE si.`id` = s.`iconId` AND t.`tabId`= ?d AND s.`id` = t.`rank1`
ORDER BY t.`row`, t.`column`',
$tabs[$tabIdx]['id']
);
$result[$tabIdx] = array(
'n' => Util::localizedString($tabs[$tabIdx], 'name'),
't' => []
@@ -106,7 +114,7 @@ CLISetup::registerSetup("build", new class extends SetupScript
{
$petFamId = log($tabs[$tabIdx]['creatureFamilyMask'], 2);
$result[$tabIdx]['icon'] = $this->petFamIcons[$petFamId];
$petCategories = DB::Aowow()->SelectCol('SELECT id AS ARRAY_KEY, categoryEnumID FROM dbc_creaturefamily WHERE petTalentType = ?d', $petFamId);
$petCategories = DB::Aowow()->SelectCol('SELECT `id` AS ARRAY_KEY, `categoryEnumID` FROM dbc_creaturefamily WHERE `petTalentType` = ?d', $petFamId);
$result[$tabIdx]['f'] = array_keys($petCategories);
}

View File

@@ -14,9 +14,7 @@ var Locale = {
current: {},
// All
locales: {
/*setup:locales*/
},
locales: /*setup:locales*/,
getAll: function() {
var result = [];

View File

@@ -136,17 +136,17 @@ trait TrTemplateFile
trait TrImageProcessor
{
private $imgPath = '%sInterface/';
private $status = '';
private $maxExecTime = 30;
private $imgPath = '%sInterface/';
private $status = '';
private $maxExecTime = 30;
private static $GEN_IDX_SRC_PATH = 0; // php v8.0 make static > const
private static $GEN_IDX_SRC_REAL = 1;
private static $GEN_IDX_LOCALE = 2;
private static $GEN_IDX_SRC_INFO = 3;
private static $GEN_IDX_DEST_INFO = 4;
private const GEN_IDX_SRC_PATH = 0;
private const GEN_IDX_SRC_REAL = 1;
private const GEN_IDX_LOCALE = 2;
private const GEN_IDX_SRC_INFO = 3;
private const GEN_IDX_DEST_INFO = 4;
private static $JPEG_QUALITY = 85; // 0: worst - 100: best
private const JPEG_QUALITY = 85; // 0: worst - 100: best
private function checkSourceDirs() : bool
{
@@ -161,7 +161,7 @@ trait TrImageProcessor
// multiple genSteps can require the same resource
if (isset($foundCache[$subDir]))
{
$this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = $foundCache[$subDir];
$this->genSteps[$i][self::GEN_IDX_SRC_REAL] = $foundCache[$subDir];
continue;
}
@@ -171,16 +171,20 @@ trait TrImageProcessor
if ($p = CLISetup::filesInPathLocalized($path, $this->success, $localized))
{
$foundCache[$subDir] = $p;
$this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = $p; // php v8.2+ - make GEN_IDX_SRC_REAL a const
$this->genSteps[$i][self::GEN_IDX_SRC_REAL] = $p;
}
else
$this->success = false;
}
$locList = [];
foreach (CLISetup::$expectedPaths as $xp => $locId)
if (in_array($locId, array_keys(CLISetup::$locales)))
$locList[] = $xp;
foreach (Locale::cases() as $loc)
{
if (!$loc->validate() || !in_array($loc, CLISetup::$locales))
continue;
$locList = array_merge($locList, $loc->gameDirs());
}
CLI::write('[img-proc] required resources overview:', CLI::LOG_INFO);
@@ -194,29 +198,29 @@ trait TrImageProcessor
$foundCache[$subDir] = true;
if (!$realPaths)
{
CLI::write(CLI::red('MISSING').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $locList).'/]').$subDir);
CLI::write(CLI::red('MISSING').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $locList).'/]').$subDir);
$this->success = false;
}
else if ($localized)
{
$foundLoc = [];
foreach (CLISetup::$expectedPaths as $xp => $lId)
if (in_array($lId, array_keys(CLISetup::$locales)))
foreach (CLISetup::$locales as $lId => $loc)
foreach ($loc->gameDirs() as $xp)
if (isset($realPaths[$lId]) && ($n = stripos($realPaths[$lId], DIRECTORY_SEPARATOR.$xp.DIRECTORY_SEPARATOR)))
$foundLoc[$lId] = substr($realPaths[$lId], $n + 1, 4);
if ($diff = array_diff_key(CLISetup::$locales, $foundLoc))
{
$buff = [];
foreach ($diff as $d => $_)
$buff[] = CLI::red(Util::$localeStrings[$d]);
foreach ($diff as $loc)
$buff[] = CLI::red($loc->json());
foreach ($foundLoc as $str)
$buff[] = CLI::green($str);
CLI::write(CLI::yellow('PARTIAL').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $buff).'/]').$subDir);
CLI::write(CLI::yellow('PARTIAL').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $buff).'/]').$subDir);
}
else
CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/,', $foundLoc).'/]').$subDir);
CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.sprintf($this->imgPath, '['.implode('/ ', $foundLoc).'/]').$subDir);
}
else
CLI::write(CLI::green('FOUND ').' - '.str_pad($subDir, $outTblLen).' @ '.reset($realPaths));
@@ -227,7 +231,7 @@ trait TrImageProcessor
// if not localized directly return result
foreach ($this->genSteps as $i => [$subDir, $realPaths, $localized, , ])
if (!$localized && $realPaths)
$this->genSteps[$i][self::$GEN_IDX_SRC_REAL] = reset($realPaths);
$this->genSteps[$i][self::GEN_IDX_SRC_REAL] = reset($realPaths);
return $this->success;
}
@@ -235,7 +239,7 @@ trait TrImageProcessor
// prefer manually converted PNG files (as the imagecreatefromblp-script has issues with some formats)
// alpha channel issues observed with locale deDE Hilsbrad and Elwynn - maps
// see: https://github.com/Kanma/BLPConverter
private function loadImageFile(string $path, ?bool &$noSrc = false) // : ?GdImage
private function loadImageFile(string $path, ?bool &$noSrc = false) : ?GdImage
{
$result = null;
$noSrc = false;
@@ -260,7 +264,7 @@ trait TrImageProcessor
return $result;
}
private function writeImageFile(/* GdImage */ $src, string $outFile, array $srcDims, array $destDims) : bool
private function writeImageFile(GdImage $src, string $outFile, array $srcDims, array $destDims) : bool
{
$success = false;
$outRes = imagecreatetruecolor($destDims['w'], $destDims['h']);
@@ -279,7 +283,7 @@ trait TrImageProcessor
switch ($ext)
{
case 'jpg':
$success = imagejpeg($outRes, $outFile, self::$JPEG_QUALITY);
$success = imagejpeg($outRes, $outFile, self::JPEG_QUALITY);
break;
case 'gif':
$success = imagegif($outRes, $outFile);
@@ -309,7 +313,7 @@ trait TrComplexImage
{
use TrImageProcessor { TrImageProcessor::writeImageFile as _writeImageFile; }
private function writeImageFile(/* GdImage */ $src, string $outFile, int $w, int $h) : bool
private function writeImageFile(GdImage $src, string $outFile, int $w, int $h) : bool
{
$srcDims = array(
'x' => 0,
@@ -327,7 +331,7 @@ trait TrComplexImage
return $this->_writeImageFile($src, $outFile, $srcDims, $destDims);
}
private function createAlphaImage(int $w, int $h) //: ?GdImage
private function createAlphaImage(int $w, int $h) : ?GdImage
{
$img = imagecreatetruecolor($w, $h);
if (!$img)
@@ -347,7 +351,7 @@ trait TrComplexImage
return $img;
}
private function assembleImage(string $baseName, array $tileData, int $destW, int $destH) //: ?GdImage
private function assembleImage(string $baseName, array $tileData, int $destW, int $destH) : ?GdImage
{
$dest = imagecreatetruecolor($destW, $destH);
if (!$dest)
@@ -464,8 +468,8 @@ abstract class SetupScript
if (!$this->localized)
$dirs[] = $dir;
else
foreach (CLISetup::$locales as $str)
$dirs[] = $dir . $str . DIRECTORY_SEPARATOR;
foreach (CLISetup::$locales as $loc)
$dirs[] = $dir . $loc->json() . DIRECTORY_SEPARATOR;
foreach ($dirs as $d)
{

View File

@@ -74,14 +74,14 @@ CLISetup::registerSetup('sql', new class extends SetupScript
CLI::write('[achievement] - serverside achievement data');
$serverAchievements = DB::World()->select('SELECT ID AS "id", IF(requiredFaction = -1, 3, IF(requiredFaction = 0, 2, 1)) AS "faction", mapID AS "map", points, flags, count AS "reqCriteriaCount", refAchievement FROM achievement_dbc{ WHERE id IN (?a)}',
$serverAchievements = DB::World()->select('SELECT `ID` AS "id", IF(`requiredFaction` = -1, 3, IF(`requiredFaction` = 0, 2, 1)) AS "faction", `mapID` AS "map", `points`, `flags`, `count` AS "reqCriteriaCount", `refAchievement` FROM achievement_dbc{ WHERE `id` IN (?a)}',
$ids ?: DBSIMPLE_SKIP
);
foreach ($serverAchievements as &$sa)
{
$sa['cuFlags'] = CUSTOM_SERVERSIDE;
foreach (Util::$localeStrings as $i => $_)
foreach (CLISetup::$locales as $i => $_)
if ($_)
$sa['name_loc'.$i] = 'Serverside - #'.$sa['id'];
}
@@ -98,11 +98,11 @@ CLISetup::registerSetup('sql', new class extends SetupScript
CLI::write('[achievement] - linking achievements to chain');
$parents = DB::Aowow()->selectCol('SELECT a.id FROM dbc_achievement a JOIN dbc_achievement b ON b.previous = a.id WHERE a.previous = 0');
$parents = DB::Aowow()->selectCol('SELECT a.`id` FROM dbc_achievement a JOIN dbc_achievement b ON b.`previous` = a.`id` WHERE a.`previous` = 0');
foreach ($parents as $chainId => $next)
{
$tree = [null, $next];
while ($next = DB::Aowow()->selectCell('SELECT id FROM dbc_achievement WHERE previous = ?d', $next))
while ($next = DB::Aowow()->selectCell('SELECT `id` FROM dbc_achievement WHERE `previous` = ?d', $next))
$tree[] = $next;
foreach ($tree as $idx => $aId)
@@ -110,7 +110,7 @@ CLISetup::registerSetup('sql', new class extends SetupScript
if (!$aId)
continue;
DB::Aowow()->query('UPDATE ?_achievement SET cuFlags = cuFlags | ?d, chainId = ?d, chainPos = ?d WHERE id = ?d',
DB::Aowow()->query('UPDATE ?_achievement SET `cuFlags` = `cuFlags` | ?d, `chainId` = ?d, `chainPos` = ?d WHERE `id` = ?d',
$idx == 1 ? ACHIEVEMENT_CU_FIRST_SERIES : (count($tree) == $idx + 1 ? ACHIEVEMENT_CU_LAST_SERIES : 0),
$chainId + 1,
$idx,
@@ -126,8 +126,8 @@ CLISetup::registerSetup('sql', new class extends SetupScript
CLI::write('[achievement] - disabling disabled achievements from table disables');
if ($criteria = DB::World()->selectCol('SELECT entry FROM disables WHERE sourceType = 4'))
DB::Aowow()->query('UPDATE ?_achievement a JOIN ?_achievementcriteria ac ON a.id = ac.refAchievementId SET a.cuFlags = ?d WHERE ac.id IN (?a)', CUSTOM_DISABLED, $criteria);
if ($criteria = DB::World()->selectCol('SELECT `entry` FROM disables WHERE `sourceType` = 4'))
DB::Aowow()->query('UPDATE ?_achievement a JOIN ?_achievementcriteria ac ON a.`id` = ac.`refAchievementId` SET a.`cuFlags` = ?d WHERE ac.`id` IN (?a)', CUSTOM_DISABLED, $criteria);
$this->reapplyCCFlags('achievement', Type::ACHIEVEMENT);

View File

@@ -26,8 +26,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript
if ($x = array_diff_key(CLISetup::$locales, $locPath))
{
$locs = array_intersect_key(CLISetup::$locales, array_flip($x));
CLI::write('[emotes] '.sprintf($globStrPath, CLI::bold('['.implode('/,', $locs).'/]')) . ' not found!', CLI::LOG_WARN);
$locs = array_intersect_key(CLISetup::$locales, $x);
CLI::write('[emotes] '.sprintf($globStrPath, '[' . Lang::concat($locs, callback: fn($x) => CLI::bold(implode('/, ', $x->gameDirs()) . '/')) . ']') . ' not found!', CLI::LOG_WARN);
CLI::write(' Emote aliasses can not be generated for affected locales!', CLI::LOG_WARN);
}
@@ -51,9 +51,9 @@ CLISetup::registerSetup("sql", new class extends SetupScript
12 female others no 4 -
*/
$this->textData = DB::Aowow()->select('SELECT id AS ARRAY_KEY, text_loc0 AS "0", text_loc2 AS "2", text_loc3 AS "3", text_loc4 AS "4", text_loc6 AS "6", text_loc8 AS "8" FROM dbc_emotestextdata');
$this->textData = DB::Aowow()->select('SELECT `id` AS ARRAY_KEY, `text_loc0` AS "0", `text_loc2` AS "2", `text_loc3` AS "3", `text_loc4` AS "4", `text_loc6` AS "6", `text_loc8` AS "8" FROM dbc_emotestextdata');
$texts = DB::Aowow()->select('SELECT et.id AS ARRAY_KEY, LOWER(command) AS `cmd`, IF(e.animationId, 1, 0) AS `anim`, -emoteId AS "parent", e.soundId, etd0, etd1, etd2, etd4, etd6, etd8, etd9, etd12 FROM dbc_emotestext et LEFT JOIN dbc_emotes e ON e.id = et.emoteId');
$texts = DB::Aowow()->select('SELECT et.`id` AS ARRAY_KEY, LOWER(`command`) AS "cmd", IF(e.`animationId`, 1, 0) AS "anim", -`emoteId` AS "parent", e.`soundId`, `etd0`, `etd1`, `etd2`, `etd4`, `etd6`, `etd8`, `etd9`, `etd12` FROM dbc_emotestext et LEFT JOIN dbc_emotes e ON e.`id` = et.`emoteId`');
foreach ($texts AS $id => $t)
{
DB::Aowow()->query(
@@ -68,12 +68,12 @@ CLISetup::registerSetup("sql", new class extends SetupScript
VALUES
(?d, ?, ?d, ?d, ?d, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)',
$id, $t['cmd'], $t['anim'], $t['parent'], $t['soundId'],
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_EN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_EN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_EN), $this->textData[$t['etd2']][LOCALE_EN] ?? '', $this->textData[$t['etd6']][LOCALE_EN] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_FR), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_FR), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_FR), $this->textData[$t['etd2']][LOCALE_FR] ?? '', $this->textData[$t['etd6']][LOCALE_FR] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_DE), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_DE), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_DE), $this->textData[$t['etd2']][LOCALE_DE] ?? '', $this->textData[$t['etd6']][LOCALE_DE] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_CN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_CN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_CN), $this->textData[$t['etd2']][LOCALE_CN] ?? '', $this->textData[$t['etd6']][LOCALE_CN] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_ES), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_ES), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_ES), $this->textData[$t['etd2']][LOCALE_ES] ?? '', $this->textData[$t['etd6']][LOCALE_ES] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], LOCALE_RU), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], LOCALE_RU), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], LOCALE_RU), $this->textData[$t['etd2']][LOCALE_RU] ?? '', $this->textData[$t['etd6']][LOCALE_RU] ?? ''
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::EN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::EN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::EN), $this->textData[$t['etd2']][Locale::EN->value] ?? '', $this->textData[$t['etd6']][Locale::EN->value] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::FR), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::FR), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::FR), $this->textData[$t['etd2']][Locale::FR->value] ?? '', $this->textData[$t['etd6']][Locale::FR->value] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::DE), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::DE), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::DE), $this->textData[$t['etd2']][Locale::DE->value] ?? '', $this->textData[$t['etd6']][Locale::DE->value] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::CN), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::CN), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::CN), $this->textData[$t['etd2']][Locale::CN->value] ?? '', $this->textData[$t['etd6']][Locale::CN->value] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::ES), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::ES), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::ES), $this->textData[$t['etd2']][Locale::ES->value] ?? '', $this->textData[$t['etd6']][Locale::ES->value] ?? '',
$this->mergeGenderedStrings($t['etd0'], $t['etd8'], Locale::RU), $this->mergeGenderedStrings($t['etd1'], $t['etd9'], Locale::RU), $this->mergeGenderedStrings($t['etd4'], $t['etd12'], Locale::RU), $this->textData[$t['etd2']][Locale::RU->value] ?? '', $this->textData[$t['etd6']][Locale::RU->value] ?? ''
);
}
@@ -114,10 +114,10 @@ CLISetup::registerSetup("sql", new class extends SetupScript
return $allOK;
}
private function mergeGenderedStrings(int $maleTextId, int $femaleTextId, int $locale) : string
private function mergeGenderedStrings(int $maleTextId, int $femaleTextId, Locale $loc) : string
{
$maleText = $this->textData[$maleTextId][$locale] ?? '';
$femaleText = $this->textData[$femaleTextId][$locale] ?? '';
$maleText = $this->textData[$maleTextId][$loc->value] ?? '';
$femaleText = $this->textData[$femaleTextId][$loc->value] ?? '';
if (!$maleText && !$femaleText)
return '';

View File

@@ -79,16 +79,17 @@ CLISetup::registerSetup("sql", new class extends SetupScript
29 => [901, 900, 899, 898, 897, 896, 895, 894, 893, 892, 891, 890, 889, 888, 887, 886, 885, 884, 883]
);
// well .. fuck
private $tagsByNamePart = array(
17 => ['gladiator'], // "Arena Season 1 Set",
19 => ['merciless'], // "Arena Season 2 Set",
20 => ['vengeful'], // "Arena Season 3 Set",
22 => ['brutal'], // "Arena Season 4 Set",
24 => ['deadly', 'hateful', 'savage'], // "Arena Season 5 Set",
26 => ['furious'], // "Arena Season 6 Set",
28 => ['relentless'], // "Arena Season 7 Set",
30 => ['wrathful'] // "Arena Season 8 Set",
// in pvp we hope nobody fucked with the item level
private $tagsByItemlevel = array(
123 => 17, // "Arena Season 1 Set"
136 => 19, // "Arena Season 2 Set"
146 => 20, // "Arena Season 3 Set"
159 => 22, // "Arena Season 4 Set"
200 => 24, // "Arena Season 5 Set"
213 => 24, //
232 => 26, // "Arena Season 6 Set"
251 => 28, // "Arena Season 7 Set"
270 => 30 // "Arena Season 8 Set"
);
private function getSetType(array $items) : int
@@ -113,11 +114,11 @@ CLISetup::registerSetup("sql", new class extends SetupScript
{
switch ($item['subclass'])
{
case 0: $type = 8; break; // 1H-Axe
case 4: $type = 9; break; // 1H-Mace
case 7: $type = 10; break; // 1H-Sword
case 13: $type = 7; break; // Fist Weapon
case 15: $type = 5; break; // Dagger
case ITEM_SUBCLASS_1H_AXE: $type = 8; break;
case ITEM_SUBCLASS_1H_MACE: $type = 9; break;
case ITEM_SUBCLASS_1H_SWORD: $type = 10; break;
case ITEM_SUBCLASS_FIST_WEAPON: $type = 7; break;
case ITEM_SUBCLASS_DAGGER: $type = 5; break;
}
}
else if ($item['class'] == ITEM_CLASS_ARMOR)
@@ -150,11 +151,8 @@ CLISetup::registerSetup("sql", new class extends SetupScript
return $tag;
// try arena set
if ($item['ItemLevel'] >= 120 && $item['AllowableClass'] && ($item['AllowableClass'] & CLASS_MASK_ALL) != CLASS_MASK_ALL)
foreach ($this->tagsByNamePart as $tag => $strings)
foreach ($strings as $str)
if (stripos($item['name'], $str) === 0)
return $tag;
if ($item['AllowableClass'] && ($item['AllowableClass'] & CLASS_MASK_ALL) != CLASS_MASK_ALL)
return $this->tagsByItemlevel[$item['ItemLevel']] ?? 0;
return 0;
}
@@ -188,14 +186,14 @@ CLISetup::registerSetup("sql", new class extends SetupScript
public function generate(array $ids = []) : bool
{
// find events associated with holidayIds
if ($pairs = DB::World()->selectCol('SELECT holiday AS ARRAY_KEY, eventEntry FROM game_event WHERE holiday IN (?a)', array_values($this->setToHoliday)))
if ($pairs = DB::World()->selectCol('SELECT `holiday` AS ARRAY_KEY, `eventEntry` FROM game_event WHERE `holiday` IN (?a)', array_values($this->setToHoliday)))
foreach ($this->setToHoliday as &$hId)
$hId = !empty($pairs[$hId]) ? $pairs[$hId] : 0;
DB::Aowow()->query('TRUNCATE TABLE ?_itemset');
$virtualId = 0;
$sets = DB::Aowow()->select('SELECT *, id AS ARRAY_KEY FROM dbc_itemset');
$sets = DB::Aowow()->select('SELECT *, `id` AS ARRAY_KEY FROM dbc_itemset');
foreach ($sets as $setId => $setData)
{
@@ -237,22 +235,22 @@ CLISetup::registerSetup("sql", new class extends SetupScript
$descText = [];
foreach (Util::mask2bits(Cfg::get('LOCALES')) as $loc)
foreach (CLISetup::$locales as $locId => $loc)
{
User::useLocale($loc);
Lang::load($loc);
$row['name_loc'.$loc] = Util::localizedString($setData, 'name');
$row['name_loc'.$locId] = Util::localizedString($setData, 'name');
foreach ($bonusSpells->iterate() as $__)
{
if (!isset($descText[$loc]))
$descText[$loc] = '';
if (!isset($descText[$locId]))
$descText[$locId] = '';
$descText[$loc] .= $bonusSpells->parseText()[0]."\n";
$descText[$locId] .= $bonusSpells->parseText()[0]."\n";
}
// strip rating blocks - e.g. <!--rtg19-->14&nbsp;<small>(<!--rtg%19-->0.30%&nbsp;@&nbsp;L<!--lvl-->80)</small>
$row['bonusText_loc'.$loc] = preg_replace('/<!--rtg\d+-->(\d+)&nbsp.*?<\/small>/i', '\1', $descText[$loc]);
$row['bonusText_loc'.$locId] = preg_replace('/<!--rtg\d+-->(\d+)&nbsp.*?<\/small>/i', '\1', $descText[$locId]);
}
@@ -260,7 +258,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript
/* determine type and reuse from pieces */
/****************************************/
$pieces = DB::World()->select('SELECT entry, name, class, subclass, Quality, AllowableClass, ItemLevel, RequiredLevel, itemset, IF (Flags & ?d, 1, 0) AS heroic, IF(InventoryType = 15, 26, IF(InventoryType = 5, 20, InventoryType)) AS slot, entry AS ARRAY_KEY FROM item_template WHERE itemset = ?d', ITEM_FLAG_HEROIC, $setId);
$pieces = DB::World()->select('SELECT `entry`, `name`, `class`, `subclass`, `Quality`, `AllowableClass`, `ItemLevel`, `RequiredLevel`, `itemset`, IF (`Flags` & ?d, 1, 0) AS "heroic", IF(`InventoryType` = 15, 26, IF(`InventoryType` = 5, 20, `InventoryType`)) AS "slot", `entry` AS ARRAY_KEY FROM item_template WHERE `itemset` = ?d', ITEM_FLAG_HEROIC, $setId);
/*
possible cases:
@@ -294,7 +292,7 @@ CLISetup::registerSetup("sql", new class extends SetupScript
else if (in_array($data['slot'], [INVTYPE_WEAPON, INVTYPE_FINGER, INVTYPE_TRINKET]))
$sorted[$k][-$data['slot']] = $data;
// slot confict. If item is being sold, replace old item (imperfect solution :/)
else if (DB::World()->selectCell('SELECT SUM(n) FROM (SELECT COUNT(1) AS n FROM npc_vendor WHERE item = ?d UNION SELECT COUNT(1) AS n FROM game_event_npc_vendor WHERE item = ?d) x', $data['entry'], $data['entry']))
else if (DB::World()->selectCell('SELECT SUM(`n`) FROM (SELECT COUNT(1) AS "n" FROM npc_vendor WHERE `item` = ?d UNION SELECT COUNT(1) AS "n" FROM game_event_npc_vendor WHERE `item` = ?d) x', $data['entry'], $data['entry']))
$sorted[$k][$data['slot']] = $data;
}

View File

@@ -9,7 +9,7 @@ if (!empty($this->contribute)):
<div class="text" style="margin-right: 310px">
<div class="tabbed-contents" style="clear: none">
<?php
$this->localizedBrick('contrib', User::$localeId);
$this->localizedBrick('contrib', Lang::getLocale());
?>
</div>
</div>

View File

@@ -21,8 +21,8 @@ if (!empty($this->gPageInfo)):
endif;
if (!empty($this->pageTemplate)):
if (User::$localeId && $this->pageTemplate['pageName'] != 'home'):
echo " Locale.set(".User::$localeId.");\n";
if (Lang::getLocale()->value && $this->pageTemplate['pageName'] != 'home'):
echo " Locale.set(".Lang::getLocale()->value.");\n";
endif;
echo " PageTemplate.set(".Util::toJSON($this->pageTemplate).");\n";
@@ -35,4 +35,3 @@ if (!empty($fi)):
endif;
?>
//]]></script>

View File

@@ -66,8 +66,8 @@ endif;
?>
<script type="text/javascript">//<![CDATA[
<?php
if (User::$localeId):
echo " Locale.set(".User::$localeId.");\n";
if (Lang::getLocale()->value):
echo " Locale.set(".Lang::getLocale()->value.");\n";
endif;
echo $this->writeGlobalVars();

View File

@@ -44,7 +44,7 @@ endforeach;
<?php
$idx = 0;
foreach ($this->pieces as $iId => $piece):
echo ' <tr><th align="right" id="iconlist-icon'.(++$idx).'"></th><td><span class="q'.$piece['quality'].'"><a href="?item='.$iId.'">'.$piece['name_'.User::$localeString]."</a></span></td></tr>\n";
echo ' <tr><th align="right" id="iconlist-icon'.(++$idx).'"></th><td><span class="q'.$piece['quality'].'"><a href="?item='.$iId.'">'.$piece['name_'.Lang::getLocale()->json()]."</a></span></td></tr>\n";
endforeach;
?>
</table>

View File

@@ -31,7 +31,7 @@ $this->brick('infobox');
<?=Lang::screenshot('caption').Lang::main('colon'); ?><input type="text" name="screenshotalt" style="width: 55%" maxlength="200" /> <small> <?=Lang::screenshot('charLimit'); ?></small><br />
<div class="pad"></div>
<?php $this->localizedBrick('ssReminder', User::$localeId); ?>
<?php $this->localizedBrick('ssReminder', Lang::getLocale()); ?>
<input type="submit" value="<?=Lang::main('submit'); ?>" />
<input type="hidden" name="coords" />