Temporary Editor-lite permissions in Lab-like environments for designing and experimenting.
Mods introducing new content into the game.
Change blueprint behavior.
Please refer to this github issue: https://github.com/Quix0r/AbandonedRuins/issues/4
My mod supports excluding whole surfaces from spawning any ruins. To do so, please add this code to your Init.Player() function:
if script.active_mods["AbandonedRuins_updated_fork"] then
remote.call("AbandonedRuins", "exclude_surface", labName)
end
You might have to remove script.active_ as Factorio maybe doesn't support global script during that function invocation? Sometimes it is confusing ...
You might want to add ?AbandonedRuins_updated_fork as a dependency to your info.json as this mod optionally then supports AbandonedRuins_updated_fork.
Hoping this can be fixed soon
What?
I also don't understand why this has been marked as "No this mod" while this mod has to add some code or otherwise my mod becomes more monolithic and not lesser.
I had replied a few days ago, but I don't see it right now, so there was some submission issue.
Can you post an actual reproducible example of the issue? This mod has for quite some time already supported excluding Abandoned Ruins, and in a way that's more stable and correct than what you suggested; when I tried to reproduce the issue, I could not - as expected, ruins spawned on Nauvis, but not in the Sandboxes.
In my initial post I have linked the github issue where you can find an example. It looks like ruins are spawning inside blueprint surfaces which is, of course, disrupting creating blueprint and need to be prevented. The easiest way here is to register each blueprint surface during creation with my mod as an excluded surface. The above code should do that. What you have to make sure is that the surface doesn't have a planet assigned to it.
So please kindly add that above code to your function Lab.GetOrCreateSurface(), maybe inside the if not surface then block?
The documentation of the remote-call function exclude_surface() says:
-- Any surface whose name contains this string will not have any ruins from any ruin-set mod spawned on it.
-- Please note, that this feature is intended for "internal" or "hidden" surfaces, such as `NiceFill` uses
-- and not for having an entire planet not having any ruins spawned.
---@param name string
The reason here for only allowing "internal" surfaces and not planetary surfaces is very simple. Planet creators might add a call to this function to their control.lua and think they have fixed "a problem". But in truth they have then banned the entire spawning process on ANY planet, not just on theirs. I will soon add some documentation for that issue as they need to invoke an other remote-call function, not this one.
Since your mod isn't creating any planets but only a temporary surface, your choice is to invoke exclude_surface() which I can support if anything breaks. For supporting issues I have published a simple instruction on the FAQ page: https://mods.factorio.com/mod/AbandonedRuins_updated_fork/faq So please kindly redirect your users to there if they have an issue with my mod. Thank you! :-)
I appreciate that you are trying to provide so much information, but it's all quite unnecessary. I've been following everything you've said, what was in the originally reported issue, and the implications of your suggestions, for the entire time.
The literal first version of this mod included that remote-call. You've been looking for places to add that call - you didn't seem to find where it already was being called.
Probably on account of that first thing I said. Even more than this, I confirmed via the logs that the surfaces were properly excluded and not generating any ruins.
You have not included any examples of the issue. I saw a picture - that proves nothing. I have actual, reproducible evidence that there are no issues.
It is now on you to prove that there is an issue in a way that I can easily confirm. I'm not going to reply again unless you can acknowledge what I am trying to tell you.
While looking for this issue, I found that your mod crashes when the debug logging is enabled:
Error while running event AbandonedRuins_updated_fork::on_nth_tick(10)
__AbandonedRuins_updated_fork__/lua/utilities.lua:88: bad argument #4 of 5 to 'format' (number expected, got nil)
stack traceback:
[C]: in function 'format'
__AbandonedRuins_updated_fork__/lua/utilities.lua:88: in function 'safe_damage'
__AbandonedRuins_updated_fork__/lua/spawning.lua:153: in function 'spawn_entity'
__AbandonedRuins_updated_fork__/lua/spawning.lua:225: in function 'spawn_entities'
__AbandonedRuins_updated_fork__/lua/spawning.lua:366: in function 'spawn_ruin'
__AbandonedRuins_updated_fork__/lua/spawning.lua:420: in function 'spawn_random_ruin'
__AbandonedRuins_updated_fork__/lua/events.lua:85: in function <__AbandonedRuins_updated_fork__/lua/events.lua:54>
Thank you for explaining it, I now understand it. Yes, I was not looking at that spot. So I wondered how the reporting user was able to get this bug. I close it as invalid.
For 5) I have prepared 1.4.9, LUA seem to be a non-declarative language.
Hmm, the screenshot contains ruins around the blueprint in the center of the map. That's what shouldn't happen. I can try to install your mod for testing it myself as exclude_surface should prevent any spawning.
I guess I have the solution on how the user was able to create this bug:
1) Exit to Factorio's main menu
2) Choose: Single player -> New game -> Blueprint sandboxes
3) Configure as desired and start the game
The ruins are spawning because of that "sandbox surface" is called nauvis. My idea here is that you invoke exclude_surface for the surface's name.
Add this code to scenarios/sandbox/control.lua in on_init hook:
if remote.interfaces["AbandonedRuins"] then
pcall(remote.call, "AbandonedRuins", "exclude_surface", surface.name)
end
Then it should be fixed. Or is the user misusing your mod here?
DUPLICATE!
A next thing I tried:
- I then converted my save into a scenario and hit the Fill with lab tiles button. I did this on planet Nauvis so of course, ruins are spawning, because Nauvis is never excluded. I then choose an other surface, a "hidden" surface called "NiceFill_nauvis" and clicked again on Fill with lab tiles. I then moved around and no ruins were spawned.
Here is the log message of the inclusion (Nauvis planet surface):
3142.908 Script @__AbandonedRuins_updated_fork__/lua/utilities.lua:48: [str_contains_any_from_table]: haystack='nauvis' does not contain any needles - EXIT!
And here one with NiceFill:
2873.320 Script @__AbandonedRuins_updated_fork__/lua/utilities.lua:43: [str_contains_any_from_table]: Found needle='NiceFill' - EXIT!
2873.320 Script @__AbandonedRuins_updated_fork__/lua/events.lua:107: [on_chunk_generated]: event.surface.name='NiceFill_nauvis' is excluded - EXIT!
I included also the on_chunk_generated line where the ruin-spawning is taking place. So as you can see, the mod itself is working.
Then next I checked your code and found out that Lab.AfterCreate(surface) is only being invoked when the surface is actually a sandbox:
if not Sandbox.IsSandbox(surface) then
return
end
This is the code where Factorio bails out and doesn't invoke exclude_surface. So I looked further into the matter and found out that Sandbox.IsSandbox() is checking if the force's name contains some string.
Next I finally found how you intended to use the blueprint editor: SHIFT-B. I then found the message that confirms, that your invocation of exclude_surface did take place:
4239.257 Script @__AbandonedRuins_updated_fork__/lua/utilities.lua:43: [str_contains_any_from_table]: Found needle='bpsb-lab-p-roland77' - EXIT!
4239.257 Script @__AbandonedRuins_updated_fork__/lua/events.lua:107: [on_chunk_generated]: event.surface.name='bpsb-lab-p-roland77' is excluded - EXIT!
And a grep exclude_surface factorio-current.log shows it:
4150.792 Script @__AbandonedRuins_updated_fork__/control.lua:72: [exclude_surface]: name[]='string',ruin_sets[]='nil' - CALLED!
4150.792 Script @__AbandonedRuins_updated_fork__/control.lua:80: [exclude_surface]: Excluding surface name='bpsb-lab-p-roland77' ...
4150.792 Script @__AbandonedRuins_updated_fork__/control.lua:84: [exclude_surface]: EXIT!
What you probably want to invoke on exiting the "lab" mode is to invoke reinclude_surface which actually sets the exclusion to nil.
Script lua/surfaces.lua, somewhere line 55 (can change over time, look for reinclude instead, please):
surfaces.excluded[name] = nil
So I wonder now what "New game -> Blueprint sandboxes" is for?
However, a bit strange that ruin_sets[]='nil' is there. exclude_surface has only one parameter.
I think I found the culprit: AbandonedRuins does no longer store excluded surfaces in the save-game. It is only registered in a local "array" (or map) surfaces.excluded{} which isn't persisted (anymore). I have changed that to reduce size of the save-game and when the player decides to uninstall a mod, which might have registered a surface, it is maybe not unregistered (reinclude_surface not invoked).
Adding a similar method to Lab.AfterCreate() will have the downside effect, that surfaces get excluded but on switching back to the previous surface, they won't get "unregistered" causing the said array to grow but not shrink anymore. A better suggestion here is to invoke such "hooks" (maybe other mods need some code being executed on surface change, too) inside the Sandbox.OnPlayerSurfaceChanged() method by adding two methods: Lab.AfterEnteringSandbox(surface)andLab.AfterLeavingSandbox(surface). You can add those method invocations in the properif()` blocks.
I think I found the culprit: AbandonedRuins does no longer store excluded surfaces in the save-game. It is only registered in a local "array" (or map) surfaces.excluded{} which isn't persisted (anymore).
That's a significant problem; you need persistence. I'm not going to make any changes that are only necessary because of that fundamental flaw. What's more important? Some very small amount of space taken in a save file? Or, bugs, extra code, and maintenance like this, making both users and developers unhappy?
These are fatally flawed and will never leave to good results.
What you probably want to invoke on exiting the "lab" mode is to invoke reinclude_surface which actually sets the exclusion to nil.
I have no idea why you're suggesting this. We never want ruins to spawn on Sandbox surfaces, right? It should be immediately obvious that running code that explicitly aims to "generate ruins on the Sandbox" is dead-on-arrival - not even an option to consider.
A better suggestion here is to invoke such "hooks" (maybe other mods need some code being executed on surface change, too) inside the Sandbox.OnPlayerSurfaceChanged() method by adding two methods: Lab.AfterEnteringSandbox(surface) and Lab.AfterLeavingSandbox(surface).
Again, I have no idea why this is a suggestion. What does the player's current surface have to do with whether that surface should be generating ruins or not? You know that chunks can be generated on surfaces that players are not on, right?
This is where I was thinking the original problem was. If someone adds Abandoned Ruins (or similar mods) after the game already exists and surfaces are created, then they won't be excluded, because they're only excluded after the surface is created.
This is another simple problem to solve. This explains why resetting the sandbox did not fix the exclusion problem (because it will never be excluded).
I moved temporary table surfaces.excluded to storage and registered on the on_pre_surface_deleted event to be able to re-include (=unregister) the surface which is being about to be deleted.
PS: I NEVER considered allowing ruins to spawn in Sandboxes, you said that, but I never wanted that. I was asking for a solution here. And yes, surfaces are not excluded when later AR is installed, how should my mod be aware of it? Does Factorio provide a generic information? I'm not happy about the idea to expand the ever-growing storage.excluded table with hard-coded surface list, plus your mod includes the player's name to the surface (understandable for your mod).
Do you have any remote-call functions like is_lab_name(name_of_surface) ? Then I can easily invoke it and your mod does make the check. Duplicating your code to my mod doesn't make sense as I then have to maintain it to followup with your changes.
Plus: I CAN exclude all non-planet surfaces, which means including your Sandbox surfaces, but it also means surfaces from Subsurface mod are also excluded by default. Then I have to ask these mod owners to add some code. Currently mod owners only have to exclude their "internal" or "hidden" surface by invoking remote-call function exclude_surface.
I however can add a remote-call function e.g. allow_spawning_on which allows spawning on non-planet surfaces then, that's possible.
Under Blueprint Sandboxes' Problem I noted that I would Excluding surfaces after mods change, which should take care of AR being installed after BS. I can aim for that sometime this week; the current workaround is for a user to Reset the Sandbox, which will recreate therefore reexclude the surface.