What changed in 7.5¶
Version 7.5.0 added a planned road system and an inter-city highway network. Both are on by default. A setup that worked on 7.4.12 generates different cities after the upgrade, with no change to your config and no change to your datapack. code review
This page documents 7.5.1 for Minecraft 1.20.1, read from that jar. The same system is in 8.4.1, 9.5.1 and 10.0.1, where it is identical. See The NeoForge line. code review
Your datapack still means the same thing
The claim-test pack written for 7.4.12 runs
unchanged on 7.5.1 and gives the same 28 results. Palette merge order, the
128-slot rule, loot and mob resolving through a Condition, range counting
storeys, stair shape recalculation, the torch gate, tag, character
truncation and the belowpart bug all behave identically.
7.5 changed where cities put things, not what a datapack means. Everything on this page is about placement. Nothing on the reference pages changes. game test
The one measurable side effect on an unchanged pack: doorways move. The mod cuts a doorway toward an adjacent city chunk, and the road planner changes which neighbours those are, so wall counts shift by multiples of 16 even with buildings pinned to identical coordinates. game test
buildingchance no longer fills every eligible chunk
The mod refuses a building in any chunk the road planner has claimed, and it
refuses it before it rolls buildingchance. Setting buildingchance to
1.0 therefore no longer puts a building in every city chunk. To restore the
7.4.12 behaviour, set streetGenerationMode to LEGACY.
A broken refpalette now fails the building¶
On 7.4.12 a building whose refpalette did not resolve still generated, as long as every one of its parts carried a working refpalette of its own. The building's palette was never needed, so the broken name was never dereferenced. game test
From 7.5 that palette is resolved regardless, and the building fails instead. Measured on the same pack across five versions: game test game test
| Version | The building | Chunks failing on that palette game test game test game test |
|---|---|---|
| 6.0.3 | absent, and the server does not survive it | generation stops |
| 7.4.12 | generates, 512 blocks | 2, neither of them the building's |
| 7.5.1 | absent | 8, including the building's own |
| 8.2.2 | generates, 768 blocks | 2, the same two 7.4.12 fails |
| 9.5.1 | absent | 8, including the building's own |
Tolerance is a window rather than a direction. 6.0.3 already resolved the palette regardless, 7.4.12 and 8.2.2 do not, and 7.5.1 and later do again. 8.2.2 is 7.4-era code on a 1.21 loader, which is why it sits with 7.4.12 here. See Traps specific to one version. game test
The newer behaviour is the better one, because the mistake becomes visible. It is listed here because a pack that appeared correct on 7.4.12 for this reason loses that building on 7.5, with no key having changed. game test
The three keys that decide everything¶
These three cover most authoring needs. All three defaults were read from
the field assignments in LostCityProfile, not from the list of accepted values. code review
| Key | Values | Default | Meaning code review |
|---|---|---|---|
streetGenerationMode |
LEGACY, HIERARCHICAL_GRID_V1 |
HIERARCHICAL_GRID_V1 |
LEGACY generates streets as 7.4.12 does, from the city shape alone. HIERARCHICAL_GRID_V1 plans a road grid first, then fits buildings into what is left. |
highwayGenerationMode |
LEGACY, INTERCITY_NETWORK_V1 |
INTERCITY_NETWORK_V1 |
LEGACY generates highways on fixed intervals as 7.4.12 does. INTERCITY_NETWORK_V1 places hubs near likely cities and routes highways between them. |
multiBuildingStreetConflict |
BLOCK_ALL, OVERRIDE_MINOR, OVERRIDE_ALL |
OVERRIDE_MINOR |
Decides which planned roads stop a multi-building. See the table below. |
Restoring 7.4.12 behaviour¶
Set both modes to LEGACY in config/lostcities/common.toml: code review
streetGenerationMode = "LEGACY"
highwayGenerationMode = "LEGACY"
multiBuildingStreetConflict then has no effect, because there are no planned
roads for a multi-building to conflict with. code review
How multiBuildingStreetConflict resolves¶
The mod asks the value whether a given planned road type blocks the multi-building. The answer is exact: code review
| Value | Blocks on PRIMARY |
Blocks on SECONDARY |
Blocks on TERTIARY |
Blocks on NONE code review |
|---|---|---|---|---|
BLOCK_ALL |
Yes | Yes | Yes | No |
OVERRIDE_MINOR |
Yes | No | No | No |
OVERRIDE_ALL |
No | No | No | No |
With the default OVERRIDE_MINOR, a multi-building cuts through secondary and
tertiary roads, and a primary road still stops it. code review
An unrecognised value throws IllegalArgumentException. The mod uppercases the
string first, so override_minor is accepted. code review
The mode is stored per world, not per config¶
The two mode keys set what a new world gets. The mod writes the chosen mode into the world's saved data and reads it back on every later load. code review
| Situation | Result code review |
|---|---|
| New world | Takes the mode from the config key. |
| Existing world | Keeps the mode it was created with. Changing the config key does nothing. |
| Saved mode is not a recognised name | Falls back to LEGACY and logs Unknown persisted street mode '<name>' for <dimension>; using LEGACY. |
The same applies to highwayGenerationMode, with the message
Unknown persisted highway mode '<name>' for <dimension>; using LEGACY. code review
Changing the config key does not convert an existing world
The mod reads the persisted mode, not the config key, for any world that already exists. To change the road system of a world you already generated, you must start a new world.
The road hierarchy¶
HIERARCHICAL_GRID_V1 classifies every city chunk as one of four planned road
types. The type decides whether a building may stand there. code review
| Type | What it is | Building allowed code review |
|---|---|---|
PRIMARY |
The main corridors. Spacing is set by primaryRoadSpacingX and primaryRoadSpacingZ. |
No |
SECONDARY |
Roads inside a primary block. Count is set by secondaryRoadMinCountX, secondaryRoadMaxCountX and the matching Z pair. |
No |
TERTIARY |
Short access roads into a subdivided block. | No |
NONE |
Not a planned road. | Yes, subject to buildingchance |
The order the mod decides in¶
For each city chunk, checkBuildingPossibility runs these tests in this order and
returns at the first one that matches: code review
- A predefined building is at this chunk. Building.
- A predefined street is at this chunk. No building.
- The chunk is part of a multi-building. Building.
- The planned road type is not
NONE. No building. - The
buildingchanceroll fails. No building. - Highway and level tests follow. code review
Step 4 sits above step 5. That is the whole reason buildingchance stopped
behaving as it did in 7.4.12. code review
Step 3 sits above step 4. A multi-building that survived the
multiBuildingStreetConflict test wins against a planned road. code review
New profile keys¶
Version 7.5.1 adds 29 profile keys and removes none. The 3 above are covered already. The remaining 26 tune the two planners. code review
Defaults and ranges are read from the registration calls. The meanings below are traced to the code that reads each key, not copied from the mod's own comments. code review
Primary roads¶
A chunk column is a candidate corridor when
floorMod(chunkX - offset, primaryRoadSpacingX) is 0. code review
The offset is derived from the world seed and from a hash of the dimension name, and it lands between 0 and the spacing. The grid therefore does not align to chunk 0, and 2 dimensions in the same world get different offsets. code review
A candidate becomes an actual road in one of 2 ways. It is forced when
floorMod(candidateIndex, primaryRoadForceEvery) is 0. Otherwise a deterministic
hash decides, against primaryRoadOptionalChance. code review
| Key | Default | Range | Meaning code review |
|---|---|---|---|
primaryRoadSpacingX |
8 |
8 to 128 |
Chunks between candidate corridors along the X axis, which run north to south. A candidate is not necessarily a road. |
primaryRoadSpacingZ |
8 |
8 to 128 |
The same along the Z axis, for corridors running east to west. |
primaryRoadForceEvery |
4 |
1 to 16 |
Every Nth candidate becomes a road with no roll. At 1 every candidate is forced, and primaryRoadOptionalChance then has no effect. This value times the spacing is the largest possible gap between primary roads, so 32 chunks at the defaults. |
primaryRoadOptionalChance |
0.45 |
0.0 to 1.0 |
The chance that a candidate which was not forced becomes a road. At 0.0 only the forced corridors exist. At 1.0 every candidate becomes a road. |
Secondary roads¶
Inside a block bounded by primary roads, the planner picks a count, then picks positions for that many roads. code review
The count is not uniform across the range. It is 75 percent driven by a local density value and 25 percent by a hash. code review
Positions are drawn from minimumRoadEdgeDistance to
blockSize - minimumRoadEdgeDistance, shuffled deterministically, then accepted one
at a time only when far enough from every road already accepted. code review
| Key | Default | Range | Meaning code review |
|---|---|---|---|
secondaryRoadMinCountX |
0 |
0 to 128 |
The fewest north/south secondary roads a block may get. |
secondaryRoadMaxCountX |
2 |
0 to 128 |
The most it may get. When the minimum equals the maximum, that exact count is used with no roll. |
secondaryRoadMinCountZ |
0 |
0 to 128 |
The same for east/west roads. |
secondaryRoadMaxCountZ |
2 |
0 to 128 |
The same for east/west roads. |
minimumRoadSeparation |
4 |
2 to 32 |
Chunks required between 2 parallel secondary roads. A position closer than this to an accepted road is rejected. |
minimumRoadEdgeDistance |
3 |
2 to 32 |
Chunks kept clear at each edge of the block. If twice this value leaves no room inside the block, the block gets no secondary roads at all. |
The count is a maximum, not a guarantee
Positions are accepted greedily against minimumRoadSeparation, and the planner
stops when it runs out of candidates. A block that cannot fit the chosen number
of roads gets fewer, silently. Raising secondaryRoadMaxCountX without lowering
minimumRoadSeparation therefore changes nothing once the block is full.
Tertiary roads¶
A subdivided block gets at most 1 tertiary road. The planner rolls the chance, then picks a direction, then picks a length. code review
| Key | Default | Range | Meaning code review |
|---|---|---|---|
tertiaryRoadChance |
0.4 |
0.0 to 1.0 |
The chance that a block gets its 1 tertiary road. At 0.0 none are generated. |
tertiaryRoadMinLength |
2 |
1 to 16 |
The shortest acceptable road, in chunks. If the space available is below this after the maximum is applied, the block gets no tertiary road even though the chance roll succeeded. |
tertiaryRoadMaxLength |
5 |
1 to 32 |
The longest road, in chunks. Available space is capped to this value before the minimum is tested. |
Bridges over water¶
| Key | Default | Range | Meaning code review |
|---|---|---|---|
plannedPrimaryBridgeChance |
1.0 |
0.0 to 1.0 |
The chance that an eligible water crossing becomes a bridge. The roll is made once for the whole crossing, not per chunk, so a crossing is either entirely a bridge or entirely not. At 0.0 no planned bridges are generated. |
plannedPrimaryBridgeMaxLength |
12 |
1 to 64 |
The furthest, in chunks, that the planner searches for the far bank. A water gap wider than this produces no bridge. |
Open lots¶
| Key | Default | Range | Meaning code review |
|---|---|---|---|
openLotParkChance |
0.8 |
0.0 to 1.0 |
The chance that an open lot receives a park part. A city style may override this through profile_overrides, which is the only key that object accepts. |
Highway hubs¶
The world is divided into square planning cells. Each cell holds at most 1 hub. The planner tests candidate positions inside the cell, scores each one by city potential, keeps the best, and then discards it if the score is too low. code review
The score is the city potential clamped to 0 to 1 and scaled to an integer, and the
threshold is highwayHubMinimumPotential scaled the same way, so the key reads as a
direct 0 to 1 cutoff. code review
| Key | Default | Range | Meaning code review |
|---|---|---|---|
highwayPlanningCellSize |
128 |
32 to 512 |
The side of one planning cell, in chunks. A larger cell means fewer hubs, and so fewer highways. |
highwayHubSampleSpacing |
16 |
1 to 512 |
Chunks between the candidate hub positions tested inside a cell. A smaller value tests more positions and finds better sites. It may not exceed the cell size. |
highwayHubMinimumPotential |
0.2 |
0.0 to 1.0 |
The city-potential score a cell's best candidate must reach. Below it the cell produces no hub. Raising this gives fewer hubs. |
highwayHubSearchRadiusCells |
2 |
0 to 8 |
How many cells outward a hub looks when searching for neighbours to connect to. At 0 a hub sees no neighbours, so no routes are formed. |
Highway routes¶
| Key | Default | Range | Meaning code review |
|---|---|---|---|
highwayMinimumHubDistance |
64 |
0 to 4096 |
Hubs closer together than this, in chunks, are not connected to each other. |
highwayMaximumHubDistance |
320 |
0 to 4096 |
Hubs further apart than this are not connected. |
highwayMaximumConnectionsPerHub |
2 |
1 to 8 |
The most connections accepted at a single hub. A denser network needs a higher value here as well as a wider search radius. |
highwayMinimumRouteLength |
40 |
0 to 4096 |
A candidate route shorter than this many chunks is discarded. |
highwayRouteCityPenalty |
1.0 |
0.0 to 1000.0 |
The weight given to city potential when the planner chooses where an L-shaped route bends. |
highwayNetworkLevel |
0 |
0 to 32 |
The fixed level used for every highway when highwayLevelFromCities is 4. It is ignored for every other value of that key. |
Existing keys that changed¶
Three keys that already existed behave differently in 7.5.1. No key was removed. code review
highwayLevelFromCities changed its default¶
| 7.4.12 | 7.5.1 code review | |
|---|---|---|
| Range | 0 to 3 |
0 to 4 |
| Default | 0 |
3 |
Two separate changes, and the default is the one that affects you. On 7.4.12 a
highway took its height from one endpoint city. On 7.5.1 it takes the average
height of both, unless you set the key back to 0. code review
The new value 4 makes the mod use the fixed highwayNetworkLevel instead of
deriving the level from the endpoint cities. code review
The description of value 0 also changed, from "take height from top-left city" to
"take height from the first endpoint city". code review
The spawn search changed¶
Neither key changed its default or its range. What the numbers mean changed. code review
| Key | 7.4.12 | 7.5.1 code review |
|---|---|---|
spawnCheckAttempts |
A count of attempts. | A count of chunks to check. |
spawnCheckRadius |
The start radius. The mod widened it by a fixed 100 on failure. | The start radius. The mod spirals outward from the world centre and widens by spawnRadiusIncrease. |
If you raised spawnCheckAttempts on 7.4.12 to work around a spawn failure, the
same number now means a different amount of searching.
These ranges are enforced¶
Unlike the building keys, these are validated. The mod rejects combinations that cannot work, with messages such as: code review
Secondary road minimum counts cannot exceed maximum countshighwayMinimumHubDistance cannot exceed highwayMaximumHubDistancehighwayHubSampleSpacing cannot exceed highwayPlanningCellSizetertiaryRoadMinLength cannot exceed tertiaryRoadMaxLengthPrimary road candidate spacing must be between 8 and 128 chunksRoad separation and edge distance must be between 2 and 32 chunksSecondary road counts must be between 0 and 128code review
New datapack keys¶
Version 7.5.1 adds 15 datapack keys, removes none, and changes no key from optional to required or back. Every 7.4.12 datapack still loads. code review
| Asset | Key | Notes code review |
|---|---|---|
| City style | profile_overrides |
An object holding per-city-style profile values. |
City style, inside profile_overrides |
openLotParkChance |
The only key the object accepts in 7.5.1. |
| Selectors | largebridges |
Selector list, alongside the existing bridge selectors. |
| Street settings | largeparts |
Part names for the wider planned roads. |
| Street settings | tertiaryparts |
Part names for tertiary access roads. |
| Street parts | connector |
The shape where a wide road meets a narrower one. |
| Street parts | stair |
The shape where a road changes city level. |
| Highway parts | open_bend, open_t |
Bend and T shapes for an open highway. |
| Highway parts | bridge_bend, bridge_t |
The same two for a bridge section. |
| Highway parts | tunnel_bend, tunnel_t |
The same two for a tunnel section. |
| Scattered building | supportpart |
Part name used underneath a scattered building. |
| Scattered building | clearhighwayrailing |
Whether the scattered building clears highway railings. |
This table said 7 keys until the extraction was rebuilt
The eight highway and street shapes were missing from it. All eight belong to
HighwayParts and StreetParts, two of the three codec types that register
their fields through a helper rather than through fieldOf, so an extraction
reading only fieldOf walked straight past them. testrig/extract-keys.py
reads all three, and the counts on this page and on
Key Availability come from it. code review
Why the six highway shapes matter. Before 7.5 a highway could only run straight
or cross another at the same level, so open, bridge, tunnel and their _bi
partners covered every case. The planned road network turns corners and branches,
which needs a bend and a T for each of the three section kinds. A pack that
overrides highway parts on 7.4.12 and moves to 7.5 will keep its straight sections
and get the mod's own parts at every corner until it names the new six. code review
What profile_overrides actually adds¶
profile_overrides holds exactly one key, openLotParkChance. That is its whole
contents in 7.5.1. code review
It is not a general override mechanism, and a city style could already override
profile values before 7.5.1. What 7.5.1 adds is a single resolution point,
EffectiveCitySettings, which reads 14 values from the city style and falls back
to the profile for each one it does not find: code review
buildingchance, minFloorCount, maxFloorCount, minCellarCount,
maxCellarCount, parkchance, openLotParkChance, fountainchance,
frontchance, corridorchance, avoidfoliage, parkborder, parkelevation,
parkstreetthreshold. code review
Thirteen of those already resolved this way in 7.4.12, through the city style's
existing buildingsettings, parksettings, streetsettings and
corridorsettings. Only openLotParkChance is new, and it needed a new home
because no existing settings object covered open lots. code review
What is new inside the mod¶
For orientation only. 7.5.1 adds 67 classes over 7.4.12 and removes one. code review
| Package | Classes | Purpose code review |
|---|---|---|
worldgen.highway |
24 | Hub placement, route planning, persistence of the hub graph. |
worldgen.street |
12 | The planned road grid, bridge planning, road types. |
worldgen.gen |
12 to 22 | Grew, including scattered-building placement. |
The only removal is LostCityTerrainFeature$AvoidChunk. code review