050b8251a7
ci / verify (push) Successful in 48s
Four always-on-screen slots, items as data, and loot tables on enemies and bosses. Health potions drop rarely from trash and always from the Warden; the Warden also drops a Warden's Ration, one per living player, which does nothing at all. The ration is not filler. Player-instanced loot is a separate code path from shared loot -- a distinct entity per owner, filtered per peer in the snapshot encoder -- and the cheapest way to keep that path honest is to have something in the game that exercises it on every boss kill. Item actions ride the input frame rather than becoming new client messages. InputFrame gained BTN_USE, BTN_DROP and a slot byte, which buys the packet-loss redundancy, the replay guard on last_input_tick, ordering against movement on the same tick, and a rate limit of one action per tick -- all of which a separate RPC would have needed bolted back on. The cost is that anything in the frame which must not repeat has to be edge-triggered, since frames are resent and a starved server coasts on the last one it holds. Instanced loot is enforced in NetCodec.encode_snapshot, beside the actor interest radius: a peer is never told another player's copy exists. Hiding it client-side would have been the same mistake as relying on fog to hide enemies. Inventories live on the character and are written to the store on every transaction, so a crash between "picked it up" and "wrote it down" cannot lose or duplicate an item. Anything dropped becomes world-shared whatever it was before, and a potion used at full health is refused rather than spent. tools/diag_loot.tscn covers drop -> snapshot -> pick up -> persist -> use -> drop plus both visibilities on the wire, for the same reason diag_progression exists: bots are poor shots and almost never produce a drop. It asserts each input frame was actually consumed, after an early version silently dropped its first press and every later check passed for the wrong reason. check.sh clean, 266 tests, SMOKE PASS, all three diagnostics green. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
113 lines
5.5 KiB
Markdown
113 lines
5.5 KiB
Markdown
# Asset packs and attribution
|
|
|
|
The packs themselves are **not in git** (see
|
|
[`assetpacks/README.md`](../assetpacks/README.md)), which means their bundled
|
|
licence files are not either. This file is the record that survives. Keep it
|
|
current when a pack is added or removed.
|
|
|
|
## How assets get from a pack into the game
|
|
|
|
`assetpacks/` carries a `.gdignore`, so Godot skips it entirely — nothing there
|
|
can be referenced from a scene or script. Files are copied into `res://assets/`
|
|
in game-ready form, and only then imported. The tree is 3.9 GB and
|
|
`tools/check.sh` runs `--import`, which would otherwise walk all of it every run.
|
|
|
|
What is in the game today totals **548 KB** across seven files: three sprite
|
|
sheets and four sounds. Sprite rects and sound paths are all declared in one
|
|
place, [src/view/art.gd](../src/view/art.gd), and
|
|
`tests/unit/test_art.gd` asserts every rect lands inside its texture — a wrong
|
|
atlas coordinate does not error, it silently draws the wrong pixels.
|
|
|
|
## Licence findings
|
|
|
|
Checked against each pack's itch.io page. **Two of the four forbid
|
|
redistribution**, which is what publishing a repository containing them would
|
|
be — so they are not in the repository.
|
|
|
|
| Pack | Licence | Commercial | Credit | In this repo? |
|
|
| --- | --- | --- | --- | --- |
|
|
| [0x72 DungeonTileset II](https://0x72.itch.io/dungeontileset-ii) | **CC0 1.0** (public domain) | Yes | Not required | **Yes** — `assets/sprites/dungeon_tileset.png` |
|
|
| [Helton Yan Pixel Combat](https://heltonyan.itch.io/pixelcombat) | **CC BY 4.0** | Yes | **Required** | **Yes** — `assets/audio/sfx/` |
|
|
| [Fire Pixel Bullet 16x16](https://bdragon1727.itch.io/fire-pixel-bullet-16x16) | Custom | Free tier non-commercial; **paid tier allows commercial** | Encouraged | **No, at any tier** — local only |
|
|
| [750+ Effect and FX Pixel All](https://bdragon1727.itch.io/750-effect-and-fx-pixel-all) | Custom | Free tier non-commercial; **paid tier allows commercial** | Encouraged | **No, at any tier** — local only |
|
|
|
|
### The blocking clause
|
|
|
|
Both bdragon1727 packs state, verbatim:
|
|
|
|
> **You cannot do:** Resell / redistribute this asset.
|
|
|
|
And the paid tier of the FX pack is no better for this purpose:
|
|
|
|
> You can NOT re-distribute the file, no matter how much you modify it you can
|
|
> use it but not share or re-sell it.
|
|
|
|
Putting those files in a public repository distributes them to everyone who
|
|
clones it, which is squarely what that forbids. Paying for the commercial tier
|
|
does **not** unlock it — the restriction survives payment and survives
|
|
modification.
|
|
|
|
So they live in `assets/local/`, which is gitignored. `Art.bullets_texture()`
|
|
and `Art.impact_texture()` load them at runtime if present and return null if
|
|
not; the bullet renderer falls back to a generated dot. Verified both ways: with
|
|
the files present the game uses them, and with them hidden the suite still
|
|
passes 156/156 and the game runs.
|
|
|
|
This is also why nothing there may be `preload()`ed — `preload` resolves at
|
|
compile time and would fail the build on every machine that lacks the files.
|
|
|
|
### Two obligations this creates
|
|
|
|
1. **Helton Yan's CC BY 4.0 requires attribution**, and it is not satisfied by
|
|
a file in the source tree once the game ships. Players need to be able to
|
|
see it. [CREDITS.md](../CREDITS.md) records it for now; an in-game credits
|
|
screen is a todo.
|
|
2. **Both bdragon packs are non-commercial in their free tier.** Buying the
|
|
full tier *does* fix that — confirmed verbatim from the FX pack's paid
|
|
licence: "You may use these assets in personal, commercial or
|
|
non-commercial projects."
|
|
|
|
It does **not** fix the repository problem. The paid licence's very next
|
|
sentence is: "You can NOT re-distribute the file, no matter how much you
|
|
modify it you can use it but not share or re-sell it." Redistribution is
|
|
forbidden at every tier, so paying moves these assets from
|
|
*local-only-and-non-commercial* to *local-only-and-commercial*. They cannot
|
|
be committed to a public repo at any price.
|
|
|
|
The only route that puts bullet and FX art back into the repository is
|
|
replacing it with something permissive (CC0, or CC BY with attribution),
|
|
which would also remove the local-asset fallback machinery.
|
|
|
|
### Not in use
|
|
|
|
`assetpacks/considering_dont_use_yet/` is the "not chosen" marker and nothing
|
|
there is referenced. It contains RF Catacombs v1.0 (public domain per its
|
|
bundled `public-license.txt` — free for personal or commercial use, credit
|
|
appreciated, no reselling; artwork by Szadi art), plus Tiny RPG Character Pack
|
|
02 and neo_zero demos, whose terms are unrecorded.
|
|
|
|
## Converting audio before use
|
|
|
|
Helton Yan's pack is 24-bit / 96 kHz stereo — studio masters, averaging ~2 MB
|
|
per file and 5 MB at the largest. That is roughly a hundred times what a game
|
|
needs for a gunshot.
|
|
|
|
Downsample to 16-bit / 44.1 kHz mono before copying anything into
|
|
`res://assets/`. Godot imports `.wav` losslessly and keeps it in memory
|
|
uncompressed for low-latency playback, so the source format is what you pay for
|
|
in RAM and in export size.
|
|
|
|
## Where converted assets go
|
|
|
|
`res://assets/`, which is committed and imported. See
|
|
[`assets/README.md`](../assets/README.md). Art is Stage 2 in
|
|
[ROADMAP.md](ROADMAP.md); everything currently on screen is drawn from
|
|
primitives plus one runtime-generated dot texture.
|
|
|
|
## Placeholder art worth revisiting
|
|
|
|
- **Warden's Ration** draws as a gold flask (`Art.ITEM_ICONS[1]`). The 0x72
|
|
tileset has no food sprite, and the item is deliberately useless flavour, so a
|
|
recoloured flask stands in until the art pass. It reads as a potion, which is
|
|
the wrong thing for it to read as.
|