This document explains how this RME fork exports Cyclopedia house data, map data, minimap assets, and satellite assets.
For follow-up performance work that intentionally stays outside the compatibility contract, see cyclopedia-export-roadmap.md.
Scope:
staticdata-<sha256>.datstaticmapdata-<sha256>.datmap-<sha256>.datminimap-<scale>-<chunk_x>-<chunk_y>-<floor>-<sha256>.bmp.lzmasatellite-<scale>-<chunk_x>-<chunk_y>-<floor>-<sha256>.bmp.lzma- integration through
catalog-content.json
Main code references:
source/protobuf/staticdata.protosource/protobuf/staticmapdata.protosource/protobuf/mapdata.protosource/iomap_otbm.cppIOMapOTBM::saveStaticData(...)IOMapOTBM::saveCyclopediaMapData(...)IOMapOTBM::serializeCyclopediaMapData(...)mergeStaticDataTemplate(...)buildStaticMapHouseTemplate(...)buildStaticMapHousePreviewData(...)buildStaticMapHouseTemplates(...)
The Cyclopedia export is split into two user-facing flows:
- Static house export writes
staticdataandstaticmapdata. - Cyclopedia map export writes
mapdataand its referenced minimap/satellite assets.
In the client, Cyclopedia combines:
- static house data (
staticdata+staticmapdata) - map data and map assets (
mapdata+minimap/satellite) - dynamic state from the server, such as house auctions, status, and bids
Data files are written under the selected assets directory and referenced by catalog-content.json.
Catalog entries managed by the exporter:
type: "staticdata"points tostaticdata-<sha256>.dat.type: "staticmapdata"points tostaticmapdata-<sha256>.dat.type: "map"points tomap-<sha256>.dat.
Minimap and satellite files are not listed directly in catalog-content.json. They are referenced by MapData.mapassets inside map-<sha256>.dat.
Important rules:
- the hash in every hash-named data filename must match the file content.
- template files are rejected when their filename hash does not match their content.
- the default template lookup names are
staticdata.dat,staticmapdata.dat, andmap.dat, but final written files use hash-named filenames. - existing replaced files are moved to a timestamped snapshot under
bkpsbefore the new file is written. - backup snapshots are never overwritten; if two exports happen in the same second, a numeric suffix is added to the snapshot directory.
- when
mapdatais replaced, the previousmapdatafile and its referenced minimap/satellite assets are moved to the export snapshot. - template
SUBAREAassets are preserved in place because mergedmapdatakeeps referencing them. - if a preserved
SUBAREAasset is missing from the output assets directory, the exporter restores it from the newest matching backup snapshot or from the source client assets before writing the newmapdata. - before updating
catalog-content.json, every asset referenced by the finalmapdatamust exist in the output assets directory.
Contains per-house metadata:
- house id
- name
- city
- rent
- beds
- square meters
- flags
- anchor position
Primary uses:
- filling the Cyclopedia house list
- resolving static metadata by
houseId - serving as the base for id remapping during template merge
Legacy CIP-compatible house preview format:
house_iddata.origin (pos_x, pos_y, pos_z)data.dimensions (pos_x=width, pos_y=height, pos_z=floors)data.preview.layer.tile[]item[].value(item client ids)skip
Map data contains Cyclopedia map bounds and asset descriptors:
topleftedgebottomrightedgemapassets[]type(SUBAREA,MINIMAP, orSATELLITE)topleftfilenamewidthsquareheightsquarescale
The exporter scans floors 0..7 and emits minimap and satellite chunks for each floor that contains visible tile data. SUBAREA entries come from the template mapdata and are kept for client compatibility.
Current emitted scales:
1/64with1024square chunks and0.5pixels per square.1/32with512square chunks and1.0pixel per square.1/16with256square chunks and2.0pixels per square.
The same scale set is emitted for both minimap and satellite assets.
staticmapdata tiles are serialized linearly inside a width * height * floors volume.
Decoding:
linearIndexstarts at0.- each serialized entry represents the current cell.
- next index is
linearIndex = linearIndex + skip + 1.
Index-to-local-coordinate mapping:
floorArea = width * heightfloor = linearIndex / floorAreaplaneIndex = linearIndex % floorAreax = planeIndex / heighty = planeIndex % height
Absolute world coordinate:
worldX = origin.x + xworldY = origin.y + yworldZ = origin.z + floor
Static house export:
- load
staticdataandstaticmapdatatemplates when they are available. - serialize current map house data.
- merge generated
staticdatawith the template only when at least one current-map house matches it. - build house preview templates from template
staticmapdataonly for compatible template exports. - export each house preview while preserving template framing when available, otherwise use dynamic map framing.
- write hash-named final files and update
catalog-content.json.
Cyclopedia map export:
- load the existing
maptemplate when available. - scan map bounds across floors
0..7. - render minimap chunks from tile minimap colors.
- render satellite chunks for Surface View from the actual tile sprite stack, with minimap colors used only as fallback terrain.
- write each chunk as BMP bytes inside the CIP LZMA asset container.
- merge compatible template
mapdatafields. - write hash-named
map-<sha256>.dat, write referenced assets, and updatecatalog-content.json.
Compatibility details currently applied:
- no per-tile house/context mask is serialized in the compatibility export.
- when a valid house template is present, template framing (
origin/dimensions/skip) is preserved. - template item payload can be preserved to keep visual parity with the CIP client.
- dynamic fallback is used for custom maps or houses without a matching template entry.
- minimap sea/background pixels use the Cip minimap water color
(51, 102, 153). - minimap downscaling uses weighted averaging to avoid checker/pixel aliasing.
- minimap upscaling stays nearest-neighbor to keep tile-aligned pixels.
- Surface View must be emitted as
SATELLITEassets; minimap colors are only used as a fallback behind sprite pixels. - Surface View draws the ground, border, and item sprites in tile draw order so the exported map stays close to CipSoft's surface view.
- Surface View sprites are composed on a transparent intermediate image; satellite sea color is only applied to pixels that remain empty on the ground layer.
- downscaling preserves alpha during sampling, then exported Surface View pixels that contain sprite data are resolved as opaque so the client does not tint them with the sea/background color.
Logical flow:
- client loads
staticdata,staticmapdata, andmapfrom assets. mapdatapoints the client to minimap and satellite chunk filenames.- server sends dynamic house list/state using house ids.
- client matches dynamic
houseIdwith static metadata/preview. - house preview is decoded via
origin + dimensions + tile/skip/item. - map chunks are rendered from
MapData.mapassetsusingtopleft,widthsquare,heightsquare, andscale;MINIMAPfeeds Map View andSATELLITEfeeds Surface View. - external house context (
outside/blur background) is rendered in a separate pass, aligned to the same preview frame.
Key point:
- outside blur/context depends on correct house framing.
- if
origin/dimensionsdiverge from the expected CIP frame, context appears stretched, shifted, or out-of-scale. - if minimap chunks are downscaled by nearest-neighbor sampling, large areas can look checker-patterned or overly pixelated.
House preview symptom:
- house tiles look mostly correct, but outside blur/context has wrong scale/alignment.
Typical causes:
- exported
staticmapdatahasorigin/dimensionsdifferent from the CIP template. - template file was loaded from a hash-mismatched asset.
Map asset symptom:
- exported minimap appears checker-patterned or too pixelated.
Typical causes:
- downscaled minimap chunks used point sampling instead of averaging.
- the
1/16layer was not emitted, forcing the client to magnify a lower-resolution layer.
Current exporter protections:
- validates embedded hash in data filenames.
- rejects invalid templates.
- tries a hash-valid sibling template when available.
- falls back to current-map dynamic export when no compatible template is found.
- skips out-of-bounds map coordinates before tile lookup so preview and map asset scans cannot alias negative coordinates into high map regions.
- ignores tiles whose minimap color is
0so they do not overwrite the chunk background with black pixels. - writes filenames whose embedded hash matches the generated content.
- emits
1/64,1/32, and1/16minimap/satellite layers. - stores backups in timestamped
bkps/export-*snapshots instead of replacing an existing.bkpfile. - provides a
File > Client Assets > Restore Client Assets Backupmenu action that restores a selected snapshot and first moves overwritten current files into abkps/restore-*safety snapshot. - uses
GameSprite::getSpriteID(...)for exported sprite image lookup;GameSprite::getHardwareID(...)is a GL texture/atlas id and must not be serialized or used as an asset sprite id. - preserves full-size sprite images for export sampling so multi-tile sprites can be sampled with draw offsets instead of being cropped to one tile.
- verify final data file hashes.
sha256sum assets/staticmapdata-<hash>.dat
sha256sum assets/staticdata-<hash>.dat
sha256sum assets/map-<hash>.dat-
computed hash must match
<hash>in each data filename. -
verify
catalog-content.jsonreferences the currentstaticdata,staticmapdata, andmapfiles. -
inspect
map-<hash>.datand verify eachMapData.mapassets[].filenameexists under the assets directory. -
validate reference houses in client:
4050340211405101030110302
- if house preview mismatch appears, compare:
origindimensions- serialized tile count
skipprogression semantics
- if map image mismatch appears, compare:
- emitted scale list
topleftwidthsquareheightsquare- generated chunk filename
- BMP dimensions after LZMA decode
- use hash-valid CIP templates for original CIP-compatible maps.
- do not reintroduce per-tile house/context mask serialization in the compatibility path.
- do not shift template framing during merge/remap.
- keep linear decode semantics (
+ skip + 1). - keep custom-map exports independent from unmatched CIP templates.
- keep minimap and satellite
mapassetsmetadata aligned with the generated chunk dimensions. - keep the
1/16layer when changing map asset generation. - keep Surface View sprite-based: draw ground, borders, and items into
SATELLITEassets in tile draw order, using minimap colors only as fallback terrain. - do not use GL texture/atlas ids as exported sprite ids; use
GameSprite::getSpriteID(...). - validate changes on a real CIP-compatible client after exporter modifications.
Cyclopedia quality depends on:
- correct static files (
staticdata+staticmapdata). - correct map files (
mapdata+ referenced minimap/satellite assets). - CIP-preserving house framing (
origin/dimensions/skip) so house and outside context share the same projection space. - complete, correctly scaled map asset layers so the client does not over-magnify a lower-resolution chunk.
When export preserves this contract, house geometry, outside blur/context, minimap, and satellite chunks align with expected CIP behavior.