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:
parent
574199575b
commit
b7c958c39b
3 changed files with 107 additions and 25 deletions
|
@ -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 }));
|
||||||
},
|
},
|
||||||
|
|
|
@ -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) => {
|
||||||
|
|
|
@ -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`
|
||||||
|
|
Loading…
Reference in a new issue