Skip to content

Commit

Permalink
save new fuel GUI
Browse files Browse the repository at this point in the history
  • Loading branch information
bengardner committed Feb 16, 2024
1 parent 0ade9ed commit 6fa2930
Show file tree
Hide file tree
Showing 13 changed files with 513 additions and 59 deletions.
89 changes: 74 additions & 15 deletions src/GlobalState.lua
Original file line number Diff line number Diff line change
Expand Up @@ -141,6 +141,12 @@ function M.inner_setup()
global.mod.mine_queue = {}
end

-- used to configure the preferred fuels for an entity
-- key=entity name, val={ preferred=name, blocked={ name=true }}
if global.mod.fuel_config == nil then
global.mod.fuel_config = {}
end

-- scan prototypes to see if we need to rescan all surfaces
local name_service_map = M.scan_prototypes()
if true or not tables_have_same_keys(name_service_map, global.name_service_map) then
Expand Down Expand Up @@ -405,6 +411,7 @@ function M.remove_old_ui()
end
end
end

end

-------------------------------------------------------------------------------
Expand Down Expand Up @@ -1207,23 +1214,25 @@ function M.auto_network_chest(entity)
return requests, provides
end

-------------------------------------------------------------------------------

function M.get_fuel_table()
if global.fuel_table == nil then
local fuels = {} -- array { name=name, val=energy per stack, cat=category }
for _, prot in pairs(game.item_prototypes) do
local fc = prot.fuel_category
if fc ~= nil then
local value = prot.fuel_value
-- HACK: make processed-fuel preferrible to nearly everything, coke not wanted
if prot.name == 'processed-fuel' then
value = value * 100
elseif prot.name == 'coke' then
value = value / 10
end
--table.insert(fuels, { name=prot.name, val=prot.stack_size * prot.fuel_value, cat=fc })
table.insert(fuels, { name=prot.name, val=value, cat=fc })
for _, prot in pairs(game.item_prototypes) do
local fc = prot.fuel_category
if fc ~= nil and not prot.has_flag("hidden") then
local value = prot.fuel_value
-- HACK: make processed-fuel preferrible to nearly everything, coke not wanted
if prot.name == 'processed-fuel' then
value = value * 100
elseif prot.name == 'coke' then
value = value / 10
end
--table.insert(fuels, { name=prot.name, val=prot.stack_size * prot.fuel_value, cat=fc })
table.insert(fuels, { name=prot.name, val=value, cat=fc })
end
end
table.sort(fuels, function (a, b) return a.val > b.val end)

print(string.format("fuel table: %s", serpent.line(fuels)))
Expand All @@ -1232,7 +1241,29 @@ function M.get_fuel_table()
return global.fuel_table
end

function M.fuel_config_get(entity_name)
return global.mod.fuel_config[entity_name] or {}
end

function M.fuel_config_set(entity_name, config)
-- fuel config has 2 members: preferred:string, blocked:{name=true}
global.mod.fuel_config[entity_name] = config
end

function M.get_best_available_fuel(entity)
local config = M.fuel_config_get(entity.name)

-- check for the preferred fuel first
local fuel_name = config.preferred
if fuel_name ~= nil then
-- TODO: verify that the fuel is still valid
local n_avail = M.get_item_count(fuel_name)
if n_avail > 0 then
-- clog("FUEL: %s preferred fuel %s and we have %s", entity.name, fuel_name, n_avail)
return fuel_name, n_avail
end
end

--clog("called get best fuel on %s", entity.name)
local bprot = entity.prototype.burner_prototype
if bprot ~= nil then
Expand All @@ -1241,7 +1272,7 @@ function M.get_best_available_fuel(entity)
local ff = M.get_fuel_table()
--clog(" fuel tab: %s", serpent.line(ff))
for _, fuel in ipairs(ff) do
if fct[fuel.cat] ~= nil then
if fct[fuel.cat] ~= nil and config[fuel.name] ~= true then
local n_avail = M.get_item_count(fuel.name)
if n_avail > 0 then
--clog("FUEL: %s can use %s and we have %s", entity.name, fuel.name, n_avail)
Expand Down Expand Up @@ -1448,12 +1479,14 @@ function M.scan_prototypes()
}

if true or settings.global["item-network-service-assemblers"].value then
clog("Adding 'assembling-machine' to the list")
-- clog("Adding 'assembling-machine' to the list")
type_to_service["assembling-machine"] = "assembling-machine"
end

for _, prot in pairs(game.entity_prototypes) do
if prot.type == "logistic-container" then
if prot.has_flag("hidden") or not prot.has_flag("player-creation") then
-- not ading it
elseif prot.type == "logistic-container" then
--if prot.logistic_mode == "requester" or prot.logistic_mode == "buffer" or prot.logistic_mode == "storage" then
name_to_service[prot.name] = "logistic-chest-" .. prot.logistic_mode
--elseif prot.logistic_mode == "active-provider" then
Expand Down Expand Up @@ -1501,6 +1534,32 @@ function M.scan_surfaces()
clog("[%s] item-network: Scanning complete", game.tick)
end

--[[
Determine the recipe name based on ore based on the inputs, last_recipe or info.ore_name
]]
function M.furnace_get_ore_recipe(ore_name)
local o2fr = global.ore_to_furnce_recipe
if o2fr == nil then
o2fr = {}
global.ore_to_furnce_recipe = o2fr

-- for a recipe to be valid for a furnace, it must be a "smelting" and have one ingredient.
-- assume assembbles will be used for anything else
for _, recipe in pairs(game.recipe_prototypes) do
if recipe.category == 'smelting' and #recipe.ingredients == 1 then
local ing = recipe.ingredients[1]
print(string.format("FURNACE RECIPE %s => %s %s", recipe.name, ing.name, ing.amount))
o2fr[ing.name] = recipe.name
end
end
print(serpent.line(o2fr))
end
local recipe_name = o2fr[ore_name]
if recipe_name ~= nil then
return game.recipe_prototypes[recipe_name]
end
end

-------------------------------------------------------------------------------

-- not sure this belongs here...
Expand Down
8 changes: 7 additions & 1 deletion src/GuiManager.lua
Original file line number Diff line number Diff line change
Expand Up @@ -8,9 +8,15 @@ local GlobalState = require "src.GlobalState"
local clog = require("src.log_console").log

local GuiManager = {}

local GuiManager__metatable = {
__index = GuiManager
}
script.register_metatable("GuiManager", GuiManager__metatable)

function GuiManager.new(name)
local self = { name=name }
return setmetatable(self, { __index = GuiManager })
return setmetatable(self, GuiManager__metatable)
end

function GuiManager:get(player_index)
Expand Down
2 changes: 2 additions & 0 deletions src/NetworkViewUi.lua
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ local UiNetworkItems = require "src.UiNetworkItems"
local UiNetworkFluid = require "src.UiNetworkFluid"
local UiNetworkLimits = require "src.UiNetworkLimits"
local UiNetworkShortages = require "src.UiNetworkShortages"
local UiNetworkFuels = require "src.UiNetworkFuels"
local clog = require("src.log_console").log

local M = {}
Expand Down Expand Up @@ -173,6 +174,7 @@ function M.open_main_frame(player_index)
add_tab("Fluids", UiNetworkFluid)
add_tab("Shortages", UiNetworkShortages)
add_tab("Limits", UiNetworkLimits)
add_tab("Fuels", UiNetworkFuels)

-- select "items" (not really needed, as that is the default)
tabbed_pane.selected_tab_index = 1
Expand Down
3 changes: 0 additions & 3 deletions src/NetworkViewUi_test.lua
Original file line number Diff line number Diff line change
Expand Up @@ -745,9 +745,6 @@ local function update_player_selected(player)
end
end

if ent.name == "entity-ghost" then
end

if false then -- need 'pipe-connectable' entity
local nn = ent.neighbours
if nn ~= nil then
Expand Down
148 changes: 118 additions & 30 deletions src/ServiceEntity.lua
Original file line number Diff line number Diff line change
Expand Up @@ -69,46 +69,78 @@ local promote_fuel = {
coal = 'processed-fuel',
}


local function service_refuel_empty(entity, inv)
local fuel_name, n_avail = GlobalState.get_best_available_fuel(entity)
if fuel_name == nil or n_avail == nil then
return
end
--sclog("best fuel for %s is %s and we have %s", entity.name, fuel_name, n_avail)
if n_avail > 0 then
local prot = game.item_prototypes[fuel_name]
local n_add = (#inv * prot.stack_size) -- - 12
transfer_item_to_inv(entity, inv, fuel_name, math.min(n_avail, n_add))
end
return
end

--[[
Add fuel to the entity.
If empty, we pick the best available fuel and add that.
If non-empty, we top off the current fuel.
- preferred
- not blocked
If non-empty, we check to make sure the current fuel is not blocked.
If blocked, we remove it.
If not preferred and we have the preferred fuel, then remove the fuel.
Ideally, the amount of fuel would be enough for 3 * service period ticks.
]]
local function service_refuel(entity, inv)
if inv.is_empty() then
local fuel_name, n_avail = GlobalState.get_best_available_fuel(entity)
if fuel_name == nil or n_avail == nil then
return
local cfg = GlobalState.fuel_config_get(entity.name)
local preferred = cfg.preferred

-- See if we need to purge non-preferred fuel
local purge = false
if preferred ~= nil then
local n_avail = GlobalState.get_item_count(preferred)
if n_avail > 5 then
purge = true
end
--sclog("best fuel for %s is %s and we have %s", entity.name, fuel_name, n_avail)
if n_avail > 0 then
local prot = game.item_prototypes[fuel_name]
local n_add = (#inv * prot.stack_size) -- - 12
transfer_item_to_inv(entity, inv, fuel_name, math.min(n_avail, n_add))
end

-- remove unwanted fuel
local contents = inv.get_contents()
for fuel, count in pairs(contents) do
-- if blocked or we are purging and the fuel isn't preferred
if cfg[fuel] == true or (purge and fuel ~= preferred) then
local n_taken = inv.remove({name=fuel, count=count})
if n_taken > 0 then
GlobalState.increment_item_count(fuel, n_taken)
if n_taken == count then
contents[fuel] = nil
else
contents[fuel] = count - n_taken
end
end
end
end

-- We might have just removed all fuel
if next(contents) == nil then
service_refuel_empty(entity, inv)
return
else
-- try to top off the fuel(s)
for fuel, _ in ipairs(inv.get_contents()) do
local fuel_prot = game.item_prototypes[fuel]
if fuel_prot ~= nil then
local n_need = inv.get_insertable_count(fuel) - 12
-- start requesting when fuel is below 1/2 stack
if n_need > fuel_prot.stack_size / 2 then
local promo = promote_fuel[fuel]
if promo ~= nil then
local fcnt = GlobalState.get_item_count(promo)
if fcnt > 10 then
GlobalState.items_inv_to_net(inv)
transfer_item_to_inv(entity, inv, promo, math.min(fcnt, 20))
return
end
end
transfer_item_to_inv(entity, inv, fuel, n_need)
end
end

-- try to top off existing fuel(s)
for fuel, count in pairs(contents) do
local fuel_prot = game.item_prototypes[fuel]
if fuel_prot ~= nil then
local n_need = inv.get_insertable_count(fuel) - 12
-- start requesting when fuel is below 1/2 stack
if n_need > fuel_prot.stack_size / 2 then
transfer_item_to_inv(entity, inv, fuel, n_need)
end
end
end
Expand Down Expand Up @@ -457,6 +489,17 @@ local function assembling_machine_clone(dst_info, src_info)
assembling_machine_paste(dst_info, src_info.entity)
end

local ore_to_furnce_recipe

--[[
Determine the recipe name based on ore based on the inputs, last_recipe or info.ore_name
]]
function M.furnace_get_ore_recipe(ore_name)
local recipe_name = GlobalState.furnace_get_ore_recipe(ore_name)
-- go with whatever was last configured (inputs and outputs are empty)
return info.ore_name
end

-- determine the ore based on the inputs, last_recipe or info.ore_name
function M.furnace_get_ore(info)
local entity = info.entity
Expand All @@ -481,6 +524,41 @@ function M.furnace_get_ore(info)
return info.ore_name
end

--[[
Get the required refill level.
]]
function M.furnace_get_ore_count(info)
if info.ore_name == nil then
return nil
end
local recipe = GlobalState.furnace_get_ore_recipe(info.ore_name)
if recipe == nil then
return nil
end

local rtime = recipe.energy / info.entity.crafting_speed -- time to finish one recipe
local svc_ticks = info.service_tick_delta or (10 * 60) -- assume 60 seconds on first service
local mult = math.ceil(svc_ticks / (rtime * 60))

local ing = recipe.ingredients[1]
--print(string.format("Furnace: name=%s amount=%s mult=%s", ing.name, ing.amount, mult))
return ing.amount * mult
end

--[[
This services a furnace.
- adds fuel
- removes burnt results
- removes output
- adds ore
NOTE that we can't get the current recipe.
Determining the ore to add:
- same ore(s) as is currently present in the input
- record in info.ore_name
- use info.ore_name
- check the output
]]
function M.furnace_update(info)
local entity = info.entity

Expand Down Expand Up @@ -525,7 +603,14 @@ function M.furnace_update(info)
end

if info.ore_name ~= nil then
transfer_item_to_inv_max(entity, inv_src, info.ore_name)
local ore_count = M.furnace_get_ore_count(info)
if ore_count ~= nil then
--print(string.format("ore level: %s %s", info.ore_name, ore_count))
transfer_item_to_inv_level(entity, inv_src, info.ore_name, ore_count)
else
--print(string.format("ore max: %s", info.ore_name))
transfer_item_to_inv_max(entity, inv_src, info.ore_name)
end
end
return GlobalState.UPDATE_STATUS.UPDATE_PRI_MAX
end
Expand Down Expand Up @@ -625,7 +710,10 @@ function M.lab_service(info)
return
end

-- try to load each lib_input at a minimum level
-- clog("lab inputs: %s", serpent.line(entity.prototype.lab_inputs))
for _, item in ipairs(entity.prototype.lab_inputs) do
-- want to check force.technologies, but that is not accurate
transfer_item_to_inv_level(entity, inv, item, 10)
end

Expand Down
Loading

0 comments on commit 6fa2930

Please sign in to comment.