Code Monkey home page Code Monkey logo

factorio-auto-resource-redux's People

Contributors

bengardner avatar udf avatar

Stargazers

 avatar  avatar  avatar

Watchers

 avatar  avatar  avatar

factorio-auto-resource-redux's Issues

Save item priority

They can be persisted via the player's mod settings (only save when editing). Upon joining a force, the player's settings would be applied if the force has not already changed a particular priority list (would need a new flag for if a list was changed, or we could deep compare with the stock list because it's not a frequent code path). Only the item order and quantities would be saved/loaded.

GUI Syncing

Currently only the item priority list updates for every player when a change is made. It would be nice if every GUI behaved like this. Note that vanilla does not have this behavior, despite it being intuitive.

To extend that implementation to every GUI, we would need a function that walks the component tree and tags every interactable component (buttons, inputs, etc) with it's position in the tree, for example a button in a frame in the ABC GUI would have a key like "ABC.1.1". These can then be stored into globals, keyed by the player ID:

{ ["ABC.1.1"] = { [player_id] = component } }

We would also need to tag the component with our event handler, then after its own handlers are called our handler can update every similar component by referencing the table in globals.

The item priority list can use this implementation by tagging its table with a special key, something like mpgui_fn = "blabla". Our code would then propagate that tag to every child component so that the relevant handler can be called. This would allow our code to make the item priority list clear and recreate every player's components (it would have to call our code to re-propagate the tags after clearing).

Unified Variable Rate Service Queue

Servicing items only when they need it can save a bunch of CPU time.

The Item Network has a unified service queue. It would pull off and service 20 items per tick.
That scales really well, but the service rate gets a bit slow. 2000 entities at 120 entities per second => 16.6 seconds between service.
It was observed that most items don't need to be serviced that often. We considered using multiple queues to separate out high-priority items from low-priority.

My fork added a priority based queue, with 32 queues that span 20 ticks each. Servicing 20 entities per tick means 400 items per queue or 12,800 entities before it can no longer keep up. In my game runs, I didn't get near that limit, so I deemed that 'good enough'.

The max time between services was ~10.6 seconds (32 * 20 / 60).
Most items don't need to be serviced more often than every 10 seconds.
Some could go even longer. Some need to be serviced every few seconds.

The entity queue is a simple circular queue of tables, each with a 'deadline'. Each entity has a priority and the bucket is determined by the priority. If the current table index is 1, then priority=0 would put it at index 2, priority=1 is at index 3, etc.
Entities are pulled from the current queue until empty AND the deadline has been reached.
Then it goes to the next queue index.

Pretty simple stuff, but I had trouble fine-tuning the priorities.
I ended up adjusting the priority up or down by 1 depending on the state. It would also peg the priority to the max in some instanced.
For example, if a provider chest was full at service time and was empty after service, the priority would be increased (-1), as it is filling faster than it could be emptied. If the chest was over half-full and then emptied, then the priority would stay the same. If it was less than half-full, then the priority would be lowered (+1). If it couldn't be emptied (global item limit), then the priority would go to the lowest value.
Assemblers were treated in a similar manner. Ingredients were calculated based on the elapsed time since the last service. The priority was only increased if the input ingredients were maxed out and still ran out before service. Likewise with the output, If it was full, then the priority would increase to service the assembler more often.

Since then, I changed the Service Queue again to be a tick-based deadline queue. When an entity is queued, it will be serviced on the requested tick or later (due to overload.)

Anyway, this is getting a bit long, but ARR is using a bunch of independent service queues. It doesn't appear to vary the service rate. The net effect is that this will run into performance issues when there are too many entities.

I'll probably end up ripping out the current queues and replacing them with a unified queue at some point in my fork. That change will break any hope of keeping my fork in sync. Same thing happened with my fork of Item Network. My changes were too much to merge back upstream.

Anyway, so my question is: would a unified deadline-based service queue this be something of interest for this mod?

We'd have to:

  • add the unified service queue (That part is easy!)
  • change each entity service function to return the number of desired ticks until the next service

If interested, I'll try to implement it in small review-able chunks. The various queues will be merged one at a time.

Auto-detect fluid (water, steam)

I have been toying with a fork of Item Network for quite a while.
I oddly ended up with something that was nearly the same as this mod, but not as refined. (And a lot more of a cheat.)
I started pulling in the 'better' features from this mod and then decided it might be quicker to go the other way.

One of the features I added that I really love is the auto-configuration of requester pipes based on the fluid box requirement.
Most of that had to do with assemblers, which doesn't apply here since this mod directly adds fluids to the assembling machine.

However, boilers and steam engines don't seem to auto populate with steam or water.
I think some sort of auto-config would be useful for those cases.

The logic isn't terribly complicated:

  • the requester pipe/tank starts in 'auto' mode (not configured).
  • on each service, it scans the connected fluid boxes looking for requests.
  • if it finds demand for exactly one fluid, then the pipe/tank is reconfigured to request that fluid

On the other side, when the assembler changes recipe, it resets any directly-connected pipe/tank to auto mode.
I'm not sure that applies here, as the assemblers don't need a requester pipe.

The net effect is that I rarely needed to configure a requester pipe.

Is there any interest in that feature? I think it would be helpful for water/steam.

The last WIP code, for reference (ugly, but functional).
https://github.com/bengardner/item-network-factorio-mod/blob/arr-entity-gui/src/NetworkTankAutoConfig.lua

Resource trend icons

It can be hard to tell if a resource shortage is recovering without staring at the resource list for a couple of seconds.
image

Little arrow icons like this could help. I'm not sure what to base them on, probably the delta between the current value of a rolling average and its value ~5 seconds ago.

The icons would need to be composited onto every item icon in the data stage, as there doesn't seem to be another way to do it (the cleanest way would be a way to stack GUI elements but I don't think that's possible).

Non-recoverable error

The mod Auto Resource Redux (0.0.6) caused a non-recoverable error.
Please report this error to the mod author.

Error while running event auto-resource-redux::on_nth_tick(1)
LuaGuiElement doesn't contain key toggled.
stack traceback:
[C]: in function '__newindex'
auto-resource-redux/src/GUIResourceList.lua:130: in function 'update_gui'
auto-resource-redux/src/GUIResourceList.lua:158: in function 'on_tick'
auto-resource-redux/control.lua:47: in function <auto-resource-redux/control.lua:38>

bug

i got two bug with v0.0.5 + SE mod and their dependencies, first when i tried to change a value of fuel and second when i drop item to auto resource storage chest. here's the error code i received.

The mod Auto Resource Redux (0.0.5) caused a non-recoverable error.
Please report this error to the mod author.

this is the first bug
The mod Auto Resource Redux (0.0.5) caused a non-recoverable error.
Please report this error to the mod author.

Error while running event auto-resource-redux::on_gui_click (ID 1)
LuaGuiElement doesn't contain key toggled.
stack traceback:
[C]: in function '__newindex'
auto-resource-redux/src/GUIComponentItemPrioritySet.lua:81: in function 'update_buttons'
auto-resource-redux/src/GUIComponentItemPrioritySet.lua:114: in function 'update_components'
auto-resource-redux/src/GUIComponentItemPrioritySet.lua:249: in function 'handler'
auto-resource-redux/src/GUIDispatcher.lua:49: in function <auto-resource-redux/src/GUIDispatcher.lua:36>

and this is the second
Error while running event auto-resource-redux::on_nth_tick(1)
LuaGuiElement doesn't contain key toggled.
stack traceback:
[C]: in function '__newindex'
auto-resource-redux/src/GUIResourceList.lua:130: in function 'update_gui'
auto-resource-redux/src/GUIResourceList.lua:158: in function 'on_tick'
auto-resource-redux/control.lua:47: in function <auto-resource-redux/control.lua:38>

Reorder-able resource gui

Right click the gear to enter reorder mode, which adds up/down arrows to each category table (probably also set style to bordered table to make the separation clearer). Saved in the player's mod settings. It is unknown if subcategory rows would need to be reordered.

Mining Drill - add fluid

There is a comment about not being able to get the mining fluid easily. It references a 2017 forum post.

    -- there is no easy way to know what fluid a miner wants, the fluid is a property of the ore's prototype
    -- and the expected resources aren't simple to find: https://forums.factorio.com/viewtopic.php?p=247019
    -- so it will have to be done manually using the fluid access tank

However, the game has since added the entity.mining_target field. It is now rather easy to get the mining fluid.

Just for a demo, I added this print code.

function EntityHandlers.handle_mining_drill(o)
   ...
  if #o.entity.fluidbox > 0 then
    local target = o.entity.mining_target
    if target ~= nil then
      local dfluid = target.prototype.mineable_properties.required_fluid
      if dfluid ~= nil then
        print(("Drill @ %s requires %s"):format(serpent.line(o.entity.position), dfluid))
      end
    end

And see output like:

Drill @ {x = -239.5, y = -50.5} requires sulfuric-acid

I used that in the 'auto-configure requester tank' PR. #10

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.