[2026] consumables

This commit is contained in:
Devin Zuczek
2026-10-13 14:37:37 -04:00
parent 33d235f8ad
commit ba6c703050
3 changed files with 7589 additions and 10 deletions
+9 -8
View File
@@ -42,6 +42,7 @@ import { censorSwears } from '../../api/src/sanitize'
import { BalanceAddType } from '../../notify/src/notification-payloads'
import { NotificationType } from '../../notify/src/notification-types'
import adCarouselItems from '../static/ad-carousel-items.json'
import consumableDefinitions from '../static/consumables.json'
import defaultAvatarItems from '../static/default-avatar-items.json'
import defaultAvatar from '../static/default-avatar.json'
import defaultBaseAvatarItems from '../static/default-base-avatar-items.json'
@@ -4976,19 +4977,19 @@ const app = new Hono<App>({ strict: false })
)
// The consumable DEFINITIONS the client knows how to use (`?supportedVersion=2`), as
// opposed to the ones a player owns. A stub: none are served yet, so the list is empty.
// A real row is `{ ConsumableItemDesc, InitialCount, CreatedAt, ThumbnailImageName,
// FriendlyName, RoomieCategory, ConsumableToolName, ConfigurationData }`, where
// `ConfigurationData` is JSON escaped into a STRING (`"{\"MeshConfigurationData\":null,…}"`).
// opposed to the ones a player owns. Served verbatim from `static/consumables.json`, the
// live game's list; `supportedVersion` is accepted and unused. A row's `ConfigurationData`
// is JSON escaped into a STRING (`"{\"MeshConfigurationData\":null,…}"`), or null.
.get(
'/api/consumables/v1/all',
describeRoute({
tags: ['Consumables'],
summary: 'All consumable definitions (stub)',
description: 'Always [] — no consumable definitions are served yet.',
responses: { 200: json(JsonArray, 'The consumable definitions (always empty)') },
summary: 'All consumable definitions',
description:
'Every consumable definition, verbatim from static/consumables.json. supportedVersion is ignored.',
responses: { 200: json(JsonArray, 'The consumable definitions') },
}),
(c) => c.json([])
(c) => c.json(consumableDefinitions)
)
// Unlocked consumables. [Authorize]. The consumables the player has bought (from
+12 -2
View File
@@ -3772,10 +3772,20 @@ describe('econ endpoints', () => {
}
})
test('GET /api/consumables/v1/all is a stub: returns []', async () => {
test('GET /api/consumables/v1/all serves the consumable definitions', async () => {
const res = await exports.default.fetch(`${ORIGIN}/api/consumables/v1/all?supportedVersion=2`)
expect(res.status).toBe(200)
expect(await res.json()).toEqual([])
const body = await res.json<Array<Record<string, unknown>>>()
expect(body.length).toBeGreaterThan(0)
expect(body[0]).toMatchObject({
ConsumableItemId: 1,
ConsumableItemDesc: 'frOMH6WxDEG1fBqC4_83vg',
FriendlyName: 'Black & White Camera Film',
})
// ConfigurationData is JSON escaped into a string (or null), never a nested object.
for (const item of body) {
expect(item.ConfigurationData === null || typeof item.ConfigurationData === 'string').toBe(true)
}
})
test('GET /api/consumables/v2/getUnlocked 401s without a token, returns []', async () => {