Realistic Fusion Power


Adds a new way to produce energy through nuclear fusion. Fully compatible with K2, Angel's/Bob's, SE and IR2. Currently getting rewritten (see end of description).

Content
11 months ago
0.17 - 1.1
26.3K
Power

b UPS issues

2 years ago
(updated 2 years ago)

Hello I installed this mod but now its using a lot of UPS (60->50)
https://ibb.co/HCDRHL8
I don't have any magnetic pipes placed or any buildings from the mod

UPS is fine if I change the update count setting to 0

Could you look into this? Thanks

2 years ago

What CPU do you have? For me it has very negligible impact on UPS.
Try reducing the update count without setting it to 0 outright, if the performance is still bad then I guess you'll just have to keep it at 0.

2 years ago

Where is that update count setting may I ask ? Maybe I'm blind but I don't see it in the mod settings.
I installed this to use with the Realistic Fusion Weaponry btw

2 years ago

You have to go under the "global" tab for mod settings

2 years ago
(updated 2 years ago)

I also have multi-millisecond usage times when setting the update count to anything above 0 (even 1), which does have a significant impact on the UPS. However, setting it to 0 does fix it.

I'm curious, is there no way to only allow a certain fluid in certain pipes in the Factorio API (a fluidboxfilter or something, unsure how those work, make plasma temp high enough and set a filter on any other fluid tank without an appropriate filter to not accept the high plasma temp maybe)? Fluids are something I haven't messed with yet.

Or in a worst-case what about just using the events to see when pipes are placed or a building that outputs plasma is placed and just checking those immediate connections and if there is an unsupported pipe ever attached to that building then deny it instead (disable the pipe or building itself or so so it can't function on that immediate output). Sure it's less explosive but it would be significantly less laggy and would completely get rid of the ontick event? (And of course repeat that check on all pipe neighbors on any pipe being placed so your plasma pipes and any other pipe aren't actually allowed to connect)

2 years ago

I'm curious, is there no way to only allow a certain fluid in certain pipes in the Factorio API (a fluidboxfilter or something, unsure how those work, make plasma temp high enough and set a filter on any other fluid tank without an appropriate filter to not accept the high plasma temp maybe)? Fluids are something I haven't messed with yet.

Sort of... Factorio's fluidboxes have a filter property, but that only supports a single fluid. Only way that I've found to get around this is making sure that the allowed fluids always have the same unique temperature (some random number like 984635°C), then setting the minimum_temperature and maximum_temperature of the fluidbox to that value.
The problem is that this allows those fluids and those fluids only into the fluidbox, so magnetic pipes could only transport plasma or antimatter. I guess it could be possible by instead setting only the maximum_temperature to something like 50000°C for every pipe except the magnetic ones, but that would almost definitely cause issues when it comes to mod compatibility. And the pipes wouldn't explode when you put something you shouldn't in there, where's the fun in that?

Or in a worst-case what about just using the events to see when pipes are placed or a building that outputs plasma is placed and just checking those immediate connections and if there is an unsupported pipe ever attached to that building then deny it instead (disable the pipe or building itself or so so it can't function on that immediate output). Sure it's less explosive but it would be significantly less laggy and would completely get rid of the ontick event? (And of course repeat that check on all pipe neighbors on any pipe being placed so your plasma pipes and any other pipe aren't actually allowed to connect)

There is no way to "disable" an entity through scripts. I had to deal with this when making Powered Belts, and let me tell you that having to work around that is really difficult. Best that I could do is replacing the belts with a different entity of the same name which has a speed 0 though scripts, but doing something similar would cause way more problems than the current implementation.

2 years ago
(updated 2 years ago)

Also, I've looked at the code just now and managed to optimize it to the point where it's over 10x faster than before, so... problem solved? Try 1.8.6 and tell me if it's the same on your computer.

2 years ago

There is no way to "disable" an entity through scripts. I had to deal with this when making Powered Belts, and let me tell you that having to work around that is really difficult. Best that I could do is replacing the belts with a different entity of the same name which has a speed 0 though scripts, but doing something similar would cause way more problems than the current implementation.

Isn't that the Entity.active field? I've used it before without issues (though again not on a pipe, but I'd be surprised if tanks moved fluids in an inactive pipe? But it is possible as it is cross-entity interactions... I've not modded pipes to date).

Also, I've looked at the code just now and managed to optimize it to the point where it's over 10x faster than before, so... problem solved? Try 1.8.6 and tell me if it's the same on your computer.

Woot, I'll test it on the server tonight, it's getting updates so perfect timing!

2 years ago
(updated 2 years ago)

Found a desync bug!!!

In control.lua you have if settings.global["rfp-operations-per-tick"].value ~= 0 then at the top that is surrounding code that registers events. Events must not be conditionally registered or it can desync multiplayer (as it did here, fixed my server case though).

Once I fixed the desync bug (it happens when I loaded the server, changed the map config from 0 to something else, then join with another client, and boom, they had mismatched event registrations, just had to save and rehost the map with the new setting, in general just always register events or never register them, don't conditionally register them and don't dynamically register them, if you want something conditional then add an early-return to the callback instead, which you already have with your stop variable so you can take more advantage of it if the count is 0 but while keeping the events registered, might want to listen for the event for when the settings change too so you can update the stop based on the count if 0 or not, it's faster than querying the settings each time, which involves a much slower hashmap lookup, though not really slow enough to worry about in a single case, but would need to check that settings value to early out too instead of just stop) then it looks like the times are taking about 0.092ms on average with the default 16 value, that is SO much better!! Awesome work!!

2 years ago

Should be fixed in 1.8.7, thanks for telling me.

2 years ago
(updated 2 years ago)

Cool, testing same condition... and it desynched again. Checking the code... In the control.lua file there is still a if settings.global["rfp-operations-per-tick"].value ~= 0 then line on line 54 that is wrapping script.on_init, script.on_load, and script.on_event(defines.events.on_tick event registrations, so that would be why the mismatch desync again. No events at all in factorio may be dynamically registered, they must either always be registered for the given mod and callback, or never, it must not be conditional based on something like the above if settings.global["rfp-operations-per-tick"].value ~= 0 then line.

2 years ago
(updated 2 years ago)

There are a few good links about how to make sure your code won't desync, here's the one on the official wiki:
https://wiki.factorio.com/Tutorial:Modding_tutorial/Gangsir#Multiplayer_and_desyncs

A more general page about desyncs and their causes is on the main Desynchronization page but it doesn't give examples of code that cause the issues.

In the above Gangsir tutorial note this section:

Conditional event subscribing

Mods in factorio may subscribe to events in order to be notified when they happen. This allows mods to react to events when they occur. Typically, event subscription is done at the top level of a lua file.

Doing event subscription inside of a conditional, function, or other event is dangerous, as doing it incorrectly will lead to desyncs. Basically, since both the server and client need to reach the same conclusion after running code, conditional subscription can lead to certain clients or the server being subscribed to an event when the others are not, causing desyncs.

This is what is happening in this case as it happens during changing the case of allowing the rfp-operations-per-tick from 0 to 16, which then causes that server to forever desync again when a client joins until things are fully reset.

2 years ago
(updated 2 years ago)

Also, if you want lower UPS usage of the script then instead of processing some of the list every tick you could use the on_nth_tick (docs) callback and do it every 10 or 30 or 60 or whatever ticks instead, in exchange for a slightly slower response on making an explosion, which seems fine in this case.

2 years ago

Okay, the desync should be fixed now. I think.
I'm not using on_nth_tick because that causes minifreezes every time it runs instead of slightly lowering overall UPS. If there's still an issue with performance just turn the operations per tick setting down a bit.

2 years ago
(updated 2 years ago)

because that causes minifreezes every time it runs

o.O It never has here? Have you profiled it to see what's causing that (factorio has pretty good script profiling facilities via the commandline, I've used them to great effect).

And it looks like the events are registered globally now, doing a quick last look over things... I do see one issue, the stop variable is set globally based on the settings value, and then updated in on_init, what this means is that if a map is started with the settings value at 0, then it's update to be >0 then it will never update and actually start processing. You need another event callback for on settings changed to update the stop based on the new settings value. As it is now the map will never process if it's started on 0 to begin with as the global stop is updated based on that local variable instead of the other way (the global.stop should take precedence). Because of this though it is possible another desync could happen because the global.stop is updated based on a local variable instead of the other way first if the global.stop ~= nil. So that global.stop = stop line in on_init should probably be something like if global.stop == nil then global.stop = stop end or so, though the things with the global k and global entities seem a little odd too and could potentially cause on-join desyncs at times, but they are 'probably' safe enough. In general though, if a script local variable is just a short name of a global table variable then the global table value should be conditionally set first, then set the local from that one, not the other way.

But yeah, definitely need to handle the on settings changed callback to update the stop based on the new settings value so it can be enabled dynamically if it was disabled at startup. :-)

2 years ago
(updated 2 years ago)

because that causes minifreezes every time it runs

It never has here?

It's not noticeable, but instead of running for example 16 times every tick it would have to run 16*x times every x ticks, which doesn't really improve anything. Especially not smoothness or performance.
Regarding the other stuff, I decided to go the lazy way and removed all of the local variables, so now the mod is using the global ones directly. Should fix things. Also added the event hook for the setting change.

2 years ago

It's not noticeable, but instead of running for example 16 times every tick it would have to run 16*x times every x ticks, which doesn't really improve anything. Especially not smoothness or performance.

Eh, I wasn't implying to increase the rate, it's not like pipe connections change often so only checking, say, even 1 every half second will eventually catch any misset ones even if it takes a little longer. As it is now it's low enough it's not an issue, 0.1ms is fine enough even if still a touch higher than expected. :-)

Regarding the other stuff, I decided to go the lazy way and removed all of the local variables, so now the mod is using the global ones directly. Should fix things.

Ah awesome, that is the safest way to go. It's a "touch" slower on access but honestly not really anything measurable so don't worry about it unless you want to micro-optimize (but there's other better things to do than that if you go that route, lol).

Also added the event hook for the setting change.

Awesome, not looked at it yet but combined with the global vars this likely fixes all desync issues, I'll check on the next server restart. :-)

1 year, 10 months ago

How much UPS does it take for 1 max level reactor?

8 months ago

Reactor count doesn't really change UPS, nor does really the 'count' of anything, it's just the tick scripting handler that was causing it by scanning pipes.

New response