* 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

@@ -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;
}