144 lines
4.8 KiB
Markdown
144 lines
4.8 KiB
Markdown
# sprite-catalog
|
|
|
|
The sprite catalog that drives trade matching and giveaways in the Sprites Trading HQ
|
|
Discord server. One JSON file per season, validated against a JSON Schema.
|
|
|
|
This repo is **data, not code**. It is public so anyone can read it, build against it,
|
|
or run their own bot from it.
|
|
|
|
---
|
|
|
|
## Why JSON
|
|
|
|
The catalog is a public data source other people consume. JSON is readable in every
|
|
language and in the browser with zero dependencies; YAML needs a parser everywhere.
|
|
|
|
JSON's one real weakness for a hand-maintained file is that it has no comments and is
|
|
unforgiving about syntax. Both are covered: the schema in [`schema/`](schema/) gives
|
|
editors autocomplete and inline validation as you type, CI rejects malformed files
|
|
before merge, and every object accepts a `notes` field for anything you would otherwise
|
|
have written as a comment.
|
|
|
|
---
|
|
|
|
## Layout
|
|
|
|
```
|
|
schema/sprite-catalog.schema.json the contract — CI and editors both use it
|
|
seasons/c7s3.json one file per season, named for the season
|
|
seasons/c7s4.json
|
|
```
|
|
|
|
Season files are **append-mostly**. Entries are never deleted — a sprite that leaves
|
|
circulation gets `"status": "hidden"`, which drops it out of matching while keeping it
|
|
in the inventories of everyone who already holds one.
|
|
|
|
---
|
|
|
|
## Format
|
|
|
|
Variants nest under their base sprite so `base_name` and `row_name` aren't repeated for
|
|
every skin. The bot flattens this to one row per variant on load.
|
|
|
|
```json
|
|
{
|
|
"season": "c7s3",
|
|
"game_mode": "br",
|
|
"cross_mode_trading": false,
|
|
"sprites": [
|
|
{
|
|
"base_name": "Example Sprite",
|
|
"row_name": "Example Row",
|
|
"variants": [
|
|
{
|
|
"variant": "Default",
|
|
"status": "released",
|
|
"released_at": "2026-03-14",
|
|
"max_stack": 5,
|
|
"confirmed": true
|
|
},
|
|
{
|
|
"variant": "Gold",
|
|
"status": "unreleased",
|
|
"notes": "Datamined; not yet obtainable in game."
|
|
}
|
|
]
|
|
}
|
|
]
|
|
}
|
|
```
|
|
|
|
### The three statuses
|
|
|
|
| Status | Meaning |
|
|
|---|---|
|
|
| `unreleased` | Known but not yet obtainable. Excluded from matching. |
|
|
| `released` | Obtainable and tradeable. |
|
|
| `hidden` | Dropped out of matching, retained in inventories. **Reversible.** |
|
|
|
|
`hidden` deliberately replaces a `retired` concept that appeared in earlier drafts.
|
|
Sprites usually come back, and if one never does, nothing is lost by having called it
|
|
hidden — whereas `retired` implies a permanence the data can't promise.
|
|
|
|
### Fields worth explaining
|
|
|
|
- **`confirmed`** — variant lists are assumed-complete guesses until someone is actually
|
|
recorded owning one. Unconfirmed variants are deprioritised in autocomplete and left
|
|
out of the coverage metric, so a speculative entry can't quietly distort either.
|
|
- **`rarity_weight`** — display and analytics only. **The matcher does not read it.**
|
|
Rarity matching was removed on purpose: value-matching is how selfish players win and
|
|
the pool starves. Trades are N-for-N by count, never by value.
|
|
- **`max_stack`** — anything above 1 means spare copies can enter the give pool.
|
|
- **`cross_mode_trading`** — defaults to `false`. Leave it there unless the policy is
|
|
deliberately changed.
|
|
|
|
---
|
|
|
|
## Contributing
|
|
|
|
1. Fork or branch, edit the season file.
|
|
2. Open a PR. CI validates every file in `seasons/` against the schema and fails on
|
|
malformed JSON, unknown fields, bad status values, or a `season` value that doesn't
|
|
match the filename.
|
|
3. A mod merges. The bot picks it up on the next `/mod catalog reload`, which shows a
|
|
diff preview ("adds 6 sprites, 14 variants, no removals — apply?") before anything
|
|
is written.
|
|
|
|
The bot's exporter opens a draft PR automatically when it sees a sprite ID it doesn't
|
|
recognise, so most additions start here rather than being typed by hand.
|
|
|
|
**Editor setup** — point your editor at `schema/sprite-catalog.schema.json` and you get
|
|
completion and error squiggles inline. In VS Code, add to `.vscode/settings.json`:
|
|
|
|
```json
|
|
{
|
|
"json.schemas": [
|
|
{ "fileMatch": ["seasons/*.json"], "url": "./schema/sprite-catalog.schema.json" }
|
|
]
|
|
}
|
|
```
|
|
|
|
---
|
|
|
|
## Consuming it
|
|
|
|
The bot fetches raw files over HTTP and caches them in memory — autocomplete has a hard
|
|
3-second budget with no defer available, so it never queries a database per keystroke.
|
|
|
|
The raw URL is configurable via `CATALOG_REPO_RAW`, so you can point a development bot
|
|
at your own fork without touching code:
|
|
|
|
```
|
|
CATALOG_REPO_RAW=https://git.thewichersfamily.com/thethreemagi/sprite-catalog/raw/branch/main
|
|
```
|
|
|
|
Nothing about the format is bot-specific. Fetch the JSON and use it however you like.
|
|
|
|
---
|
|
|
|
## Note on history
|
|
|
|
Commits here carry no AI attribution — see [`.githooks/commit-msg`](.githooks/commit-msg),
|
|
enabled with `git config core.hooksPath .githooks && chmod +x .githooks/commit-msg`.
|
|
Please keep it that way in PRs.
|