Building Part Reference¶
TL;DR
parts/<name>.json holds the block grid itself: one chunk footprint, one floor level, 16 by 16 by 6. This is the file a schematic converter produces. See Editing and Tooling for ways to generate one without typing it, and Examples for a complete working part.
Keys¶
| Key | Required | Meaning code review |
|---|---|---|
xsize / zsize |
yes | The footprint size in blocks. Use 16 and 16. See the warning below. |
slices |
yes | The list of layers, bottom to top. Each layer is a list of row strings. |
refpalette |
no | The name of a shared palette. |
palette |
no | An embedded palette, used instead of refpalette. It is a whole palette asset, so the entry list nests under a second palette key. See below. |
meta |
no | A list of typed key and value pairs. The key is meta, not metadata. |
An embedded palette nests, and gets no error if it does not
This key is parsed with the palette asset's own codec, not as a list of entries. A palette file is {"palette": [ ... ]}, so an embedded one is nested the same way. code review
"palette": { "palette": [ { "char": "D", "block": "minecraft:diamond_block" } ] }
"palette": [ { "char": "D", "block": "minecraft:diamond_block" } ]
The bare list is the natural guess and it is not an error. The field decodes to nothing, the characters resolve to nothing, and the building's filler takes the part's whole volume. Measured on a character no other palette defines: 0 blocks written bare, 256 written nested, nothing logged either way. If the character also exists in the Style's palettes, both forms appear to work, which is what makes this hard to notice. game test
The shape of slices¶
slices holds one entry per Y layer. Each layer holds zsize strings, and each string is xsize characters long. Every character is a palette lookup. A space means air in practice, because the shipped common palette defines it that way. code review
{
"xsize": 4,
"zsize": 4,
"slices": [
[
"αααα",
"α α",
"α α",
"αααα"
]
]
}
That is one layer: a hollow 4 by 4 box made of whatever block α maps to.
A wrong row length produces a diagonal smear, not an error
The mod concatenates the rows of a layer into one flat string at load, then indexes them as row * xsize + column. Nothing verifies that a row is xsize characters long, or that a layer has zsize rows.
A row one character short pulls the next row's first character into its last slot. It shifts everything after it in that layer by one, which looks like a generation bug rather than a typo. If the whole layer ends up shorter than xsize * zsize, you get a string index crash during chunk generation instead. game test
The lookup is slices[y].charAt(z * xsize + x), so row breaks in the JSON are formatting only. A layer is one 256-character sequence, and a wrong length anywhere in it moves every character after that point. game test
Confirmed in game on 7.4.12, both directions: game test
| Layer total | Result game test |
|---|---|
| 257 characters, one row written 17 long | No error. A marker at the extra position was placed, one column further on, and the character at index 256 was never read. |
| 255 characters, one row written 15 long | The chunk fails with String index out of range: 255, which is the last position of a 16 by 16 layer. |
So too long is silent and too short is loud, and neither is caught by anything at load. game test
Count in UTF-16 code units, not characters. An emoji counts as two. See Palette: what counts as a valid character. game test
A footprint larger than 16 loads, then generates wrong
A part declaring xsize: 32 loads without complaint and then generates incorrectly. A write past column 15 wraps back into the same chunk instead of continuing into the next one, so an oversized part silently overwrites its own first columns. There is no error and nothing in the log.
To cover a larger area use a Multi-Building, which is the supported way to span several chunks. code review
Smaller than 16 is legal, and the mod relies on it
The mod iterates each part over its own xsize, zsize and slice count, so a part smaller than the chunk simply writes a smaller area. It is not corrupted, and it is not unsupported.
The mod's own building fronts are 2 by 16 and 3 by 16 strips, placed along one edge of a street chunk and rotated for each of the four sides. code review
The rule that matters is: never exceed 16, and match the footprint to the job. A part used where a full chunk is expected, such as a building floor or a street, should be 16 by 16, or it will cover only part of the chunk and leave the rest as it was. game test
Slices, floors and height¶
Each floor of a building occupies 6 blocks of vertical space, and the mod stacks parts at 6-block intervals. A part with more than 6 slices has its upper slices overwritten by the floor above. A part with fewer leaves a gap. Match your slice count to 6. code review
meta¶
Each entry is a key plus exactly one typed value: boolean, char, string, integer or float. The mod accepts an unknown key and ignores it, but five keys are real and read during generation. Two of them are mandatory for certain kinds of part, so meta is not optional decoration. code review
| Key | Type | Applies to | Effect code review |
|---|---|---|---|
support |
char | Highway and bridge parts | The palette character used for the support pillars underneath. |
z1 / z2 |
integer | Stair parts | The Z range along the part's edge that the staircase occupies. |
dontconnect |
boolean | Building floor parts | If true, the mod generates no doorways between this part and the neighbouring chunk. |
nowater |
boolean | Any part | If true, hard air stays dry below sea level instead of flooding. |
support¶
{ "meta": [ { "key": "support", "char": "v" } ] }
Where a highway or bridge crosses open space, the mod drops pillars of this character downward. It stops at the first non-empty block, or after 40 blocks, whichever comes first. The profile's highwaySupports and bridgeSupports suppress the pillars entirely. All 8 shipped highway and bridge parts use v. code review
An undefined support character fails the chunk
The mod throws Cannot find support block '<char>' for highway part '<name>'! when support names a character no palette in scope defines. Define the character, or remove the support meta. Omitting support is safe, and gives you a highway with nothing holding it up.
z1 and z2¶
{ "meta": [ { "key": "z1", "integer": 5 }, { "key": "z2", "integer": 10 } ] }
These mark where the staircase meets the chunk edge, so the street border in the adjacent chunk leaves a gap there instead of walling the stairs off. Both are Z coordinates from 0 to 15. The 4 shipped stair parts use 0 and 2, 13 and 15, 4 and 11, and 5 and 10. code review
A stair part without z1 and z2 fails the chunk
The mod throws NullPointerException when the neighbouring chunk works out its border. It reads both values into Integer and passes them straight into an int parameter, with no null check, so an absent key unboxes a null.
Any part you put in a city style's stairs selector must define both keys. game test
dontconnect¶
{ "meta": [ { "key": "dontconnect", "boolean": true } ] }
Set this on a floor part to suppress doorways between it and the neighbouring chunks, in both directions. All 14 shipped shopping* parts use it. They are interior mall sections, and they should connect only through their own openings rather than have generic doorways punched through them. game test
nowater¶
{ "meta": [ { "key": "nowater", "boolean": true } ] }
Hard air below the water level normally fills with water. nowater keeps it dry. All 3 shipped monorails_* parts use it, so a monorail crossing an ocean stays an open tube. code review
This is the per-part equivalent of the profile's avoidFoliage, without the cost to trees and flowers. See Profile. code review
Any other key¶
Any other key parses, is stored, and nothing in 7.4.12 reads it. A companion mod can read it, so it is a reasonable place to keep your own data. Do not expect the mod to act on it. code review
Two of the five value types are never read either
The codec accepts boolean, char, string, integer and float, but the mod only ever reads three of them. The five real keys use char (support), integer (z1, z2) and boolean (dontconnect, nowater).
Nothing in the mod calls the string or float accessors at all. Those two types exist for a reader that does not currently exist, so a string or float meta value is storage and nothing more. code review
Rotation¶
The mod does not always place a part the way you authored it. A building reuses one part on several sides of the same structure, and streets, highways and rails reuse a small set of shapes in whatever orientation an intersection needs. So the same part JSON is commonly placed rotated or mirrored. code review
Most blocks do not reorient when that happens. Only stairs and rails do by default. See Palette: rotation and the lostcities:rotatable tag if your part uses doors, furnaces, or any other block whose facing matters. game test
See also¶
- Building Reference for how the mod selects parts
- Palette Reference for what the characters resolve to, and for the rotation tag
- Editing and Tooling for ways to produce these files without typing them
- Error Messages if a part is crashing generation