[DO:CityBlocks] Playtest fixes, and fix build restrictions being bypassable by bots - #1580
Merged
grilledham merged 3 commits intoAug 14, 2026
Merged
Conversation
Playtest findings on DO/City-Blocks, and one shared bug behind two of them.
Ore density is halved. A room is 4x4 chunks of solid single-ore field, so
at canonical richness one room outlasts anything built in it and clearing
ground stops being a decision.
Rooms now keep a 3 tile ore-free band along their edge with the rail
corridor. Previously the ore ran flush to the corridor, so a train stop
or inserter needed a bay hand-mined first and nothing in a fresh room
could be automated until it had been cleared by hand.
entity_placement_restriction never refunded anything. It read the item
from event.consumed_items.get_contents()[1], which in 2.0 returns plain
ItemWithQualityCount tables ({name, quality, count}) with no `valid`
field, then gated the refund on `stack.valid` - always nil, so every
entity it destroyed was silently deleted and the item lost. The refund
item now comes from the entity prototype with quality preserved, which
also works for robot builds, whose event carries no consumed_items at
all.
The module also only hooked on_built_entity, so every rule built on it
was bypassable with construction robots: place a ghost, let the bots
finish it. It now hooks on_robot_built_entity too and refunds to the
robot so the item returns to the network. This closes the same hole on
DO/Safety-Ores, which uses the module for its inverse rule.
Note for anyone chasing the same suspicion on the ore restriction: the
live ore rule is modules/allowed_entities.lua, and it already hooks both
build events and already refunds via items_to_place_this. It was not
affected. modules/banned_entities.lua is dead code with no requires.
Corridor naming is unified on "rail corridor" (was variously strip, wall
and corridor).
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
Players want them there for the same reason they would on any map, and refusing costs nothing to protect: a roboport's logistics_radius is 25 and roboports join into a single network when their logistic zones touch, so two placed inside adjacent rooms already reach across a 32 tile corridor. Bots could ferry between rooms without anything ever standing on a corridor, so the rule was only denying the tidy placement, not the capability. Trains still move the tonnage; belts still cannot cross. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
grilledham
reviewed
Aug 13, 2026
grilledham
left a comment
Collaborator
There was a problem hiding this comment.
Thanks for the entity_placement_restriction.lua fix. One minor comment.
I can't remember the last time we played concrete jungle so probably not a priority to fix, but a fix in another PR would be welcome.
Review feedback: the note about consumed_items.get_contents() returning tables with no valid field described the old code, not this code. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Playtest findings on DO/City-Blocks, plus one shared-module bug that turned out to sit behind two of them.
DO/City-Blocks
Ore density halved. A room is 4x4 chunks of solid single-ore field, so at canonical richness one room outlasts anything you can build in it and clearing ground stops being a decision. Uses the existing
ore_configs:scale_richness(0.5).Rooms now keep a 3 tile ore-free band along their edge with the rail corridor. Previously the ore ran flush to the corridor, so a train stop or inserter needed a bay hand-mined first — nothing in a fresh room could be automated until it had been cleared by hand. The band keeps the room's ore tiles, so it looks the same, it just places no ore entity there.
Roboports are now allowed on the rail corridors. The rule was only denying tidy placement, not capability:
logistics_radiusis 25 and roboports merge into one network when their logistic zones touch, so two placed inside adjacent rooms already reach across a 32 tile corridor without anything ever standing on the corridor. Trains still move the tonnage; belts still cannot cross.Corridor naming is unified on "rail corridor" (was variously strip, wall, corridor).
map_gen/shared/entity_placement_restriction.luaThis is the part that affects other maps.
Refunds never worked. The module read the item from
event.consumed_items.get_contents()[1], which in 2.0 returns plainItemWithQualityCounttables ({name, quality, count}) with novalidfield, then gated the refund onstack.valid— always nil. Every entity the module destroyed was silently deleted and the item lost. The refund item now comes from the entity prototype'sitems_to_place_thiswith quality preserved.Rules were bypassable with construction robots. Only
on_built_entitywas hooked, so any rule built on this module could be sidestepped by placing a ghost and letting bots finish it. It now hookson_robot_built_entitytoo and refunds to the robot, so the item returns to the network.Both changes apply to every map using the module:
danger_ores/presets/danger_ore_safety.luashared/danger_ore_banned_entities.lua→toxic_danger_ore_jungle.luaconcrete_jungle.luadino_island.luarail_grid/rail_grid_restrictions.luacrash_site/presets/steam_all_the_way.luacrash_site/presets/raining_bullets.luaThe refund fix is a straight improvement everywhere. The robot hook is a gameplay tightening: on Raining Bullets, for example, you can currently ghost a laser turret and let bots finish it, and after this you cannot. That is the intent, but it is a behaviour change on live maps and worth a second opinion.
Not affected: the danger-ore ore restriction is
modules/allowed_entities.lua, which already hooked both build events and already refunded viaitems_to_place_this. (modules/banned_entities.luais dead code — nothing requires it.)Known follow-up: Concrete Jungle
Both events can now fire with
player_index = nilfor robot builds. Five of the seven handlers readevent.playerand nil-guard it correctly.concrete_jungle.lua:304does not, and it also readsevent.entity, a field this module has never set — it sendscreated_entity. Sincestackis a plain table in 2.0,stack.valid_for_readis always nil, so that handler falls intoentity.nameon a nil value on every player build already, i.e. it is broken ondeveloptoday independently of this PR. This PR adds a second path into it via robot builds.Left out deliberately, as a fix there is a judgement call about another map's UX (the blueprint-vs-ghost warning can no longer be identified from the item stack). Happy to do it here instead if a Concrete Jungle owner would rather see it in one PR.
Also note that spill and the anti-grief callback are skipped for robot builds, since both take a player. Concrete Jungle is the only map using spill, and it only matters if bots fast-replace an entity that has items in it onto unsupported ground.
Changelog
Entries added under
2026-07-29inmap_gen/maps/danger_ores/changelog.lua.🤖 Generated with Claude Code