Subsurface - build beneath your base!

by Natha

While everyone is looking up to space, other planets and the rest of the universe, there is a whole world buried directly underneath us. Use this opportunity to declutter your factory logistics by routing it under your base and explore the underground!

Content
2 days ago
1.1 - 2.0
6.04K
Environment Mining

b [Fixed] attempt to index field 'schedule' (a nil value)

6 days ago

Hello,
I like your mod!!!!

I'm experiencing a recurring crash with your Subsurface mod (version 1.1.14) and wanted to provide a bug report.
The game crashes during the on_tick event with the following error, which seems to be related to handling subway trains.
Here is the full crash log:
code
Code
Error while running event Subsurface::on_tick (ID 0)
Subsurface/scripts/trains.lua:100: attempt to index field 'schedule' (a nil value)
stack traceback:
Subsurface/scripts/trains.lua:100: in function 'handle_subways'
Subsurface/control.lua:376: in function <Subsurface/control.lua:363>
1364.397 Error ClientMultiplayerManager.cpp:86: MultiplayerManager failed: "模组「Subsurface - build beneath your base! (1.1.14)」引发了无法恢复的错误。

Analysis:
It looks like the handle_subways function in trains.lua is trying to access the .schedule of a train object. However, at that specific moment, the train object it's trying to check is nil, which causes the game to crash.
This might happen if a train has been destroyed or removed from the game right before this check occurs, or perhaps when it's interacting with other mods that might alter train states (for example, a teleporter mod). A simple safety check to ensure the train object exists before trying to access its schedule (e.g., if train and train.schedule then ... end) would likely fix this crash.
Thank you for your great mod and for looking into this!

5 days ago
(updated 5 days ago)

Hello,
I'm a big fan of your Subsurface mod and wanted to share a fun experience and a couple of bug reports that came out of it.
For fun, I was doing something unusual: trying to build a subsurface entrance on a Space Exploration (SE) space platform orbit. To do this, I used admin commands to create a 24x24 patch of grass on the platform, placed the surface drill, and successfully drilled a hole.
When I went down, I made a hilarious discovery: the entire subsurface level was filled with water!
While doing this, I encountered two repeatable crashes. I'm not a programmer myself, but with the help of an AI, I was able to analyze the errors and fix them. I wanted to share the detailed fixes in case it's helpful for improving the mod's robustness in these edge cases.

Bug 1 : bad argument #1 of 2 to 'pairs' (table expected, got nil)
Trigger: This happened during the on_tick event, likely related to pollution processing.
Fix: In control.lua, right before the line for _, chunk in pairs(storage.exposed_chunks[subsurface.index]) do, we added the following line to prevent the crash:

storage.exposed_chunks[subsurface.index] = storage.exposed_chunks[subsurface.index] or {}

Bug 2 : Unknown variable: subsurface_seed
Trigger: This happened during the on_resource_depleted event when trying to regenerate resources underground.
Analysis: It seems the space platform surface was created without the subsurface_seed map gen variable, which your mod needs for procedural generation.
Fix: We implemented a "first-tick migration" pattern. This ensures that any subsurface created by older mod versions or in unusual ways (like mine) gets patched on game load. Here are the detailed changes to control.lua:
Step 1: Create a dedicated patcher function. We added this new function to control.lua:

function patch_missing_map_gen_properties()
for _, s in pairs(game.surfaces) do
local mgs = s.map_gen_settings
local changed = false

    -- This part fixes the missing subsurface_seed
    if is_subsurface(s) and not mgs.property_expression_names["subsurface_seed"] then
        local _, _, topname, _ = string.find(s.name, "(.+)_subsurface_([0-9]+)$")
        if topname and game.get_surface(topname) then
            local top_surface_seed = game.get_surface(topname).map_gen_settings.seed
            mgs.property_expression_names["subsurface_seed"] = bit32.band(bit32.bxor(simple_hash(s.name), top_surface_seed), 0xFFFFFFF)
            changed = true
        end
    end

    if changed then
        s.map_gen_settings = mgs
    end
end

end

Step 2: Modify script.on_init to run the patcher and set a flag.

script.on_init(function()
setup_globals()
patch_missing_map_gen_properties()
storage.migration_applied_for_seeds = true -- Set flag for new games

for _, s in pairs(game.surfaces) do
    if allow_subsurfaces(s) then manipulate_resource_data(s) end
end

register_subsurface_walls()

end)

Step 3: Modify script.on_event(defines.events.on_tick, ...) to run the patcher on the first tick for existing saves. We added this block at the very beginning of the on_tick function:

script.on_event(defines.events.on_tick, function(event)

-- First-tick migration logic
if not storage.migration_applied_for_seeds then
    patch_missing_map_gen_properties()
    storage.migration_applied_for_seeds = true
end

-- ... original on_tick code continues here ...

end)

This solution is robust and handles both new games and loading old/unusual saves.
Again, I'm just a player who was having some fun, and an AI helped me with the code analysis and fixes. I hope this report is useful to you!
Thanks for the amazing mod!
https://www.youtube.com/watch?v=8XC5P_nph8A

5 days ago
(updated 5 days ago)

The game crashes during the on_tick event with the following error, which seems to be related to handling subway trains.

The scheduler object is already accessed in some lines before 100, but they dont throw this error. Line 100 is a special case that removes consecutive appearances of the same subway stop. The error is only thrown when the schedule has only subway stops. Will fix it

5 days ago

The game crashes during the on_tick event with the following error, which seems to be related to handling subway trains.

Could you provide a savegame where this happens? The scheduler object is already accessed in some lines before 100, but they dont throw this error.

Thank you for your quick response and willingness to investigate!
I've managed to pinpoint the exact condition that triggers the crash, and it's due to a mistake in how I configured a train's schedule.
Reproducible Case:
The crash occurs when a train's schedule contains two identical and consecutive Subway stations. This happened because I accidentally selected the same Subway entrance station twice in a row when setting up the schedule.
How to reproduce (easily, no savegame needed initially):
Create a train.
In its schedule, add two identical and consecutive Subway entrance stations. (e.g., [Subway A] -> [Subway A] -> [Destination]).
Send the train into the first Subway entrance.
The crash (attempt to index field 'schedule' (a nil value) in trains.lua:100) consistently triggers the moment the train is about to enter the Subway.
You should be able to reproduce this without my savegame. However, if you still require it for further debugging, I am happy to provide it.
Here is the savegame share link (if needed):
https://drive.google.com/file/d/1pwHHw2XHBI483UY69cUaj7HXVwA8L02A/view?usp=drive_link

5 days ago

Didn't expect you to respond that quickly, i already found the cause in the meantime ;)

Regarding the other issue, i don't think it is worth fixing because this cannot occur when not cheating.

5 days ago

Didn't expect you to respond that quickly, i already found the cause in the meantime ;)

Regarding the other issue, i don't think it is worth fixing because this cannot occur when not cheating.

Okay, I understand. I was just doing it for fun, wanting to see what the underground pit under the space platform looked like. It won't matter if it's not repaired, hahaha.

a day ago

iyeah thx the fix

New response