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