mirror of
https://github.com/smogon/sprites.git
synced 2026-09-09 18:45:39 -05:00
Layer the xy set on published names, not filenames
xy/ takes the first source that offers a sprite, keyed until now on the filename. That held while gen 5 was only there for the CAPs the models never got: a CAP has one file and one name. The Smogon Sprite Project's batch broke it. gen 5 now carries a file per forme slot, and the slots the games gave a single sprite share a published name, so the six Minior meteors and the two Zygarde Power Construct slots each arrived as their own filename asking for a name the models had already published. The manifest rejected the first of them, `duplicate sprite name minior-meteor.gif`, and the deploy stopped there. Key the layering on the published name, which is what has to be unique, and lift the name off rules/publish.ts as publishedNames() so both the layering and spritecopy read it from one place. Sprites that publish nothing (back, shiny, asymmetrical, and the x literals) come back as no names and copy nothing, as before. xy/ gains 13 sprites, all of them from the new gen 5 files, and is now 1650 names against the 1637 it held before the batch. Seven are Gigantamax: Blastoise, Cinderace, Inteleon, Rillaboom, Urshifu, Urshifu-Rapid-Strike and Venusaur, which is exactly what models/ lacks of the 33 Gigantamax formes gen 5 draws. The other six are Greninja-Bond, Pikachu-World, Ribombee-Totem, Rockruff-Dusk, Sneasel-Hisui-F and Xerneas-Neutral. Everything else in the batch is a species the models, gen9species or champions already cover. Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -64,25 +64,34 @@ function extOf(f: Sprite, ext?: string): string {
|
||||
return result;
|
||||
}
|
||||
|
||||
export async function spritecopy(manifest: Manifest, f: Sprite, dest: Dest,
|
||||
allowUnknown = false): Promise<void> {
|
||||
// The names a sprite publishes under on the smogon side, or none where it
|
||||
// isn't published at all. A set that backfills another needs this before it
|
||||
// copies, since the mapping isn't one name per filename in either direction:
|
||||
// Meowstic answers to two, and the forme slots the games gave one sprite (the
|
||||
// six Minior meteors, Zygarde's Power Construct pair) answer to the same one.
|
||||
export function publishedNames(f: Sprite, allowUnknown = false): string[] {
|
||||
let sn = spritedata.parseFilename(f.name);
|
||||
|
||||
// Skip asymmetrical for now
|
||||
if (sn.extra.has('a') || sn.extra.has('b') || sn.extra.has('s')) {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
|
||||
if (sn.kind === 'x') {
|
||||
// Skip these, we don't use Unknown/Substitute
|
||||
if (!allowUnknown || sn.name !== 'unknown') {
|
||||
return;
|
||||
return [];
|
||||
}
|
||||
} else if (sn.kind !== 's') {
|
||||
throw new Error(`Not a specie sprite: ${f.name}`);
|
||||
}
|
||||
|
||||
for (let name of spritedata.smogonNames(sn)) {
|
||||
return spritedata.smogonNames(sn);
|
||||
}
|
||||
|
||||
export async function spritecopy(manifest: Manifest, f: Sprite, dest: Dest,
|
||||
allowUnknown = false): Promise<void> {
|
||||
for (let name of publishedNames(f, allowUnknown)) {
|
||||
await manifest.copy(f, dest, name);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
|
||||
import {gen10Modelslike} from './rules/modelslike.ts';
|
||||
import {Manifest, type Sprite, spritecopy} from './rules/publish.ts';
|
||||
import {Manifest, type Sprite, publishedNames, spritecopy} from './rules/publish.ts';
|
||||
import {forEachRule} from './tools/build/artifact.ts';
|
||||
import {compresspng, trimimg} from './tools/build/helpers.ts';
|
||||
import {deploy} from './tools/deploy/api.ts';
|
||||
@@ -19,7 +19,9 @@ let xyModels = forEachRule('src/gen9species/*.png', {
|
||||
|
||||
let xyChampions = gen10Modelslike();
|
||||
|
||||
// Non-model gen 5 CAPs.
|
||||
// Whatever the models don't cover, in gen 5 style: the CAPs that never got a
|
||||
// model, and, since the Smogon Sprite Project's batch landed, the Gigantamax
|
||||
// formes and a few others.
|
||||
|
||||
let xyGen5 = forEachRule('src/sprites/gen5/*.png', [
|
||||
// TODO, add customizable compression for gif
|
||||
@@ -29,14 +31,22 @@ let xyGen5 = forEachRule('src/sprites/gen5/*.png', [
|
||||
], '%B.gif');
|
||||
|
||||
deploy(async ctx => {
|
||||
let seenModels = new Set<string>();
|
||||
let seen = new Set<string>();
|
||||
let manifest = new Manifest(ctx);
|
||||
// First source wins per published name rather than per filename, because
|
||||
// the later sources are backfills and a name can be spelled more than one
|
||||
// way. gen 5 carries a sprite per forme slot, so its six Minior meteors
|
||||
// and two Zygarde Power Construct slots all want the name the models
|
||||
// already publish, which the manifest would reject as a duplicate.
|
||||
let xycopy = async (f: Sprite) => {
|
||||
if (seenModels.has(f.name)) {
|
||||
let names = publishedNames(f);
|
||||
if (names.some(n => seen.has(n))) {
|
||||
return;
|
||||
}
|
||||
seenModels.add(f.name);
|
||||
await spritecopy(manifest, f, {dir: 'xy'});
|
||||
for (let name of names) {
|
||||
seen.add(name);
|
||||
await manifest.copy(f, {dir: 'xy'}, name);
|
||||
}
|
||||
};
|
||||
|
||||
for (let f of await ctx.list('src/models')) {
|
||||
@@ -48,7 +58,6 @@ deploy(async ctx => {
|
||||
for (let f of xyChampions) {
|
||||
await xycopy(f);
|
||||
}
|
||||
// Non-model CAPs
|
||||
for (let f of await ctx.list('src/sprites/gen5')) {
|
||||
if (f.ext === 'gif') {
|
||||
await xycopy(f);
|
||||
|
||||
Reference in New Issue
Block a user