Skip to content

Streets, Highways, Rails & Monorails

TL;DR

Streets, highways, rails and monorails each expect a set of default part names to exist. Any of those names can point at a custom part instead. Streets, highways and railways also accept a list of parts, sampled at random per placement. Monorails accept one name only.

This is a contract, not a suggestion. If a part named street_full does not exist and nothing overrides that name, that piece of infrastructure does not generate. game test

One shape can have several parts

The single most common assumption is that each street shape is locked to exactly one part. It is not. Streets, highways, and railways accept either a single name or a list of names, and the mod picks one at random each time it places that piece: game test

Both forms are valid in the same object
{
  "streetblocks": {
    "parts": {
      "full":     ["street_full", "mypack:street_full_cracked", "mypack:street_full_grassy"],
      "straight": "mypack:street_straight_wide"
    }
  }
}
Category Multiple variants? How one is chosen code review
Streets Yes, list or single string Uniform random, every entry equally likely
Highways Yes, list or single string Uniform random
Railways Yes, list or single string Uniform random
Monorails No, single string only n/a

Passing a list to a monorail key is a datapack load error, not a silent fallback. code review

There is no weighting

Unlike building selectors or Conditions, these lists have no factor key. Every entry in the list is equally likely. If you want one variant to be rare, you cannot express that here, list it once among many common ones, or use a Variant inside the palette instead (see below).

Adjacent chunks roll independently, with no attempt to match neighbours. Two touching straight-street chunks can and often will pick different variants, so variants need to line up seamlessly at chunk edges or the seams will be obvious. Do not count on predicting which variant a given chunk gets before you visit it; once a chunk is generated it is saved, so it will not change afterward. game test

Where each override goes

The two families live in different files, which is easy to get wrong: code review

citystyles/<name>.json
{
  "streetblocks": {
    "parts": {
      "full":     ["street_full"],
      "straight": ["street_straight"],
      "end":      ["street_end"],
      "bend":     ["street_bend"],
      "t":        ["street_t"],
      "none":     ["street_none"],
      "all":      ["street_all"]
    }
  }
}

Because streets are a City Style property, and a World Style can pick city styles per biome, streets can vary by biome: give citystyle_desert its own streetblocks.parts and desert cities get different roads. code review

worldstyles/<name>.json
{
  "outsidestyle": "outside",
  "citystyles": [ ... ],
  "parts": {
    "highways": {
      "tunnel": ["highway_tunnel", "mypack:highway_tunnel_lit"],
      "open":   "highway_open"
    },
    "railways": {
      "railshorizontal": ["rails_horizontal", "mypack:rails_horizontal_broken"]
    },
    "monorails": {
      "both": "mypack:monorails_both_neon"
    }
  }
}

These are one set per world style, resolved with no biome input, so highways, rails, and monorails cannot vary by biome. The only way to differentiate them is a separate world style entirely. code review

A name given here replaces the mod's part for that shape rather than joining a pool alongside it. Pointing every highway shape at one part makes every highway in the world that part, and the same holds for railways. game test

Monorail parts have not been placed in a test

Highway and railway parts named this way were run in a world and counted. Monorail parts were not: no arrangement tried placed one, including two spheres present, monorailChance at 1.0, and the spheres shrunk so the chunks between them lie outside both. Treat a custom monorail part as untested rather than as working. unverified

The part name keys

Any key you leave out keeps its default part name. The keys are not always spelled like the part names they default to. code review

A World Style's parts block takes three keys, one per family, and each holds the shape keys listed below it: code review

Key Holds code review
highways The highway shape keys
railways The railway shape keys
monorails The three monorail keys

Streets are not in that block. They live on a City Style under streetblocks.parts, which is what lets them vary by biome while these three cannot. code review

Streets

Key Default part Used when code review
full street_full Never. See below.
straight street_straight 2 connections, opposite sides
bend street_bend 2 connections, adjacent sides
t street_t 3 connections
all street_all 4 connections (crossroads)
end street_end 1 connection
none street_none 0 connections
connector street_large_connector Where a wide road meets a narrower one. 7.5.1 and later
stair street_stair Where a road changes city level. 7.5.1 and later

The key is literally "t", not "tsplit". code review

The last two arrived with the planned road network. The same block of keys appears three times on a 7.5 city style, under parts for ordinary streets, largeparts for the wide planned roads and tertiaryparts for access roads, each taking the full set independently. See What changed in 7.5. code review

full never generates. Setting it does nothing.

A street chunk is assigned one of 3 street types. PARK is chosen by parkchance. Otherwise the mod picks at random from the remaining types:

streetType = StreetType.values()[ random.nextInt(0, StreetType.values().length - 2) ]

StreetType has 3 constants, NORMAL, FULL and PARK, so this is nextInt(0, 1). The upper bound is exclusive, so the only value it can return is 0, which is NORMAL. FULL is never assigned anywhere in the mod. game test

The 6 other keys above are reached through the connection count and work normally. Only full is unreachable. code review

Verified unreachable in 7.4.12, 7.5.1, 8.4.1, 9.5.1 and 10.0.1. The subtraction looks like it should be 1 rather than 2, so this reads as an off-by-one in the mod, not a design decision. code review

Confirmed in game: a city style whose full key pointed at 2 clearly marked parts produced neither marker anywhere across a world of streets. game test

Highways

Six keys in 7.4.12 and twelve from 7.5.1 onward. code review

Key Default part Needs code review
tunnel highway_tunnel 7.4.12
open highway_open 7.4.12
bridge highway_bridge 7.4.12
tunnel_bi highway_tunnel_bi 7.4.12
open_bi highway_open_bi 7.4.12
bridge_bi highway_bridge_bi 7.4.12
open_bend highway_open_bend 7.5.1
open_t highway_open_t 7.5.1
bridge_bend highway_bridge_bend 7.5.1
bridge_t highway_bridge_t 7.5.1
tunnel_bend highway_tunnel_bend 7.5.1
tunnel_t highway_tunnel_t 7.5.1

_bi ("bidirectional") is used where an X highway and a Z highway meet at the same level. code review

The six _bend and _t shapes arrived with the planned road network in 7.5.1. Before it a highway only ran straight or crossed another at the same level, so there was nothing to turn a corner with. On 7.4.12 these six keys are unknown and ignored, which means a pack written for 7.5 loads on 7.4.12 rather than failing. The reverse is the trap: a 7.4.12 pack that overrides every highway shape keeps its straight sections on 7.5 and gets the mod's own parts at every corner. code review

Railways

Sixteen keys. Note they are all lowercase with no separators, while the default part names they map to are snake_case, an easy source of silent typos. code review

Key Default part code review
stationunderground station_underground
stationopen station_open
stationopenroof station_openroof
stationundergroundstairs station_underground_stairs
stationstaircase station_staircase
stationstaircasesurface station_staircase_surface
railshorizontal rails_horizontal
railshorizontalend rails_horizontal_end
railshorizontalwater rails_horizontal_water
railsvertical rails_vertical
railsverticalwater rails_vertical_water
rails3split rails_3split
railsbend rails_bend
railsflat rails_flat
railsdown1 rails_down1
railsdown2 rails_down2

A surface station gets one extra step. The mod flips a fair coin between the stationopen and stationopenroof lists, then draws a variant at random from whichever list won. code review

Monorails

Key Default part List allowed code review
both monorails_both No
vertical monorails_vertical No
station monorails_station No

Rules your custom parts must follow

A typo in a part name fails in two very different ways

Category If the named part does not exist
Streets The mod logs a warning, and that chunk simply gets no street layer. There is no crash and no fallback, just a gap in the road. In a list of 3 where one name is wrong, roughly 1 in 3 of those street chunks silently comes out broken.
Highways, railways, monorails The mod throws and world generation stops. Loud, but at least obvious.

There is never a fallback to the default part name. Check your spelling, and remember that a bare name means lostcities:<name>, so your own parts need your namespace. See Namespaces. game test

The silent warn-and-skip is wider than streets

Streets are the most visible case. The mod uses the same warn-and-skip lookup for every one of these:

fountains, parks, stairs, rail dungeons, building fronts, and a city sphere's centerpart. game test

A wrong name in any of them produces Cannot find '<name>' in minecraft:root! as a log warning and then nothing at that spot. If a park or a fountain never appears and no error is raised, check the log before you check your selectors. game test

An infrastructure part must be exactly 16×16. A street, highway, railway or monorail part fills its whole chunk, so anything else leaves gaps or corrupts. Larger than 16 is the dangerous case: a write past column 15 wraps back into the same chunk instead of spilling into the next one. All 32 default infrastructure parts are 16×16. code review

This is a rule about these four families, not about parts in general. A building front is deliberately a narrow strip, and the mod ships three of them at 2×16 and 3×16. code review

Author variants in the same orientation as the part they replace. The mod picks the rotation from the road layout, not from your part, so a street_bend variant gets rotated by the same rule the built-in one does. If your bend is drawn facing a different way than the original, it will be rotated wrongly at three quarters of the corners in your world. full, none, and all are never rotated, so those can safely be asymmetric. code review

Reuse the palette characters the category expects. A highway part expects its support character, and a rail part expects the rail palette. A part that references a character its palette does not define throws during generation. code review

For streets, the character that matters is the city style's street. Its streetbase and streetvariant neighbours look like they belong in the same list, but neither is read during generation. See City Style. What a street is actually built from is the characters inside the street part, resolved against the merged palette like any other part. code review

Varying the material instead of the part

If the goal is "my streets look too repetitive," authoring several near-identical parts is usually the harder path. The Style and Variant systems already randomize blocks underneath a single part:

variants/blackstone.json (shipped with the mod)
{
  "blocks": [
    { "random": 32,   "block": "minecraft:polished_blackstone_bricks" },
    { "random": 32,   "block": "minecraft:cracked_polished_blackstone_bricks" },
    { "random": 1000, "block": "minecraft:polished_blackstone" }
  ]
}

That gives per-block variation with weighting, which flat part lists cannot do, and it costs one file instead of several parts. Use part lists when the shape differs (a roundabout, a collapsed section, a checkpoint), and variants when only the material differs. game test

The mod ships zero examples of the list form

None of the built-in world styles or city styles override these part names at all, they all run on exactly one variant per slot. The feature is real and present in the code, it just has no demonstration in the default content, which is why it is widely assumed not to exist.

An inheritance trap for street parts

City style inherit handles streetblocks.parts as one unit: writing any parts block at all, even a partial one, stops the parent's parts from being inherited. Keys you did not list fall back to the hardcoded defaults, not to the parent's overrides. game test

If a parent city style overrides full and bend, and your child overrides only full, the child's bend reverts to the built-in street_bend, it does not keep the parent's. Restate every key you want to keep. See City Style: Inheritance. game test

See also