don't restrict zones if the item is not compatible

Previously, if you switched species/color such that one of your items was no longer compatible, we _would_ still apply its zone restrictions to the visible layer set.

In this change, we fix that server-side, since I think it makes the most sense for an empty appearance to be truly empty!
This commit is contained in:
Emi Matchu 2020-09-01 17:00:27 -07:00
parent 574199575b
commit b7c958c39b
3 changed files with 107 additions and 25 deletions

View file

@ -360,7 +360,17 @@ const resolvers = {
return allSwfAssets.filter((sa) => sa.url.endsWith(".swf")); return allSwfAssets.filter((sa) => sa.url.endsWith(".swf"));
}, },
restrictedZones: async ({ item: { id: itemId } }, _, { itemLoader }) => { restrictedZones: async (
{ item: { id: itemId }, bodyId },
_,
{ itemSwfAssetLoader, itemLoader }
) => {
// Check whether this appearance is empty. If so, restrict no zones.
const allSwfAssets = await itemSwfAssetLoader.load({ itemId, bodyId });
if (allSwfAssets.length === 0) {
return [];
}
const item = await itemLoader.load(itemId); const item = await itemLoader.load(itemId);
return getRestrictedZoneIds(item.zonesRestrict).map((id) => ({ id })); return getRestrictedZoneIds(item.zonesRestrict).map((id) => ({ id }));
}, },

View file

@ -276,38 +276,41 @@ const buildSwfAssetLoader = (db) =>
}); });
const buildItemSwfAssetLoader = (db, loaders) => const buildItemSwfAssetLoader = (db, loaders) =>
new DataLoader(async (itemAndBodyPairs) => { new DataLoader(
const conditions = []; async (itemAndBodyPairs) => {
const values = []; const conditions = [];
for (const { itemId, bodyId } of itemAndBodyPairs) { const values = [];
conditions.push( for (const { itemId, bodyId } of itemAndBodyPairs) {
"(rel.parent_id = ? AND (sa.body_id = ? OR sa.body_id = 0))" conditions.push(
); "(rel.parent_id = ? AND (sa.body_id = ? OR sa.body_id = 0))"
values.push(itemId, bodyId); );
} values.push(itemId, bodyId);
}
const [rows, _] = await db.execute( const [rows, _] = await db.execute(
`SELECT sa.*, rel.parent_id FROM swf_assets sa `SELECT sa.*, rel.parent_id FROM swf_assets sa
INNER JOIN parents_swf_assets rel ON INNER JOIN parents_swf_assets rel ON
rel.parent_type = "Item" AND rel.parent_type = "Item" AND
rel.swf_asset_id = sa.id rel.swf_asset_id = sa.id
WHERE ${conditions.join(" OR ")}`, WHERE ${conditions.join(" OR ")}`,
values values
); );
const entities = rows.map(normalizeRow); const entities = rows.map(normalizeRow);
for (const swfAsset of entities) { for (const swfAsset of entities) {
loaders.swfAssetLoader.prime(swfAsset.id, swfAsset); loaders.swfAssetLoader.prime(swfAsset.id, swfAsset);
} }
return itemAndBodyPairs.map(({ itemId, bodyId }) => return itemAndBodyPairs.map(({ itemId, bodyId }) =>
entities.filter( entities.filter(
(e) => (e) =>
e.parentId === itemId && (e.bodyId === bodyId || e.bodyId === "0") e.parentId === itemId && (e.bodyId === bodyId || e.bodyId === "0")
) )
); );
}); },
{ cacheKeyFn: ({ itemId, bodyId }) => `${itemId},${bodyId}` }
);
const buildPetSwfAssetLoader = (db, loaders) => const buildPetSwfAssetLoader = (db, loaders) =>
new DataLoader(async (petStateIds) => { new DataLoader(async (petStateIds) => {

View file

@ -152,6 +152,75 @@ describe("Item", () => {
`); `);
}); });
it("returns empty appearance for incompatible items", async () => {
const res = await query({
query: gql`
query {
items(ids: ["38912"]) {
id
name
appearanceOn(speciesId: "1", colorId: "8") {
layers {
id
}
# Pay particular attention to this: normally this item restricts
# zones, but not when the appearance is empty!
restrictedZones {
id
}
}
}
}
`,
});
expect(res).toHaveNoErrors();
expect(res.data).toMatchInlineSnapshot(`
Object {
"items": Array [
Object {
"appearanceOn": Object {
"layers": Array [],
"restrictedZones": Array [],
},
"id": "38912",
"name": "Zafara Agent Robe",
},
],
}
`);
expect(getDbCalls()).toMatchInlineSnapshot(`
Array [
Array [
"SELECT * FROM item_translations WHERE item_id IN (?) AND locale = \\"en\\"",
Array [
"38912",
],
],
Array [
"SELECT * FROM pet_types WHERE (species_id = ? AND color_id = ?)",
Array [
"1",
"8",
],
],
Array [
"SELECT sa.*, rel.parent_id FROM swf_assets sa
INNER JOIN parents_swf_assets rel ON
rel.parent_type = \\"Item\\" AND
rel.swf_asset_id = sa.id
WHERE (rel.parent_id = ? AND (sa.body_id = ? OR sa.body_id = 0))",
Array [
"38912",
"93",
],
],
]
`);
});
it("skips appearance data for audio assets", async () => { it("skips appearance data for audio assets", async () => {
const res = await query({ const res = await query({
query: gql` query: gql`