diff --git a/packages/game/JSExport/GameInterface.cs b/packages/game/JSExport/GameInterface.cs index 5bcfbc42e..8dabdc292 100644 --- a/packages/game/JSExport/GameInterface.cs +++ b/packages/game/JSExport/GameInterface.cs @@ -240,14 +240,16 @@ public partial class GameInterface if (dataTable == null) { - throw new ArgumentException($"Unknown tank part: {part}"); + Console.WriteLine($"Unknown tank part (no matching data table): {part}"); + return []; } dataTable.TryGetDataTableRow(part, StringComparison.Ordinal, out var row); if (row == null) { - throw new ArgumentException($"Unknown tank part: {part}"); + Console.WriteLine($"Unknown tank part (no matching row): {part}"); + return []; } var visualData = row.Get("VisualData"); diff --git a/packages/website-ue/src/api/bufferProxy.ts b/packages/website-ue/src/api/bufferProxy.ts new file mode 100644 index 000000000..3b31a3cea --- /dev/null +++ b/packages/website-ue/src/api/bufferProxy.ts @@ -0,0 +1,20 @@ +import { notFoundResponse } from "./responses"; + +const cache = new Map>(); + +export function bufferProxy(cook: () => number[], key: string) { + let array = cache.get(key); + + if (array === undefined) { + const bytes = cook(); + array = new Uint8Array(bytes); + + if (import.meta.env.DEV) { + cache.set(key, array); + } + } + + if (array.length === 0) return notFoundResponse; + + return new Response(array); +} diff --git a/packages/website-ue/src/api/imageProxy.ts b/packages/website-ue/src/api/imageProxy.ts index 6097b42c0..65bc4ec97 100644 --- a/packages/website-ue/src/api/imageProxy.ts +++ b/packages/website-ue/src/api/imageProxy.ts @@ -1,4 +1,5 @@ import sharp from "sharp"; +import { bufferProxy } from "./bufferProxy"; export async function imageProxy(url: string) { if (import.meta.env.DEV) { diff --git a/packages/website-ue/src/pages/[media]/consumables/[id].webp.ts b/packages/website-ue/src/pages/[media]/consumables/[id].webp.ts index 5e9961f77..f00338701 100644 --- a/packages/website-ue/src/pages/[media]/consumables/[id].webp.ts +++ b/packages/website-ue/src/pages/[media]/consumables/[id].webp.ts @@ -4,6 +4,7 @@ import { mixStaticPaths } from "../../../astro/mixStaticPaths"; import { game } from "../../../game/game"; import { getStaticPaths as _getStaticPaths } from "../_index"; import { assertDiscoveryTag } from "../../../game/assertDiscoveryTag"; +import { bufferProxy } from "../../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, () => { return api.metadata @@ -11,13 +12,10 @@ export const getStaticPaths = mixStaticPaths(_getStaticPaths, () => { .map(({ id }) => ({ params: { id } })); }); - export function GET({ params }: APIContext) { const item = api.metadata.item(params.id); const assetsDiscovery = item.BlitzStaticAssetsDiscovery(); const tag = assertDiscoveryTag(assetsDiscovery); - const icon = game!.consumableIcon(tag); - const array = new Uint8Array(icon); - return new Response(array); + return bufferProxy(() => game!.consumableIcon(tag), `consumable-icon-${tag}`); } diff --git a/packages/website-ue/src/pages/[media]/equipment/[id].webp.ts b/packages/website-ue/src/pages/[media]/equipment/[id].webp.ts index f92c338f9..0d02c16a5 100644 --- a/packages/website-ue/src/pages/[media]/equipment/[id].webp.ts +++ b/packages/website-ue/src/pages/[media]/equipment/[id].webp.ts @@ -5,6 +5,7 @@ import { mixStaticPaths } from "../../../astro/mixStaticPaths"; import { game } from "../../../game/game"; import { getStaticPaths as _getStaticPaths } from "../_index"; import { assertDiscoveryTag } from "../../../game/assertDiscoveryTag"; +import { bufferProxy } from "../../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, () => { return api.metadata @@ -20,8 +21,6 @@ export function GET({ params }: APIContext) { const item = api.metadata.item(params.id); const assetsDiscovery = item.BlitzStaticAssetsDiscovery(); const tag = assertDiscoveryTag(assetsDiscovery); - const icon = game!.equipmentIcon(tag); - const array = new Uint8Array(icon); - return new Response(array); + return bufferProxy(() => game!.equipmentIcon(tag), `equipment-icon-${tag}`); } diff --git a/packages/website-ue/src/pages/[media]/flags/cards/[id].webp.ts b/packages/website-ue/src/pages/[media]/flags/cards/[id].webp.ts index 7cd9dba42..b93c73f42 100644 --- a/packages/website-ue/src/pages/[media]/flags/cards/[id].webp.ts +++ b/packages/website-ue/src/pages/[media]/flags/cards/[id].webp.ts @@ -5,6 +5,7 @@ import { mixStaticPaths } from "../../../../astro/mixStaticPaths"; import { game } from "../../../../game/game"; import { clientUnmounted } from "../../../../game/unmounted"; import { getStaticPaths as _getStaticPaths } from "../../_index"; +import { bufferProxy } from "../../../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => { return Object.values(Nation) @@ -20,7 +21,6 @@ export async function GET({ params }: APIContext) { const enumName = Nation[Number(params.id)]; const nationName = enumName.replace("NATION_", "").toLowerCase(); - const flag = game!.flag(nationName); - return new Response(new Uint8Array(flag)); + return bufferProxy(() => game!.flag(nationName), `flag-card-${nationName}`); } diff --git a/packages/website-ue/src/pages/[media]/tanks/big/[id].webp.ts b/packages/website-ue/src/pages/[media]/tanks/big/[id].webp.ts index 499500f26..dadafa89e 100644 --- a/packages/website-ue/src/pages/[media]/tanks/big/[id].webp.ts +++ b/packages/website-ue/src/pages/[media]/tanks/big/[id].webp.ts @@ -6,6 +6,7 @@ import { assertDiscoveryTag } from "../../../../game/assertDiscoveryTag"; import { game } from "../../../../game/game"; import { clientUnmounted } from "../../../../game/unmounted"; import { getStaticPaths as _getStaticPaths } from "../../_index"; +import { bufferProxy } from "../../../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => { const { list } = await api.tankList(); @@ -18,8 +19,6 @@ export async function GET({ params }: APIContext) { const item = api.metadata.item(params.id); const assetDiscovery = item.BlitzStaticAssetsDiscovery(); const tag = assertDiscoveryTag(assetDiscovery); - const icon = game!.tankBigIcon(tag); - const array = new Uint8Array(icon); - return new Response(array); + return bufferProxy(() => game!.tankBigIcon(tag), `tank-icon-big-${tag}`); } diff --git a/packages/website-ue/src/pages/[models]/tanks/[id]/[part].glb.ts b/packages/website-ue/src/pages/[models]/tanks/[id]/[part].glb.ts index 82ba47521..7b1c95887 100644 --- a/packages/website-ue/src/pages/[models]/tanks/[id]/[part].glb.ts +++ b/packages/website-ue/src/pages/[models]/tanks/[id]/[part].glb.ts @@ -5,6 +5,7 @@ import { mixStaticPaths } from "../../../../astro/mixStaticPaths"; import { getStaticPaths as _getStaticPaths } from "../../_index"; import { assertDiscoveryTag } from "../../../../game/assertDiscoveryTag"; import { game } from "../../../../game/game"; +import { bufferProxy } from "../../../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, async () => { const tanks = await api.tanks(); @@ -36,8 +37,9 @@ export async function GET({ const item = api.metadata.item(params.id); const assetDiscovery = item.BlitzStaticAssetsDiscovery(); const tag = assertDiscoveryTag(assetDiscovery); - const bytes = game!.tankPart(tag, params.part); - const array = new Uint8Array(bytes); - return new Response(array); + return bufferProxy( + () => game!.tankPart(tag, params.part), + `tank-part-${tag}-${params.part}`, + ); } diff --git a/packages/website-ue/src/pages/[textures]/[name].webp.ts b/packages/website-ue/src/pages/[textures]/[name].webp.ts index 0287eff2e..ad49399a9 100644 --- a/packages/website-ue/src/pages/[textures]/[name].webp.ts +++ b/packages/website-ue/src/pages/[textures]/[name].webp.ts @@ -2,13 +2,15 @@ import type { APIContext } from "astro"; import { mixStaticPaths } from "../../astro/mixStaticPaths"; import { game } from "../../game/game"; import { getStaticPaths as _getStaticPaths } from "./_index"; +import { bufferProxy } from "../../api/bufferProxy"; export const getStaticPaths = mixStaticPaths(_getStaticPaths, () => { return game!.textures.map((name) => ({ params: { name } })); }); export function GET({ params }: APIContext) { - const image = game!.texture(params.name); - const array = new Uint8Array(image); - return new Response(array); + return bufferProxy( + () => game!.texture(params.name), + `texture-${params.name}`, + ); }