mirror of
https://github.com/Sarjuuk/aowow.git
synced 2025-11-29 15:58:16 +08:00
Setup:
- setup can now be run from CLI. Use "> php index.php --help" to start off - updated logging for use with CLI - added generators for client imagery (icons, maps, talents, ect) DBC: - parsed DBCs are now expected in the Aowow-DB, prefixed with dbc_* (they are joined with these tables, so its easier to have them here altogether) - setup/db_setup_3.zip may be reapplied (optionally) - alternatively aowow will now extract you own DBCs alongside your textures. They will be parsed and saved to DB, as needed. Misc: * HOST_URL and STATIC_URL will now be determined automaticly once and * then saved to ?_config (setup by CLI requires these to be set) Spell: * added glyph-symbol to infobox for glyph-related spells
This commit is contained in:
@@ -28,7 +28,7 @@ class DB
|
|||||||
$options = &self::$optionsCache[$idx];
|
$options = &self::$optionsCache[$idx];
|
||||||
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
|
$interface = DbSimple_Generic::connect(self::createConnectSyntax($options));
|
||||||
|
|
||||||
$interface->setErrorHandler(array('DB', 'errorHandler'));
|
$interface->setErrorHandler(['DB', 'errorHandler']);
|
||||||
|
|
||||||
if ($interface->error)
|
if ($interface->error)
|
||||||
die('Failed to connect to database.');
|
die('Failed to connect to database.');
|
||||||
@@ -46,9 +46,9 @@ class DB
|
|||||||
if (!error_reporting())
|
if (!error_reporting())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
echo "DB ERROR:<br /><br />\n\n<pre>";
|
$error = "DB ERROR:<br /><br />\n\n<pre>".print_r($data, true)."</pre>";
|
||||||
print_r($data);
|
|
||||||
echo "</pre>";
|
echo CLI ? strip_tags($error) : $error;
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -4,18 +4,22 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
die('illegal access');
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
require 'includes/defines.php';
|
if (file_exists('config/config.php'))
|
||||||
require 'config/config.php';
|
require_once 'config/config.php';
|
||||||
require 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master)
|
else
|
||||||
require 'includes/utilities.php'; // misc™ data 'n func
|
$AoWoWconf = [];
|
||||||
require 'includes/ajaxHandler.class.php'; // handles ajax and jsonp requests
|
|
||||||
require 'includes/user.class.php';
|
require_once 'includes/defines.php';
|
||||||
require 'includes/markup.class.php'; // manipulate markup text
|
require_once 'includes/libs/DbSimple/Generic.php'; // Libraray: http://en.dklab.ru/lib/DbSimple (using variant: https://github.com/ivan1986/DbSimple/tree/master)
|
||||||
require 'includes/database.class.php'; // wrap DBSimple
|
require_once 'includes/utilities.php'; // misc™ data 'n func
|
||||||
require 'includes/community.class.php'; // handle comments, screenshots and videos
|
require_once 'includes/ajaxHandler.class.php'; // handles ajax and jsonp requests
|
||||||
require 'includes/loot.class.php'; // build lv-tabs containing loot-information
|
require_once 'includes/user.class.php';
|
||||||
require 'localization/lang.class.php';
|
require_once 'includes/markup.class.php'; // manipulate markup text
|
||||||
require 'pages/genericPage.class.php';
|
require_once 'includes/database.class.php'; // wrap DBSimple
|
||||||
|
require_once 'includes/community.class.php'; // handle comments, screenshots and videos
|
||||||
|
require_once 'includes/loot.class.php'; // build lv-tabs containing loot-information
|
||||||
|
require_once 'localization/lang.class.php';
|
||||||
|
require_once 'pages/genericPage.class.php';
|
||||||
|
|
||||||
|
|
||||||
// autoload List-classes, associated filters and pages
|
// autoload List-classes, associated filters and pages
|
||||||
@@ -31,24 +35,22 @@ spl_autoload_register(function ($class) {
|
|||||||
if (strpos($class, 'list'))
|
if (strpos($class, 'list'))
|
||||||
{
|
{
|
||||||
if (!class_exists('BaseType'))
|
if (!class_exists('BaseType'))
|
||||||
require 'includes/types/basetype.class.php';
|
require_once 'includes/types/basetype.class.php';
|
||||||
|
|
||||||
if (file_exists('includes/types/'.strtr($class, ['list' => '']).'.class.php'))
|
if (file_exists('includes/types/'.strtr($class, ['list' => '']).'.class.php'))
|
||||||
require 'includes/types/'.strtr($class, ['list' => '']).'.class.php';
|
require_once 'includes/types/'.strtr($class, ['list' => '']).'.class.php';
|
||||||
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_exists('pages/'.strtr($class, ['page' => '']).'.php'))
|
if (file_exists('pages/'.strtr($class, ['page' => '']).'.php'))
|
||||||
require 'pages/'.strtr($class, ['page' => '']).'.php';
|
require_once 'pages/'.strtr($class, ['page' => '']).'.php';
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
// Setup DB-Wrapper
|
// Setup DB-Wrapper
|
||||||
if (!empty($AoWoWconf['aowow']['db']))
|
if (!empty($AoWoWconf['aowow']['db']))
|
||||||
DB::load(DB_AOWOW, $AoWoWconf['aowow']);
|
DB::load(DB_AOWOW, $AoWoWconf['aowow']);
|
||||||
else
|
|
||||||
die('no database credentials given for: aowow');
|
|
||||||
|
|
||||||
if (!empty($AoWoWconf['world']['db']))
|
if (!empty($AoWoWconf['world']['db']))
|
||||||
DB::load(DB_WORLD, $AoWoWconf['world']);
|
DB::load(DB_WORLD, $AoWoWconf['world']);
|
||||||
@@ -56,15 +58,14 @@ if (!empty($AoWoWconf['world']['db']))
|
|||||||
if (!empty($AoWoWconf['auth']['db']))
|
if (!empty($AoWoWconf['auth']['db']))
|
||||||
DB::load(DB_AUTH, $AoWoWconf['auth']);
|
DB::load(DB_AUTH, $AoWoWconf['auth']);
|
||||||
|
|
||||||
|
if (!empty($AoWoWconf['characters']))
|
||||||
foreach ($AoWoWconf['characters'] as $realm => $charDBInfo)
|
foreach ($AoWoWconf['characters'] as $realm => $charDBInfo)
|
||||||
if (!empty($charDBInfo))
|
if (!empty($charDBInfo))
|
||||||
DB::load(DB_CHARACTERS . $realm, $charDBInfo);
|
DB::load(DB_CHARACTERS . $realm, $charDBInfo);
|
||||||
|
|
||||||
unset($AoWoWconf); // link set up: delete passwords
|
|
||||||
|
|
||||||
|
|
||||||
// load config to constants
|
// load config to constants
|
||||||
$sets = DB::Aowow()->select('SELECT `key` AS ARRAY_KEY, `value`, `flags` FROM ?_config');
|
$sets = DB::isConnectable(DB_AOWOW) ? DB::Aowow()->select('SELECT `key` AS ARRAY_KEY, `value`, `flags` FROM ?_config') : [];
|
||||||
foreach ($sets as $k => $v)
|
foreach ($sets as $k => $v)
|
||||||
{
|
{
|
||||||
// this should not have been possible
|
// this should not have been possible
|
||||||
@@ -80,7 +81,7 @@ foreach ($sets as $k => $v)
|
|||||||
else if ($v['flags'] & CON_FLAG_TYPE_BOOL)
|
else if ($v['flags'] & CON_FLAG_TYPE_BOOL)
|
||||||
$val = (bool)$v['value'];
|
$val = (bool)$v['value'];
|
||||||
else if ($v['flags'] & CON_FLAG_TYPE_STRING)
|
else if ($v['flags'] & CON_FLAG_TYPE_STRING)
|
||||||
$val = preg_replace('/[^\p{L}0-9\s_\-\'\.,]/ui', '', $v['value']);
|
$val = preg_replace('/[^\p{L}0-9~\s_\-\'\/\.,]/ui', '', $v['value']);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
Util::addNote(U_GROUP_ADMIN | U_GROUP_DEV, 'Kernel: '.($php ? 'PHP' : 'Aowow').' config value '.($php ? strtolower($k) : 'CFG_'.strtoupper($k)).' has no type set. Value forced to 0!');
|
Util::addNote(U_GROUP_ADMIN | U_GROUP_DEV, 'Kernel: '.($php ? 'PHP' : 'Aowow').' config value '.($php ? strtolower($k) : 'CFG_'.strtoupper($k)).' has no type set. Value forced to 0!');
|
||||||
@@ -94,38 +95,60 @@ foreach ($sets as $k => $v)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || CFG_FORCE_SSL;
|
error_reporting($AoWoWconf && CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0);
|
||||||
$protocoll = $secure ? 'https://' : 'http://';
|
|
||||||
|
|
||||||
define('STATIC_URL', substr($protocoll.$_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1).'/static'); // points js to images & scripts (change here if you want to use a separate subdomain)
|
$secure = (!empty($_SERVER['HTTPS']) && $_SERVER['HTTPS'] != 'off') || ($AoWoWconf && CFG_FORCE_SSL);
|
||||||
define('HOST_URL', substr($protocoll.$_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1)); // points js to executable files
|
if (defined('CFG_STATIC_HOST')) // points js to images & scripts
|
||||||
|
define('STATIC_URL', ($secure ? 'https://' : 'http://').CFG_STATIC_HOST);
|
||||||
|
|
||||||
$e = CFG_DEBUG ? (E_ALL & ~(E_DEPRECATED | E_USER_DEPRECATED | E_STRICT)) : 0;
|
if (defined('CFG_SITE_HOST')) // points js to executable files
|
||||||
error_reporting($e);
|
define('HOST_URL', ($secure ? 'https://' : 'http://').CFG_SITE_HOST);
|
||||||
|
|
||||||
|
|
||||||
// debug: measure execution times
|
|
||||||
Util::execTime(CFG_DEBUG);
|
|
||||||
|
|
||||||
|
|
||||||
|
if (!CLI)
|
||||||
|
{
|
||||||
// Setup Session
|
// Setup Session
|
||||||
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
|
session_set_cookie_params(15 * YEAR, '/', '', $secure, true);
|
||||||
session_cache_limiter('private');
|
session_cache_limiter('private');
|
||||||
session_start();
|
session_start();
|
||||||
if (User::init())
|
if ($AoWoWconf && User::init())
|
||||||
User::save(); // save user-variables in session
|
User::save(); // save user-variables in session
|
||||||
|
|
||||||
|
// todo: (low) - move to setup web-interface (when it begins its existance)
|
||||||
|
if (!defined('CFG_SITE_HOST') || !defined('CFG_STATIC_HOST'))
|
||||||
|
{
|
||||||
|
$host = substr($_SERVER['SERVER_NAME'].strtr($_SERVER['SCRIPT_NAME'], ['index.php' => '']), 0, -1);
|
||||||
|
|
||||||
|
define('HOST_URL', ($secure ? 'https://' : 'http://').$host);
|
||||||
|
define('STATIC_URL', ($secure ? 'https://' : 'http://').$host.'/static');
|
||||||
|
if (User::isInGroup(U_GROUP_ADMIN) && $AoWoWconf) // initial set
|
||||||
|
{
|
||||||
|
DB::Aowow()->query('INSERT IGNORE INTO ?_config VALUES (?, ?, ?d, ?), (?, ?, ?d, ?)',
|
||||||
|
'site_host', $host, CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.' - points js to executable files (automaticly set on first run)',
|
||||||
|
'static_host', $host.'/static', CON_FLAG_TYPE_STRING | CON_FLAG_PERSISTENT, 'default: '.$host.'/static - points js to images & scripts (automaticly set on first run)'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// hard-override locale for this call (should this be here..?)
|
// hard-override locale for this call (should this be here..?)
|
||||||
// all strings attached..
|
// all strings attached..
|
||||||
|
if ($AoWoWconf)
|
||||||
|
{
|
||||||
if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale'])))
|
if (isset($_GET['locale']) && (CFG_LOCALES & (1 << (int)$_GET['locale'])))
|
||||||
User::useLocale($_GET['locale']);
|
User::useLocale($_GET['locale']);
|
||||||
|
|
||||||
Lang::load(User::$localeString);
|
Lang::load(User::$localeString);
|
||||||
|
}
|
||||||
|
|
||||||
// parse page-parameters .. sanitize before use!
|
// parse page-parameters .. sanitize before use!
|
||||||
@list($str, $trash) = explode('&', $_SERVER['QUERY_STRING'], 2);
|
@list($str, $trash) = explode('&', $_SERVER['QUERY_STRING'], 2);
|
||||||
@list($pageCall, $pageParam) = explode('=', $str, 2);
|
@list($pageCall, $pageParam) = explode('=', $str, 2);
|
||||||
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
|
Util::$wowheadLink = 'http://'.Util::$subDomains[User::$localeId].'.wowhead.com/'.$str;
|
||||||
|
}
|
||||||
|
else if ($AoWoWconf)
|
||||||
|
Lang::load('enus');
|
||||||
|
|
||||||
|
|
||||||
|
$AoWoWconf = null; // empty auths
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
43
index.php
43
index.php
@@ -1,28 +1,39 @@
|
|||||||
<?php
|
<?php
|
||||||
|
|
||||||
define('AOWOW_REVISION', 12);
|
define('AOWOW_REVISION', 12);
|
||||||
|
define('CLI', PHP_SAPI === 'cli');
|
||||||
|
|
||||||
if (!file_exists('config/config.php'))
|
|
||||||
{
|
|
||||||
$cwDir = /*$_SERVER['DOCUMENT_ROOT']; //*/getcwd();
|
|
||||||
require 'setup/setup.php';
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring', 'mcrypt'];
|
$reqExt = ['SimpleXML', 'gd', 'mysqli', 'mbstring'];
|
||||||
$error = '';
|
$error = '';
|
||||||
foreach ($reqExt as $r)
|
foreach ($reqExt as $r)
|
||||||
if (!extension_loaded($r))
|
if (!extension_loaded($r))
|
||||||
$error .= 'Required Extension <b>'.$r."</b> was not found. Please see if it exists, using <i>php -m</i>\n\n";
|
$error .= 'Required Extension <b>'.$r."</b> was not found. Please check if it should exist, using \"<i>php -m</i>\"\n\n";
|
||||||
|
|
||||||
if (version_compare(PHP_VERSION, '5.5.0') < 0)
|
if (version_compare(PHP_VERSION, '5.5.0') < 0)
|
||||||
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!";
|
$error .= 'PHP Version <b>5.5.0</b> or higher required! Your version is <b>'.PHP_VERSION."</b>.\nCore functions are unavailable!\n";
|
||||||
|
|
||||||
|
// not in root dir
|
||||||
|
if (CLI && getcwd().DIRECTORY_SEPARATOR.'index.php' != __FILE__)
|
||||||
|
$error .= "Aowow must be used from root directory\n";
|
||||||
|
|
||||||
if ($error)
|
if ($error)
|
||||||
die('<pre>'.$error.'</pre>');
|
{
|
||||||
|
echo CLI ? strip_tags($error) : $error;
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
// include all necessities, set up basics
|
// include all necessities, set up basics
|
||||||
require 'includes/kernel.php';
|
require_once 'includes/kernel.php';
|
||||||
|
|
||||||
|
|
||||||
|
if (CLI || !file_exists('config/config.php'))
|
||||||
|
{
|
||||||
|
$cwDir = /*$_SERVER['DOCUMENT_ROOT']; //*/getcwd();
|
||||||
|
require 'setup/setup.php';
|
||||||
|
die();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
$altClass = '';
|
$altClass = '';
|
||||||
@@ -82,6 +93,7 @@ switch ($pageCall)
|
|||||||
case 'title':
|
case 'title':
|
||||||
case 'titles':
|
case 'titles':
|
||||||
// case 'user': // tool: user profiles [nyi]
|
// case 'user': // tool: user profiles [nyi]
|
||||||
|
case 'video':
|
||||||
case 'zone':
|
case 'zone':
|
||||||
case 'zones':
|
case 'zones':
|
||||||
if (in_array($pageCall, ['admin', 'account', 'profile']))
|
if (in_array($pageCall, ['admin', 'account', 'profile']))
|
||||||
@@ -134,7 +146,8 @@ switch ($pageCall)
|
|||||||
case 'build':
|
case 'build':
|
||||||
if (User::isInGroup(U_GROUP_EMPLOYEE))
|
if (User::isInGroup(U_GROUP_EMPLOYEE))
|
||||||
{
|
{
|
||||||
require 'setup/tools/filegen/scriptGen.php';
|
define('TMP_BUILD', 1); // todo (med): needs better solution
|
||||||
|
require 'setup/setup.php';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'sql':
|
case 'sql':
|
||||||
@@ -143,12 +156,6 @@ switch ($pageCall)
|
|||||||
require 'setup/tools/database/_'.$pageParam.'.php';
|
require 'setup/tools/database/_'.$pageParam.'.php';
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case 'setup':
|
|
||||||
if (User::isInGroup(U_GROUP_EMPLOYEE))
|
|
||||||
{
|
|
||||||
require 'setup/syncronize.php';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
default: // unk parameter given -> ErrorPage
|
default: // unk parameter given -> ErrorPage
|
||||||
if (isset($_GET['power']))
|
if (isset($_GET['power']))
|
||||||
die('$WowheadPower.register(0, '.User::$localeId.', {})');
|
die('$WowheadPower.register(0, '.User::$localeId.', {})');
|
||||||
|
|||||||
@@ -221,6 +221,19 @@ class SpellPage extends GenericPage
|
|||||||
if ($id == $this->typeId) // "Mode" seems to be multilingual acceptable
|
if ($id == $this->typeId) // "Mode" seems to be multilingual acceptable
|
||||||
$infobox[] = '[li]Mode'.Lang::$main['colon'].Lang::$game['modes'][$n].'[/li]';
|
$infobox[] = '[li]Mode'.Lang::$main['colon'].Lang::$game['modes'][$n].'[/li]';
|
||||||
|
|
||||||
|
$effects = $this->createEffects($infobox, $redButtons);
|
||||||
|
$infobox = $infobox ? '[ul]'.implode('', $infobox).'[/ul]' : '';
|
||||||
|
|
||||||
|
// append glyph symbol if available
|
||||||
|
$glyphId = 0;
|
||||||
|
for ($i = 1; $i < 4; $i++)
|
||||||
|
if ($this->subject->getField('effect'.$i.'Id') == 74)
|
||||||
|
$glyphId = $this->subject->getField('effect'.$i.'MiscValue');
|
||||||
|
|
||||||
|
if ($_ = DB::Aowow()->selectCell('SELECT si.iconString FROM ?_glyphproperties gp JOIN ?_spellicon si ON gp.iconId = si.id WHERE gp.spellId = ?d { OR gp.id = ?d }', $this->typeId, $glyphId ?: DBSIMPLE_SKIP))
|
||||||
|
if (file_exists('static/images/wow/interface/Spellbook/'.$_.'.png'))
|
||||||
|
$infobox .= '[img src='.STATIC_URL.'/images/wow/interface/Spellbook/'.$_.'.png border=0 float=center margin=15]';
|
||||||
|
|
||||||
|
|
||||||
/****************/
|
/****************/
|
||||||
/* Main Content */
|
/* Main Content */
|
||||||
@@ -236,8 +249,8 @@ class SpellPage extends GenericPage
|
|||||||
$this->scaling = $this->createScalingData();
|
$this->scaling = $this->createScalingData();
|
||||||
$this->items = $this->createRequiredItems();
|
$this->items = $this->createRequiredItems();
|
||||||
$this->tools = $this->createTools();
|
$this->tools = $this->createTools();
|
||||||
$this->effects = $this->createEffects($infobox, $redButtons);
|
$this->effects = $effects;
|
||||||
$this->infobox = $infobox ? '[ul]'.implode('', $infobox).'[/ul]' : null;
|
$this->infobox = $infobox;
|
||||||
$this->powerCost = $this->subject->createPowerCostForCurrent();
|
$this->powerCost = $this->subject->createPowerCostForCurrent();
|
||||||
$this->castTime = $this->subject->createCastTimeForCurrent(false, false);
|
$this->castTime = $this->subject->createCastTimeForCurrent(false, false);
|
||||||
$this->name = $this->subject->getField('name', true);
|
$this->name = $this->subject->getField('name', true);
|
||||||
@@ -934,8 +947,8 @@ class SpellPage extends GenericPage
|
|||||||
'params' => array(
|
'params' => array(
|
||||||
'id' => 'teaches-spell',
|
'id' => 'teaches-spell',
|
||||||
'name' => '$LANG.tab_teaches',
|
'name' => '$LANG.tab_teaches',
|
||||||
'visibleCols' => '$'.json_encode($vis),
|
'visibleCols' => '$'.Util::toJSON($vis),
|
||||||
'hiddenCols' => $hid ? '$'.json_encode($hid) : null
|
'hiddenCols' => $hid ? '$'.Util::toJSON($hid) : null
|
||||||
)
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
@@ -1087,7 +1100,7 @@ class SpellPage extends GenericPage
|
|||||||
{
|
{
|
||||||
$this->extendGlobalData($sc[1]);
|
$this->extendGlobalData($sc[1]);
|
||||||
$tab = "<script type=\"text/javascript\">\n" .
|
$tab = "<script type=\"text/javascript\">\n" .
|
||||||
"var markup = ConditionList.createTab(".json_encode($sc[0], JSON_NUMERIC_CHECK).");\n" .
|
"var markup = ConditionList.createTab(".Util::toJSON($sc[0]).");\n" .
|
||||||
"Markup.printHtml(markup, 'tab-conditions', { allow: Markup.CLASS_STAFF })" .
|
"Markup.printHtml(markup, 'tab-conditions', { allow: Markup.CLASS_STAFF })" .
|
||||||
"</script>";
|
"</script>";
|
||||||
|
|
||||||
@@ -1116,12 +1129,12 @@ class SpellPage extends GenericPage
|
|||||||
if ($tt = $this->subject->renderTooltip())
|
if ($tt = $this->subject->renderTooltip())
|
||||||
{
|
{
|
||||||
$pt[] = "\ttooltip_".User::$localeString.": '".Util::jsEscape($tt[0])."'";
|
$pt[] = "\ttooltip_".User::$localeString.": '".Util::jsEscape($tt[0])."'";
|
||||||
$pt[] = "\tspells_".User::$localeString.": ".json_encode($tt[1], JSON_UNESCAPED_UNICODE);
|
$pt[] = "\tspells_".User::$localeString.": ".Util::toJSON($tt[1]);
|
||||||
}
|
}
|
||||||
if ($btt = $this->subject->renderBuff())
|
if ($btt = $this->subject->renderBuff())
|
||||||
{
|
{
|
||||||
$pt[] = "\tbuff_".User::$localeString.": '".Util::jsEscape($btt[0])."'";
|
$pt[] = "\tbuff_".User::$localeString.": '".Util::jsEscape($btt[0])."'";
|
||||||
$pt[] = "\tbuffspells_".User::$localeString.": ".json_encode($btt[1], JSON_UNESCAPED_UNICODE);;
|
$pt[] = "\tbuffspells_".User::$localeString.": ".Util::toJSON($btt[1]);;
|
||||||
}
|
}
|
||||||
$x .= implode(",\n", $pt)."\n});";
|
$x .= implode(",\n", $pt)."\n});";
|
||||||
|
|
||||||
|
|||||||
Binary file not shown.
376
setup/setup.php
Normal file
376
setup/setup.php
Normal file
@@ -0,0 +1,376 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('invalid access');
|
||||||
|
|
||||||
|
|
||||||
|
function buildDirStruct($dir, &$idx = 1, $parent = [], $depths = 0) {
|
||||||
|
$struct = [];
|
||||||
|
|
||||||
|
if ($depths > 3)
|
||||||
|
return 'null';
|
||||||
|
|
||||||
|
$iterator = new RecursiveDirectoryIterator($dir);
|
||||||
|
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
|
||||||
|
|
||||||
|
$basePath = '';
|
||||||
|
foreach ($iterator as $path)
|
||||||
|
{
|
||||||
|
$path = $path->getPathname();
|
||||||
|
if (!is_dir($path) || $path[0] == '.') // also skip hidden dirs
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$idx++;
|
||||||
|
$newParent = $parent;
|
||||||
|
$newParent[] = basename($path);
|
||||||
|
$struct[] = "[".$idx.", \"".basename($path)."\", setPath.bind(this, el, '/".implode($newParent, '/')."'), ".buildDirStruct($path, $idx, $newParent, $depths + 1)."]";
|
||||||
|
}
|
||||||
|
|
||||||
|
return empty($struct) ? 'null' : '['.implode($struct, ",").']';
|
||||||
|
}
|
||||||
|
|
||||||
|
function checkDbcDir($dir, $reqFiles) {
|
||||||
|
$handle = opendir($dir);
|
||||||
|
$content = array();
|
||||||
|
|
||||||
|
while (false !== ($entry = readdir($handle))) {
|
||||||
|
if (is_dir($dir.'\\'.$entry))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$file = explode('.', $entry);
|
||||||
|
if ($file[1] == 'dbc')
|
||||||
|
$content[] = strToLower($file[0]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
if (empty($content))
|
||||||
|
return array(-4, null); // arbitrary directory .. silent death
|
||||||
|
|
||||||
|
foreach ($reqFiles as $k => $v) {
|
||||||
|
if (in_array(strToLower($v), $content))
|
||||||
|
unset($reqFiles[$k]);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (empty($reqFiles)) {
|
||||||
|
$f = fopen($dir.'\\Resistances.dbc', 'rb');
|
||||||
|
|
||||||
|
|
||||||
|
if (fread($f, 4) != "WDBC" || filesize($dir.'\\Resistances.dbc') < 20)
|
||||||
|
return array(-1, 'File looks like DBC but is not in proper format!');
|
||||||
|
|
||||||
|
$parse = dbc2array($dir.'\\Resistances.dbc', "xxxsssssssssxxxxxxxx");
|
||||||
|
|
||||||
|
for ($i = 0; $i <= 8; $i++) {
|
||||||
|
if (empty($parse[0][$i]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (in_array($i, array(0, 2, 3, 6, 8))) // en, X, fr, de, X, X, es, ru
|
||||||
|
return array($i, count($content));
|
||||||
|
else
|
||||||
|
return array(-2, 'locale ":$i." not supported!');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$path = array_pop(explode('\\', $dir));
|
||||||
|
return array(-3, 'Requird files are missing!', '<div>- '.str_replace($cwDir, '', $path).'\\'.implode($reqFiles, '.dbc<br />- '.str_replace($cwDir, '', $path).'\\').'.dbc</div>');
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CLI || defined('TMP_BUILD'))
|
||||||
|
{
|
||||||
|
require_once 'tools/filegen/fileGen.class.php';
|
||||||
|
require_once 'tools/dbc.class.php';
|
||||||
|
require_once 'tools/imagecreatefromblp.php';
|
||||||
|
|
||||||
|
FileGen::init(@$pageParam ?: '');
|
||||||
|
|
||||||
|
if (FileGen::$subScripts)
|
||||||
|
{
|
||||||
|
// start file generation
|
||||||
|
FileGen::status('begin generation of '. implode(', ', FileGen::$subScripts));
|
||||||
|
FileGen::status();
|
||||||
|
|
||||||
|
// files with template
|
||||||
|
foreach (FileGen::$tplFiles as $name => list($file, $destPath))
|
||||||
|
{
|
||||||
|
if (!in_array($name, FileGen::$subScripts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!file_exists(FileGen::$tplPath.$file.'.in'))
|
||||||
|
{
|
||||||
|
FileGen::status(sprintf(ERR_MISSING_FILE, FileGen::$tplPath.$file.'.in'), MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!FileGen::writeDir($destPath))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ($content = file_get_contents(FileGen::$tplPath.$file.'.in'))
|
||||||
|
{
|
||||||
|
if ($dest = @fOpen($destPath.$file, "w"))
|
||||||
|
{
|
||||||
|
// replace constants
|
||||||
|
$content = strtr($content, FileGen::$txtConstants);
|
||||||
|
|
||||||
|
// must generate content
|
||||||
|
// PH format: /*setup:<setupFunc>*/
|
||||||
|
if (preg_match('/\/\*setup:([\w\d_-]+)\*\//i', $content, $m))
|
||||||
|
{
|
||||||
|
if (file_exists('setup/tools/filegen/'.$m[1].'.func.php'))
|
||||||
|
require_once 'setup/tools/filegen/'.$m[1].'.func.php';
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileGen::status(sprintf(ERR_MISSING_INCL, $m[1], 'setup/tools/filegen/'.$m[1].'.func.php'), MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (function_exists($m[1]))
|
||||||
|
$content = str_replace('/*setup:'.$m[1].'*/', $m[1](), $content);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$content = '';
|
||||||
|
FileGen::status('Placeholder in template file does not match any known function name.', MSG_LVL_ERROR);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fWrite($dest, $content))
|
||||||
|
FileGen::status(sprintf(ERR_NONE, $destPath.$file), MSG_LVL_OK);
|
||||||
|
else
|
||||||
|
FileGen::status(sprintf(ERR_WRITE_FILE, $destPath.$file, MSG_LVL_ERROR));
|
||||||
|
|
||||||
|
fClose($dest);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status(sprintf(ERR_CREATE_FILE, $destPath.$file), MSG_LVL_ERROR);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status(sprintf(ERR_READ_FILE, FileGen::$tplPath.$file.'.in'), MSG_LVL_ERROR);
|
||||||
|
}
|
||||||
|
|
||||||
|
// files without template
|
||||||
|
foreach (FileGen::$datasets as $file)
|
||||||
|
{
|
||||||
|
if (!in_array($file, FileGen::$subScripts))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (file_exists('setup/tools/filegen/'.$file.'.func.php'))
|
||||||
|
{
|
||||||
|
require_once 'setup/tools/filegen/'.$file.'.func.php';
|
||||||
|
|
||||||
|
if (function_exists($file))
|
||||||
|
FileGen::status(' - subscript \''.$file.'\' returned '.($file() ? 'sucessfully' : 'with errors'));
|
||||||
|
else
|
||||||
|
FileGen::status(' - subscript \''.$file.'\' not defined in included file', MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
set_time_limit(FileGen::$defaultExecTime); // reset to default for the next script
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status(sprintf(ERR_MISSING_INCL, $file, 'setup/tools/filegen/'.$file.'.func.php', MSG_LVL_ERROR));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// end
|
||||||
|
FileGen::status();
|
||||||
|
FileGen::status('finished file generation');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status('no valid script names supplied');
|
||||||
|
}
|
||||||
|
/*
|
||||||
|
else
|
||||||
|
{
|
||||||
|
if (isset($_GET['pathMenu'])) {
|
||||||
|
// set_time_limit(240); // parsing directory-structures seems to be costy...
|
||||||
|
die(buildDirStruct($cwDir.'/setup', $c));
|
||||||
|
}
|
||||||
|
|
||||||
|
$step = @intVal($_GET['step']);
|
||||||
|
$fields = @explode(';', $_GET['fields']);
|
||||||
|
|
||||||
|
if ($step == 1) {
|
||||||
|
// unset saved credentials
|
||||||
|
$_SESSION['step1']['progress'] &= ~(1 << $fields[0]);
|
||||||
|
$_SESSION['step1'][$fields[0]] = array($fields[1], $fields[3], $fields[4], $fields[2]);
|
||||||
|
|
||||||
|
// try to connect to db with data provided
|
||||||
|
$link = @mysql_connect($fields[1], $fields[3], $fields[4], true);
|
||||||
|
if ($link) {
|
||||||
|
switch ($fields[0]) {
|
||||||
|
case 0:
|
||||||
|
if (mysql_select_db($fields[2], $link)) {
|
||||||
|
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."glyphpropperties'")))
|
||||||
|
die('{"errno":-1, "errstr":"Tables already present in this database will be overwritten!"}');
|
||||||
|
else {
|
||||||
|
$_SESSION['step1']['progress'] |= 0x1;
|
||||||
|
die('{"errno":0, "errstr":""}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (mysql_errno() == 1044) // why doesn't this occur earlier?
|
||||||
|
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
|
||||||
|
else {
|
||||||
|
$_SESSION['step1']['progress'] |= 0x1;
|
||||||
|
die('{"errno":-1, "errstr":"Database will be created during installation!"}');
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
if (mysql_select_db($fields[2], $link)) {
|
||||||
|
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."item_template'"))) {
|
||||||
|
$_SESSION['step1']['progress'] |= 0x2;
|
||||||
|
die('{"errno":0, "errstr":""}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 2:
|
||||||
|
if (mysql_select_db($fields[2], $link)) {
|
||||||
|
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."account'"))) {
|
||||||
|
$_SESSION['step1']['progress'] |= 0x4;
|
||||||
|
die('{"errno":0, "errstr":""}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 3:
|
||||||
|
if (mysql_select_db($fields[2], $link)) {
|
||||||
|
if (mysql_fetch_row(mysql_query("SHOW TABLES FROM ".$fields[2]." LIKE '".$fields[5]."characters'"))) {
|
||||||
|
$_SESSION['step1']['progress'] |= 0x8;
|
||||||
|
die('{"errno":0, "errstr":""}');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if(!mysql_errno())
|
||||||
|
die('{"errno":-1, "errstr":"Required table not found in selected database!"}');
|
||||||
|
else
|
||||||
|
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
|
||||||
|
}
|
||||||
|
else
|
||||||
|
die('{"errno":'.mysql_errno().', "errstr":"'.mysql_error().'"}');
|
||||||
|
|
||||||
|
}
|
||||||
|
else if ($step == 2) {
|
||||||
|
$final = array();
|
||||||
|
|
||||||
|
// sanitize .. clamp dir-choice to DOCUMENT_ROOT
|
||||||
|
$dir = $cwDir.'/setup'.str_replace(['/..', '/.', '../', './'], '', str_replace(',', '/', $fields[1]));
|
||||||
|
|
||||||
|
// unset saved credentials
|
||||||
|
$_SESSION['step2']['progress'] &= ~(1 << $fields[0]);
|
||||||
|
$_SESSION['step2'][$fields[0]] = $dir;
|
||||||
|
|
||||||
|
if (!is_dir($dir))
|
||||||
|
die(json_encode(array(str_replace($cwDir, '', $dir) => array("errno" => 5, "errstr" => "Not a directory!"))));
|
||||||
|
|
||||||
|
$handle = opendir($dir);
|
||||||
|
|
||||||
|
switch ($fields[0]) {
|
||||||
|
case 0: {
|
||||||
|
$reqDBCs = array_keys($dbcStructure);
|
||||||
|
// check this directory
|
||||||
|
$result = checkDbcDir($dir, $reqDBCs);
|
||||||
|
if ($result[0] < 0 && isset($result[1]))
|
||||||
|
$final[str_replace($cwDir, '', $dir)] = array('errno' => -$result[0], 'errstr' => $result[1], 'tooltip' => $result[2]);
|
||||||
|
else if ($result[0] >= 0) {
|
||||||
|
if ($result[1] == 246)
|
||||||
|
$final[str_replace($cwDir, '', $dir)] = array('locale' => $result[0], 'errno' => 0, 'errstr' => '');
|
||||||
|
else
|
||||||
|
$final[str_replace($cwDir, '', $dir)] = array('locale' => $result[0], 'errno' => -1, 'errstr' => (246 - $result[1]).' optional files missing.');
|
||||||
|
}
|
||||||
|
|
||||||
|
// check first-level child direcotries
|
||||||
|
while (false !== ($entry = readdir($handle))) {
|
||||||
|
if ($entry == "." || $entry == "..")
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (is_dir($dir.'\\'.$entry) === true) {
|
||||||
|
$result = checkDbcDir($dir.'\\'.$entry, $reqDBCs);
|
||||||
|
|
||||||
|
if ($result[0] < 0 && isset($result[1]))
|
||||||
|
$final[$entry] = array('errno' => -$result[0], 'errstr' => $result[1], 'tooltip' => $result[2]);
|
||||||
|
else if ($result[0] >= 0) {
|
||||||
|
if ($result[1] == 246)
|
||||||
|
$final[$entry] = array('locale' => $result[0], 'errno' => 0, 'errstr' => '');
|
||||||
|
else
|
||||||
|
$final[$entry] = array('locale' => $result[0], 'errno' => -1, 'errstr' => (246 - $result[1]).' optional files missing.');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
foreach ($final as $v)
|
||||||
|
if ($v['errno'] <= 0)
|
||||||
|
$_SESSION['step2']['progress'] |= 0x1;
|
||||||
|
|
||||||
|
die(json_encode($final));
|
||||||
|
}
|
||||||
|
case 1: {
|
||||||
|
$loc = array('enUS' => 0, 'enGB' => 0, 'frFR' => 2, 'deDE' => 3, 'esES' => 6, 'esMX' => 6, 'ruRU' => 8);
|
||||||
|
$expectDir = array('Icons' => array(6308, "/[\w\d\_]+[\.tga|\s|\.]?.blp/i"), 'Spellbook' => array(20, "/UI\-Glyph\-Rune\-[0-9]+\.blp/i"), 'Worldmap' => array(117));
|
||||||
|
|
||||||
|
foreach ($loc as $k => $v) {
|
||||||
|
if (!is_dir($dir.'\\'.$k))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isset($final[$v]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$final[$v] = array();
|
||||||
|
$j = 0;
|
||||||
|
foreach ($expectDir as $sk => $sv) {
|
||||||
|
if (!is_dir($dir.'\\'.$k.'\\'.$sk))
|
||||||
|
break;
|
||||||
|
|
||||||
|
$handle = opendir($dir.'\\'.$k.'\\'.$sk);
|
||||||
|
$i = 0;
|
||||||
|
while (false !== ($entry = readdir($handle))) {
|
||||||
|
if (isset($sv[1])) {
|
||||||
|
if (is_dir($dir.'\\'.$k.'\\'.$sk.'\\'.$entry) === true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (preg_match($sv[1], $entry, $result))
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (is_dir($dir.'\\'.$k.'\\'.$sk.'\\'.$entry) === false || $entry == '.' || $entry == '..')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ($i == $sv[0]) {
|
||||||
|
$final[$v][$sk] = array('errno' => 0, 'errstr' => '');
|
||||||
|
$final['total'] |= (1 << $j);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$final[$v][$sk] = array('errno' => 1, 'errstr' => ($sv[0] - $i).' files missing in '.$k.'\\'.$sk.'!');
|
||||||
|
|
||||||
|
$j++;
|
||||||
|
}
|
||||||
|
if (empty($final[$v]))
|
||||||
|
$final[$v] = array('errno' => 3, 'errstr' => 'locale directory '.$k.' is empty!');
|
||||||
|
}
|
||||||
|
if ($final['total'] == 0x7)
|
||||||
|
$_SESSION['step2']['progress'] |= 0x2;
|
||||||
|
|
||||||
|
die(json_encode($final));
|
||||||
|
}
|
||||||
|
case 2: {
|
||||||
|
while (false !== ($entry = readdir($handle))) {
|
||||||
|
if (is_dir($entry) === true)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$file = explode('.', $entry);
|
||||||
|
if ($file[1] != 'sql')
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$fRes = fopen($dir."\\".$entry, 'rb');
|
||||||
|
if (preg_match('/\/\* AoWoW 3\.3\.5 (en|fr|de|es|ru)[a-z]{2} locales \*\//i', fread($fRes, 30), $result))
|
||||||
|
$final[$result[1]] = str_replace($cwDir, '', $dir).'\\'.$entry;
|
||||||
|
}
|
||||||
|
if (!empty($final))
|
||||||
|
$_SESSION['step2']['progress'] |= 0x4;
|
||||||
|
|
||||||
|
die(json_encode($final));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
include 'setup.tpl.php';
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
?>
|
||||||
390
setup/tools/dbc.class.php
Normal file
390
setup/tools/dbc.class.php
Normal file
@@ -0,0 +1,390 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
/*
|
||||||
|
DBC::read - PHP function for loading DBC file into array
|
||||||
|
This file is a part of AoWoW project.
|
||||||
|
Copyright (C) 2009-2010 Mix <ru-mangos.ru>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
class DBC
|
||||||
|
{
|
||||||
|
private $_formats = array(
|
||||||
|
'talent' => 'niiiiiiiixxxxixxixxixii',
|
||||||
|
'talenttab' => 'nsxssxxsxsxxxxxxxxiiiiis',
|
||||||
|
'gtchancetomeleecrit' => 'f',
|
||||||
|
'gtchancetomeleecritbase' => 'f',
|
||||||
|
'gtchancetospellcrit' => 'f',
|
||||||
|
'gtchancetospellcritbase' => 'f',
|
||||||
|
'gtoctregenhp' => 'f',
|
||||||
|
'gtregenmpperspt' => 'f',
|
||||||
|
'gtregenhpperspt' => 'f',
|
||||||
|
'spellicon' => 'ns',
|
||||||
|
'itemdisplayinfo' => 'nssxxsxxxxxxxxxxxxxxxxxxx',
|
||||||
|
'holidays' => 'nxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxixxxxxxxxxxiisxix',
|
||||||
|
'chrclasses' => 'nxixsxssxxsxsxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxsxixi',
|
||||||
|
'worldmaparea' => 'niisffffxix', // 4.x - niisffffxixxxx
|
||||||
|
'worldmapoverlay' => 'niixxxxxsiiiixxxx', // 4.x - niixxxsiiiixxxx
|
||||||
|
);
|
||||||
|
private $_fields = array(
|
||||||
|
'talent' => 'Id,tabId,row,column,rank1,rank2,rank3,rank4,rank5,reqTalent,reqRank,talentSpell,petCategory1,petCategory2',
|
||||||
|
'talenttab' => 'Id,nameEN,nameFR,nameDE,nameES,nameRU,iconId,raceMask,classMask,creatureFamilyMask,tabNumber,textureFile',
|
||||||
|
'gtchancetomeleecrit' => 'chance',
|
||||||
|
'gtchancetomeleecritbase' => 'chance',
|
||||||
|
'gtchancetospellcrit' => 'chance',
|
||||||
|
'gtchancetospellcritbase' => 'chance',
|
||||||
|
'gtoctregenhp' => 'ratio',
|
||||||
|
'gtregenmpperspt' => 'ratio',
|
||||||
|
'gtregenhpperspt' => 'ratio',
|
||||||
|
'spellicon' => 'Id,iconPath',
|
||||||
|
'itemdisplayinfo' => 'Id,leftModelName,rightModelName,inventoryIcon1',
|
||||||
|
'holidays' => 'Id,looping,nameId,descriptionId,textureString,scheduleType',
|
||||||
|
'chrclasses' => 'Id,powerType,nameMaleEN,nameMaleFR,nameMaleDE,nameMaleES,nameMaleRU,nameINT,flags,addon',
|
||||||
|
'worldmaparea' => 'Id,mapId,areaId,nameINT,left,right,top,bottom,defaultDungeonMapId',
|
||||||
|
'worldmapoverlay' => 'Id,worldMapAreaId,areaTableId,textureString,w,h,x,y',
|
||||||
|
);
|
||||||
|
|
||||||
|
private $isGameTable = false;
|
||||||
|
|
||||||
|
public $result = [];
|
||||||
|
public $fields = [];
|
||||||
|
public $format = '';
|
||||||
|
public $file = '';
|
||||||
|
|
||||||
|
public function __construct($file)
|
||||||
|
{
|
||||||
|
$file = strtolower($file);
|
||||||
|
if (empty($this->_fields[$file]) || empty($this->_formats[$file]))
|
||||||
|
{
|
||||||
|
FileGen::status('no structure known for '.$file.'.dbc, aborting.', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->fields = explode(',', $this->_fields[$file]);
|
||||||
|
$this->format = $this->_formats[$file];
|
||||||
|
$this->file = $file;
|
||||||
|
|
||||||
|
// gameTable-DBCs don't have an index and are accessed through value order
|
||||||
|
// allas, you cannot do this with mysql, so we add a 'virtual' index
|
||||||
|
$this->isGameTable = $this->format == 'f' && substr($file, 0, 2) == 'gt';
|
||||||
|
}
|
||||||
|
|
||||||
|
public function writeToDB()
|
||||||
|
{
|
||||||
|
if (!$this->result)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
$n = 0;
|
||||||
|
$pKey = $this->fields[0];
|
||||||
|
$query = 'CREATE TABLE `dbc_'.$this->file.'` (';
|
||||||
|
|
||||||
|
if ($this->isGameTable)
|
||||||
|
{
|
||||||
|
$query .= '`idx` BIGINT(20) NOT NULL, ';
|
||||||
|
$pKey = 'idx';
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (str_split($this->format) as $idx => $f)
|
||||||
|
{
|
||||||
|
if ($f == 'f')
|
||||||
|
$query .= '`'.$this->fields[$n].'` FLOAT NOT NULL, ';
|
||||||
|
else if ($f == 's' || $f == 'b')
|
||||||
|
$query .= '`'.$this->fields[$n].'` TEXT NOT NULL, ';
|
||||||
|
else if ($f == 'i' || $f == 'n')
|
||||||
|
$query .= '`'.$this->fields[$n].'` BIGINT(20) NOT NULL, ';
|
||||||
|
|
||||||
|
if ($f == 'n')
|
||||||
|
$pKey = $this->fields[$n];
|
||||||
|
|
||||||
|
if ($f != 'x')
|
||||||
|
$n++;
|
||||||
|
}
|
||||||
|
$query .= 'PRIMARY KEY (`'.$pKey.'`)) COLLATE=\'utf8_general_ci\' ENGINE=MyISAM';
|
||||||
|
|
||||||
|
DB::Aowow()->query('DROP TABLE IF EXISTS ?#', 'dbc_'.$this->file);
|
||||||
|
DB::Aowow()->query($query);
|
||||||
|
|
||||||
|
// make inserts more manageable
|
||||||
|
$offset = 0;
|
||||||
|
$limit = 1000;
|
||||||
|
$fields = $this->fields;
|
||||||
|
|
||||||
|
if ($this->isGameTable)
|
||||||
|
array_unshift($fields, 'idx');
|
||||||
|
|
||||||
|
while (($offset * $limit) < count($this->result))
|
||||||
|
DB::Aowow()->query('INSERT INTO ?# (?#) VALUES (?a)', 'dbc_'.$this->file, $fields, array_slice($this->result, $offset++ * $limit, $limit));
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readFiltered(Closure $filterFunc = null, $localized = false, $safeIf = true)
|
||||||
|
{
|
||||||
|
$result = $this->readArbitrary($localized, $safeIf);
|
||||||
|
|
||||||
|
if (is_object($filterFunc))
|
||||||
|
foreach ($result as $key => &$val)
|
||||||
|
if (!$filterFunc($val, $key))
|
||||||
|
unset($result[$key]);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readArbitrary($localized = false, $safeIf = true)
|
||||||
|
{
|
||||||
|
// try DB first
|
||||||
|
if (!$this->result)
|
||||||
|
$this->readFromDB();
|
||||||
|
|
||||||
|
// try file second
|
||||||
|
if (!$this->result)
|
||||||
|
if ($this->readFromFile($localized) && $safeIf)
|
||||||
|
$this->writeToDB();
|
||||||
|
|
||||||
|
return $this->getIndexed();
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readFromDB()
|
||||||
|
{
|
||||||
|
if (!DB::Aowow()->selectCell('SHOW TABLES LIKE ?', 'dbc_'.$this->file))
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$key = strstr($this->format, 'n') ? $this->fields[strpos($this->format, 'n')] : '';
|
||||||
|
|
||||||
|
$this->result = DB::Aowow()->select('SELECT '.($key ? 'tbl.`'.$key.'` AS ARRAY_KEY, ' : '').'tbl.* FROM ?# tbl', 'dbc_'.$this->file);
|
||||||
|
|
||||||
|
return $this->result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public function readFromFile($localized = false)
|
||||||
|
{
|
||||||
|
if (!$this->file)
|
||||||
|
return [];
|
||||||
|
|
||||||
|
$foundMask = 0x0;
|
||||||
|
foreach (FileGen::$expectedPaths as $locStr => $locId)
|
||||||
|
{
|
||||||
|
if ($foundMask & (1 << $locId))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$fullpath = FileGen::$srcDir.($locStr ? $locStr.'/' : '').'DBFilesClient/'.$this->file.'.dbc';
|
||||||
|
if (!FileGen::fileExists($fullpath))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
FileGen::status(' - reading '.($localized ? 'and merging ' : '').'data from '.$fullpath);
|
||||||
|
|
||||||
|
if (!$this->read($fullpath, $localized))
|
||||||
|
FileGen::status(' - DBC::read() returned with error', MSG_LVL_ERROR);
|
||||||
|
else
|
||||||
|
$foundMask |= (1 << $locId);
|
||||||
|
|
||||||
|
if (!$localized) // one match is enough
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $this->getIndexed();
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
Convert DBC file content into a 2-dimentional array
|
||||||
|
$filename - name of the file
|
||||||
|
$format - format string, that contains 1 character for each field
|
||||||
|
Supported format characters:
|
||||||
|
x - not used/unknown, 4 bytes
|
||||||
|
X - not used/unknown, 1 byte
|
||||||
|
s - char*
|
||||||
|
f - float, 4 bytes (rounded to 4 digits after comma)
|
||||||
|
i - unsigned int, 4 bytes
|
||||||
|
b - unsigned char, 1 byte
|
||||||
|
d - sorted by this field, not included in array
|
||||||
|
n - same, but field included in array
|
||||||
|
*/
|
||||||
|
private function read($filename, $mergeStrings = false)
|
||||||
|
{
|
||||||
|
$file = fopen($filename, 'rb');
|
||||||
|
|
||||||
|
if (!$file)
|
||||||
|
{
|
||||||
|
FileGen::status('cannot open file '.$filename, MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$filesize = filesize($filename);
|
||||||
|
if ($filesize < 20)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$filename.' is too small for a DBC file', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (fread($file, 4) != 'WDBC')
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$filename.' has incorrect magic bytes', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = unpack('VrecordCount/VfieldCount/VrecordSize/VstringSize', fread($file, 16));
|
||||||
|
|
||||||
|
// Different debug checks to be sure, that file was opened correctly
|
||||||
|
$debugStr = '(recordCount='.$header['recordCount'].
|
||||||
|
' fieldCount=' .$header['fieldCount'] .
|
||||||
|
' recordSize=' .$header['recordSize'] .
|
||||||
|
' stringSize=' .$header['stringSize'] .')';
|
||||||
|
|
||||||
|
if ($header['recordCount'] * $header['recordSize'] + $header['stringSize'] + 20 != $filesize)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$filename.' has incorrect size '.$filesize.': '.$debugstr, MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($header['fieldCount'] != strlen($this->format))
|
||||||
|
{
|
||||||
|
FileGen::status('incorrect format string ('.$this->format.') specified for file '.$filename.' fieldCount='.$header['fieldCount'], MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$unpackStr = '';
|
||||||
|
$unpackFmt = array(
|
||||||
|
'x' => 'x/x/x/x',
|
||||||
|
'X' => 'x',
|
||||||
|
's' => 'V',
|
||||||
|
'f' => 'f',
|
||||||
|
'i' => 'V',
|
||||||
|
'b' => 'C',
|
||||||
|
'd' => 'x4',
|
||||||
|
'n' => 'V'
|
||||||
|
);
|
||||||
|
|
||||||
|
// Check that record size also matches
|
||||||
|
$recSize = 0;
|
||||||
|
for ($i = 0; $i < strlen($this->format); $i++)
|
||||||
|
{
|
||||||
|
$ch = $this->format[$i];
|
||||||
|
if ($ch == 'X' || $ch == 'b')
|
||||||
|
$recSize += 1;
|
||||||
|
else
|
||||||
|
$recSize += 4;
|
||||||
|
|
||||||
|
if (!isset($unpackFmt[$ch]))
|
||||||
|
{
|
||||||
|
FileGen::status('unknown format parameter \''.$ch.'\' in format string', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$unpackStr .= '/'.$unpackFmt[$ch];
|
||||||
|
|
||||||
|
if ($ch != 'X' && $ch != 'x')
|
||||||
|
$unpackStr .= 'f'.$i;
|
||||||
|
}
|
||||||
|
|
||||||
|
$unpackStr = substr($unpackStr, 1);
|
||||||
|
|
||||||
|
// Optimizing unpack string: 'x/x/x/x/x/x' => 'x6'
|
||||||
|
while (preg_match('/(x\/)+x/', $unpackStr, $r))
|
||||||
|
$unpackStr = substr_replace($unpackStr, 'x'.((strlen($r[0]) + 1) / 2), strpos($unpackStr, $r[0]), strlen($r[0]));
|
||||||
|
|
||||||
|
// The last debug check (most of the code in this function is for debug checks)
|
||||||
|
if ($recSize != $header['recordSize'])
|
||||||
|
{
|
||||||
|
FileGen::status('format string size ('.$recSize.') for file '.$filename.' does not match actual size ('.$header['recordSize'].') '.$debugstr, MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache the data to make it faster
|
||||||
|
$data = fread($file, $header['recordCount'] * $header['recordSize']);
|
||||||
|
$strings = fread($file, $header['stringSize']);
|
||||||
|
fclose($file);
|
||||||
|
|
||||||
|
// And, finally, extract the records
|
||||||
|
$cache = [];
|
||||||
|
$rSize = $header['recordSize'];
|
||||||
|
$rCount = $header['recordCount'];
|
||||||
|
$fCount = strlen($this->format);
|
||||||
|
|
||||||
|
for ($i = 0; $i < $rCount; $i++)
|
||||||
|
{
|
||||||
|
$row = [];
|
||||||
|
$idx = $i;
|
||||||
|
$record = unpack($unpackStr, substr($data, $i * $rSize, $rSize));
|
||||||
|
|
||||||
|
// add 'virtual' enumerator for gt*-dbcs
|
||||||
|
if ($this->isGameTable)
|
||||||
|
$row[] = $i;
|
||||||
|
|
||||||
|
for ($j = 0; $j < $fCount; $j++)
|
||||||
|
{
|
||||||
|
if (!isset($record['f'.$j]))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$value = $record['f'.$j];
|
||||||
|
if ($this->format[$j] == 's')
|
||||||
|
{
|
||||||
|
if (isset($cache[$value]))
|
||||||
|
$value = $cache[$value];
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$s = substr($strings, $value);
|
||||||
|
$s = substr($s, 0, strpos($s, "\000"));
|
||||||
|
$cache[$value] = $s;
|
||||||
|
$value = $s;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if ($this->format[$j] == 'f')
|
||||||
|
$value = round($value, 8);
|
||||||
|
|
||||||
|
$row[] = $value;
|
||||||
|
|
||||||
|
if ($this->format[$j] == 'n')
|
||||||
|
$idx = $value;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$mergeStrings || empty($this->result[$idx]))
|
||||||
|
$this->result[$idx] = $row;
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$n = 0;
|
||||||
|
for ($j = 0; $j < $fCount; $j++)
|
||||||
|
{
|
||||||
|
if ($this->format[$j] == 's')
|
||||||
|
if (!$this->result[$idx][$n] && $row[$n])
|
||||||
|
$this->result[$idx][$n] = $row[$n];
|
||||||
|
|
||||||
|
if ($this->format[$j] != 'x')
|
||||||
|
$n++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !empty($this->result);
|
||||||
|
}
|
||||||
|
|
||||||
|
private function getIndexed()
|
||||||
|
{
|
||||||
|
$result = $this->result;
|
||||||
|
$fields = $this->fields;
|
||||||
|
if ($this->isGameTable)
|
||||||
|
array_unshift($fields, 'idx');
|
||||||
|
|
||||||
|
foreach ($result as &$row)
|
||||||
|
$row = array_combine($fields, $row);
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
729
setup/tools/filegen/complexImg.func.php
Normal file
729
setup/tools/filegen/complexImg.func.php
Normal file
@@ -0,0 +1,729 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
generate maps - code for extracting regular maps for AoWoW
|
||||||
|
This file is a part of AoWoW project.
|
||||||
|
Copyright (C) 2010 Mix <ru-mangos.ru>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
// note: for the sake of simplicity, this function handles all images, that must be stitched together (which are mostly maps)
|
||||||
|
function complexImg()
|
||||||
|
{
|
||||||
|
if (isset(FileGen::$cliOpts['help']))
|
||||||
|
{
|
||||||
|
echo "\n";
|
||||||
|
echo "available options for subScript 'complexImg':\n"; // modeMask
|
||||||
|
echo "--talentbgs (backgrounds for talent calculator)\n"; // 0x01
|
||||||
|
echo "--maps (generates worldmaps)\n"; // 0x02
|
||||||
|
echo "--spawn-maps (creates alphaMasks of each zone to check spawns against)\n"; // 0x04
|
||||||
|
echo "--artwork (optional: imagery from /glues/credits (not used, skipped by default))\n"; // 0x08
|
||||||
|
echo "--area-maps (optional: renders maps with highlighted subZones for each area)\n"; // 0x10
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists('DBC'))
|
||||||
|
{
|
||||||
|
FileGen::status(' - simpleImg: required class DBC was not included', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('imagecreatefromblp'))
|
||||||
|
{
|
||||||
|
FileGen::status(' - complexImg: required include imagecreatefromblp() was not included', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$mapWidth = 1002;
|
||||||
|
$mapHeight = 668;
|
||||||
|
$runTime = ini_get('max_execution_time');
|
||||||
|
$locStr = null;
|
||||||
|
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/';
|
||||||
|
$imgPath = FileGen::$srcDir.'%sInterface/';
|
||||||
|
$destDir = 'static/images/wow/';
|
||||||
|
$success = true;
|
||||||
|
$paths = ['WorldMap/', 'TalentFrame/', 'Glues/Credits/'];
|
||||||
|
$modeMask = 0x7; // talentBGs, regular maps, spawn-related alphaMaps
|
||||||
|
|
||||||
|
$createAlphaImage = function($w, $h)
|
||||||
|
{
|
||||||
|
$img = imagecreatetruecolor($w, $h);
|
||||||
|
|
||||||
|
imagesavealpha($img, true);
|
||||||
|
imagealphablending($img, false);
|
||||||
|
|
||||||
|
$bgColor = imagecolorallocatealpha($img, 0, 0, 0, 127);
|
||||||
|
imagefilledrectangle($img, 0, 0, imagesx($img) - 1, imagesy($img) - 1, $bgColor);
|
||||||
|
imagecolordeallocate($img, $bgColor);
|
||||||
|
|
||||||
|
imagealphablending($img, true);
|
||||||
|
|
||||||
|
return $img;
|
||||||
|
};
|
||||||
|
|
||||||
|
// 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
|
||||||
|
$loadImageFile = function($path)
|
||||||
|
{
|
||||||
|
$result = null;
|
||||||
|
|
||||||
|
$file = $path.'.png';
|
||||||
|
if (FileGen::fileExists($file))
|
||||||
|
$result = imagecreatefrompng($file);
|
||||||
|
|
||||||
|
if (!$result)
|
||||||
|
{
|
||||||
|
$file = $path.'.blp';
|
||||||
|
if (FileGen::fileExists($file))
|
||||||
|
$result = imagecreatefromblp($file);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
};
|
||||||
|
|
||||||
|
$assembleImage = function($baseName, $order, $w, $h) use ($loadImageFile)
|
||||||
|
{
|
||||||
|
$dest = imagecreatetruecolor($w, $h);
|
||||||
|
imagesavealpha($dest, true);
|
||||||
|
imagealphablending($dest, false);
|
||||||
|
|
||||||
|
$_h = $h;
|
||||||
|
foreach ($order as $y => $row)
|
||||||
|
{
|
||||||
|
$_w = $w;
|
||||||
|
foreach ($row as $x => $suffix)
|
||||||
|
{
|
||||||
|
$src = $loadImageFile($baseName.$suffix);
|
||||||
|
if (!$src)
|
||||||
|
{
|
||||||
|
FileGen::status(' - complexImg: tile '.$baseName.$suffix.'.blp missing.', MSG_LVL_ERROR);
|
||||||
|
unset($dest);
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagecopyresampled($dest, $src, 256 * $x, 256 * $y, 0, 0, min($_w, 256), min($_h, 256), min($_w, 256), min($_h, 256));
|
||||||
|
$_w -= 256;
|
||||||
|
|
||||||
|
unset($src);
|
||||||
|
}
|
||||||
|
$_h -= 256;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $dest;
|
||||||
|
};
|
||||||
|
|
||||||
|
$writeImage = function($name, $ext, $src, $w, $h, $done)
|
||||||
|
{
|
||||||
|
$ok = false;
|
||||||
|
$dest = imagecreatetruecolor($w, $h);
|
||||||
|
imagesavealpha($dest, true);
|
||||||
|
imagealphablending($dest, false);
|
||||||
|
imagecopyresampled($dest, $src, 0, 0, 0, 0, $w, $h, imagesx($src), imagesy($src));
|
||||||
|
|
||||||
|
switch ($ext)
|
||||||
|
{
|
||||||
|
case 'jpg':
|
||||||
|
$ok = imagejpeg($dest, $name.'.'.$ext, 85);
|
||||||
|
break;
|
||||||
|
case 'png':
|
||||||
|
$ok = imagepng($dest, $name.'.'.$ext);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedestroy($dest);
|
||||||
|
|
||||||
|
if ($ok)
|
||||||
|
{
|
||||||
|
chmod($name.'.'.$ext, FileGen::$accessMask);
|
||||||
|
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status($done.' - could not create image '.$name.'.'.$ext, MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
return $ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
$createSpawnMap = function($img, $zoneId) use ($mapHeight, $mapWidth)
|
||||||
|
{
|
||||||
|
FileGen::status(' - creating spawn map');
|
||||||
|
|
||||||
|
$tmp = imagecreate(1000, 1000);
|
||||||
|
$cbg = imagecolorallocate($tmp, 255, 255, 255);
|
||||||
|
$cfg = imagecolorallocate($tmp, 0, 0, 0);
|
||||||
|
|
||||||
|
for ($y = 0; $y < 1000; $y++)
|
||||||
|
{
|
||||||
|
for ($x = 0; $x < 1000; $x++)
|
||||||
|
{
|
||||||
|
$a = imagecolorat($img, ($x * $mapWidth) / 1000, ($y * $mapHeight) / 1000) >> 24;
|
||||||
|
imagesetpixel($tmp, $x, $y, $a < 30 ? $cfg : $cbg);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
imagepng($tmp, 'cache/alphaMaps/' . $zoneId . '.png');
|
||||||
|
|
||||||
|
imagecolordeallocate($tmp, $cbg);
|
||||||
|
imagecolordeallocate($tmp, $cfg);
|
||||||
|
imagedestroy($tmp);
|
||||||
|
};
|
||||||
|
|
||||||
|
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths, &$modeMask)
|
||||||
|
{
|
||||||
|
$incomplete = false;
|
||||||
|
foreach ($paths as $idx => $subDir)
|
||||||
|
{
|
||||||
|
if ($idx == 0 && !($modeMask & 0x16)) // map related
|
||||||
|
continue;
|
||||||
|
else if ($idx == 1 && !($modeMask & 0x1)) // talentBGs
|
||||||
|
continue;
|
||||||
|
else if ($idx == 2 && !($modeMask & 0x8)) // artwork
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$p = sprintf($imgPath, $sub).$subDir;
|
||||||
|
if (!FileGen::fileExists($p))
|
||||||
|
{
|
||||||
|
$missing[] = $p;
|
||||||
|
$incomplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($modeMask & 0x17)
|
||||||
|
{
|
||||||
|
$p = sprintf($dbcPath, $sub);
|
||||||
|
if (!FileGen::fileExists($p))
|
||||||
|
{
|
||||||
|
$missing[] = $p;
|
||||||
|
$incomplete = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return !$incomplete;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
// do not change order of params!
|
||||||
|
if ($_ = FileGen::hasOpt('talentbgs', 'maps', 'spawn-maps', 'artwork', 'area-maps'))
|
||||||
|
$modeMask = $_;
|
||||||
|
|
||||||
|
foreach (FileGen::$expectedPaths as $xp => $__)
|
||||||
|
{
|
||||||
|
if ($xp) // if sun subDir add trailing slash
|
||||||
|
$xp .= '/';
|
||||||
|
|
||||||
|
if ($checkSourceDirs($xp, $missing))
|
||||||
|
{
|
||||||
|
$locStr = $xp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// if no subdir had sufficient data, diaf
|
||||||
|
if ($locStr === null)
|
||||||
|
{
|
||||||
|
FileGen::status('one or more required directories are missing:', MSG_LVL_ERROR);
|
||||||
|
foreach ($missing as $m)
|
||||||
|
FileGen::status(' - '.$m, MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**************/
|
||||||
|
/* TalentTabs */
|
||||||
|
/**************/
|
||||||
|
|
||||||
|
if ($modeMask & 0x01)
|
||||||
|
{
|
||||||
|
if (FileGen::writeDir($destDir.'hunterpettalents/') && FileGen::writeDir($destDir.'talents/backgrounds/'))
|
||||||
|
{
|
||||||
|
// [classMask, creatureFamilyMask, tabNr, textureStr]
|
||||||
|
$talentTab = (new DBC('TalentTab'))->readArbitrary();
|
||||||
|
$chrClass = (new DBC('ChrClasses'))->readArbitrary();
|
||||||
|
$order = array(
|
||||||
|
['-TopLeft', '-TopRight'],
|
||||||
|
['-BottomLeft', '-BottomRight']
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($chrClass && $talentTab)
|
||||||
|
{
|
||||||
|
$sum = 0;
|
||||||
|
$total = count($talentTab);
|
||||||
|
FileGen::status('Processing '.$total.' files from TalentFrame/ ...');
|
||||||
|
|
||||||
|
foreach ($talentTab as $tt)
|
||||||
|
{
|
||||||
|
ini_set('max_execution_time', 30); // max 30sec per image (loading takes the most time)
|
||||||
|
$sum++;
|
||||||
|
$done = ' - '.str_pad($sum.'/'.$total, 8).str_pad('('.number_format($sum * 100 / $total, 2).'%)', 9);
|
||||||
|
|
||||||
|
if ($tt['creatureFamilyMask']) // is PetCalc
|
||||||
|
{
|
||||||
|
$size = [244, 364];
|
||||||
|
$name = $destDir.'hunterpettalents/bg_'.(log($tt['creatureFamilyMask'], 2) + 1);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$size = [204, 554];
|
||||||
|
$name = $destDir.'talents/backgrounds/'.strtolower($chrClass[log($tt['classMask'], 2) + 1]['nameINT']).'_'.($tt['tabNumber'] + 1);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.jpg'))
|
||||||
|
{
|
||||||
|
FileGen::status($done.' - file '.$name.'.jpg was already processed');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$im = $assembleImage(sprintf($imgPath, $locStr).'TalentFrame/'.$tt['textureFile'], $order, 256 + 44, 256 + 75);
|
||||||
|
if (!$im)
|
||||||
|
{
|
||||||
|
FileGen::status(' - could not assemble file '.$tt['textureFile'], MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$writeImage($name, 'jpg', $im, $size[0], $size[1], $done))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
ini_set('max_execution_time', $runTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/************/
|
||||||
|
/* Worldmap */
|
||||||
|
/************/
|
||||||
|
|
||||||
|
if ($modeMask & 0x16)
|
||||||
|
{
|
||||||
|
$mapDirs = array(
|
||||||
|
['maps/%snormal/', 'jpg', 488, 325],
|
||||||
|
['maps/%soriginal/', 'jpg', 0, 0], // 1002, 668
|
||||||
|
['maps/%ssmall/', 'jpg', 224, 163],
|
||||||
|
['maps/%szoom/', 'jpg', 772, 515]
|
||||||
|
);
|
||||||
|
|
||||||
|
// as the js expects them
|
||||||
|
$baseLevelFix = array(
|
||||||
|
// WotLK maps
|
||||||
|
// Halls of Stone; The Nexus; Violet Hold; Gundrak; Obsidian Sanctum; Eye of Eternity; Vault of Archavon; Trial of the Champion; The Forge of Souls; Pit of Saron; Halls of Reflection
|
||||||
|
4264 => 1, 4265 => 1, 4415 => 1, 4416 => 1, 4493 => 0, 4500 => 1, 4603 => 1, 4723 => 1, 4809 => 1, 4813 => 1, 4820 => 1,
|
||||||
|
// Cata maps for WotLK instances
|
||||||
|
// TheStockade; TheBloodFurnace; Ragefire; TheUnderbog; TheBotanica; WailingCaverns; TheSlavePens; TheShatteredHalls; HellfireRamparts; RazorfenDowns; RazorfenKraul; ManaTombs
|
||||||
|
// ShadowLabyrinth; TheTempleOfAtalHakkar (simplified layout); BlackTemple; TempestKeep; MoltenCore; GruulsLair; CoilfangReservoir; MagtheridonsLair; OnyxiasLair; SunwellPlateau;
|
||||||
|
717 => 1, 3713 => 1, 2437 => 1, 3716 => 1, 3847 => 1, 718 => 1, 3717 => 1, 3714 => 1, 3562 => 1, 722 => 1, 491 => 1, 3792 => 1,
|
||||||
|
3789 => 1, 1477 => 1, 3959 => 0, 3845 => 1, 2717 => 1, 3923 => 1, 3607 => 1, 3836 => 1, 2159 => 1, 4075 => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
$tmp = (new DBC('WorldMapArea'))->readArbitrary();
|
||||||
|
$wma = [];
|
||||||
|
foreach ($tmp as $row)
|
||||||
|
{
|
||||||
|
// fixups...
|
||||||
|
if (!$row['areaId'])
|
||||||
|
{
|
||||||
|
switch ($row['Id'])
|
||||||
|
{
|
||||||
|
case 13: $row['areaId'] = -6; break; // Kalimdor
|
||||||
|
case 14: $row['areaId'] = -3; break; // Eastern Kingdoms
|
||||||
|
case 466: $row['areaId'] = -2; break; // Outland
|
||||||
|
case 485: $row['areaId'] = -5; break; // Northrend
|
||||||
|
}
|
||||||
|
}
|
||||||
|
$wma[] = $row;
|
||||||
|
}
|
||||||
|
|
||||||
|
$tmp = (new DBC('WorldMapOverlay'))->readFiltered(function(&$val) { return !empty($val['textureString']); });
|
||||||
|
$wmo = [];
|
||||||
|
foreach ($tmp as $row)
|
||||||
|
$wmo[$row['worldMapAreaId']][] = $row;
|
||||||
|
|
||||||
|
if (!$wma || !$wmo)
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
FileGen::status(' - could not read required dbc files: WorldMapArea.dbc ['.count($wma).' entries]; WorldMapOverlay.dbc ['.count($wmo).' entries]', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// more fixups to WorldMapArea
|
||||||
|
array_unshift($wma, ['Id' => -1, 'areaId' => -1, 'nameINT' => 'World'], ['Id' => -4, 'areaId' => -4, 'nameINT' => 'Cosmic']);
|
||||||
|
|
||||||
|
$sumMaps = count(FileGen::$localeIds) * count($wma);
|
||||||
|
|
||||||
|
FileGen::status('Processing '.$sumMaps.' files from WorldMap/ ...');
|
||||||
|
|
||||||
|
foreach (FileGen::$localeIds as $progressLoc => $l)
|
||||||
|
{
|
||||||
|
// create destination directories
|
||||||
|
$dirError = false;
|
||||||
|
foreach ($mapDirs as $md)
|
||||||
|
if (!FileGen::writeDir($destDir . sprintf($md[0], strtolower(Util::$localeStrings[$l]).'/')))
|
||||||
|
$dirError = true;
|
||||||
|
|
||||||
|
if ($modeMask & 0x04)
|
||||||
|
if (!FileGen::writeDir('cache/alphaMaps'))
|
||||||
|
$dirError = true;
|
||||||
|
|
||||||
|
if ($dirError)
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
FileGen::status(' - complexImg: could not create map directories for locale '.$l.'. skipping...', MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
// source for mapFiles
|
||||||
|
$mapSrcDir = null;
|
||||||
|
$locDirs = array_filter(FileGen::$expectedPaths, function($var) use ($l) { return !$var || $var == $l; });
|
||||||
|
foreach ($locDirs as $mapLoc => $__)
|
||||||
|
{
|
||||||
|
if ($mapLoc) // and trailing slash again
|
||||||
|
$mapLoc .= '/';
|
||||||
|
|
||||||
|
$p = sprintf($imgPath, $mapLoc).$paths[0];
|
||||||
|
if (FileGen::fileExists($p))
|
||||||
|
{
|
||||||
|
FileGen::status(' - using files from '.($mapLoc ?: '/').' for locale '.Util::$localeStrings[$l], MSG_LVL_WARN);
|
||||||
|
$mapSrcDir = $p.'/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($mapSrcDir === null)
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
FileGen::status(' - no suitable localized map files found for locale '.$l, MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
foreach ($wma as $progressArea => $areaEntry)
|
||||||
|
{
|
||||||
|
$curMap = $progressArea + count($wma) * $progressLoc;
|
||||||
|
$progress = ' - ' . str_pad($curMap.'/'.($sumMaps), 10) . str_pad('('.number_format($curMap * 100 / $sumMaps, 2).'%)', 9);
|
||||||
|
|
||||||
|
$wmaId = $areaEntry['Id'];
|
||||||
|
$zoneId = $areaEntry['areaId'];
|
||||||
|
$textureStr = $areaEntry['nameINT'];
|
||||||
|
|
||||||
|
$path = $mapSrcDir.$textureStr;
|
||||||
|
if (!FileGen::fileExists($path))
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
FileGen::status('worldmap file '.$path.' missing for selected locale '.Util::$localeStrings[$l], MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fmt = array(
|
||||||
|
[1, 2, 3, 4],
|
||||||
|
[5, 6, 7, 8],
|
||||||
|
[9, 10, 11, 12]
|
||||||
|
);
|
||||||
|
|
||||||
|
FileGen::status($textureStr . " [" . $zoneId . "]");
|
||||||
|
|
||||||
|
$overlay = $createAlphaImage($mapWidth, $mapHeight);
|
||||||
|
|
||||||
|
// zone has overlays (is in open world; is not multiLeveled)
|
||||||
|
if (isset($wmo[$wmaId]))
|
||||||
|
{
|
||||||
|
FileGen::status(' - area has '.count($wmo[$wmaId]).' overlays');
|
||||||
|
|
||||||
|
foreach ($wmo[$wmaId] as &$row)
|
||||||
|
{
|
||||||
|
$i = 1;
|
||||||
|
$y = 0;
|
||||||
|
while ($y < $row['h'])
|
||||||
|
{
|
||||||
|
$x = 0;
|
||||||
|
while ($x < $row['w'])
|
||||||
|
{
|
||||||
|
$img = $loadImageFile($path . '/' . $row['textureString'] . $i);
|
||||||
|
if (!$img)
|
||||||
|
{
|
||||||
|
FileGen::status(' - complexImg: tile '.$path.'/'.$row['textureString'].$i.'.blp missing.', MSG_LVL_ERROR);
|
||||||
|
break 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagecopy($overlay, $img, $row['x'] + $x, $row['y'] + $y, 0, 0, imagesx($img), imagesy($img));
|
||||||
|
|
||||||
|
// prepare subzone image
|
||||||
|
if ($modeMask & 0x10)
|
||||||
|
{
|
||||||
|
if (!isset($row['maskimage']))
|
||||||
|
{
|
||||||
|
$row['maskimage'] = $createAlphaImage($row['w'], $row['h']);
|
||||||
|
$row['maskcolor'] = imagecolorallocatealpha($row['maskimage'], 255, 64, 192, 64);
|
||||||
|
}
|
||||||
|
|
||||||
|
for ($my = 0; $my < imagesy($img); $my++)
|
||||||
|
for ($mx = 0; $mx < imagesx($img); $mx++)
|
||||||
|
if ((imagecolorat($img, $mx, $my) >> 24) < 30)
|
||||||
|
imagesetpixel($row['maskimage'], $x + $mx, $y + $my, $row['maskcolor']);
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedestroy($img);
|
||||||
|
|
||||||
|
$x += 256;
|
||||||
|
$i++;
|
||||||
|
}
|
||||||
|
$y += 256;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// create spawn-maps if wanted
|
||||||
|
if ($modeMask & 0x04)
|
||||||
|
$createSpawnMap($overlay, $zoneId);
|
||||||
|
}
|
||||||
|
|
||||||
|
// check, if the current zone is multiLeveled
|
||||||
|
// if there are also files present without layer-suffix assume them as layer: 0
|
||||||
|
$multiLeveled = false;
|
||||||
|
$multiLevel = 0;
|
||||||
|
do
|
||||||
|
{
|
||||||
|
if (!FileGen::filesInPath('/'.$textureStr.'\/'.$textureStr.($multiLevel + 1).'_\d\.blp/i', true))
|
||||||
|
break;
|
||||||
|
|
||||||
|
$multiLevel++;
|
||||||
|
$multiLeveled = true;
|
||||||
|
}
|
||||||
|
while ($multiLevel < 18); // Karazhan has 17 frickin floors
|
||||||
|
|
||||||
|
// check if we can create base map anyway
|
||||||
|
$file = $path.'/'.$textureStr.'1.blp';
|
||||||
|
$hasBaseMap = FileGen::fileExists($file);
|
||||||
|
|
||||||
|
FileGen::status(' - area has '.($multiLeveled ? $multiLevel . ' levels' : 'only base level'));
|
||||||
|
|
||||||
|
$map = null;
|
||||||
|
for ($i = 0; $i <= $multiLevel; $i++)
|
||||||
|
{
|
||||||
|
ini_set('max_execution_time', 120); // max 120sec per image
|
||||||
|
|
||||||
|
$file = $path.'/'.$textureStr;
|
||||||
|
|
||||||
|
if (!$i && !$hasBaseMap)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// if $multiLeveled also suffix -0 to baseMap if it exists
|
||||||
|
if ($i && $multiLeveled)
|
||||||
|
$file .= $i.'_';
|
||||||
|
|
||||||
|
$doSkip = 0x0;
|
||||||
|
$outFile = [];
|
||||||
|
|
||||||
|
foreach ($mapDirs as $idx => $info)
|
||||||
|
{
|
||||||
|
$outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $zoneId;
|
||||||
|
|
||||||
|
$floor = $i;
|
||||||
|
if ($zoneId == 4100) // ToCStratholme: map order fix
|
||||||
|
$floor += 1;
|
||||||
|
|
||||||
|
if ($multiLeveled && !(isset($baseLevelFix[$zoneId]) && $i == $baseLevelFix[$zoneId]))
|
||||||
|
$outFile[$idx] .= '-'.$floor;
|
||||||
|
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1]))
|
||||||
|
{
|
||||||
|
FileGen::status($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed');
|
||||||
|
$doSkip |= (1 << $idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($doSkip == 0xF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$map = $assembleImage($file, $fmt, $mapWidth, $mapHeight);
|
||||||
|
if (!$map)
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
FileGen::status(' - could not create image resource for map '.$zoneId.($multiLevel ? ' level '.$i : ''));
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$multiLeveled)
|
||||||
|
{
|
||||||
|
imagecolortransparent($overlay, imagecolorat($overlay, imagesx($overlay)-1, imagesy($overlay)-1));
|
||||||
|
imagecopymerge($map, $overlay, 0, 0, 0, 0, imagesx($overlay), imagesy($overlay), 100);
|
||||||
|
imagedestroy($overlay);
|
||||||
|
}
|
||||||
|
|
||||||
|
// create map
|
||||||
|
if ($modeMask & 0x02)
|
||||||
|
{
|
||||||
|
foreach ($mapDirs as $idx => $info)
|
||||||
|
{
|
||||||
|
if ($doSkip & (1 << $idx))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!$writeImage($outFile[$idx], $info[1], $map, $info[2] ?: $mapWidth, $info[3] ?: $mapHeight, $progress))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// also create subzone-maps
|
||||||
|
if ($map && isset($wmo[$wmaId]) && $modeMask & 0x10)
|
||||||
|
{
|
||||||
|
foreach ($wmo[$wmaId] as &$row)
|
||||||
|
{
|
||||||
|
$doSkip = 0x0;
|
||||||
|
$outFile = [];
|
||||||
|
|
||||||
|
foreach ($mapDirs as $idx => $info)
|
||||||
|
{
|
||||||
|
$outFile[$idx] = $destDir . sprintf($info[0], strtolower(Util::$localeStrings[$l]).'/') . $row['areaTableId'];
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($outFile[$idx].'.'.$info[1]))
|
||||||
|
{
|
||||||
|
FileGen::status($progress.' - file '.$outFile[$idx].'.'.$info[1].' was already processed');
|
||||||
|
$doSkip |= (1 << $idx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($doSkip == 0xF)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$subZone = imagecreatetruecolor($mapWidth, $mapHeight);
|
||||||
|
imagecopy($subZone, $map, 0, 0, 0, 0, imagesx($map), imagesy($map));
|
||||||
|
imagecopy($subZone, $row['maskimage'], $row['x'], $row['y'], 0, 0, imagesx($row['maskimage']), imagesy($row['maskimage']));
|
||||||
|
|
||||||
|
foreach ($mapDirs as $idx => $info)
|
||||||
|
{
|
||||||
|
if ($doSkip & (1 << $idx))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!$writeImage($outFile[$idx], $info[1], $subZone, $info[2] ?: $mapWidth, $info[3] ?: $mapHeight, $progress))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedestroy($subZone);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($map)
|
||||||
|
imagedestroy($map);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/***********/
|
||||||
|
/* Credits */
|
||||||
|
/***********/
|
||||||
|
|
||||||
|
if ($modeMask & 0x08) // optional tidbits (not used by default)
|
||||||
|
{
|
||||||
|
if (FileGen::writeDir($destDir.'interface/Glues/Credits/'))
|
||||||
|
{
|
||||||
|
// tile ordering
|
||||||
|
$order = array(
|
||||||
|
1 => array(
|
||||||
|
[1]
|
||||||
|
),
|
||||||
|
2 => array(
|
||||||
|
[1],
|
||||||
|
[2]
|
||||||
|
),
|
||||||
|
4 => array(
|
||||||
|
[1, 2],
|
||||||
|
[3, 4]
|
||||||
|
),
|
||||||
|
6 => array(
|
||||||
|
[1, 2, 3],
|
||||||
|
[4, 5, 6]
|
||||||
|
),
|
||||||
|
8 => array(
|
||||||
|
[1, 2, 3, 4],
|
||||||
|
[5, 6, 7, 8]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$imgGroups = [];
|
||||||
|
$srcPath = sprintf($imgPath, $locStr).'Glues/Credits/';
|
||||||
|
$files = FileGen::filesInPath($srcPath);
|
||||||
|
foreach ($files as $f)
|
||||||
|
{
|
||||||
|
if (preg_match('/([^\/]+)(\d).blp/i', $f, $m))
|
||||||
|
{
|
||||||
|
if ($m[1] && $m[2])
|
||||||
|
{
|
||||||
|
if (!isset($imgGroups[$m[1]]))
|
||||||
|
$imgGroups[$m[1]] = $m[2];
|
||||||
|
else if ($imgGroups[$m[1]] < $m[2])
|
||||||
|
$imgGroups[$m[1]] = $m[2];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// errör-korrekt
|
||||||
|
$imgGroups['Desolace'] = 4;
|
||||||
|
$imgGroups['BloodElf_Female'] = 6;
|
||||||
|
|
||||||
|
$total = count($imgGroups);
|
||||||
|
$sum = 0;
|
||||||
|
|
||||||
|
FileGen::status('Processing '.$total.' files from Glues/Credits/...');
|
||||||
|
|
||||||
|
foreach ($imgGroups as $file => $fmt)
|
||||||
|
{
|
||||||
|
ini_set('max_execution_time', 30); // max 30sec per image (loading takes the most time)
|
||||||
|
|
||||||
|
$sum++;
|
||||||
|
$done = ' - '.str_pad($sum.'/'.$total, 8).str_pad('('.number_format($sum * 100 / $total, 2).'%)', 9);
|
||||||
|
$name = $destDir.'interface/Glues/Credits/'.$file;
|
||||||
|
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($name.'.png'))
|
||||||
|
{
|
||||||
|
FileGen::status($done.' - file '.$name.'.png was already processed');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!isset($order[$fmt]))
|
||||||
|
{
|
||||||
|
FileGen::status(' - pattern for file '.$name.' not set. skipping', MSG_LVL_WARN);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
$im = $assembleImage($srcPath.$file, $order[$fmt], count($order[$fmt][0]) * 256, count($order[$fmt]) * 256);
|
||||||
|
if (!$im)
|
||||||
|
{
|
||||||
|
FileGen::status(' - could not assemble file '.$name, MSG_LVL_ERROR);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$writeImage($name, 'png', $im, count($order[$fmt][0]) * 256, count($order[$fmt]) * 256, $done))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
ini_set('max_execution_time', $runTime);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -52,18 +52,17 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function enchants(&$log, $locales)
|
function enchants()
|
||||||
{
|
{
|
||||||
// from g_item_slots: 13:"One-Hand", 26:"Ranged", 17:"Two-Hand",
|
// from g_item_slots: 13:"One-Hand", 26:"Ranged", 17:"Two-Hand",
|
||||||
$slotPointer = [13, 17, 26, 26, 13, 17, 17, 13, 17, null, 17, null, null, 13, null, 13, null, null, null, null, 17];
|
$slotPointer = [13, 17, 26, 26, 13, 17, 17, 13, 17, null, 17, null, null, 13, null, 13, null, null, null, null, 17];
|
||||||
$locales = [LOCALE_EN, LOCALE_FR, LOCALE_DE, LOCALE_ES, LOCALE_RU];
|
|
||||||
$castItems = [];
|
$castItems = [];
|
||||||
$successs = true;
|
$successs = true;
|
||||||
$enchantSpells = new SpellList([['effect1Id', 53], ['name_loc0', 'QA%', '!'], CFG_SQL_LIMIT_NONE]); // enchantItemPermanent && !qualityAssurance
|
$enchantSpells = new SpellList([['effect1Id', 53], ['name_loc0', 'QA%', '!'], CFG_SQL_LIMIT_NONE]); // enchantItemPermanent && !qualityAssurance
|
||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
$enchIds = [];
|
$enchIds = [];
|
||||||
@@ -73,7 +72,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$enchMisc = [];
|
$enchMisc = [];
|
||||||
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
|
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
set_time_limit(120);
|
set_time_limit(120);
|
||||||
|
|
||||||
@@ -135,11 +134,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$ench['jsonequip']['requiredLevel'] = $enchMisc[$eId]['requiredLevel'];
|
$ench['jsonequip']['requiredLevel'] = $enchMisc[$eId]['requiredLevel'];
|
||||||
|
|
||||||
// check if the spell has an entry in skill_line_ability -> Source:Profession
|
// check if the spell has an entry in skill_line_ability -> Source:Profession
|
||||||
if ($skill = DB::Aowow()->SelectCell('SELECT skillLineId FROM dbc.skilllineability WHERE spellId = ?d', $enchantSpells->id))
|
if ($skills = $enchantSpells->getField('skillLines'))
|
||||||
{
|
{
|
||||||
$ench['name'][] = $enchantSpells->getField('name', true);
|
$ench['name'][] = $enchantSpells->getField('name', true);
|
||||||
$ench['source'][] = $enchantSpells->id;
|
$ench['source'][] = $enchantSpells->id;
|
||||||
$ench['skill'] = $skill;
|
$ench['skill'] = $skills[0];
|
||||||
$ench['slots'][] = $slot;
|
$ench['slots'][] = $slot;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,12 +208,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
if (is_array($v) && count($v) == 1 && $k != 'jsonequip')
|
if (is_array($v) && count($v) == 1 && $k != 'jsonequip')
|
||||||
$ench[$k] = $v[0];
|
$ench[$k] = $v[0];
|
||||||
|
|
||||||
$toFile = "var g_enchants = ";
|
$toFile = "var g_enchants = ".Util::toJSON($enchantsOut).";";
|
||||||
$toFile .= json_encode($enchantsOut, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
|
||||||
$toFile .= ";";
|
|
||||||
$file = 'datasets/'.User::$localeString.'/enchants';
|
$file = 'datasets/'.User::$localeString.'/enchants';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
423
setup/tools/filegen/fileGen.class.php
Normal file
423
setup/tools/filegen/fileGen.class.php
Normal file
@@ -0,0 +1,423 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// shared strings
|
||||||
|
define('ERR_CREATE_FILE', 'could not create file at destination %s' );
|
||||||
|
define('ERR_WRITE_FILE', 'could not write to file at destination %s' );
|
||||||
|
define('ERR_READ_FILE', 'file %s could not be read' );
|
||||||
|
define('ERR_MISSING_FILE', 'file %s not found' );
|
||||||
|
define('ERR_NONE', 'created file %s' );
|
||||||
|
define('ERR_MISSING_INCL', 'required function %s() could not be found at %s');
|
||||||
|
|
||||||
|
define('MSG_LVL_OK', 0);
|
||||||
|
define('MSG_LVL_WARN', 1);
|
||||||
|
define('MSG_LVL_ERROR', 2);
|
||||||
|
|
||||||
|
|
||||||
|
class FileGen
|
||||||
|
{
|
||||||
|
public static $success = false;
|
||||||
|
|
||||||
|
public static $srcDir = 'setup/mpqData/';
|
||||||
|
public static $tplPath = 'setup/tools/filegen/templates/';
|
||||||
|
|
||||||
|
// update paths [yes, you can have en empty string as key]
|
||||||
|
public static $expectedPaths = array(
|
||||||
|
'frFR' => 2,
|
||||||
|
'deDE' => 3,
|
||||||
|
'esES' => 6, 'esMX' => 6,
|
||||||
|
'ruRU' => 8,
|
||||||
|
'' => 0, 'enGB' => 0, 'enUS' => 0,
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $cliOpts = [];
|
||||||
|
private static $shortOpts = 'fh';
|
||||||
|
private static $longOpts = array(
|
||||||
|
'build:', 'log::', 'help', 'locales::', 'force', 'mpqDataDir::', // general
|
||||||
|
'icons', 'glyphs', 'pagetexts', 'loadingscreens', // whole images
|
||||||
|
'artwork', 'talentbgs', 'maps', 'spawn-maps', 'area-maps' // images from image parts
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $subScripts = [];
|
||||||
|
public static $tplFiles = array(
|
||||||
|
'searchplugin' => ['aowow.xml', 'static/download/searchplugins/'],
|
||||||
|
'power' => ['power.js', 'static/widgets/' ],
|
||||||
|
'searchboxScript' => ['searchbox.js', 'static/widgets/' ],
|
||||||
|
'demo' => ['demo.html', 'static/widgets/power/' ],
|
||||||
|
'searchboxBody' => ['searchbox.html', 'static/widgets/searchbox/' ],
|
||||||
|
'realmMenu' => ['profile_all.js', 'static/js/' ],
|
||||||
|
'locales' => ['locale.js', 'static/js/' ],
|
||||||
|
// 'itemScaling => ['item-scaling', 'datasets/' ], # provided 'as is', as dbc-content doesn't usualy change
|
||||||
|
);
|
||||||
|
public static $datasets = array(
|
||||||
|
'pets', 'simpleImg', 'complexImg',
|
||||||
|
'realms', 'statistics', 'profiler', // profiler related
|
||||||
|
'talents', 'talentIcons', 'glyphs', // talentCalc related
|
||||||
|
'itemsets', 'enchants', 'gems' // comparison related
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $defaultExecTime = 30;
|
||||||
|
|
||||||
|
public static $accessMask = 0755;
|
||||||
|
|
||||||
|
private static $logFile = '';
|
||||||
|
private static $logHandle = null;
|
||||||
|
|
||||||
|
private static $mpqFiles = [];
|
||||||
|
|
||||||
|
private static $locales = [];
|
||||||
|
public static $localeIds = [];
|
||||||
|
|
||||||
|
private static $reqDirs = array(
|
||||||
|
'static/uploads/screenshots/normal',
|
||||||
|
'static/uploads/screenshots/pending',
|
||||||
|
'static/uploads/screenshots/resized',
|
||||||
|
'static/uploads/screenshots/temp',
|
||||||
|
'static/uploads/screenshots/thumb',
|
||||||
|
'static/uploads/temp/'
|
||||||
|
);
|
||||||
|
|
||||||
|
public static $txtConstants = array(
|
||||||
|
'CFG_NAME' => CFG_NAME,
|
||||||
|
'CFG_NAME_SHORT' => CFG_NAME_SHORT,
|
||||||
|
'HOST_URL' => HOST_URL,
|
||||||
|
'STATIC_URL' => STATIC_URL
|
||||||
|
);
|
||||||
|
|
||||||
|
public static function init($scriptList = '')
|
||||||
|
{
|
||||||
|
self::$defaultExecTime = ini_get('max_execution_time');
|
||||||
|
$doScripts = [];
|
||||||
|
if (CLI)
|
||||||
|
{
|
||||||
|
if (getopt(self::$shortOpts, self::$longOpts))
|
||||||
|
self::handleCLIOpts($doScripts);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
self::printCLIHelp(array_merge(array_keys(self::$tplFiles), self::$datasets));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$doScripts = explode(',', $scriptList);
|
||||||
|
self::$locales = Util::$localeStrings;
|
||||||
|
}
|
||||||
|
|
||||||
|
// check passed subscript names; limit to real scriptNames
|
||||||
|
self::$subScripts = array_merge(array_keys(self::$tplFiles), self::$datasets);
|
||||||
|
if ($doScripts)
|
||||||
|
self::$subScripts = array_intersect($doScripts, self::$subScripts);
|
||||||
|
|
||||||
|
// restrict actual locales
|
||||||
|
foreach (self::$locales as $idx => $str)
|
||||||
|
{
|
||||||
|
if (!$str)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (!defined('CFG_LOCALES'))
|
||||||
|
self::$localeIds[] = $idx;
|
||||||
|
else if (CFG_LOCALES & (1 << $idx))
|
||||||
|
self::$localeIds[] = $idx;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!self::$localeIds)
|
||||||
|
{
|
||||||
|
self::status('No valid locale specified. Check your config or --locales parameter, if used', MSG_LVL_ERROR);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// create directory structure
|
||||||
|
self::status('FileGen::init() - creating required directories');
|
||||||
|
$pathOk = 0;
|
||||||
|
foreach (self::$reqDirs as $rd)
|
||||||
|
if (self::writeDir($rd))
|
||||||
|
$pathOk++;
|
||||||
|
|
||||||
|
FileGen::status('created '.$pathOk.' extra paths'.($pathOk == count(self::$reqDirs) ? '' : ' with errors'));
|
||||||
|
FileGen::status();
|
||||||
|
}
|
||||||
|
|
||||||
|
// shared funcs
|
||||||
|
public static function writeFile($file, $content)
|
||||||
|
{
|
||||||
|
$success = false;
|
||||||
|
if ($handle = @fOpen($file, "w"))
|
||||||
|
{
|
||||||
|
if (fWrite($handle, $content))
|
||||||
|
{
|
||||||
|
$success = true;
|
||||||
|
self::status(sprintf(ERR_NONE, $file), MSG_LVL_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self::status(sprintf(ERR_WRITE_FILE, $file), MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
fClose($handle);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self::status(sprintf(ERR_CREATE_FILE, $file), MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
if ($success)
|
||||||
|
@chmod($file, FileGen::$accessMask);
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function writeDir($dir)
|
||||||
|
{
|
||||||
|
if (is_dir($dir))
|
||||||
|
{
|
||||||
|
if (!is_writable($dir) && !@chmod($dir, FileGen::$accessMask))
|
||||||
|
self::status('cannot write into output directory '.$dir, MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
return is_writable($dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (@mkdir($dir, FileGen::$accessMask, true))
|
||||||
|
return true;
|
||||||
|
|
||||||
|
self::status('could not create output directory '.$dir, MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function status($txt = '', $lvl = -1)
|
||||||
|
{
|
||||||
|
if (isset(self::$cliOpts['help']))
|
||||||
|
return;
|
||||||
|
|
||||||
|
$cliColor = "\033[%sm%s\033[0m";
|
||||||
|
$htmlColor = '<span style="color:%s;">%s</span>';
|
||||||
|
|
||||||
|
if (self::$logFile && !self::$logHandle)
|
||||||
|
{
|
||||||
|
if (!file_exists(self::$logFile))
|
||||||
|
self::$logHandle = fopen(self::$logFile, 'w');
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$logFileParts = pathinfo(self::$logFile);
|
||||||
|
|
||||||
|
$i = 1;
|
||||||
|
while (file_exists($logFileParts['dirname'].'/'.$logFileParts['filename'].$i.'.'.$logFileParts['extension']))
|
||||||
|
$i++;
|
||||||
|
|
||||||
|
self::$logFile = $logFileParts['dirname'].'/'.$logFileParts['filename'].$i.'.'.$logFileParts['extension'];
|
||||||
|
self::$logHandle = fopen(self::$logFile, 'w');
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg = $raw = "\n";
|
||||||
|
if ($txt)
|
||||||
|
{
|
||||||
|
$msg = $raw = str_pad(date('H:i:s'), 10);
|
||||||
|
switch ($lvl)
|
||||||
|
{
|
||||||
|
case MSG_LVL_ERROR: // red error
|
||||||
|
$str = 'Error: ';
|
||||||
|
$raw .= $str;
|
||||||
|
$msg .= CLI ? sprintf($cliColor, '0;31', $str) : sprintf($htmlColor, 'darkred', $str);
|
||||||
|
break;
|
||||||
|
case MSG_LVL_WARN: // yellow warn
|
||||||
|
$str = 'Notice: ';
|
||||||
|
$raw .= $str;
|
||||||
|
$msg .= CLI ? sprintf($cliColor, '0;33', $str) : sprintf($htmlColor, 'orange', $str);
|
||||||
|
break;
|
||||||
|
case MSG_LVL_OK: // green success
|
||||||
|
$str = 'Success:';
|
||||||
|
$raw = $raw . $str;
|
||||||
|
$msg .= CLI ? sprintf($cliColor, '0;32', $str) : sprintf($htmlColor, 'darkgreen', $str);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$msg .= ' ';
|
||||||
|
$raw .= ' ';
|
||||||
|
}
|
||||||
|
|
||||||
|
$msg .= ' '.$txt."\n";
|
||||||
|
$raw .= ' '.$txt."\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (CLI)
|
||||||
|
{
|
||||||
|
// maybe for future use: writing \x08 deletes the last char, use to repeatedly update single line (and even WIN should be able to handle it)
|
||||||
|
|
||||||
|
echo substr(PHP_OS, 0, 3) == 'WIN' ? $raw : $msg;
|
||||||
|
|
||||||
|
if (self::$logHandle)
|
||||||
|
fwrite(self::$logHandle, $raw);
|
||||||
|
|
||||||
|
@ob_flush();
|
||||||
|
flush();
|
||||||
|
@ob_end_flush();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
echo "<pre>".$msg."</pre>\n";
|
||||||
|
}
|
||||||
|
|
||||||
|
private static function handleCLIOpts(&$doScripts)
|
||||||
|
{
|
||||||
|
$_ = getopt(self::$shortOpts, self::$longOpts);
|
||||||
|
|
||||||
|
if ((isset($_['help']) || isset($_['h'])) && empty($_['build']))
|
||||||
|
{
|
||||||
|
self::printCLIHelp(array_merge(array_keys(self::$tplFiles), self::$datasets));
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// required subScripts
|
||||||
|
if (!empty($_['build']))
|
||||||
|
$doScripts = explode(',', $_['build']);
|
||||||
|
|
||||||
|
// optional logging
|
||||||
|
if (!empty($_['log']))
|
||||||
|
self::$logFile = trim($_['log']);
|
||||||
|
|
||||||
|
// optional, overwrite existing files
|
||||||
|
if (isset($_['f']))
|
||||||
|
self::$cliOpts['force'] = true;
|
||||||
|
|
||||||
|
// alternative data source (no quotes, use forward slash)
|
||||||
|
if (!empty($_['mpqDataDir']))
|
||||||
|
self::$srcDir = str_replace(['\\', '"', '\''], ['/', '', ''], $_['mpqDataDir']);
|
||||||
|
|
||||||
|
if (isset($_['h']))
|
||||||
|
self::$cliOpts['help'] = true;
|
||||||
|
|
||||||
|
// optional limit handled locales
|
||||||
|
if (!empty($_['locales']))
|
||||||
|
{
|
||||||
|
// engb and enus are identical for all intents and purposes
|
||||||
|
$from = ['engb', 'esmx'];
|
||||||
|
$to = ['enus', 'eses'];
|
||||||
|
$_['locales'] = str_replace($from, $to, strtolower($_['locales']));
|
||||||
|
|
||||||
|
self::$locales = array_intersect(Util::$localeStrings, explode(',', $_['locales']));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
self::$locales = Util::$localeStrings;
|
||||||
|
|
||||||
|
// mostly build-instructions from longOpts
|
||||||
|
foreach (self::$longOpts as $opt)
|
||||||
|
if (!strstr($opt, ':') && isset($_[$opt]))
|
||||||
|
self::$cliOpts[$opt] = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function hasOpt(/* ...$opt */)
|
||||||
|
{
|
||||||
|
$result = 0x0;
|
||||||
|
foreach (func_get_args() as $idx => $arg)
|
||||||
|
{
|
||||||
|
if (!is_string($arg))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isset(self::$cliOpts[$arg]))
|
||||||
|
$result |= (1 << $idx);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* the problem
|
||||||
|
1) paths provided in dbc files are case-insensitive and random
|
||||||
|
2) paths to the actual textures contained in the mpq archives are case-insensitive and random
|
||||||
|
unix systems will throw a fit if you try to get from one to the other, so lets save the paths from 2) and cast it to lowecase
|
||||||
|
lookups will be done in lowercase. A successfull match will return the real path.
|
||||||
|
*/
|
||||||
|
private static function buildFileList()
|
||||||
|
{
|
||||||
|
self::status('FileGen::init() - reading MPQdata from '.self::$srcDir.' to list for first time use...');
|
||||||
|
|
||||||
|
$setupDirs = glob('setup/*');
|
||||||
|
foreach ($setupDirs as $sd)
|
||||||
|
{
|
||||||
|
if (substr(self::$srcDir, -1) == '/')
|
||||||
|
self::$srcDir = substr(self::$srcDir, 0, -1);
|
||||||
|
|
||||||
|
if (substr($sd, -1) == '/')
|
||||||
|
$sd = substr($sd, 0, -1);
|
||||||
|
|
||||||
|
if (strtolower($sd) == strtolower(self::$srcDir))
|
||||||
|
{
|
||||||
|
self::$srcDir = $sd.'/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
$iterator = new RecursiveDirectoryIterator(self::$srcDir);
|
||||||
|
$iterator->setFlags(RecursiveDirectoryIterator::SKIP_DOTS);
|
||||||
|
|
||||||
|
foreach (new RecursiveIteratorIterator($iterator, RecursiveIteratorIterator::SELF_FIRST) as $path)
|
||||||
|
{
|
||||||
|
$_ = str_replace('\\', '/', $path->getPathname());
|
||||||
|
self::$mpqFiles[strtolower($_)] = $_;
|
||||||
|
}
|
||||||
|
|
||||||
|
self::status('done');
|
||||||
|
self::status();
|
||||||
|
}
|
||||||
|
catch (UnexpectedValueException $e) { self::status('- mpqData dir '.self::$srcDir.' does not exist', MSG_LVL_ERROR); }
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function fileExists(&$file)
|
||||||
|
{
|
||||||
|
// read mpq source file structure to tree
|
||||||
|
if (!self::$mpqFiles)
|
||||||
|
self::buildFileList();
|
||||||
|
|
||||||
|
// backslash to forward slash
|
||||||
|
$_ = strtolower(str_replace('\\', '/', $file));
|
||||||
|
|
||||||
|
// remove trailing slash
|
||||||
|
if (substr($_, -1, 1) == '/')
|
||||||
|
$_ = substr($_, 0, -1);
|
||||||
|
|
||||||
|
if (isset(self::$mpqFiles[$_]))
|
||||||
|
{
|
||||||
|
$file = self::$mpqFiles[$_];
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function filesInPath($path, $useRegEx = false)
|
||||||
|
{
|
||||||
|
$result = [];
|
||||||
|
|
||||||
|
// read mpq source file structure to tree
|
||||||
|
if (!self::$mpqFiles)
|
||||||
|
self::buildFileList();
|
||||||
|
|
||||||
|
// backslash to forward slash
|
||||||
|
$_ = strtolower(str_replace('\\', '/', $path));
|
||||||
|
|
||||||
|
foreach (self::$mpqFiles as $lowerFile => $realFile)
|
||||||
|
{
|
||||||
|
if (!$useRegEx && strstr($lowerFile, $_))
|
||||||
|
$result[] = $realFile;
|
||||||
|
else if ($useRegEx && preg_match($path, $lowerFile))
|
||||||
|
$result[] = $realFile;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $result;
|
||||||
|
}
|
||||||
|
|
||||||
|
public static function printCLIHelp($scripts)
|
||||||
|
{
|
||||||
|
echo "usage: php index.php --build=<subScriptList,> [-h --help] [--log logfile] [-f --force] [--mpqDataDir=path/to/mpqData/] [--locales=<regionCodes,>]\n\n";
|
||||||
|
echo "build -> available subScripts:\n";
|
||||||
|
foreach ($scripts as $s)
|
||||||
|
echo " - ".str_pad($s, 20).(isset(self::$tplFiles[$s]) ? self::$tplFiles[$s][1].self::$tplFiles[$s][0] : 'static data file')."\n";
|
||||||
|
|
||||||
|
echo "help -> shows this info\n";
|
||||||
|
echo "log -> writes ouput to file\n";
|
||||||
|
echo "force -> enforces overwriting existing files\n";
|
||||||
|
echo "locales -> limits setup to enUS, frFR, deDE, esES and/or ruRU (does not override config settings)\n";
|
||||||
|
echo "mpqDataDir -> manually point to directory with extracted mpq data (default: setup/mpqData/)\n";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
?>
|
||||||
@@ -21,7 +21,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function gems(&$log, $locales)
|
function gems()
|
||||||
{
|
{
|
||||||
// sketchy, but should work
|
// sketchy, but should work
|
||||||
// Id < 36'000 || ilevel < 70 ? BC : WOTLK
|
// Id < 36'000 || ilevel < 70 ? BC : WOTLK
|
||||||
@@ -41,7 +41,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
$enchIds = [];
|
$enchIds = [];
|
||||||
@@ -51,7 +51,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$enchMisc = [];
|
$enchMisc = [];
|
||||||
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
|
$enchJSON = Util::parseItemEnchantment($enchIds, false, $enchMisc);
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -72,12 +72,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$toFile = "var g_gems = ";
|
$toFile = "var g_gems = ".Util::toJSON($gemsOut).";";
|
||||||
$toFile .= json_encode($gemsOut, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
|
||||||
$toFile .= ";";
|
|
||||||
$file = 'datasets/'.User::$localeString.'/gems';
|
$file = 'datasets/'.User::$localeString.'/gems';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,7 +20,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function glyphs(&$log, $locales)
|
function glyphs()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$glyphList = DB::Aowow()->Select(
|
$glyphList = DB::Aowow()->Select(
|
||||||
@@ -42,12 +42,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
$glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE));
|
$glyphSpells = new SpellList(array(['s.id', array_keys($glyphList)], CFG_SQL_LIMIT_NONE));
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
set_time_limit(30);
|
set_time_limit(30);
|
||||||
|
|
||||||
@@ -76,12 +76,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$toFile = "var g_glyphs = ";
|
$toFile = "var g_glyphs = ".Util::toJSON($glyphsOut).";";
|
||||||
$toFile .= json_encode($glyphsOut, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
|
||||||
$toFile .= ";";
|
|
||||||
$file = 'datasets/'.User::$localeString.'/glyphs';
|
$file = 'datasets/'.User::$localeString.'/glyphs';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -29,7 +29,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function itemsets(&$log, $locales)
|
function itemsets()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY refSetId DESC');
|
$setList = DB::Aowow()->Select('SELECT * FROM ?_itemset ORDER BY refSetId DESC');
|
||||||
@@ -37,10 +37,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
User::useLocale($lId);
|
User::useLocale($lId);
|
||||||
Lang::load(Util::$localeStrings[$lId]);
|
Lang::load(Util::$localeStrings[$lId]);
|
||||||
@@ -120,12 +120,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$itemsetOut[$setOut['id']] = $setOut;
|
$itemsetOut[$setOut['id']] = $setOut;
|
||||||
}
|
}
|
||||||
|
|
||||||
$toFile = "var g_itemsets = ";
|
$toFile = "var g_itemsets = ".Util::toJSON($itemsetOut).";";
|
||||||
$toFile .= json_encode($itemsetOut, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
|
||||||
$toFile .= ";";
|
|
||||||
$file = 'datasets/'.User::$localeString.'/itemsets';
|
$file = 'datasets/'.User::$localeString.'/itemsets';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// Create 'locale.js'-file in static/js
|
// Create 'locale.js'-file in static/js
|
||||||
// available locales have to be set in aowow.aowow_config
|
// available locales have to be set in aowow.aowow_config
|
||||||
|
|
||||||
function locales(&$log, $locales)
|
function locales()
|
||||||
{
|
{
|
||||||
$result = [];
|
$result = [];
|
||||||
$available = array(
|
$available = array(
|
||||||
@@ -43,7 +43,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
" }",
|
" }",
|
||||||
);
|
);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
if (isset($available[$l]))
|
if (isset($available[$l]))
|
||||||
$result[] = $available[$l];
|
$result[] = $available[$l];
|
||||||
|
|
||||||
|
|||||||
@@ -5,8 +5,6 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
|
|
||||||
// builds 'pets'-file for available locales
|
// builds 'pets'-file for available locales
|
||||||
// this script requires the following dbc-files to be parsed and available
|
|
||||||
// CreatureFamily, CreatureDisplayInfo, FactionTemplate, AreaTable
|
|
||||||
|
|
||||||
/* Example data
|
/* Example data
|
||||||
30: {
|
30: {
|
||||||
@@ -25,7 +23,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function pets(&$log, $locales)
|
function pets()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$locations = [];
|
$locations = [];
|
||||||
@@ -38,22 +36,21 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
cr.rank AS classification,
|
cr.rank AS classification,
|
||||||
cr.family,
|
cr.family,
|
||||||
cr.displayId1 AS displayId,
|
cr.displayId1 AS displayId,
|
||||||
cdi.skin1 AS skin,
|
cr.textureString AS skin,
|
||||||
SUBSTRING_INDEX(cf.iconFile, "\\\\", -1) AS icon,
|
p.iconString AS icon,
|
||||||
cf.petTalentType AS type
|
p.type
|
||||||
FROM ?_creature cr
|
FROM ?_creature cr
|
||||||
JOIN ?_factiontemplate ft ON ft.Id = cr.faction
|
JOIN ?_factiontemplate ft ON ft.Id = cr.faction
|
||||||
JOIN dbc.creaturefamily cf ON cf.Id = cr.family
|
JOIN ?_pet p ON p.id = cr.family
|
||||||
JOIN dbc.creaturedisplayinfo cdi ON cdi.id = cr.displayId1
|
WHERE cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
|
||||||
WHERE cf.petTalentType <> -1 AND cr.typeFlags & 0x1 AND (cr.cuFlags & 0x2) = 0
|
|
||||||
ORDER BY cr.id ASC');
|
ORDER BY cr.id ASC');
|
||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
User::useLocale($lId);
|
User::useLocale($lId);
|
||||||
Lang::load(Util::$localeStrings[$lId]);
|
Lang::load(Util::$localeStrings[$lId]);
|
||||||
@@ -82,12 +79,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
$toFile = "var g_pets = ";
|
$toFile = "var g_pets = ".Util::toJSON($petsOut).";";
|
||||||
$toFile .= json_encode($petsOut, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
|
||||||
$toFile .= ";";
|
|
||||||
$file = 'datasets/'.User::$localeString.'/pets';
|
$file = 'datasets/'.User::$localeString.'/pets';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -7,7 +7,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// gatheres quasi-static data used in profiler: all available quests, achievements, titles, mounts, companions, factions, recipes
|
// gatheres quasi-static data used in profiler: all available quests, achievements, titles, mounts, companions, factions, recipes
|
||||||
// this script requires a fully set up database and is expected to be run last
|
// this script requires a fully set up database and is expected to be run last
|
||||||
|
|
||||||
function profiler(&$log, $locales)
|
function profiler()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$scripts = [];
|
$scripts = [];
|
||||||
@@ -15,7 +15,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/**********/
|
/**********/
|
||||||
/* Quests */
|
/* Quests */
|
||||||
/**********/
|
/**********/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = [
|
$condition = [
|
||||||
@@ -35,7 +35,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$relCurr = new CurrencyList(array(['id', $_]));
|
$relCurr = new CurrencyList(array(['id', $_]));
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(20);
|
set_time_limit(20);
|
||||||
|
|
||||||
@@ -44,15 +44,15 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$buff = "var _ = g_gatheredcurrencies;\n";
|
$buff = "var _ = g_gatheredcurrencies;\n";
|
||||||
foreach ($relCurr->getListviewData() as $id => $data)
|
foreach ($relCurr->getListviewData() as $id => $data)
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
|
|
||||||
$buff .= "\n\nvar _ = g_quests;\n";
|
$buff .= "\n\nvar _ = g_quests;\n";
|
||||||
foreach ($questz->getListviewData() as $id => $data)
|
foreach ($questz->getListviewData() as $id => $data)
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
|
|
||||||
$buff .= "\ng_quest_catorder = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n";
|
$buff .= "\ng_quest_catorder = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10];\n";
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-quests', $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-quests', $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -62,7 +62,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/****************/
|
/****************/
|
||||||
/* Achievements */
|
/* Achievements */
|
||||||
/****************/
|
/****************/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = array(
|
$condition = array(
|
||||||
@@ -72,7 +72,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
$achievez = new AchievementList($condition);
|
$achievez = new AchievementList($condition);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -84,7 +84,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
foreach ($achievez->getListviewData(ACHIEVEMENTINFO_PROFILE) as $id => $data)
|
foreach ($achievez->getListviewData(ACHIEVEMENTINFO_PROFILE) as $id => $data)
|
||||||
{
|
{
|
||||||
$sumPoints += $data['points'];
|
$sumPoints += $data['points'];
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
// categories to sort by
|
// categories to sort by
|
||||||
@@ -92,7 +92,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// sum points
|
// sum points
|
||||||
$buff .= "\ng_achievement_points = [".$sumPoints."];\n";
|
$buff .= "\ng_achievement_points = [".$sumPoints."];\n";
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-achievements', $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-achievements', $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -102,7 +102,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/**********/
|
/**********/
|
||||||
/* Titles */
|
/* Titles */
|
||||||
/**********/
|
/**********/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = array(
|
$condition = array(
|
||||||
@@ -111,7 +111,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
$titlez = new TitleList($condition);
|
$titlez = new TitleList($condition);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -125,10 +125,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
{
|
{
|
||||||
$data['name'] = Util::localizedString($titlez->getEntry($id), $g ? 'female' : 'male');
|
$data['name'] = Util::localizedString($titlez->getEntry($id), $g ? 'female' : 'male');
|
||||||
unset($data['namefemale']);
|
unset($data['namefemale']);
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-titles-'.$g, $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-titles-'.$g, $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -139,7 +139,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/**********/
|
/**********/
|
||||||
/* Mounts */
|
/* Mounts */
|
||||||
/**********/
|
/**********/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = array(
|
$condition = array(
|
||||||
@@ -149,7 +149,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
$mountz = new SpellList($condition);
|
$mountz = new SpellList($condition);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -161,10 +161,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
{
|
{
|
||||||
$data['quality'] = $data['name'][0];
|
$data['quality'] = $data['name'][0];
|
||||||
$data['name'] = substr($data['name'], 1);
|
$data['name'] = substr($data['name'], 1);
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-mounts', $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-mounts', $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -174,7 +174,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/**************/
|
/**************/
|
||||||
/* Companions */
|
/* Companions */
|
||||||
/**************/
|
/**************/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = array(
|
$condition = array(
|
||||||
@@ -184,7 +184,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
$companionz = new SpellList($condition);
|
$companionz = new SpellList($condition);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -196,10 +196,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
{
|
{
|
||||||
$data['quality'] = $data['name'][0];
|
$data['quality'] = $data['name'][0];
|
||||||
$data['name'] = substr($data['name'], 1);
|
$data['name'] = substr($data['name'], 1);
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-companions', $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-companions', $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -209,7 +209,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/************/
|
/************/
|
||||||
/* Factions */
|
/* Factions */
|
||||||
/************/
|
/************/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
$success = true;
|
$success = true;
|
||||||
$condition = array( // todo (med): exclude non-gaining reputation-header
|
$condition = array( // todo (med): exclude non-gaining reputation-header
|
||||||
@@ -218,7 +218,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
$factionz = new FactionList($condition);
|
$factionz = new FactionList($condition);
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(5);
|
set_time_limit(5);
|
||||||
|
|
||||||
@@ -227,11 +227,11 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$buff = "var _ = g_factions;\n";
|
$buff = "var _ = g_factions;\n";
|
||||||
foreach ($factionz->getListviewData() as $id => $data)
|
foreach ($factionz->getListviewData() as $id => $data)
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
|
|
||||||
$buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n";
|
$buff .= "\ng_faction_order = [0, 469, 891, 1037, 1118, 67, 1052, 892, 936, 1117, 169, 980, 1097];\n";
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-factions', $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-factions', $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -241,7 +241,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
/***********/
|
/***********/
|
||||||
/* Recipes */
|
/* Recipes */
|
||||||
/***********/
|
/***********/
|
||||||
$scripts[] = function(&$log) use ($locales)
|
$scripts[] = function()
|
||||||
{
|
{
|
||||||
// special case: secondary skills are always requested, so put them in one single file (185, 129, 356); it also contains g_skill_order
|
// special case: secondary skills are always requested, so put them in one single file (185, 129, 356); it also contains g_skill_order
|
||||||
$skills = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, [185, 129, 356]];
|
$skills = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, [185, 129, 356]];
|
||||||
@@ -269,7 +269,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($locales as $l)
|
foreach (FileGen::$localeIds as $l)
|
||||||
{
|
{
|
||||||
set_time_limit(10);
|
set_time_limit(10);
|
||||||
|
|
||||||
@@ -278,12 +278,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$buff = '';
|
$buff = '';
|
||||||
foreach ($recipez->getListviewData() as $id => $data)
|
foreach ($recipez->getListviewData() as $id => $data)
|
||||||
$buff .= '_['.$id.'] = '.json_encode($data, JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).";\n";
|
$buff .= '_['.$id.'] = '.Util::toJSON($data).";\n";
|
||||||
|
|
||||||
if (!$buff)
|
if (!$buff)
|
||||||
{
|
{
|
||||||
// this behaviour is intended, do not create an error
|
// this behaviour is intended, do not create an error
|
||||||
$log[] = [time(), ' notice: profiler - file datasets/'.User::$localeString.'/p-recipes-'.$file.' has no content => skipping'];
|
FileGen::status('profiler - file datasets/'.User::$localeString.'/p-recipes-'.$file.' has no content => skipping', MSG_LVL_WARN);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -292,7 +292,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
if (is_array($s))
|
if (is_array($s))
|
||||||
$buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n";
|
$buff .= "\ng_skill_order = [171, 164, 333, 202, 182, 773, 755, 165, 186, 393, 197, 185, 129, 356];\n";
|
||||||
|
|
||||||
if (!writeFile('datasets/'.User::$localeString.'/p-recipes-'.$file, $buff, $log))
|
if (!FileGen::writeFile('datasets/'.User::$localeString.'/p-recipes-'.$file, $buff))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -302,12 +302,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
// run scripts
|
// run scripts
|
||||||
foreach ($scripts as $func)
|
foreach ($scripts as $func)
|
||||||
if (!$func($log))
|
if (!$func())
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
return $success;
|
return $success;
|
||||||
|
|||||||
@@ -33,15 +33,13 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
];
|
];
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function mnProfiles(/* &$log */)
|
function realmMenu()
|
||||||
{
|
{
|
||||||
|
$subEU = [];
|
||||||
|
$subUS = [];
|
||||||
$menu = [
|
$menu = [
|
||||||
["us", "US & Oceanic", null,[
|
['us', 'US & Oceanic', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subEU]]],
|
||||||
[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, []]
|
['eu', 'Europe', null,[[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, &$subUS]]]
|
||||||
]],
|
|
||||||
["eu", "Europe", null,[
|
|
||||||
[Util::urlize(CFG_BATTLEGROUP), CFG_BATTLEGROUP, null, []]
|
|
||||||
]]
|
|
||||||
];
|
];
|
||||||
|
|
||||||
$rows = DB::Auth()->select('SELECT name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0');
|
$rows = DB::Auth()->select('SELECT name, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0');
|
||||||
@@ -52,22 +50,22 @@ function mnProfiles(/* &$log */)
|
|||||||
if ($row['region'] == 'eu')
|
if ($row['region'] == 'eu')
|
||||||
{
|
{
|
||||||
$set |= 0x1;
|
$set |= 0x1;
|
||||||
$menu[1][3][0][3][] = [Util::urlize($row['name']),$row['name']];
|
$subEU[] = [Util::urlize($row['name']), $row['name']];
|
||||||
}
|
}
|
||||||
else if ($row['region'] == 'us')
|
else if ($row['region'] == 'us')
|
||||||
{
|
{
|
||||||
$set |= 0x2;
|
$set |= 0x2;
|
||||||
$menu[0][3][0][3][] = [Util::urlize($row['name']),$row['name']];
|
$subUS[] = [Util::urlize($row['name']), $row['name']];
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!($set & 0x1))
|
if (!($set & 0x1))
|
||||||
array_pop($menu);
|
|
||||||
|
|
||||||
if (!($set & 0x2))
|
|
||||||
array_shift($menu);
|
array_shift($menu);
|
||||||
|
|
||||||
return json_encode($menu, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
if (!($set & 0x2))
|
||||||
|
array_pop($menu);
|
||||||
|
|
||||||
|
return Util::toJSON($menu);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
@@ -23,13 +23,14 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
},
|
},
|
||||||
*/
|
*/
|
||||||
|
|
||||||
function realms(&$log)
|
function realms()
|
||||||
{
|
{
|
||||||
$file = 'datasets/realms';
|
$realms = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, ? AS battlegroup, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0', CFG_BATTLEGROUP);
|
||||||
$rows = DB::Auth()->select('SELECT id AS ARRAY_KEY, name, ? AS battlegroup, IF(timezone IN (8, 9, 10, 11, 12), "eu", "us") AS region FROM realmlist WHERE allowedSecurityLevel = 0', CFG_BATTLEGROUP);
|
|
||||||
$str = 'var g_realms = '.json_encode($rows, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE).';';
|
|
||||||
|
|
||||||
return writeFile($file, $str, $log);
|
$toFile = "var g_realms = ".Util::toJSON($realms).";";
|
||||||
|
$file = 'datasets/realms';
|
||||||
|
|
||||||
|
return FileGen::writeFile($file, $toFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
?>
|
?>
|
||||||
|
|||||||
@@ -1,211 +0,0 @@
|
|||||||
<?php
|
|
||||||
|
|
||||||
if (!defined('AOWOW_REVISION'))
|
|
||||||
die('illegal access');
|
|
||||||
|
|
||||||
|
|
||||||
// shared funcs
|
|
||||||
function writeFile($file, $content, &$log)
|
|
||||||
{
|
|
||||||
$success = false;
|
|
||||||
if ($handle = @fOpen($file, "w"))
|
|
||||||
{
|
|
||||||
if (fWrite($handle, $content))
|
|
||||||
{
|
|
||||||
$success = true;
|
|
||||||
$log[] = [time(), sprintf(ERR_NONE, $file)];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_WRITE_FILE, $file)];
|
|
||||||
|
|
||||||
fClose($handle);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_CREATE_FILE, $file)];
|
|
||||||
|
|
||||||
if ($success)
|
|
||||||
@chmod($file, 0766);
|
|
||||||
|
|
||||||
return $success;
|
|
||||||
}
|
|
||||||
|
|
||||||
function writeDir($dir, &$log)
|
|
||||||
{
|
|
||||||
if (is_dir($dir))
|
|
||||||
{
|
|
||||||
if (!is_writable($dir))
|
|
||||||
$log[] = [time(), ' error: cannot write into output directory '.$dir];
|
|
||||||
|
|
||||||
return is_writable($dir);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (@mkdir($dir, 0766, true))
|
|
||||||
return true;
|
|
||||||
|
|
||||||
$log[] = [time(), ' error: could not create output directory '.$dir];
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// shared strings
|
|
||||||
define('ERR_CREATE_FILE', ' error: could not create file at destination %s');
|
|
||||||
define('ERR_WRITE_FILE', ' error: could not write to file at destination %s');
|
|
||||||
define('ERR_READ_FILE', ' error: file %s could not be read');
|
|
||||||
define('ERR_MISSING_FILE', ' error: file %s not found');
|
|
||||||
define('ERR_NONE', 'success: created file(s) %s');
|
|
||||||
define('ERR_MISSING_INCL', ' error: required function %s() could not be found at %s');
|
|
||||||
|
|
||||||
$log = [];
|
|
||||||
$locales = [];
|
|
||||||
$tplPath = 'setup/tools/filegen/templates/';
|
|
||||||
$pairs = array(
|
|
||||||
'CFG_NAME' => CFG_NAME,
|
|
||||||
'CFG_NAME_SHORT' => CFG_NAME_SHORT,
|
|
||||||
'HOST_URL' => HOST_URL,
|
|
||||||
'STATIC_URL' => STATIC_URL
|
|
||||||
);
|
|
||||||
$tplFiles = array(
|
|
||||||
'searchplugin' => ['aowow.xml', 'static/download/searchplugins/'],
|
|
||||||
'power' => ['power.js', 'static/widgets/' ],
|
|
||||||
'searchboxScript' => ['searchbox.js', 'static/widgets/' ],
|
|
||||||
'demo' => ['demo.html', 'static/widgets/power/' ],
|
|
||||||
'searchboxBody' => ['searchbox.html', 'static/widgets/searchbox/' ],
|
|
||||||
'realmMenu' => ['profile_all.js', 'static/js/' ],
|
|
||||||
'locales' => ['locale.js', 'static/js/' ],
|
|
||||||
// 'itemScaling => ['item-scaling', 'datasets/' ], # provided 'as is', as dbc-content doesn't usualy change
|
|
||||||
);
|
|
||||||
$datasets = array(
|
|
||||||
'realms', 'statistics', 'profiler', // profiler related
|
|
||||||
'talents', 'talentIcons', 'glyphs', // talentCalc related
|
|
||||||
'itemsets', 'enchants', 'gems', // comparison related
|
|
||||||
'pets',
|
|
||||||
);
|
|
||||||
$reqDirs = array(
|
|
||||||
'static/uploads/screenshots/normal',
|
|
||||||
'static/uploads/screenshots/pending',
|
|
||||||
'static/uploads/screenshots/resized',
|
|
||||||
'static/uploads/screenshots/temp',
|
|
||||||
'static/uploads/screenshots/thumb',
|
|
||||||
'static/uploads/temp/'
|
|
||||||
);
|
|
||||||
|
|
||||||
// restrict actual locales
|
|
||||||
foreach (Util::$localeStrings as $idx => $str)
|
|
||||||
if ($str && (CFG_LOCALES & (1 << $idx)))
|
|
||||||
$locales[] = $idx;
|
|
||||||
|
|
||||||
|
|
||||||
// check $pageParam; limit to real scriptNames
|
|
||||||
$scList = array_merge(array_keys($tplFiles), $datasets);
|
|
||||||
if ($pageParam)
|
|
||||||
$scList = array_intersect(explode(';', $pageParam), $scList);
|
|
||||||
|
|
||||||
|
|
||||||
if ($scList)
|
|
||||||
{
|
|
||||||
// create directory structure
|
|
||||||
$log[] = [time(), 'begin creation of directory structure'];
|
|
||||||
$pathOk = 0;
|
|
||||||
foreach ($reqDirs as $d)
|
|
||||||
if (writeDir($d, $log))
|
|
||||||
$pathOk++;
|
|
||||||
|
|
||||||
$log[] = [time(), 'finished directory structure.'];
|
|
||||||
$log[] = [time(), 'created '.$pathOk.' extra paths'.($pathOk == count($reqDirs) ? '' : ' with errors')];
|
|
||||||
$log[] = null;
|
|
||||||
|
|
||||||
// start file generation
|
|
||||||
$log[] = [time(), 'begin generation of '. implode(', ', $scList)];
|
|
||||||
$log[] = null;
|
|
||||||
|
|
||||||
// files with template
|
|
||||||
foreach ($tplFiles as $name => list($file, $destPath))
|
|
||||||
{
|
|
||||||
if ($scList && !in_array($name, $scList))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (!file_exists($tplPath.$file.'.in'))
|
|
||||||
{
|
|
||||||
$log[] = [time(), sprintf(ERR_MISSING_FILE, $tplPath.$file.'.in')];
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!writeDir($destPath, $log))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if ($content = file_get_contents($tplPath.$file.'.in'))
|
|
||||||
{
|
|
||||||
if ($dest = @fOpen($destPath.$file, "w"))
|
|
||||||
{
|
|
||||||
// replace constants
|
|
||||||
$content = strtr($content, $pairs);
|
|
||||||
|
|
||||||
// must generate content
|
|
||||||
// PH format: /*setup:<setupFunc>*/
|
|
||||||
if (preg_match('/\/\*setup:([\w\d_-]+)\*\//i', $content, $m))
|
|
||||||
{
|
|
||||||
$res = '';
|
|
||||||
if (file_exists('setup/tools/filegen/'.$m[1].'.func.php'))
|
|
||||||
{
|
|
||||||
include 'setup/tools/filegen/'.$m[1].'.func.php';
|
|
||||||
$res = $m[1]($log, $locales);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_MISSING_INCL, $m[1], 'setup/tools/filegen/'.$m[1].'.func.php')];
|
|
||||||
|
|
||||||
$content = str_replace('/*setup:'.$m[1].'*/', $res, $content);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (fWrite($dest, $content))
|
|
||||||
$log[] = [time(), sprintf(ERR_NONE, $destPath.$file)];
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_WRITE_FILE, $destPath.$file)];
|
|
||||||
|
|
||||||
fClose($dest);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_CREATE_FILE, $destPath.$file)];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_READ_FILE, $tplPath.$file.'.in')];
|
|
||||||
}
|
|
||||||
|
|
||||||
// files without template
|
|
||||||
foreach ($datasets as $file)
|
|
||||||
{
|
|
||||||
if ($scList && !in_array($file, $scList))
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (file_exists('setup/tools/filegen/'.$file.'.func.php'))
|
|
||||||
{
|
|
||||||
include 'setup/tools/filegen/'.$file.'.func.php';
|
|
||||||
if ($file($log, $locales))
|
|
||||||
$log[] = [time(), ' - subscript returned sucessfully'];
|
|
||||||
else
|
|
||||||
$log[] = [time(), ' - subscript returned with errors'];
|
|
||||||
|
|
||||||
set_time_limit(30); // reset to default for the next script
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), sprintf(ERR_MISSING_INCL, $file, 'setup/tools/filegen/'.$file.'.func.php')];
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
// end
|
|
||||||
$log[] = null;
|
|
||||||
$log[] = [time(), 'finished file generation'];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
$log[] = [time(), 'no valid script names supplied'];
|
|
||||||
|
|
||||||
|
|
||||||
// print accumulated log
|
|
||||||
echo "<pre>\n";
|
|
||||||
foreach ($log as $l)
|
|
||||||
if ($l)
|
|
||||||
echo date('H:i:s', $l[0]) . ' ' . $l[1]."\n";
|
|
||||||
else
|
|
||||||
echo "\n";
|
|
||||||
echo "</pre>\n";
|
|
||||||
|
|
||||||
|
|
||||||
?>
|
|
||||||
428
setup/tools/filegen/simpleImg.func.php
Normal file
428
setup/tools/filegen/simpleImg.func.php
Normal file
@@ -0,0 +1,428 @@
|
|||||||
|
<?php
|
||||||
|
|
||||||
|
|
||||||
|
if (!defined('AOWOW_REVISION'))
|
||||||
|
die('illegal access');
|
||||||
|
|
||||||
|
|
||||||
|
// note: for the sake of simplicity, this function handles all whole images (which are mostly icons)
|
||||||
|
// quest icons from GossipFrame have an alphaChannel that cannot be handled by this script
|
||||||
|
// lfgFrame/lfgIcon*.blp .. candidates for zonePage, but in general too detailed to scale them down from 128 to 56, 36, ect
|
||||||
|
function simpleImg()
|
||||||
|
{
|
||||||
|
if (isset(FileGen::$cliOpts['help']))
|
||||||
|
{
|
||||||
|
echo "\n";
|
||||||
|
echo "available Options for subScript 'simpleImg':\n";
|
||||||
|
echo " --icons (generates square icons that are used for basicly everything)\n";
|
||||||
|
echo " --glyphs (decorative tidbit displayed on Infobox for Glyph Spells)\n";
|
||||||
|
echo " --pagetexts (imagery contained in PageTexts on readable GameObjects or Items)\n";
|
||||||
|
echo " --loadingscreens (loadingscreens (not used, skipped by default))\n";
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!class_exists('DBC'))
|
||||||
|
{
|
||||||
|
FileGen::status(' - simpleImg: required class DBC was not included', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!function_exists('imagecreatefromblp'))
|
||||||
|
{
|
||||||
|
FileGen::status(' - simpleImg: required include imagecreatefromblp() was not included', MSG_LVL_ERROR);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
$locStr = '';
|
||||||
|
$groups = [];
|
||||||
|
$dbcPath = FileGen::$srcDir.'%sDBFilesClient/';
|
||||||
|
$imgPath = FileGen::$srcDir.'%sInterface/';
|
||||||
|
$destDir = 'static/images/wow/';
|
||||||
|
$success = true;
|
||||||
|
$iconDirs = array(
|
||||||
|
['icons/large/', 'jpg', 0, 56, 4],
|
||||||
|
['icons/medium/', 'jpg', 0, 36, 4],
|
||||||
|
['icons/small/', 'jpg', 0, 18, 4],
|
||||||
|
['icons/tiny/', 'gif', 0, 15, 4]
|
||||||
|
);
|
||||||
|
$calendarDirs = array(
|
||||||
|
['icons/large/', 'jpg', 90, 56, 4],
|
||||||
|
['icons/medium/', 'jpg', 90, 36, 4],
|
||||||
|
['icons/small/', 'jpg', 90, 18, 4],
|
||||||
|
['icons/tiny/', 'gif', 90, 15, 4]
|
||||||
|
);
|
||||||
|
$loadScreenDirs = array(
|
||||||
|
['loadingscreens/large/', 'jpg', 0, 1024, 0],
|
||||||
|
['loadingscreens/medium/', 'jpg', 0, 488, 0],
|
||||||
|
['loadingscreens/original/', 'png', 0, 0, 0],
|
||||||
|
['loadingscreens/small/', 'jpg', 0, 244, 0]
|
||||||
|
);
|
||||||
|
$paths = array( // src, [dest, ext, srcSize, destSize, borderOffset], pattern, isIcon, tileSize
|
||||||
|
0 => ['Icons/', $iconDirs, '/*.[bB][lL][pP]', true, 0],
|
||||||
|
1 => ['Spellbook/', [['Interface/Spellbook/', 'png', 0, 0, 0]], '/UI-Glyph-Rune*.blp', true, 0],
|
||||||
|
2 => ['PaperDoll/', array_slice($iconDirs, 0, 3), '/UI-{Backpack,PaperDoll}-*.blp', true, 0],
|
||||||
|
3 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-Races.blp', $iconDirs, '', true, 64],
|
||||||
|
4 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-CLASSES.blp', $iconDirs, '', true, 64],
|
||||||
|
5 => ['GLUES/CHARACTERCREATE/UI-CharacterCreate-Factions.blp', $iconDirs, '', true, 64],
|
||||||
|
// 6 => ['Minimap/OBJECTICONS.BLP', [['icons/tiny/', 'gif', 0, 16, 2]], '', true, 32],
|
||||||
|
7 => ['FlavorImages/', [['Interface/FlavorImages/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0],
|
||||||
|
8 => ['Pictures/', [['Interface/Pictures/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0],
|
||||||
|
9 => ['PvPRankBadges/', [['Interface/PvPRankBadges/', 'png', 0, 0, 0]], '/*.[bB][lL][pP]', false, 0],
|
||||||
|
10 => ['Calendar/Holidays/', $calendarDirs, '/*{rt,a,y,h,s}.[bB][lL][pP]', true, 0],
|
||||||
|
11 => ['GLUES/LOADINGSCREENS/', $loadScreenDirs, '/[lL][oO]*.[bB][lL][pP]', false, 0]
|
||||||
|
);
|
||||||
|
// textures are composed of 64x64 icons
|
||||||
|
// numeric indexed arrays mimick the position on the texture
|
||||||
|
$cuNames = array(
|
||||||
|
2 => array(
|
||||||
|
'ui-paperdoll-slot-chest' => 'inventoryslot_chest',
|
||||||
|
'ui-backpack-emptyslot' => 'inventoryslot_empty',
|
||||||
|
'ui-paperdoll-slot-feet' => 'inventoryslot_feet',
|
||||||
|
'ui-paperdoll-slot-finger' => 'inventoryslot_finger',
|
||||||
|
'ui-paperdoll-slot-hands' => 'inventoryslot_hands',
|
||||||
|
'ui-paperdoll-slot-head' => 'inventoryslot_head',
|
||||||
|
'ui-paperdoll-slot-legs' => 'inventoryslot_legs',
|
||||||
|
'ui-paperdoll-slot-mainhand' => 'inventoryslot_mainhand',
|
||||||
|
'ui-paperdoll-slot-neck' => 'inventoryslot_neck',
|
||||||
|
'ui-paperdoll-slot-secondaryhand' => 'inventoryslot_offhand',
|
||||||
|
'ui-paperdoll-slot-ranged' => 'inventoryslot_ranged',
|
||||||
|
'ui-paperdoll-slot-relic' => 'inventoryslot_relic',
|
||||||
|
'ui-paperdoll-slot-shirt' => 'inventoryslot_shirt',
|
||||||
|
'ui-paperdoll-slot-shoulder' => 'inventoryslot_shoulder',
|
||||||
|
'ui-paperdoll-slot-tabard' => 'inventoryslot_tabard',
|
||||||
|
'ui-paperdoll-slot-trinket' => 'inventoryslot_trinket',
|
||||||
|
'ui-paperdoll-slot-waist' => 'inventoryslot_waist',
|
||||||
|
'ui-paperdoll-slot-wrists' => 'inventoryslot_wrists'
|
||||||
|
),
|
||||||
|
3 => array(
|
||||||
|
['race_human_male', 'race_dwarf_male', 'race_gnome_male', 'race_nightelf_male', 'race_draenai_male' ],
|
||||||
|
['race_tauren_male', 'race_undead_male', 'race_troll_male', 'race_orc_male', 'race_bloodelf_male' ],
|
||||||
|
['race_human_female', 'race_dwarf_female', 'race_gnome_female', 'race_nightelf_female', 'race_draenai_female' ],
|
||||||
|
['race_tauren_female', 'race_undead_female', 'race_troll_female', 'race_orc_female', 'race_bloodelf_female']
|
||||||
|
),
|
||||||
|
4 => array(
|
||||||
|
['class_warrior', 'class_mage', 'class_rogue', 'class_druid' ],
|
||||||
|
['class_hunter', 'class_shaman', 'class_priest', 'class_warlock'],
|
||||||
|
['class_paladin', 'class_deathknight' ]
|
||||||
|
),
|
||||||
|
5 => array(
|
||||||
|
['faction_alliance', 'faction_horde']
|
||||||
|
),
|
||||||
|
6 => array(
|
||||||
|
[],
|
||||||
|
[null, 'quest_start', 'quest_end', 'quest_start_daily', 'quest_end_daily']
|
||||||
|
),
|
||||||
|
10 => array( // really should have read holidays.dbc...
|
||||||
|
'calendar_winterveilstart' => 'calendar_winterveilstart',
|
||||||
|
'calendar_noblegardenstart' => 'calendar_noblegardenstart',
|
||||||
|
'calendar_childrensweekstart' => 'calendar_childrensweekstart',
|
||||||
|
'calendar_fishingextravaganza' => 'calendar_fishingextravaganzastart',
|
||||||
|
'calendar_harvestfestivalstart' => 'calendar_harvestfestivalstart',
|
||||||
|
'calendar_hallowsendstart' => 'calendar_hallowsendstart',
|
||||||
|
'calendar_lunarfestivalstart' => 'calendar_lunarfestivalstart',
|
||||||
|
'calendar_loveintheairstart' => 'calendar_loveintheairstart',
|
||||||
|
'calendar_midsummerstart' => 'calendar_midsummerstart',
|
||||||
|
'calendar_brewfeststart' => 'calendar_brewfeststart',
|
||||||
|
'calendar_darkmoonfaireelwynnstart' => 'calendar_darkmoonfaireelwynnstart',
|
||||||
|
'calendar_darkmoonfairemulgorestart' => 'calendar_darkmoonfairemulgorestart',
|
||||||
|
'calendar_darkmoonfaireterokkarstart' => 'calendar_darkmoonfaireterokkarstart',
|
||||||
|
'calendar_piratesday' => 'calendar_piratesdaystart',
|
||||||
|
'calendar_wotlklaunch' => 'calendar_wotlklaunchstart',
|
||||||
|
'calendar_dayofthedeadstart' => 'calendar_dayofthedeadstart',
|
||||||
|
'calendar_fireworks' => 'calendar_fireworksstart'
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
$writeImage = function($name, $ext, $src, $srcDims, $destDims, $done)
|
||||||
|
{
|
||||||
|
$ok = false;
|
||||||
|
$dest = imagecreatetruecolor($destDims['w'], $destDims['h']);
|
||||||
|
imagesavealpha($dest, true);
|
||||||
|
imagealphablending($dest, false);
|
||||||
|
imagecopyresampled($dest, $src, $destDims['x'], $destDims['x'], $srcDims['x'], $srcDims['y'], $destDims['w'], $destDims['h'], $srcDims['w'], $srcDims['h']);
|
||||||
|
|
||||||
|
switch ($ext)
|
||||||
|
{
|
||||||
|
case 'jpg':
|
||||||
|
$ok = imagejpeg($dest, $name.'.'.$ext, 85);
|
||||||
|
break;
|
||||||
|
case 'gif':
|
||||||
|
$ok = imagegif($dest, $name.'.'.$ext);
|
||||||
|
break;
|
||||||
|
case 'png':
|
||||||
|
$ok = imagepng($dest, $name.'.'.$ext);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
FileGen::status($done.' - unsupported file fromat: '.$ext, MSG_LVL_WARN);
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedestroy($dest);
|
||||||
|
|
||||||
|
if ($ok)
|
||||||
|
{
|
||||||
|
chmod($name.'.'.$ext, FileGen::$accessMask);
|
||||||
|
FileGen::status($done.' - image '.$name.'.'.$ext.' written', MSG_LVL_OK);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
FileGen::status($done.' - could not create image '.$name.'.'.$ext, MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
return $ok;
|
||||||
|
};
|
||||||
|
|
||||||
|
$checkSourceDirs = function($sub, &$missing = []) use ($imgPath, $dbcPath, $paths)
|
||||||
|
{
|
||||||
|
foreach (array_column($paths, 0) as $subDir)
|
||||||
|
{
|
||||||
|
$p = sprintf($imgPath, $sub).$subDir;
|
||||||
|
if (!FileGen::fileExists($p))
|
||||||
|
$missing[] = $p;
|
||||||
|
}
|
||||||
|
|
||||||
|
$p = sprintf($dbcPath, $sub);
|
||||||
|
if (!FileGen::fileExists($p))
|
||||||
|
$missing[] = $p;
|
||||||
|
|
||||||
|
return !$missing;
|
||||||
|
};
|
||||||
|
|
||||||
|
if (isset(FileGen::$cliOpts['icons']))
|
||||||
|
array_push($groups, 0, 2, 3, 4, 5, 10);
|
||||||
|
if (isset(FileGen::$cliOpts['glyphs']))
|
||||||
|
$groups[] = 1;
|
||||||
|
if (isset(FileGen::$cliOpts['pagetexts']))
|
||||||
|
array_push($groups, 7, 8, 9);
|
||||||
|
if (isset(FileGen::$cliOpts['loadingscreens']))
|
||||||
|
$groups[] = 11;
|
||||||
|
|
||||||
|
// filter by pasaed options
|
||||||
|
if (!$groups) // by default do not generate loadingscreens
|
||||||
|
unset($paths[11]);
|
||||||
|
else
|
||||||
|
foreach (array_keys($paths) as $k)
|
||||||
|
if (!in_array($k, $groups))
|
||||||
|
unset($paths[$k]);
|
||||||
|
|
||||||
|
foreach (FileGen::$localeIds as $l)
|
||||||
|
{
|
||||||
|
if ($checkSourceDirs(Util::$localeStrings[$l].'/'))
|
||||||
|
{
|
||||||
|
$locStr = Util::$localeStrings[$l].'/';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// manually check for enGB
|
||||||
|
if (!$locStr && $checkSourceDirs('enGB/'))
|
||||||
|
$locStr = 'enGB/';
|
||||||
|
|
||||||
|
// if no subdir had sufficient data, check mpq-root
|
||||||
|
if (!$locStr && !$checkSourceDirs('', $missing))
|
||||||
|
{
|
||||||
|
FileGen::status('one or more required directories are missing:', MSG_LVL_ERROR);
|
||||||
|
foreach ($missing as $m)
|
||||||
|
FileGen::status(' - '.$m, MSG_LVL_ERROR);
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
// init directories
|
||||||
|
foreach (array_column($paths, 1) as $subDirs)
|
||||||
|
foreach ($subDirs as $sd)
|
||||||
|
if (!FileGen::writeDir($destDir.$sd[0]))
|
||||||
|
$success = false;
|
||||||
|
|
||||||
|
// ok, departure from std::procedure here
|
||||||
|
// scan ItemDisplayInfo.dbc and SpellIcon.dbc for expected images and save them to an array
|
||||||
|
// load all icon paths into another array and xor these two
|
||||||
|
// excess entries for the directory are fine, excess entries for the dbc's are not
|
||||||
|
$dbcEntries = [];
|
||||||
|
|
||||||
|
if (isset($paths[0]) || isset($paths[1])) // generates icons or glyphs
|
||||||
|
{
|
||||||
|
$spellIcon = new DBC('SpellIcon');
|
||||||
|
if (isset($paths[0]) && !isset($paths[1]))
|
||||||
|
$siRows = $spellIcon->readFiltered(function(&$val) { return !stripos($val['iconPath'], 'glyph-rune'); });
|
||||||
|
else if (!isset($paths[0]) && isset($paths[1]))
|
||||||
|
$siRows = $spellIcon->readFiltered(function(&$val) { return stripos($val['iconPath'], 'glyph-rune'); });
|
||||||
|
else
|
||||||
|
$siRows = $spellIcon->readArbitrary();
|
||||||
|
|
||||||
|
foreach ($siRows as $row)
|
||||||
|
$dbcEntries[] = sprintf('setup/mpqdata/%s', $locStr).strtr($row['iconPath'], ['\\' => '/']).'.blp';
|
||||||
|
}
|
||||||
|
|
||||||
|
if (isset($paths[0]))
|
||||||
|
{
|
||||||
|
$itemDisplayInfo = new DBC('ItemDisplayInfo');
|
||||||
|
foreach ($itemDisplayInfo->readArbitrary() as $row)
|
||||||
|
$dbcEntries[] = sprintf($imgPath, $locStr).'Icons/'.$row['inventoryIcon1'].'.blp';
|
||||||
|
|
||||||
|
$holidays = new DBC('Holidays');
|
||||||
|
$holiRows = $holidays->readFiltered(function(&$val) { return !empty($val['textureString']); });
|
||||||
|
foreach ($holiRows as $row)
|
||||||
|
$dbcEntries[] = sprintf($imgPath, $locStr).'Calendar/Holidays/'.$row['textureString'].'Start.blp';
|
||||||
|
}
|
||||||
|
|
||||||
|
// case-insensitive array_unique *vomits silently into a corner*
|
||||||
|
$dbcEntries = array_intersect_key($dbcEntries, array_unique(array_map('strtolower',$dbcEntries)));
|
||||||
|
|
||||||
|
$allPaths = [];
|
||||||
|
foreach ($paths as $i => $p)
|
||||||
|
{
|
||||||
|
$path = sprintf($imgPath, $locStr).$p[0];
|
||||||
|
if (!FileGen::fileExists($path))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$files = glob($path.$p[2], GLOB_BRACE);
|
||||||
|
$allPaths = array_merge($allPaths, $files);
|
||||||
|
|
||||||
|
FileGen::status('processing '.count($files).' files in '.$path.'...');
|
||||||
|
|
||||||
|
$j = 0;
|
||||||
|
foreach ($files as $f)
|
||||||
|
{
|
||||||
|
ini_set('max_execution_time', 30); // max 30sec per image (loading takes the most time)
|
||||||
|
|
||||||
|
$src = null;
|
||||||
|
$img = explode('.', array_pop(explode('/', $f)));
|
||||||
|
array_pop($img); // there are a hand full of images with multiple file endings or random dots in the name
|
||||||
|
$img = implode('.', $img);
|
||||||
|
|
||||||
|
// file not from dbc -> name from array or skip file
|
||||||
|
if (!empty($cuNames[$i]))
|
||||||
|
{
|
||||||
|
if (!empty($cuNames[$i][strtolower($img)]))
|
||||||
|
$img = $cuNames[$i][strtolower($img)];
|
||||||
|
else if (!$p[4])
|
||||||
|
{
|
||||||
|
$j += count($p[1]);
|
||||||
|
FileGen::status('skipping extraneous file '.$img.' (+'.count($p[1]).')');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$nFiles = count($p[1]) * ($p[4] ? array_sum(array_map('count', $cuNames[$i])) : count($files));
|
||||||
|
|
||||||
|
foreach ($p[1] as $info)
|
||||||
|
{
|
||||||
|
if ($p[4])
|
||||||
|
{
|
||||||
|
foreach ($cuNames[$i] as $y => $row)
|
||||||
|
{
|
||||||
|
foreach ($row as $x => $name)
|
||||||
|
{
|
||||||
|
$j++;
|
||||||
|
$img = $p[3] ? strtolower($name) : $name;
|
||||||
|
$done = ' - '.str_pad($j.'/'.$nFiles, 12).str_pad('('.number_format($j * 100 / $nFiles, 2).'%)', 9);
|
||||||
|
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1]))
|
||||||
|
{
|
||||||
|
FileGen::status($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$src)
|
||||||
|
$src = imagecreatefromblp($f);
|
||||||
|
|
||||||
|
if (!$src) // error should be created by imagecreatefromblp
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$from = array(
|
||||||
|
'x' => $info[4] + $p[4] * $x,
|
||||||
|
'y' => $info[4] + $p[4] * $y,
|
||||||
|
'w' => $p[4] - $info[4] * 2,
|
||||||
|
'h' => $p[4] - $info[4] * 2
|
||||||
|
);
|
||||||
|
$to = array(
|
||||||
|
'x' => 0,
|
||||||
|
'y' => 0,
|
||||||
|
'w' => $info[3],
|
||||||
|
'h' => $info[3]
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$writeImage($destDir.$info[0].$img, $info[1], $src, $from, $to, $done))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// custom handle for combined icon 'quest_startend'
|
||||||
|
/* not used due to alphaChannel issues
|
||||||
|
if ($p[4] == 32)
|
||||||
|
{
|
||||||
|
$dest = imagecreatetruecolor(19, 16);
|
||||||
|
imagesavealpha($dest, true);
|
||||||
|
imagealphablending($dest, true);
|
||||||
|
|
||||||
|
// excalmationmark, questionmark
|
||||||
|
imagecopyresampled($dest, $src, 0, 1, 32 + 5, 32 + 2, 8, 15, 18, 30);
|
||||||
|
imagecopyresampled($dest, $src, 5, 0, 64 + 1, 32 + 1, 10, 16, 18, 28);
|
||||||
|
|
||||||
|
if (imagegif($dest, $destDir.$info[0].'quest_startend.gif'))
|
||||||
|
FileGen::status(' extra - image '.$destDir.$info[0].'quest_startend.gif written', MSG_LVL_OK);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileGen::status(' extra - could not create image '.$destDir.$info[0].'quest_startend.gif', MSG_LVL_ERROR);
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
imagedestroy($dest);
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// icon -> lowercase
|
||||||
|
if ($p[3])
|
||||||
|
$img = strtolower($img);
|
||||||
|
|
||||||
|
$j++;
|
||||||
|
$done = ' - '.str_pad($j.'/'.$nFiles, 12).str_pad('('.number_format($j * 100 / $nFiles, 2).'%)', 9);
|
||||||
|
|
||||||
|
if (!isset(FileGen::$cliOpts['force']) && file_exists($destDir.$info[0].$img.'.'.$info[1]))
|
||||||
|
{
|
||||||
|
FileGen::status($done.' - file '.$info[0].$img.'.'.$info[1].' was already processed');
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$src)
|
||||||
|
$src = imagecreatefromblp($f);
|
||||||
|
|
||||||
|
if (!$src) // error should be created by imagecreatefromblp
|
||||||
|
continue;
|
||||||
|
|
||||||
|
$from = array(
|
||||||
|
'x' => $info[4],
|
||||||
|
'y' => $info[4],
|
||||||
|
'w' => ($info[2] ?: imagesx($src)) - $info[4] * 2,
|
||||||
|
'h' => ($info[2] ?: imagesy($src)) - $info[4] * 2
|
||||||
|
);
|
||||||
|
$to = array(
|
||||||
|
'x' => 0,
|
||||||
|
'y' => 0,
|
||||||
|
'w' => $info[3] ?: imagesx($src),
|
||||||
|
'h' => $info[3] ?: imagesy($src)
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!$writeImage($destDir.$info[0].$img, $info[1], $src, $from, $to, $done))
|
||||||
|
$success = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unset($src);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// reset execTime
|
||||||
|
ini_set('max_execution_time', FileGen::$defaultExecTime);
|
||||||
|
|
||||||
|
if ($missing = array_diff(array_map('strtolower', $dbcEntries), array_map('strtolower', $allPaths)))
|
||||||
|
{
|
||||||
|
asort($missing);
|
||||||
|
FileGen::status('the following '.count($missing).' images where referenced by DBC but not in the mpqData directory. They may need to be converted by hand later on.', MSG_LVL_WARN);
|
||||||
|
foreach ($missing as $m)
|
||||||
|
FileGen::status(' - '.$m);
|
||||||
|
}
|
||||||
|
|
||||||
|
return $success;
|
||||||
|
}
|
||||||
@@ -5,11 +5,25 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
|
|
||||||
// Create 'statistics'-file in datasets
|
// Create 'statistics'-file in datasets
|
||||||
// this script requires the following dbcs to be parsed and available
|
// this script requires the following dbcs to be available
|
||||||
// gtChanceToMeleeCrit.dbc, gtChanceToSpellCrit.dbc, gtChanceToMeleeCritBase.dbc, gtChanceToSpellCritBase.dbc, gtOCTRegenHP, gtRegenHPPperSpt.dbc, gtRegenMPPerSpt.dbc
|
// gtChanceToMeleeCrit.dbc, gtChanceToSpellCrit.dbc, gtChanceToMeleeCritBase.dbc, gtChanceToSpellCritBase.dbc, gtOCTRegenHP.dbc, gtRegenMPPerSpt.dbc, gtRegenHPPerSpt.dbc
|
||||||
|
|
||||||
function statistics(&$log)
|
function statistics()
|
||||||
{
|
{
|
||||||
|
// expected dbcs
|
||||||
|
$req = ['dbc_gtchancetomeleecrit', 'dbc_gtchancetomeleecritbase', 'dbc_gtchancetospellcrit', 'dbc_gtchancetospellcritbase', 'dbc_gtoctregenhp', 'dbc_gtregenmpperspt', 'dbc_gtregenhpperspt'];
|
||||||
|
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
|
||||||
|
if ($missing = array_diff($req, $found))
|
||||||
|
{
|
||||||
|
foreach ($missing as $m)
|
||||||
|
{
|
||||||
|
$file = explode('_', $m)[1];
|
||||||
|
$dbc = new DBC($file);
|
||||||
|
if ($dbc->readFromFile())
|
||||||
|
$dbc->writeToDB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$classs = function()
|
$classs = function()
|
||||||
{
|
{
|
||||||
// constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
|
// constants and mods taken from TrinityCore (Player.cpp, StatSystem.cpp)
|
||||||
@@ -42,7 +56,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
);
|
);
|
||||||
|
|
||||||
foreach ($dataz as $class => &$data)
|
foreach ($dataz as $class => &$data)
|
||||||
$data[2] = array_values(DB::Aowow()->selectRow('SELECT mle.chance*100 cMle, spl.chance*100 cSpl FROM dbc.gtchancetomeleecritbase mle, dbc.gtchancetospellcritbase spl WHERE mle.idx = spl.idx AND mle.idx = ?d', $class - 1));
|
$data[2] = array_values(DB::Aowow()->selectRow('SELECT mle.chance*100 cMle, spl.chance*100 cSpl FROM dbc_gtchancetomeleecritbase mle, dbc_gtchancetospellcritbase spl WHERE mle.idx = spl.idx AND mle.idx = ?d', $class - 1));
|
||||||
|
|
||||||
return $dataz;
|
return $dataz;
|
||||||
};
|
};
|
||||||
@@ -89,10 +103,10 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$rows = DB::Aowow()->select('SELECT pls.level AS ARRAY_KEY, str-?d, agi-?d, sta-?d, inte-?d, spi-?d, basehp, IF(basemana <> 0, basemana, 100), mlecrt.chance*100, splcrt.chance*100, mlecrt.chance*100 * ?f, baseHP5.ratio*1, extraHP5.ratio*1 ' .
|
$rows = DB::Aowow()->select('SELECT pls.level AS ARRAY_KEY, str-?d, agi-?d, sta-?d, inte-?d, spi-?d, basehp, IF(basemana <> 0, basemana, 100), mlecrt.chance*100, splcrt.chance*100, mlecrt.chance*100 * ?f, baseHP5.ratio*1, extraHP5.ratio*1 ' .
|
||||||
'FROM player_levelstats pls JOIN player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class JOIN' .
|
'FROM player_levelstats pls JOIN player_classlevelstats pcls ON pls.level = pcls.level AND pls.class = pcls.class JOIN' .
|
||||||
' dbc.gtchancetomeleecrit mlecrt ON mlecrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
' dbc_gtchancetomeleecrit mlecrt ON mlecrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
||||||
' dbc.gtchancetospellcrit splcrt ON splcrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
' dbc_gtchancetospellcrit splcrt ON splcrt.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
||||||
' dbc.gtoctregenhp baseHP5 ON baseHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
' dbc_gtoctregenhp baseHP5 ON baseHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) JOIN' .
|
||||||
' dbc.gtregenhpperspt extraHP5 ON extraHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) ' .
|
' dbc_gtregenhpperspt extraHP5 ON extraHP5.idx = ((pls.class - 1) * 100) + (pls.level - 1) ' .
|
||||||
'WHERE pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC',
|
'WHERE pls.race = ?d AND pls.class = ?d ORDER BY pls.level ASC',
|
||||||
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4],
|
$offset[0], $offset[1], $offset[2], $offset[3], $offset[4],
|
||||||
$mod,
|
$mod,
|
||||||
@@ -114,7 +128,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// identical across classes (just use one, that acutally has mana (offset: 100))
|
// identical across classes (just use one, that acutally has mana (offset: 100))
|
||||||
// content of gtRegenMPPerSpt.dbc
|
// content of gtRegenMPPerSpt.dbc
|
||||||
|
|
||||||
return DB::Aowow()->selectCol('SELECT idx-99 AS ARRAY_KEY, ratio FROM dbc.gtregenmpperspt WHERE idx >= 100 AND idx < 100 + ?d', MAX_LEVEL);
|
return DB::Aowow()->selectCol('SELECT idx-99 AS ARRAY_KEY, ratio FROM dbc_gtregenmpperspt WHERE idx >= 100 AND idx < 100 + ?d', MAX_LEVEL);
|
||||||
};
|
};
|
||||||
|
|
||||||
$skills = function()
|
$skills = function()
|
||||||
@@ -135,15 +149,14 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$out[$s] = $res;
|
$out[$s] = $res;
|
||||||
if (!$res)
|
if (!$res)
|
||||||
{
|
{
|
||||||
$log[] = [time(), ' error: statistics - generator $'.$s.'() returned empty'];
|
FileGen::status('statistics - generator $'.$s.'() returned empty', MSG_LVL_WARN);
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$json = json_encode($out, JSON_NUMERIC_CHECK | JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE);
|
$toFile = 'g_statistics = '.preg_replace('/"\$([^$"]+)"/', '\1', Util::toJSON($out)).';';
|
||||||
$toFile = 'g_statistics = '.preg_replace('/"\$([^$"]+)"/', '\1', $json).';';
|
|
||||||
|
|
||||||
if (!writeFile('datasets/statistics', $toFile, $log))
|
if (!FileGen::writeFile('datasets/statistics', $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
return $success;
|
return $success;
|
||||||
|
|||||||
@@ -6,21 +6,35 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// builds image-textures for the talent-calculator
|
// builds image-textures for the talent-calculator
|
||||||
// spellIcons must be extracted and converted to at least medium size
|
// spellIcons must be extracted and converted to at least medium size
|
||||||
// this script requires the following dbc-files to be parsed and available
|
// this script requires the following dbc-files to be available
|
||||||
// Talent, TalentTab, Spell
|
// Talent.dbc, TalentTab.dbc
|
||||||
|
|
||||||
function talentIcons(&$log)
|
function talentIcons()
|
||||||
{
|
{
|
||||||
|
// expected dbcs
|
||||||
|
$req = ['dbc_talenttab', 'dbc_talent'];
|
||||||
|
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
|
||||||
|
if ($missing = array_diff($req, $found))
|
||||||
|
{
|
||||||
|
foreach ($missing as $m)
|
||||||
|
{
|
||||||
|
$file = explode('_', $m)[1];
|
||||||
|
$dbc = new DBC($file);
|
||||||
|
if ($dbc->readFromFile($file == 'talenttab'))
|
||||||
|
$dbc->writeToDB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$success = true;
|
$success = true;
|
||||||
$query = 'SELECT s.iconString FROM ?_spell s JOIN dbc.talent t ON t.rank1 = s.Id JOIN dbc.talenttab tt ON tt.Id = t.tabId WHERE tt.?# = ?d AND tt.tabNumber = ?d ORDER BY t.row, t.column, t.petCategory1 ASC;';
|
$query = 'SELECT s.iconString FROM ?_spell s JOIN dbc_talent t ON t.rank1 = s.Id JOIN dbc_talenttab tt ON tt.Id = t.tabId WHERE tt.?# = ?d AND tt.tabNumber = ?d ORDER BY t.row, t.column, t.petCategory1 ASC;';
|
||||||
$dims = 36; //v-pets
|
$dims = 36; //v-pets
|
||||||
$filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid'];
|
$filenames = ['icons', 'warrior', 'paladin', 'hunter', 'rogue', 'priest', 'deathknight', 'shaman', 'mage', 'warlock', null, 'druid'];
|
||||||
|
|
||||||
// create directory if missing
|
// create directory if missing
|
||||||
if (!writeDir('static/images/wow/talents/icons', $log))
|
if (!FileGen::writeDir('static/images/wow/talents/icons'))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
if (!writeDir('static/images/wow/hunterpettalents', $log))
|
if (!FileGen::writeDir('static/images/wow/hunterpettalents'))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
foreach ($filenames as $k => $v)
|
foreach ($filenames as $k => $v)
|
||||||
@@ -41,7 +55,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
if (empty($icons))
|
if (empty($icons))
|
||||||
{
|
{
|
||||||
$log[] = [time(), ' error: talentIcons - query for '.$v.' tree: '.$k.' empty'];
|
FileGen::status('talentIcons - query for '.$v.' tree: '.$k.' returned empty', MSG_LVL_ERROR);
|
||||||
$success = false;
|
$success = false;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@@ -53,7 +67,7 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg';
|
$imgFile = 'static/images/wow/icons/medium/'.strtolower($icons[$i]).'.jpg';
|
||||||
if (!file_exists($imgFile))
|
if (!file_exists($imgFile))
|
||||||
{
|
{
|
||||||
$log[] = [time(), ' error: talentIcons - raw image '.$imgFile. ' not found'];
|
FileGen::status('talentIcons - raw image '.$imgFile. ' not found', MSG_LVL_ERROR);
|
||||||
$success = false;
|
$success = false;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@@ -77,17 +91,17 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (@imagejpeg($res, $outFile))
|
if (@imagejpeg($res, $outFile))
|
||||||
$log[] = [time(), sprintf(ERR_NONE, $outFile)];
|
FileGen::status(sprintf(ERR_NONE, $outFile), MSG_LVL_OK);
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$success = false;
|
$success = false;
|
||||||
$log[] = [time(), ' error: talentIcons - '.$outFile.'.jpg could not be written!'];
|
FileGen::status('talentIcons - '.$outFile.'.jpg could not be written', MSG_LVL_ERROR);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
$success = false;
|
$success = false;
|
||||||
$log[] = [time(), ' error: talentIcons - image resource not created'];
|
FileGen::status('talentIcons - image resource not created', MSG_LVL_ERROR);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
|
|
||||||
// builds talent-tree-data for the talent-calculator
|
// builds talent-tree-data for the talent-calculator
|
||||||
// this script requires the following dbc-files to be parsed and available
|
// this script requires the following dbc-files to be available
|
||||||
// Talent, TalentTab, Spell, CreatureFamily
|
// Talent.dbc, TalentTab.dbc
|
||||||
|
|
||||||
// talents
|
// talents
|
||||||
// i - int talentId (id of aowow_talent)
|
// i - int talentId (id of aowow_talent)
|
||||||
@@ -25,8 +25,22 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
// t - array of talent-objects
|
// t - array of talent-objects
|
||||||
// f - array:int [pets only] creatureFamilies in that category
|
// f - array:int [pets only] creatureFamilies in that category
|
||||||
|
|
||||||
function talents(&$log, $locales)
|
function talents()
|
||||||
{
|
{
|
||||||
|
// expected dbcs
|
||||||
|
$req = ['dbc_talenttab', 'dbc_talent'];
|
||||||
|
$found = DB::Aowow()->selectCol('SHOW TABLES LIKE "dbc_%"');
|
||||||
|
if ($missing = array_diff($req, $found))
|
||||||
|
{
|
||||||
|
foreach ($missing as $m)
|
||||||
|
{
|
||||||
|
$file = explode('_', $m)[1];
|
||||||
|
$dbc = new DBC($file);
|
||||||
|
if ($dbc->readFromFile($file == 'talenttab'))
|
||||||
|
$dbc->writeToDB();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$success = true;
|
$success = true;
|
||||||
$buildTree = function ($class) use (&$petFamIcons, &$tSpells)
|
$buildTree = function ($class) use (&$petFamIcons, &$tSpells)
|
||||||
{
|
{
|
||||||
@@ -35,19 +49,12 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
$mask = $class ? 1 << ($class - 1) : 0;
|
$mask = $class ? 1 << ($class - 1) : 0;
|
||||||
|
|
||||||
// All "tabs" of a given class talent
|
// All "tabs" of a given class talent
|
||||||
$tabs = DB::Aowow()->select('SELECT * FROM dbc.talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $mask);
|
$tabs = DB::Aowow()->select('SELECT * FROM dbc_talenttab WHERE classMask = ?d ORDER BY `tabNumber`, `creatureFamilyMask`', $mask);
|
||||||
$result = [];
|
$result = [];
|
||||||
|
|
||||||
for ($l = 0; $l < count($tabs); $l++)
|
for ($l = 0; $l < count($tabs); $l++)
|
||||||
{
|
{
|
||||||
$talents = DB::Aowow()->select('
|
$talents = DB::Aowow()->select('SELECT t.id AS tId, t.*, s.* FROM dbc_talent t, ?_spell s WHERE t.`tabId`= ?d AND s.`Id` = t.`rank1` ORDER by t.`row`, t.`column`', $tabs[$l]['Id']);
|
||||||
SELECT t.id AS tId, t.*, s.*
|
|
||||||
FROM dbc.talent t, ?_spell s
|
|
||||||
WHERE t.`tabId`= ?d AND s.`Id` = t.`rank1`
|
|
||||||
ORDER by t.`row`, t.`column`',
|
|
||||||
$tabs[$l]['Id']
|
|
||||||
);
|
|
||||||
|
|
||||||
$result[$l] = array(
|
$result[$l] = array(
|
||||||
'n' => Util::localizedString($tabs[$l], 'name'),
|
'n' => Util::localizedString($tabs[$l], 'name'),
|
||||||
't' => []
|
't' => []
|
||||||
@@ -163,13 +170,13 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
// check directory-structure
|
// check directory-structure
|
||||||
foreach (Util::$localeStrings as $dir)
|
foreach (Util::$localeStrings as $dir)
|
||||||
if (!writeDir('datasets/'.$dir, $log))
|
if (!FileGen::writeDir('datasets/'.$dir))
|
||||||
$success = false;
|
$success = false;
|
||||||
|
|
||||||
$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');
|
||||||
$tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE));
|
$tSpells = new SpellList(array(['s.id', $tSpellIds], CFG_SQL_LIMIT_NONE));
|
||||||
|
|
||||||
foreach ($locales as $lId)
|
foreach (FileGen::$localeIds as $lId)
|
||||||
{
|
{
|
||||||
User::useLocale($lId);
|
User::useLocale($lId);
|
||||||
Lang::load(Util::$localeStrings[$lId]);
|
Lang::load(Util::$localeStrings[$lId]);
|
||||||
@@ -181,9 +188,9 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
|
|
||||||
$cId = log($cMask, 2) + 1;
|
$cId = log($cMask, 2) + 1;
|
||||||
$file = 'datasets/'.User::$localeString.'/talents-'.$cId;
|
$file = 'datasets/'.User::$localeString.'/talents-'.$cId;
|
||||||
$toFile = '$WowheadTalentCalculator.registerClass('.$cId.', '.json_encode($buildTree($cId), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).')';
|
$toFile = '$WowheadTalentCalculator.registerClass('.$cId.', '.Util::toJSON($buildTree($cId)).')';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -191,14 +198,14 @@ if (!defined('AOWOW_REVISION'))
|
|||||||
if (empty($petIcons))
|
if (empty($petIcons))
|
||||||
{
|
{
|
||||||
$pets = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, iconString FROM ?_pet');
|
$pets = DB::Aowow()->SelectCol('SELECT Id AS ARRAY_KEY, iconString FROM ?_pet');
|
||||||
$petIcons = json_encode($pets, JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK);
|
$petIcons = Util::toJSON($pets);
|
||||||
}
|
}
|
||||||
|
|
||||||
$toFile = "var g_pet_icons = ".$petIcons.";\n\n";
|
$toFile = "var g_pet_icons = ".$petIcons.";\n\n";
|
||||||
$toFile .= 'var g_pet_talents = '.json_encode($buildTree(0), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_NUMERIC_CHECK).';';
|
$toFile .= 'var g_pet_talents = '.Util::toJSON($buildTree(0)).';';
|
||||||
$file = 'datasets/'.User::$localeString.'/pet-talents';
|
$file = 'datasets/'.User::$localeString.'/pet-talents';
|
||||||
|
|
||||||
if (!writeFile($file, $toFile, $log))
|
if (!FileGen::writeFile($file, $toFile))
|
||||||
$success = false;
|
$success = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
var mn_profiles = /*setup:mnProfiles*/;
|
var mn_profiles = /*setup:realmMenu*/;
|
||||||
|
|
||||||
var mn_guilds = $.extend(true,[],mn_profiles);
|
var mn_guilds = $.extend(true,[],mn_profiles);
|
||||||
var mn_arenateams = $.extend(true,[],mn_profiles);
|
var mn_arenateams = $.extend(true,[],mn_profiles);
|
||||||
|
|||||||
318
setup/tools/imagecreatefromblp.php
Normal file
318
setup/tools/imagecreatefromblp.php
Normal file
@@ -0,0 +1,318 @@
|
|||||||
|
<?php
|
||||||
|
/*
|
||||||
|
imagecreatefromblp - a PHP function which loads images from BLP files
|
||||||
|
This file is a part of AoWoW project.
|
||||||
|
Copyright (C) 2010 Mix <ru-mangos.ru>
|
||||||
|
|
||||||
|
This program is free software: you can redistribute it and/or modify
|
||||||
|
it under the terms of the GNU Affero General Public License as published by
|
||||||
|
the Free Software Foundation, either version 3 of the License, or
|
||||||
|
(at your option) any later version.
|
||||||
|
|
||||||
|
This program is distributed in the hope that it will be useful,
|
||||||
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
GNU Affero General Public License for more details.
|
||||||
|
|
||||||
|
You should have received a copy of the GNU Affero General Public License
|
||||||
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
// Usage example:
|
||||||
|
// $img = imagecreatefromblp("fileName.blp");
|
||||||
|
// imagejpeg($img);
|
||||||
|
// imagedestroy($img);
|
||||||
|
|
||||||
|
function imagecreatefromblp($fileName, $imgId = 0)
|
||||||
|
{
|
||||||
|
if (!FileGen::fileExists($fileName))
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' could not be found', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$file = fopen($fileName, 'rb');
|
||||||
|
|
||||||
|
if (!$file)
|
||||||
|
{
|
||||||
|
FileGen::status('could not open file '.$fileName, MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$fileSize = fileSize($fileName);
|
||||||
|
if ($fileSize < 16)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' is too small for a BLP file', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$data = fread($file, $fileSize);
|
||||||
|
fclose($file);
|
||||||
|
|
||||||
|
// predict replacement patch files
|
||||||
|
// ref: http://www.zezula.net/en/mpq/patchfiles.html
|
||||||
|
if (substr($data, 0x0, 0x4) == "PTCH")
|
||||||
|
{
|
||||||
|
// strip patch header
|
||||||
|
if (substr($data, 0x40, 0x43) == "COPY")
|
||||||
|
$data = substr($data, 0x44);
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' is an incremental patch file and cannot be used by this script.', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (substr($data, 0, 4) != "BLP2")
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' has incorrect/unsupported magic bytes', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$header = unpack("Vformat/Ctype/CalphaBits/CalphaType/Cmips/Vwidth/Vheight", substr($data, 4, 16));
|
||||||
|
$header['mipsOffs'] = unpack("V16", substr($data, 20, 64));
|
||||||
|
$header['mipsSize'] = unpack("V16", substr($data, 84, 64));
|
||||||
|
|
||||||
|
$debugStr = ' header = '.print_r($header, true);
|
||||||
|
|
||||||
|
if ($header['format'] != 1)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' has unsupported format'.$debugStr, MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$offs = $header['mipsOffs'][$imgId + 1];
|
||||||
|
$size = $header['mipsSize'][$imgId + 1];
|
||||||
|
|
||||||
|
while ($imgId > 0)
|
||||||
|
{
|
||||||
|
$header['width'] /= 2;
|
||||||
|
$header['height'] /= 2;
|
||||||
|
$imgId--;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($size == 0)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' contains zeroes in a mips table'.$debugStr, MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if ($offs + $size > $fileSize)
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' is corrupted/incomplete'.$debugStr, MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($header['type'] == 1)
|
||||||
|
$img = icfb1($header['width'], $header['height'], substr($data, 148, 1024), substr($data, $offs, $size));
|
||||||
|
else if ($header['type'] == 2)
|
||||||
|
$img = icfb2($header['width'], $header['height'], substr($data, $offs, $size), $header['alphaBits'], $header['alphaType']);
|
||||||
|
else if ($header['type'] == 3)
|
||||||
|
$img = icfb3($header['width'], $header['height'], substr($data, $offs, $size));
|
||||||
|
else
|
||||||
|
{
|
||||||
|
FileGen::status('file '.$fileName.' has unsupported type'.$debugStr, MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $img;
|
||||||
|
}
|
||||||
|
|
||||||
|
// uncompressed
|
||||||
|
function icfb1($width, $height, $palette, $data)
|
||||||
|
{
|
||||||
|
$img = imagecreatetruecolor($width, $height);
|
||||||
|
imagesavealpha($img, true);
|
||||||
|
imagealphablending($img, false);
|
||||||
|
|
||||||
|
$t = unpack("V256", $palette);
|
||||||
|
$i = unpack("C*", $data);
|
||||||
|
|
||||||
|
for ($y = 0; $y < $height; $y++)
|
||||||
|
{
|
||||||
|
for ($x = 0; $x < $width; $x++)
|
||||||
|
{
|
||||||
|
$c = $t[$i[$x + $y * $width+ 1 ] + 1];
|
||||||
|
$c = imagecolorallocatealpha($img, ($c >> 16) & 255, ($c >> 8) & 255, $c & 255, (($c >> 24) & 255) >> 1);
|
||||||
|
imagesetpixel($img, $x, $y, $c);
|
||||||
|
imagecolordeallocate($img, $c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $img;
|
||||||
|
}
|
||||||
|
|
||||||
|
// DXTC
|
||||||
|
function icfb2($width, $height, $data, $alphaBits, $alphaType)
|
||||||
|
{
|
||||||
|
if (!in_array($alphaBits * 10 + $alphaType, [0, 10, 41, 81, 87, 88]))
|
||||||
|
{
|
||||||
|
FileGen::status('unsupported compression type', MSG_LVL_ERROR);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
$img = imagecreatetruecolor($width, $height);
|
||||||
|
imagesavealpha($img, true);
|
||||||
|
imagealphablending($img, false);
|
||||||
|
|
||||||
|
$offset = 0;
|
||||||
|
for ($offy = 0; $offy < $height; $offy += 4)
|
||||||
|
{
|
||||||
|
for ($offx = 0; $offx < $width; $offx += 4)
|
||||||
|
{
|
||||||
|
$alpha = [];
|
||||||
|
if ($alphaBits > 1)
|
||||||
|
{
|
||||||
|
if ($alphaType <= 1)
|
||||||
|
{
|
||||||
|
$a = unpack("V2", substr($data, $offset, 8));
|
||||||
|
$a1 = $a[1];
|
||||||
|
$a2 = $a[2];
|
||||||
|
|
||||||
|
for ($i = 0; $i < 8; $i++, $a1 >>= 4)
|
||||||
|
$alpha[$i] = (($a1 & 15) << 4) | ($a1 & 15);
|
||||||
|
|
||||||
|
for ($i = 8; $i < 16; $i++, $a2 >>= 4)
|
||||||
|
$alpha[$i] = (($a2 & 15) << 4) | ($a2 & 15);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$c = unpack("C2", substr($data, $offset, 2));
|
||||||
|
$t = [$c[1], $c[2]];
|
||||||
|
|
||||||
|
if ($t[0] <= $t[1])
|
||||||
|
{
|
||||||
|
$t[2] = (4 * $t[0] + $t[1]) / 5;
|
||||||
|
$t[3] = (3 * $t[0] + 2 * $t[1]) / 5;
|
||||||
|
$t[4] = (2 * $t[0] + 3 * $t[1]) / 5;
|
||||||
|
$t[5] = ( $t[0] + 4 * $t[1]) / 5;
|
||||||
|
$t[6] = 0;
|
||||||
|
$t[7] = 255;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$t[2] = (6 * $t[0] + $t[1]) / 7;
|
||||||
|
$t[3] = (5 * $t[0] + 2 * $t[1]) / 7;
|
||||||
|
$t[4] = (4 * $t[0] + 3 * $t[1]) / 7;
|
||||||
|
$t[5] = (3 * $t[0] + 4 * $t[1]) / 7;
|
||||||
|
$t[6] = (2 * $t[0] + 5 * $t[1]) / 7;
|
||||||
|
$t[7] = ( $t[0] + 6 * $t[1]) / 7;
|
||||||
|
}
|
||||||
|
|
||||||
|
$a = unpack("C6", substr($data, $offset + 2, 6));
|
||||||
|
$a1 = $a[1] | ($a[2] << 8) | ($a[3] << 16);
|
||||||
|
$a2 = $a[4] | ($a[5] << 8) | ($a[6] << 16);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 8; $i++, $a1 >>= 3)
|
||||||
|
$alpha[$i] = $t[$a1 & 7];
|
||||||
|
|
||||||
|
for ($i = 8; $i < 16; $i++, $a2 >>= 3)
|
||||||
|
$alpha[$i] = $t[$a2 & 7];
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset += 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
$c0 = unpack("v", substr($data, $offset, 2))[1];
|
||||||
|
|
||||||
|
$t = [];
|
||||||
|
$t[0] = array(
|
||||||
|
'r' => (($c0 >> 8) & 0xF8) | (($c0 >> 13) & 7),
|
||||||
|
'g' => (($c0 >> 3) & 0xFC) | (($c0 >> 9) & 3),
|
||||||
|
'b' => (($c0 << 3) & 0xF8) | (($c0 >> 2) & 7),
|
||||||
|
'a' => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
$c1 = unpack("v", substr($data, $offset + 2, 2))[1];
|
||||||
|
|
||||||
|
$t[1] = array(
|
||||||
|
'r' => (($c1 >> 8) & 0xF8) | (($c1 >> 13) & 7),
|
||||||
|
'g' => (($c1 >> 3) & 0xFC) | (($c1 >> 9) & 3),
|
||||||
|
'b' => (($c1 << 3) & 0xF8) | (($c1 >> 2) & 7),
|
||||||
|
'a' => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
if (($c0 <= $c1) && ($alphaBits <= 1))
|
||||||
|
{
|
||||||
|
$t[2] = array(
|
||||||
|
'r' => ($t[0]['r'] + $t[1]['r']) / 2,
|
||||||
|
'g' => ($t[0]['g'] + $t[1]['g']) / 2,
|
||||||
|
'b' => ($t[0]['b'] + $t[1]['b']) / 2,
|
||||||
|
'a' => 0
|
||||||
|
);
|
||||||
|
|
||||||
|
if ($alphaBits == 1)
|
||||||
|
$t[3] = ['r' => 0, 'g' => 0, 'b' => 0, 'a' => 255];
|
||||||
|
else
|
||||||
|
$t[3] = ['r' => 0, 'g' => 0, 'b' => 0, 'a' => 0];
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$t[2] = array(
|
||||||
|
'r' => (2 * $t[0]['r'] + $t[1]['r']) / 3,
|
||||||
|
'g' => (2 * $t[0]['g'] + $t[1]['g']) / 3,
|
||||||
|
'b' => (2 * $t[0]['b'] + $t[1]['b']) / 3,
|
||||||
|
'a' => 0
|
||||||
|
);
|
||||||
|
$t[3] = array(
|
||||||
|
'r' => ($t[0]['r'] + 2 * $t[1]['r']) / 3,
|
||||||
|
'g' => ($t[0]['g'] + 2 * $t[1]['g']) / 3,
|
||||||
|
'b' => ($t[0]['b'] + 2 * $t[1]['b']) / 3,
|
||||||
|
'a' => 0
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($alphaBits > 1)
|
||||||
|
{
|
||||||
|
$i = unpack("V", substr($data, $offset + 4, 4))[1];
|
||||||
|
|
||||||
|
for ($y = 0; $y < 4; $y++)
|
||||||
|
{
|
||||||
|
for ($x = 0; $x < 4; $x++, $i >>= 2)
|
||||||
|
{
|
||||||
|
$color = imagecolorallocatealpha($img, $t[$i & 3]['r'], $t[$i & 3]['g'], $t[$i & 3]['b'], (255 - $alpha[$x + $y * 4]) / 2);
|
||||||
|
imagesetpixel($img, $offx + $x, $offy + $y, $color);
|
||||||
|
imagecolordeallocate($img, $color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
$c = [];
|
||||||
|
for ($i = 0; $i < 4; $i++)
|
||||||
|
$c[$i] = imagecolorallocatealpha($img, $t[$i]['r'], $t[$i]['g'], $t[$i]['b'], $t[$i]['a'] / 2);
|
||||||
|
|
||||||
|
$i = unpack("V", substr($data, $offset + 4, 4))[1];
|
||||||
|
for ($y = 0; $y < 4; $y++)
|
||||||
|
for ($x = 0; $x < 4; $x++, $i >>= 2)
|
||||||
|
imagesetpixel($img, $offx + $x, $offy + $y, $c[$i & 3]);
|
||||||
|
|
||||||
|
for ($i = 0; $i < 4; $i++)
|
||||||
|
imagecolordeallocate($img, $c[$i]);
|
||||||
|
}
|
||||||
|
|
||||||
|
$offset += 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $img;
|
||||||
|
}
|
||||||
|
|
||||||
|
// plain
|
||||||
|
function icfb3($width, $height, $data)
|
||||||
|
{
|
||||||
|
$img = imagecreatetruecolor($width, $height);
|
||||||
|
$i = unpack("V*", $data);
|
||||||
|
|
||||||
|
for ($y = 0; $y < $height; $y++)
|
||||||
|
{
|
||||||
|
for ($x = 0; $x < $width; $x++)
|
||||||
|
{
|
||||||
|
$c = $i[$x + $y * $width + 1];
|
||||||
|
$c = imagecolorallocate($img, ($c >> 16) & 255, ($c >> 8) & 255, $c & 255);
|
||||||
|
imagesetpixel($img, $x, $y, $c);
|
||||||
|
imagecolordeallocate($img, $c);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return $img;
|
||||||
|
}
|
||||||
|
?>
|
||||||
Reference in New Issue
Block a user