UO-style binary asset container for human art (.idx + .bin) #2
Labels
No labels
alpha:wave-0
alpha:wave-1
alpha:wave-2
alpha:wave-3
area:assets
area:combat
area:ecology
area:infra
area:render
area:scripting
area:ui
area:world
enhancement
epic
migration
post-alpha
roadmap
tech-debt
type:bug
type:chore
type:design
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
marco/IsoMmo#2
Loading…
Reference in a new issue
No description provided.
Delete branch "%!s()"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
Replace the loose per-frame PNGs in
assets/human/with our own indexed binary container, in the spirit of Ultima Online'sanim.mul+anim.idx. Follow-up carved out of #1 (MonoGame migration) to keep that issue focused.Why
The MonoGame client currently loads human sprites as loose PNGs (
{action}_{dir}_{i}.png) viaTexture2D.FromStreamat runtime. That works, but:HumanArt.AnchorX=64,AnchorY=120) for every frame. Legacy UO art carries a real draw offset per frame; discarding it is a latent sprite-alignment bug. A container can store the true anchor alongside each frame.new Texture2D(w,h); SetData(pixels)), ships as one atomic file, and is deterministic across platforms.This is intentionally NOT PNGs concatenated together — the point is raw pixel blocks + a metadata index, so no image codec runs at runtime.
Prerequisite from #1
The MonoGame client loads human art behind a small interface (asset loader /
IHumanArtSource), so the container can slot in without touching rendering. Verify that seam exists before starting.Scope
(action, direction, frame)each carrying{offset, length, width, height, anchorX, anchorY}, and a payload of raw RGBA (MonoGameColororder) pixel blocks. Decide single-file vs.idx+.bin, and whether payload is Deflate-compressed.--packmode totools/IsoMmo.AssetExtractorthat writes the container from the legacy anim.mul, capturing the real per-frame draw offset as the anchor. Keep (or gate) a PNG-export mode for inspection/debugging.Texture2Dper frame viaSetData, expose per-frame anchor to the renderer.AnchorX/AnchorYconstants.Out of scope
Server, protocol, auth, DB. Any art beyond the human body already handled by the extractor.
Definition of Done
Delta beyond the base DoD (tests green, whole solution builds, zero warnings, multi-platform preserved):
--packmode against a realD:\Games\UOinstall produces the container, and the client renders human sprites from it in all 8 directions with correct facing/mirroring — visually indistinguishable from the loose-PNG path it replaces.(64,120)lands in the visually correct position, and this is called out in the verification notes.SetData, notTexture2D.FromStream).Design agreed — single-file
.isoacontainer (manifest + raw-pixel blob)Generalizing this beyond human art to all sprite assets (human, creatures, statics, land).
Format
[magic "ISOA"][version:int][manifestLen:int][manifest JSON utf8][raw-pixel blob]— glTF-style: inspectable JSON metadata + a binary buffer of raw RGBA32 pixels (no runtime image codec, per the original reasoning). Manifest = named animations, each{ name, fps, frames:[{offset,length,width,height,anchorX,anchorY}] }; a static/land tile is a 1-frame animation. Per-frame anchors are preserved (fixes the current single-hardcoded-anchor latent bug). Versioned header so a stale pack from a teammate fails cleanly, not silently.Library
IsoMmo.Assets(pure .NET, no MonoGame dep):AssetPackmodel +AssetPackFile.Read/Write. Referenced by client, extractor and the editor. Round-trip unit-tested.Integration: the extractor writes
.isoapacks (it already decodes true per-frame anchors —AnimFrame.CenterX/Y— currently discarded); the client's Human/Static/Land loaders read from packs; the loose-PNG path is removed. Rendering starts honoring per-frame anchors (visible alignment change to verify).Copyright note (unchanged)
A pack of UO-derived pixels is still not committable (repackaging ≠ ownership). Packs stay git-ignored and each dev regenerates from their own licensed client. A pack becomes committable/shareable only once it holds our own original art — which the editor (#NEW) enables.
Definition of Done (delta)
AssetPackFileround-trips a pack (metadata + anchors + exact pixels) in a unit test; a bad magic/version is rejected with a clear error..isoapacks for human, creatures, statics and land;just extract-allproduces them.Container part done and merged to main (
e0f61f0). IsoMmo.Assets library + .isoa format (versioned magic+manifest+raw-RGBA blob, per-frame anchors, round-trip tested); extractor writes packs for human/creatures/statics/land (just extract-all); client loads them (per-frame anchors, placeholder fallback); loose-PNG shipping path removed. 161 tests green. Remaining under this issue was human-only; generalized to all categories. The graphical editor is tracked separately in #21.