diff --git a/src/server/types/Pet.js b/src/server/types/Pet.js index 5e5ec3a..977626a 100644 --- a/src/server/types/Pet.js +++ b/src/server/types/Pet.js @@ -33,12 +33,12 @@ const resolvers = { return null; } - // Neopets may omit this field entirely; treat "missing" as null. - const altStyleId = customPetData.custom_pet.alt_style ?? null; + const speciesId = customPetData.custom_pet.species_id; + const baseColorId = customPetData.custom_pet.color_id; const petType = await petTypeBySpeciesAndColorLoader.load({ - speciesId: customPetData.custom_pet.species_id, - colorId: customPetData.custom_pet.color_id, + speciesId, + colorId: baseColorId, }); const petStates = petType ? await petStatesForPetTypeLoader.load(petType.id) @@ -55,8 +55,33 @@ const resolvers = { .sort((a, b) => Number(a) - Number(b)) .join(","); petState = petStates.find((ps) => ps.swfAssetIds === swfAssetIdsString); + + // Neopets may omit these fields entirely; treat "missing" as null. + const altStyleId = customPetData.custom_pet.alt_style; + const altColorId = customPetData.custom_pet.alt_color; + if (petState) { - return { id: petState.id, altStyleId }; + return { id: petState.id, altStyleId, altColorId }; + } + + // If that didn't work, and Neopets reported an alt color, try looking up + // the same exact-assets pet state on the species+altColor pair. + if (altColorId != null && altColorId !== baseColorId) { + const altColorPetType = await petTypeBySpeciesAndColorLoader.load({ + speciesId, + colorId: altColorId, + }); + if (altColorPetType) { + const altColorPetStates = await petStatesForPetTypeLoader.load( + altColorPetType.id, + ); + const altColorPetState = altColorPetStates.find( + (ps) => ps.swfAssetIds === swfAssetIdsString, + ); + if (altColorPetState) { + return { id: altColorPetState.id, altStyleId, altColorId }; + } + } } // Next, look for a pet state matching the same pose. (This can happen if @@ -74,7 +99,7 @@ const resolvers = { `because it matches pose ${pose}. Actual pet state for these ` + `assets not found: ${swfAssetIdsString}`, ); - return { id: petState.id, altStyleId }; + return { id: petState.id, altStyleId, altColorId }; } } @@ -88,7 +113,7 @@ const resolvers = { `as an UNKNOWN fallback pose. Actual pet state for these ` + `assets not found: ${swfAssetIdsString}`, ); - return { id: petState.id, altStyleId }; + return { id: petState.id, altStyleId, altColorId }; } // If we still don't have a pet state, raise an error. (This can happen diff --git a/src/server/types/PetAppearance.js b/src/server/types/PetAppearance.js index 6a92c8f..8695b0f 100644 --- a/src/server/types/PetAppearance.js +++ b/src/server/types/PetAppearance.js @@ -84,6 +84,12 @@ const typeDefs = gql` """ altStyleId: ID + """ + The ID of the alt color used to render this appearance, if any. + Null when this appearance is not using an alt style. + """ + altColorId: ID + species: Species! color: Color! pose: Pose! @@ -279,6 +285,7 @@ const resolvers = { }, PetAppearance: { + altColorId: ({ altColorId }) => (altColorId), id: ({ id, altStyleId }) => { if (altStyleId != null) { return `${id}-with-alt-style-${altStyleId}`;