mirror of
https://github.com/msikma/pokesprite.git
synced 2026-09-08 18:35:11 -05:00
Script for generating the icon database json file
This commit is contained in:
290
scripts/link-item-icons.php
Executable file
290
scripts/link-item-icons.php
Executable file
@@ -0,0 +1,290 @@
|
||||
#!/usr/bin/env php
|
||||
<?php
|
||||
|
||||
// Suffixed items: these appear in the database with a suffix string.
|
||||
// E.g. the database contains 'red-apricorn', for the icon 'red' in the 'apricorn' set.
|
||||
$suffix = array(
|
||||
'apricorn', 'gem', 'petal', 'shard', 'mulch', 'flute', 'incense', 'memory', 'plate', 'berry', 'ball', 'fossil', 'scarf'
|
||||
);
|
||||
// Prefixed items: as above, but suffixed. Only 'roto'.
|
||||
// E.g. in the database, 'roto-hatch', but in our files, icon 'hatch' in the 'roto' set.
|
||||
$prefix = array(
|
||||
'roto'
|
||||
);
|
||||
|
||||
// Ignored items: these items are expected to not have an icon.
|
||||
// See <https://github.com/msikma/pokesprite/pull/40#issuecomment-398071404>.
|
||||
$ignored_items = array(
|
||||
// Technical machines.
|
||||
'tm00', 'tm01', 'tm02', 'tm03', 'tm04', 'tm05', 'tm06', 'tm07', 'tm08',
|
||||
'tm09', 'tm10', 'tm11', 'tm12', 'tm13', 'tm14', 'tm15', 'tm16', 'tm17',
|
||||
'tm18', 'tm19', 'tm20', 'tm21', 'tm22', 'tm23', 'tm24', 'tm25', 'tm26',
|
||||
'tm27', 'tm28', 'tm29', 'tm30', 'tm31', 'tm32', 'tm33', 'tm34', 'tm35',
|
||||
'tm36', 'tm37', 'tm38', 'tm39', 'tm40', 'tm41', 'tm42', 'tm43', 'tm44',
|
||||
'tm45', 'tm46', 'tm47', 'tm48', 'tm49', 'tm50', 'tm51', 'tm52', 'tm53',
|
||||
'tm54', 'tm55', 'tm56', 'tm57', 'tm58', 'tm59', 'tm60', 'tm61', 'tm62',
|
||||
'tm63', 'tm64', 'tm65', 'tm66', 'tm67', 'tm68', 'tm69', 'tm70', 'tm71',
|
||||
'tm72', 'tm73', 'tm74', 'tm75', 'tm76', 'tm77', 'tm78', 'tm79', 'tm80',
|
||||
'tm81', 'tm82', 'tm83', 'tm84', 'tm85', 'tm86', 'tm87', 'tm88', 'tm89',
|
||||
'tm90', 'tm91', 'tm92', 'tm93', 'tm94', 'tm95', 'tm96', 'tm97', 'tm98',
|
||||
'tm99', 'tm100',
|
||||
|
||||
// Data cards.
|
||||
'data-card-00', 'data-card-01', 'data-card-02', 'data-card-03',
|
||||
'data-card-04', 'data-card-05', 'data-card-06', 'data-card-07',
|
||||
'data-card-08', 'data-card-09', 'data-card-10', 'data-card-11',
|
||||
'data-card-12', 'data-card-13', 'data-card-14', 'data-card-15',
|
||||
'data-card-16', 'data-card-17', 'data-card-18', 'data-card-19',
|
||||
'data-card-20', 'data-card-21', 'data-card-22', 'data-card-23',
|
||||
'data-card-24', 'data-card-25', 'data-card-26', 'data-card-27',
|
||||
'data-card-28', 'data-card-29', 'data-card-30',
|
||||
|
||||
// Hidden machines.
|
||||
'hm00', 'hm01', 'hm02', 'hm03', 'hm04', 'hm05', 'hm06', 'hm07', 'hm08',
|
||||
'hm09', 'hm10',
|
||||
|
||||
// Mega- items are in the database but don't have an icon representation.
|
||||
'mega-pendant', 'mega-glasses', 'mega-glove', 'mega-anchor', 'mega-stickpin',
|
||||
'mega-tiara', 'mega-anklet',
|
||||
);
|
||||
|
||||
// Typoed items: these items have a typo in the database and need to be redirected
|
||||
// to the correct file or we'll be unable to find the icon.
|
||||
// See <https://github.com/msikma/pokesprite/pull/40#issuecomment-398071404>.
|
||||
$typoed_items = array(
|
||||
// The Xtransceiver icons.
|
||||
'xtranceiver--red' => 'xtransceiver--red',
|
||||
'xtranceiver--yellow' => 'xtransceiver--yellow',
|
||||
);
|
||||
|
||||
// Aliased items: this is for items that share an icon but have a different name.
|
||||
// I'm not sure if any of these need to have a different icon. It could be that there are
|
||||
// extra icons that we are missing. Worth trying to check this out sometime.
|
||||
$aliased_items = array(
|
||||
'dna-splicers--merge' => 'dna-splicers',
|
||||
'dna-splicers--split' => 'dna-splicers',
|
||||
|
||||
'ss-ticket--hoenn' => 'ss-ticket',
|
||||
|
||||
'n-solarizer--merge' => 'n-solarizer',
|
||||
'n-lunarizer--merge' => 'n-lunarizer',
|
||||
'n-solarizer--split' => 'n-solarizer',
|
||||
'n-lunarizer--split' => 'n-lunarizer',
|
||||
|
||||
'ilimas-normalium-z' => 'normalium-z--bag',
|
||||
'left-poke-ball' => 'poke-ball',
|
||||
);
|
||||
|
||||
// Some icons are present in multiple sets. This disambiguates them.
|
||||
$set_disambiguation = array(
|
||||
// 'evo-item' and 'hold-item' have some identical icons.
|
||||
'hold-item' => array('evo-item', 'hold-item'),
|
||||
// Prefer 'medicine' and 'battle-item' over 'wonder-launcher'.
|
||||
'medicine' => array('wonder-launcher', 'medicine'),
|
||||
'battle-item' => array('wonder-launcher', 'battle-item'),
|
||||
);
|
||||
|
||||
// We will attempt to match every item from the item export to an icon on the disk.
|
||||
// Every item that doesn't have a matching icon is reported.
|
||||
// Every icon that doesn't get used is reported.
|
||||
$sets = get_icon_sets();
|
||||
$items = get_item_export();
|
||||
|
||||
// Finally, we will generate a new JSON file with the following structure:
|
||||
// First, a list of icon sets, which we will use when generating the icon spritesheet.
|
||||
// Secondly, a key-value store of item ID to icon file.
|
||||
$item_icon_database = array();
|
||||
$icon_database = array();
|
||||
$icon_usage = array();
|
||||
|
||||
// Run through every item in the database, match it with an icon (if it's not in the ignored item list)
|
||||
// and save the resulting item/icon object to the final data set.
|
||||
foreach ($items as $item) {
|
||||
$obj = find_item_icon($item, $sets);
|
||||
// Save the icon this item will use in the usage array.
|
||||
$icon_path = $obj['icon']['set'].'/'.$obj['icon']['filename'];
|
||||
$icon_usage[$icon_path] = true;
|
||||
// Save the object to the item/icon database.
|
||||
// If this item does not have an associated icon, the value will be null instead of a string.
|
||||
// If it does have an icon, the string is a reference to an icon ID in 'icons'.
|
||||
$item_icon_database[$obj['item']['id']] = !empty($obj['icon']['set']) ? array($obj['icon']['set'], $obj['icon']['filename']) : null;
|
||||
if (!isset($icon_database[$obj['icon']['set']])) {
|
||||
$icon_database[$obj['icon']['set']] = array();
|
||||
}
|
||||
$icon_database[$obj['icon']['set']][$obj['icon']['filename']] = $obj;
|
||||
}
|
||||
|
||||
// Now we need to run through all existing physical icons to see which ones were not linked to an item.
|
||||
// We will also add these icons to the item/icon database, but without item data.
|
||||
foreach ($sets as $set_name => $set_icons) {
|
||||
foreach ($set_icons as $slug => $icon) {
|
||||
$icon_path = $set_name.'/'.$icon['filename'];
|
||||
if (isset($icon_usage[$icon_path])) {
|
||||
continue;
|
||||
}
|
||||
// This icon has not been matched with an item.
|
||||
$obj = make_item_icon(false, $slug, $set_name, $set_icons[$slug]);
|
||||
$icon_usage[$icon_path] = true;
|
||||
|
||||
// Save the object to the item/icon database.
|
||||
if (!isset($icon_database[$set_name])) {
|
||||
$icon_database[$set_name] = array();
|
||||
}
|
||||
$icon_database[$set_name][$obj['icon']['filename']] = $obj;
|
||||
}
|
||||
}
|
||||
|
||||
// Now output the final file.
|
||||
file_put_contents('icons.json', json_encode(array('items' => $item_icon_database, 'icons' => $icon_database), JSON_PRETTY_PRINT));
|
||||
die("Output: './icons.json'. Done.\n");
|
||||
|
||||
/**
|
||||
* Returns a matching icon file for a specific item.
|
||||
* This is highly inefficient and any programmer would hate this code,
|
||||
* but it doesn't really matter.
|
||||
*/
|
||||
function find_item_icon($item, $sets) {
|
||||
global $ignored_items, $typoed_items, $aliased_items, $set_disambiguation;
|
||||
|
||||
// Match on the English language slug.
|
||||
$slug = $item['slug']['eng'];
|
||||
|
||||
// Check if we are ignoring this item.
|
||||
if (in_array($slug, $ignored_items)) {
|
||||
return make_item_icon($item, $slug);
|
||||
}
|
||||
|
||||
// Check if the item we're looking for is typoed.
|
||||
$is_typoed = false;
|
||||
if (isset($typoed_items[$slug])) {
|
||||
$slug = $typoed_items[$slug];
|
||||
$is_typoed = true;
|
||||
}
|
||||
|
||||
// Check if the item is aliased to a different icon file.
|
||||
$is_aliased = false;
|
||||
if (isset($aliased_items[$slug])) {
|
||||
$slug = $aliased_items[$slug];
|
||||
$is_aliased = true;
|
||||
}
|
||||
|
||||
$matches = array();
|
||||
foreach ($sets as $set_name => $set_icons) {
|
||||
$set_icon_slugs = array_keys($set_icons);
|
||||
if (!in_array($slug, $set_icon_slugs)) {
|
||||
continue;
|
||||
}
|
||||
// Found a match.
|
||||
$matches[$set_name] = make_item_icon($item, $slug, $set_name, $set_icons[$slug], $is_typoed, $is_aliased);
|
||||
}
|
||||
if (count($matches) > 1) {
|
||||
$keys = array_keys($matches);
|
||||
$disamb = null;
|
||||
print('Found '.count($matches).' matches for item #'.$item['id'].' ('.$item['slug']['eng'].'): ');
|
||||
foreach ($set_disambiguation as $target => $items) {
|
||||
if ($keys != $items) {
|
||||
continue;
|
||||
}
|
||||
$disamb = $target;
|
||||
}
|
||||
if (!$disamb) {
|
||||
print(implode(', ', $keys)." (no disambiguation)\n");
|
||||
}
|
||||
else {
|
||||
print(implode(', ', $keys));
|
||||
foreach ($matches as $set_name => $match_obj) {
|
||||
if ($set_name === $disamb) {
|
||||
print(" (".$disamb.")\n");
|
||||
return $match_obj;
|
||||
}
|
||||
}
|
||||
print(" (could not find disambiguation: ".$disamb.")\n");
|
||||
}
|
||||
}
|
||||
return $matches[0];
|
||||
//if (strpos($obj['icon']['slug'], 'revive') > -1) {
|
||||
|
||||
// NOTE: we're quitting the script here on error because all items should be accounted for.
|
||||
// If one isn't, we need to add it to ignored/aliased/typoed items.
|
||||
print("Error: could not find item icon: \n");
|
||||
var_dump($item);
|
||||
die();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a new format array with item and icon data.
|
||||
*/
|
||||
function make_item_icon($item = false, $slug = null, $set_name = null, $icon = false, $typoed = false, $aliased = false) {
|
||||
$icon_data = array();
|
||||
if ($item !== false) {
|
||||
$icon_data['item'] = array(
|
||||
'id' => $item['id'],
|
||||
'slug' => $item['slug'],
|
||||
'name' => $item['name'],
|
||||
);
|
||||
}
|
||||
if ($typoed !== false) {
|
||||
$icon_data['typoed'] = $typoed;
|
||||
}
|
||||
if ($aliased !== false) {
|
||||
$icon_data['aliased'] = $aliased;
|
||||
}
|
||||
if ($icon !== false) {
|
||||
$icon_data['icon'] = array(
|
||||
'slug' => $slug,
|
||||
'set' => $set_name,
|
||||
'filename' => $icon['filename'],
|
||||
);
|
||||
}
|
||||
return $icon_data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a list of all icon sets and icons inside: this is based on physical files.
|
||||
*/
|
||||
function get_icon_sets() {
|
||||
global $suffix, $prefix;
|
||||
|
||||
$sets = array();
|
||||
|
||||
// Iterate through every directory inside 'icons'.
|
||||
$root = new DirectoryIterator('./icons/');
|
||||
foreach ($root as $set) {
|
||||
$set_name = $set->getFilename();
|
||||
if ($set->isDot() || $set_name === 'pokemon' || !$set->isDir()) continue;
|
||||
|
||||
if (!isset($sets[$set_name])) {
|
||||
$sets[$set_name] = array();
|
||||
}
|
||||
|
||||
// Now iterate over all files inside.
|
||||
$dir = new DirectoryIterator('./icons/'.$set_name);
|
||||
foreach ($dir as $icon) {
|
||||
if ($icon->isDot()) continue;
|
||||
|
||||
$filename = $icon->getFilename();
|
||||
$icon_name = pathinfo($icon->getFilename(), PATHINFO_FILENAME);
|
||||
|
||||
if (in_array($set_name, $suffix)) {
|
||||
$icon_name = $icon_name.'-'.$set_name;
|
||||
}
|
||||
if (in_array($set_name, $prefix)) {
|
||||
$icon_name = $set_name.'-'.$icon_name;
|
||||
}
|
||||
|
||||
$sets[$set_name][$icon_name] = array(
|
||||
'filename' => $filename
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
return $sets;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the items from the database export.
|
||||
*/
|
||||
function get_item_export() {
|
||||
$items = json_decode(file_get_contents('./data/item-export.json'), true);
|
||||
return $items;
|
||||
}
|
||||
Reference in New Issue
Block a user