Better mining (the baby steps)


I’ve been looking at the code for mining for a while, looking for ways to improve it. Finally got going and made a mod. First time doing an actual mod instead of doing changes to the original code. The code isn’t very pretty, but so far it only changes two things and they should be considered suggestions to the devs.
Been following @RepeatPan’s instructions on monkey patching to change the existing methods so props. :slight_smile:
I’m holding off with releasing it on steam for now.

Download: better_mining.smod (2.2 KB)


Finding adjacent to blocks in ceilings
This feels like a bug. In mining_service.lua comments say that the methods get_adjacent_for_destination_block and get_adjacent_for_destination_region should be kept in sync. However, the first one looks for adjacent on all sides below the block as long as the bottom face is exposed. The second one doesn’t. It only finds adjacent positions below the block if the face on that side of the block is exposed.
This mod adds this to get_adjacent_for_destination_region:

local below = region:translated(-Point3.unit_y)
for _, direction in ipairs(csg_lib.XZ_DIRECTIONS) do
local temp = below:translated(direction)
temp = temp:extruded(‘y’, self._max_reach_up-1, 0)

Slightly improved mining of unsupported blocks
Blocks that don’t have blocks above or below are called unsupported and are handled separately. They are prioritized by how many exposed sides they have, starting with the most exposed. Only the blocks with the highest number of exposed sides are allowed to be mined (as long as the highest isn’t 4).
This works in simple cases but for complex shapes this often makes the hearthlings mine the block they need to access the rest.
The change I made so far is to check if a block is part of a one block wide bridge (straight bridge, corner bridge or connected to one).
The new order of priorities is: end piece, corner, edge, narrow bridge, surrounded blocks, flying.
There is still a lot of problems with this. If they get to a point where all blocks are considered narrow bridges then they will just take the closest one. Also, I don’t check if it’s a bridge on the side of a wall.
It could be improved more by checking the terrain more, however checking terrain isn’t good for performance (according to comments) and it won’t find ladders, witch should be considered important access points, so I’m thinking that maybe the nav mesh has some useful information stored that’s quick and easy to check. Any suggestion and pointers in the right direction are very welcome. :slight_smile:

Future plans
At some point I want to try to add automatically placed ladders (and maybe even scaffolding) but I haven’t started looking at that yet. Since that would mean extra work for the hearthlings it’s better to try to make them mine in a way that gives them access to as much as possible.
My current plan is to try to make them mine narrow stairs to the top of the mining zone and work down from there.
When mining blocks from the side they should (if they can) skip the one on the same hight as them selves and mine 3 blocks above it. Then they should look for higher places to stand and mine instead of looking for adjacent blocks to mine. If I can make the workers keep a little distance from each other and make them prioritize mining 2x2 spiral stairs, they should hopefully not interfere too much with each other.

Other things
I have some notes on minor things I noticed when looking through mining_zone_component. Will post them later.

Try it out and if you have any questions or suggestions I’m happy to hear it. :slight_smile:


This is a worthy endeavor indeed. Getting mining to behave more robustly is something the game still sorely needs. It might make sense to pass your plans by @Albert in case he has some suggestions - he’s the one who know that part of the codebase best.


Thanks for the advise :grin:


This is also stuff that’s also planned for ACE, so you may consider either doing it through them, or coordinating with them a little.


I will. Just haven’t used discord or github before and didn’t want to get delayed by it or caught up in endless design discussions. I’m running out of vacation. :frowning_face:
ACE is welcome to use any of this even if I for some reasons don’t get around to putting it in myself. :slight_smile:


@Agon - Your understanding of the code is good. One proposal that might work is to check if any of the computed adjacent blocks is standable. If not, we fall back to submitting the entire mining region as the destination region. This prevents stupid cases where the player sees clearly reachable blocks that can be mined, but were not prioritized because some concave geometry is causing it not to be considered. The downside is that this could have a significant effect on performance, but that might be addressable in other ways.


like not stripmining half the continent all at once :stuck_out_tongue: ?


Actually, crazy thought here: what if the mining areas were sub-divided into smaller chunks after being assigned? Would less to mine = less processor load, or would it mean that more mining areas to handle take up more processor load? I imagine that more concurrent mining areas can only be bad for the system, but what if each subdivision was flagged with a a priority/order so that the game only attempts to mine one of the subdivisions at a time (still allowing multiple different mining zones to be mined simultaneoulsy; just a single sub-division of each zone at one time) – would that effectively cap the amount of thinking the game has to do at any point in the mining process?

From a player’s perspective, I doubt this would make any difference in the mining time; but if it allows players to stripmine half the continent with a single zone without nuking their performance (or perhaps more importantly: allows lower-end machines to handle mining with less stress), then perhaps it’s worth the investment?


I think a Desktop Tuesday long ago talked about them having improved performance by dividing mining areas into smaller once, so that’s probably good crazy. :slight_smile:
I don’t remember seeing it in the code, but I have probably looked at later parts of the process.


I think that was building regions (seem to recall a castle being built in block chunks after failing repeatedly without that). Incorporating that logic into mining makes sense; not sure about feasibility though - still getting a hang of it all mahself.


I looked around a bit earlier but couldn’t find a DT about it, so I might imagine stuff or it could be hiding in a video that didn’t have a name that hinted of mining.
Anyway, dividing the zone into smaller chunks should be good for performance. The zone gets reevaluated more or less constantly as it changes shape, so limiting the evaluation to the chunk where the change actually happened should be better.


I assume you mean blocks adjacent to a workers current position, not blocks adjacent to the mining region?
Is there a way to check with the pathfinder/nav-mesh if a block is standable or would that just be checking if there is enough empty space above it? I’m not sure if creatures of different sizes gets different restriction. I know that when you introduced the mining golem someone commented that it was too tall for the tunnels it was digging. Don’t know if that was adjusted. I’m pretty sure that I at least haven’t seen any support in the code for creatures with different reach.


Try radiant.terrain.is_standable(...) and radiant.terrain.get_standable_point(...).


It’s the adjacent region that a worker can path to in order to mine a specific block. To be more specific, the region computed by MiningZoneComponent:_update_adjacent().


Nice work :merry:

Mostly commenting to /lurk :jubilant: