Adding fuel usage

Adding fuel usage for digging and building. Fuel storage hopper module
added to hold fuel.
This commit is contained in:
FaceDeer 2017-01-01 17:12:32 -07:00
parent 12748d2f89
commit 47e42801d2
9 changed files with 249 additions and 52 deletions

@ -45,6 +45,8 @@ Pusher Module
Aka the "can you rebuild it six inches to the left" module. This is a much simplified control module that does not trigger the digger or builder heads when right-clicked, it only moves the digging machine. It's up to you to ensure there's space for it to move into.
Since movement alone does not require fuel, a pusher module has no internal furnace.
Digger Head
-----------
@ -77,6 +79,20 @@ Inventory modules are not required for a digging-only machine. If there's not en
Digging machines can have multiple inventory modules added to expand their capacity.
Fuel Hopper Module
------------------
Digtrons have an appetite. Build operations and dig operations require a certain amount of fuel, and that fuel comes from fuel hopper modules. Note that movement does not require fuel, only digging and building.
When a control unit is triggered, it will tally up how much fuel is required for the next cycle and then burn items from the fuel hopper until a sufficient amount of heat has been generated to power the operation. Any leftover heat will be retained by the control unit for use in the next cycle; this is the "heat remaining in controller furnace". This means you don't have to worry too much about what kinds of fuel you put in the hopper, none will be wasted (unless you dig away a control unit with some heat remaining in it, that heat does get wasted).
The fuel costs for digging and building can be configured in the init.lua file. By default using one lump of coal as fuel a digtron can:
* Build 40 nodes
* Dig 40 stone nodes
* Dig 60 wood nodes
* Dig 80 dirt or sand nodes
Structural Module
-----------------

@ -8,15 +8,31 @@ dofile( minetest.get_modpath( "digtron" ) .. "/node_controllers.lua" ) -- contro
dofile( minetest.get_modpath( "digtron" ) .."/recipes.lua" )
digtron.refractory = 1.0 -- How long a digtron waits between cycles.
digtron.cycle_time = 1.0 -- How long a digtron waits between cycles.
digtron.traction_factor = 3.0 -- How many digtron nodes can be moved for each adjacent solid node that the digtron has traction against
-- fuel costs. For comparison, in the default game:
-- one default tree block is 30 units
-- one coal lump is 40 units
-- one coal block is 370 units (apparently it's slightly more productive making your coal lumps into blocks before burning)
-- one book is 3 units
local dig_cost_adjustment_factor = 0.5 -- across-the-board multiplier to make overall fuel costs easier to modify
digtron.dig_cost_default = 1.0 * dig_cost_adjustment_factor -- how much fuel is required to dig a node if not in one of the following groups.
-- If a node is in more than one of the following groups, the group with the maximum cost for that node is used.
digtron.dig_cost_cracky = 2.0 * dig_cost_adjustment_factor -- eg, stone
digtron.dig_cost_crumbly = 1.0 * dig_cost_adjustment_factor -- eg, dirt, sand
digtron.dig_cost_choppy = 1.5 * dig_cost_adjustment_factor -- eg, wood
digtron.build_cost = 1.0 -- how much fuel is required to build a node
-- digtron group numbers:
-- 1 - generic digtron node, nothing special is done with these. They're just dragged along.
-- 2 - inventory-holding digtron, has a "main" inventory that the digtron can add to and take from.
-- 3 - digger head, has an "execute_dig" method in its definition
-- 4 - builder head, has a "test_build" and "execute_build" method in its definition
-- 5 - fuel-holding digtron, has a "main" invetory that the control node can draw fuel items from. Separate from general inventory, nothing gets put here automatically.
minetest.register_lbm({
name = "digtron:sand_digger_upgrade",

@ -63,9 +63,9 @@ minetest.register_node("digtron:builder", {
"list[current_player;main;0,2.5;8,3;8]" ..
"listring[current_player;main]"
)
meta:set_string("period", 1)
meta:set_string("offset", 0)
meta:set_string("build_facing", 0)
meta:set_int("period", 1)
meta:set_int("offset", 0)
meta:set_int("build_facing", 0)
local inv = meta:get_inventory()
inv:set_size("main", 1)
@ -76,21 +76,21 @@ minetest.register_node("digtron:builder", {
local period = tonumber(fields.period)
local offset = tonumber(fields.offset)
if period and period > 0 then
meta:set_string("period", math.floor(tonumber(fields.period)))
meta:set_int("period", math.floor(tonumber(fields.period)))
end
if offset then
meta:set_string("offset", math.floor(tonumber(fields.offset)))
meta:set_int("offset", math.floor(tonumber(fields.offset)))
end
if fields.read then
local meta = minetest.get_meta(pos)
local facing = minetest.get_node(pos).param2
local buildpos = digtron.find_new_pos(pos, facing)
meta:set_string("build_facing", minetest.get_node(buildpos).param2)
meta:set_int("build_facing", minetest.get_node(buildpos).param2)
else
local build_facing = tonumber(fields.build_facing)
if build_facing and build_facing >= 0 and build_facing < 24 then
meta:set_string("build_facing", math.floor(build_facing))
meta:set_int("build_facing", math.floor(build_facing))
end
end
end,
@ -110,7 +110,7 @@ minetest.register_node("digtron:builder", {
local facing = minetest.get_node(pos).param2
local buildpos = digtron.find_new_pos(test_pos, facing)
if (buildpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then
if (buildpos[controlling_coordinate] + meta:get_int("offset")) % meta:get_int("period") ~= 0 then
--It's not the builder's turn to build right now.
return 0, nil
end
@ -152,11 +152,11 @@ minetest.register_node("digtron:builder", {
execute_build = function(pos, player, inventory_positions, protected_nodes, nodes_dug, controlling_coordinate, controller_pos)
local meta = minetest.get_meta(pos)
local build_facing = meta:get_string("build_facing")
local build_facing = meta:get_int("build_facing")
local facing = minetest.get_node(pos).param2
local buildpos = digtron.find_new_pos(pos, facing)
if (buildpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then
if (buildpos[controlling_coordinate] + meta:get_int("offset")) % meta:get_int("period") ~= 0 then
return nil
end
@ -174,13 +174,14 @@ minetest.register_node("digtron:builder", {
if success == true then
--flag this node as *not* to be dug.
nodes_dug:set(buildpos.x, buildpos.y, buildpos.z, false)
return true
else
--failed to build for some unknown reason. Put the item back in inventory.
--failed to build, target node probably obstructed. Put the item back in inventory.
digtron.place_in_specific_inventory(item_stack, sourcepos, inventory_positions, controller_pos)
return nil
end
end
end
return true -- no errors were encountered that we should notify the player about
end,
can_dig = function(pos,player)

@ -34,6 +34,12 @@ minetest.register_node("digtron:controller", {
fixed = controller_nodebox,
},
on_construct = function(pos)
local meta = minetest.env:get_meta(pos)
meta:set_float("fuel_burning", 0.0)
meta:set_string("infotext", "Heat remaining in controller furnace: 0")
end,
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos)
if meta:get_string("waiting") == "true" then
@ -63,6 +69,7 @@ minetest.register_node("digtron:controller", {
local nodes_dug = Pointset.create()
local items_dropped = {}
local digging_fuel_cost = 0
-- execute the execute_dig method on all digtron components that have one
-- This builds a set of nodes that will be dug and returns a list of products that will be generated
@ -72,12 +79,13 @@ minetest.register_node("digtron:controller", {
local target = minetest.get_node(location)
local targetdef = minetest.registered_nodes[target.name]
if targetdef.execute_dig ~= nil then
local dropped = targetdef.execute_dig(location, layout.protected, nodes_dug, controlling_coordinate)
local fuel_cost, dropped = targetdef.execute_dig(location, layout.protected, nodes_dug, controlling_coordinate)
if dropped ~= nil then
for _, itemname in pairs(dropped) do
table.insert(items_dropped, itemname)
end
end
digging_fuel_cost = digging_fuel_cost + fuel_cost
else
minetest.log(string.format("%s has digger group but is missing execute_dig method! This is an error in mod programming, file a bug.", targetdef.name))
end
@ -96,9 +104,9 @@ minetest.register_node("digtron:controller", {
end
if not can_move then
-- mark this node as waiting, will clear this flag in digtron.refractory seconds
-- mark this node as waiting, will clear this flag in digtron.cycle_time seconds
minetest.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory,
minetest.after(digtron.cycle_time,
function (pos)
minetest.get_meta(pos):set_string("waiting", nil)
end, pos
@ -114,10 +122,13 @@ minetest.register_node("digtron:controller", {
-- ask each builder node if it can get what it needs from inventory to build this cycle.
-- This is a complicated test because each builder needs to actually *take* the item it'll
-- need from inventory, and then we put it all back afterward.
-- Note that this test may overestimate the amount of work that will actually need to be done so don't treat its fuel cost as authoritative.
local can_build = true
local test_build_return_code = nil
local test_build_return_item = nil
local test_items = {}
local test_fuel_items = {}
local test_build_fuel_cost = 0
for k, location in pairs(layout.builders) do
local target = minetest.get_node(location)
local targetdef = minetest.registered_nodes[target.name]
@ -130,19 +141,34 @@ minetest.register_node("digtron:controller", {
end
if test_build_return_code == 1 then
table.insert(test_items, test_build_return_item)
test_build_fuel_cost = test_build_fuel_cost + digtron.build_cost
end
else
minetest.log(string.format("%s has builder group but is missing test_build method! This is an error in mod programming, file a bug.", targetdef.name))
end
end
local fuel_burning = meta:get_float("fuel_burning") -- get amount of burned fuel left over from last cycle
local test_fuel_needed = test_build_fuel_cost + digging_fuel_cost - fuel_burning
local test_fuel_burned = 0
if test_fuel_needed > 0 then
test_fuel_burned = digtron.burn(layout.fuelstores, test_fuel_needed, true)
end
--Put everything back where it came from
for k, item_return in pairs(test_items) do
--Put everything back where it came from
digtron.place_in_specific_inventory(item_return.item, item_return.location, layout.inventories, layout.controller)
end
if test_fuel_needed > fuel_burning + test_fuel_burned then
minetest.sound_play("buzzer", {gain=0.5, pos=pos})
meta:set_string("infotext", "Digtron needs more fuel")
return -- abort, don't dig and don't build.
end
if not can_build then
minetest.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory,
minetest.after(digtron.cycle_time,
function (pos)
minetest.get_meta(pos):set_string("waiting", nil)
end, pos
@ -181,18 +207,20 @@ minetest.register_node("digtron:controller", {
digtron.move_digtron(facing, layout.all, layout.extents, nodes_dug)
local oldpos = {x=pos.x, y=pos.y, z=pos.z}
pos = digtron.find_new_pos(pos, facing)
meta = minetest.get_meta(pos)
if move_player then
clicker:moveto(digtron.find_new_pos(player_pos, facing), true)
end
-- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong.
minetest.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory,
minetest.after(digtron.cycle_time,
function (pos)
minetest.get_meta(pos):set_string("waiting", nil)
end, pos
)
local building_fuel_cost = 0
local strange_failure = false
-- execute_build on all digtron components that have one
for k, location in pairs(layout.builders) do
@ -200,19 +228,36 @@ minetest.register_node("digtron:controller", {
local targetdef = minetest.registered_nodes[target.name]
if targetdef.execute_build ~= nil then
--using the old location of the controller as fallback so that any leftovers land with the rest of the digger output. Not that there should be any.
if targetdef.execute_build(location, clicker, layout.inventories, layout.protected, nodes_dug, controlling_coordinate, oldpos) == false then
-- Don't interrupt the build cycle as a whole, we've already moved so might as well try to complete as much as possible.
local build_return = targetdef.execute_build(location, clicker, layout.inventories, layout.protected, nodes_dug, controlling_coordinate, oldpos)
if build_return == false then
-- This happens if there's insufficient inventory, but we should have confirmed there was sufficient inventory during test phase.
-- So this should never happen. However, "should never happens" happen sometimes. So
-- don't interrupt the build cycle as a whole, we've already moved so might as well try to complete as much as possible.
strange_failure = true
elseif build_return == true then
building_fuel_cost = building_fuel_cost + digtron.build_cost
end
else
minetest.log(string.format("%s has builder group but is missing execute_build method! This is an error in mod programming, file a bug.", targetdef.name))
end
end
local status_text = ""
if strange_failure then
-- We weren't able to detect this build failure ahead of time, so make a big noise now. This is strange, shouldn't happen often.
-- We weren't able to detect this build failure ahead of time, so make a big noise now. This is strange, shouldn't happen.
minetest.sound_play("dingding", {gain=1.0, pos=pos})
minetest.sound_play("buzzer", {gain=0.5, pos=pos})
meta:set_string("infotext", "Digtron unexpectedly failed to execute a build operation.")
status_text = "Digtron unexpectedly failed to execute one or more build operations, likely due to an inventory error.\n"
end
-- acutally burn the fuel needed
fuel_burning = fuel_burning - (digging_fuel_cost + building_fuel_cost)
if fuel_burning < 0 then
fuel_burning = fuel_burning + digtron.burn(layout.fuelstores, -fuel_burning, false)
end
meta:set_float("fuel_burning", fuel_burning)
if not strange_failure then
meta:set_string("infotext", status_text .. string.format("Heat remaining in controller furnace: %d", fuel_burning))
end
-- finally, dig out any nodes remaining to be dug. Some of these will have had their flag revoked because
@ -292,9 +337,9 @@ minetest.register_node("digtron:pusher", {
end
if not can_move then
-- mark this node as waiting, will clear this flag in digtron.refractory seconds
-- mark this node as waiting, will clear this flag in digtron.cycle_time seconds
meta:set_string("waiting", "true")
minetest.after(digtron.refractory,
minetest.after(digtron.cycle_time,
function (pos)
minetest.get_meta(pos):set_string("waiting", nil)
end, pos
@ -326,7 +371,7 @@ minetest.register_node("digtron:pusher", {
-- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong.
minetest.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory,
minetest.after(digtron.cycle_time,
function (pos)
minetest.get_meta(pos):set_string("waiting", nil)
end, pos

@ -55,8 +55,8 @@ minetest.register_node("digtron:digger", {
"button_exit[2.2,0.5;1,0.1;set;Save]" ..
"tooltip[set;Saves settings]"
)
meta:set_string("period", 1)
meta:set_string("offset", 0)
meta:set_int("period", 1)
meta:set_int("offset", 0)
local inv = meta:get_inventory()
inv:set_size("main", 1)
@ -67,24 +67,25 @@ minetest.register_node("digtron:digger", {
local period = tonumber(fields.period)
local offset = tonumber(fields.offset)
if period and period > 0 then
meta:set_string("period", math.floor(tonumber(fields.period)))
meta:set_int("period", math.floor(tonumber(fields.period)))
end
if offset then
meta:set_string("offset", math.floor(tonumber(fields.offset)))
meta:set_int("offset", math.floor(tonumber(fields.offset)))
end
end,
-- returns fuel_cost, item_produced
execute_dig = function(pos, protected_nodes, nodes_dug, controlling_coordinate)
local facing = minetest.get_node(pos).param2
local digpos = digtron.find_new_pos(pos, facing)
if protected_nodes:get(digpos.x, digpos.y, digpos.z) then
return nil
return 0, nil
end
local meta = minetest.get_meta(pos)
if (digpos[controlling_coordinate] + meta:get_string("offset")) % meta:get_string("period") ~= 0 then
return nil
if (digpos[controlling_coordinate] + meta:get_int("offset")) % meta:get_int("period") ~= 0 then
return 0, nil
end
return digtron.mark_diggable(digpos, nodes_dug)
@ -134,7 +135,7 @@ minetest.register_node("digtron:soft_digger", {
local digpos = digtron.find_new_pos(pos, facing)
if protected_nodes:get(digpos.x, digpos.y, digpos.z) then
return nil
return 0, nil
end
local target_node = minetest.get_node(digpos)
@ -146,6 +147,6 @@ minetest.register_node("digtron:soft_digger", {
return digtron.mark_diggable(digpos, nodes_dug)
end
return nil
return 0, nil
end,
})

@ -58,21 +58,74 @@ minetest.register_node("digtron:inventory",
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"size[8,9]" ..
"size[8,9.3]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"list[current_name;main;0,0.3;8,4;]" ..
"list[current_player;main;0,4.85;8,1;]" ..
"list[current_player;main;0,6.08;8,3;8]" ..
"label[0,0;Inventory items]" ..
"list[current_name;main;0,0.6;8,4;]" ..
"list[current_player;main;0,5.15;8,1;]" ..
"list[current_player;main;0,6.38;8,3;8]" ..
"listring[current_name;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85)
default.get_hotbar_bg(0,5.15)
)
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
return inv:is_empty("main")
end,
})
-- Fuel storage. Controller node draws fuel from here.
-- Note that fuel stores are digtron group 5.
minetest.register_node("digtron:fuelstore",
{
description = "Digtron Fuel Hopper",
groups = {cracky = 3, stone = 1, digtron = 5},
drop = 'digtron:fuelstore',
paramtype2= 'facedir',
tiles = {"digtron_fuelstore.png"},
on_construct = function(pos)
local meta = minetest.get_meta(pos)
meta:set_string("formspec",
"size[8,9.3]" ..
default.gui_bg ..
default.gui_bg_img ..
default.gui_slots ..
"label[0,0;Fuel items]" ..
"list[current_name;main;0,0.6;8,4;]" ..
"list[current_player;main;0,5.15;8,1;]" ..
"list[current_player;main;0,6.38;8,3;8]" ..
"listring[current_name;main]" ..
"listring[current_player;main]" ..
default.get_hotbar_bg(0,5.15)
)
local inv = meta:get_inventory()
inv:set_size("main", 8*4)
end,
-- Only allow fuel items to be placed in here
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
if minetest.is_protected(pos, player:get_player_name()) then
return 0
end
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
if listname == "main" then
if minetest.get_craft_result({method="fuel", width=1, items={stack}}).time ~= 0 then
return stack:get_count()
else
return 0
end
end
end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()

@ -66,6 +66,15 @@ minetest.register_craft({
}
})
minetest.register_craft({
output = "digtron:fuelstore",
recipe = {
{"","default:furnace",""},
{"","digtron:digtron_core",""},
{"","",""}
}
})
minetest.register_craft({
output = "digtron:structure",
recipe = {

Binary file not shown.

After

Width:  |  Height:  |  Size: 760 B

@ -19,23 +19,41 @@ digtron.mark_diggable = function(pos, nodes_dug)
-- Don't *actually* dig the node yet, though, because if we dig a node with sand over it the sand will start falling
-- and then destroy whatever node we place there subsequently (either by a builder head or by moving a digtron node)
-- I don't like sand. It's coarse and rough and irritating and it gets everywhere. And it necessitates complicated dig routines.
-- returns what will be dropped by digging these nodes.
-- returns fuel cost and what will be dropped by digging these nodes.
local target = minetest.get_node(pos)
-- prevent digtrons from being marked for digging.
if minetest.get_item_group(target.name, "digtron") ~= 0 then
return nil
return 0, nil
end
local targetdef = minetest.registered_nodes[target.name]
if targetdef.can_dig == nil or targetdef.can_dig(pos, player) then
nodes_dug:set(pos.x, pos.y, pos.z, true)
if target.name ~= "air" then
return minetest.get_node_drops(target.name, "")
local in_known_group = false
local material_cost = 0
if minetest.get_item_group(target.name, "cracky") ~= 0 then
in_known_group = true
material_cost = math.max(material_cost, digtron.dig_cost_cracky)
end
if minetest.get_item_group(target.name, "crumbly") ~= 0 then
in_known_group = true
material_cost = math.max(material_cost, digtron.dig_cost_crumbly)
end
if minetest.get_item_group(target.name, "choppy") ~= 0 then
in_known_group = true
material_cost = math.max(material_cost, digtron.dig_cost_choppy)
end
if not in_known_group then
material_cost = digtron.dig_cost_default
end
return material_cost, minetest.get_node_drops(target.name, "")
end
end
return nil
return 0, nil
end
digtron.can_build_to = function(pos, protected_nodes, dug_nodes)
@ -81,10 +99,12 @@ digtron.move_node = function(pos, newpos)
newinv:set_list("main", list)
newmeta:set_string("formspec", oldformspec)
newmeta:set_string("offset", oldmeta:get_string("offset"))
newmeta:set_string("period", oldmeta:get_string("period"))
newmeta:set_string("build_facing", oldmeta:get_string("build_facing"))
newmeta:set_int("offset", oldmeta:get_int("offset"))
newmeta:set_int("period", oldmeta:get_int("period"))
newmeta:set_int("build_facing", oldmeta:get_int("build_facing"))
newmeta:set_float("fuel_burning", oldmeta:get_float("fuel_burning"))
newmeta:set_string("infotext", oldmeta:get_string("infotext"))
-- remove node from old position
minetest.remove_node(pos)
end
@ -92,13 +112,12 @@ end
digtron.get_all_digtron_neighbours = function(pos, player)
-- returns table containing a list of all digtron node locations, lists of special digtron node types, a table of the coordinate extents of the digtron array, a Pointset of protected nodes, and a number to determine how many adjacent solid non-digtron nodes there are (for traction)
--minetest.debug(string.format("digtron search started at component %d %d %d", pos.x, pos.y, pos.z))
local layout = {}
--initialize. We're assuming that the start position is a controller digtron, should be a safe assumption since only the controller node should call this
layout.traction = 0
layout.all = {}
layout.inventories = {}
layout.fuelstores = {}
layout.diggers = {}
layout.builders = {}
layout.extents = {}
@ -148,7 +167,6 @@ digtron.get_all_digtron_neighbours = function(pos, player)
local group_number = minetest.get_item_group(node.name, "digtron")
if group_number > 0 then
--minetest.debug(string.format("found digtron component at %d %d %d", testpos.x, testpos.y, testpos.z))
--found one. Add it to the digtrons output
table.insert(layout.all, testpos)
@ -167,6 +185,8 @@ digtron.get_all_digtron_neighbours = function(pos, player)
table.insert(layout.diggers, testpos)
elseif group_number == 4 then
table.insert(layout.builders, testpos)
elseif group_number == 5 then
table.insert(layout.fuelstores, testpos)
end
--queue up potential new test points adjacent to this digtron node
@ -309,4 +329,40 @@ digtron.get_controlling_coordinate = function(pos, facedir)
else
return "y"
end
end
-- Searches fuel store inventories for burnable items and burns them until target is reached or surpassed (or there's nothing left to burn). Returns the total fuel value burned
-- if the "test" parameter is set to true, doesn't actually take anything out of inventories. We can get away with this sort of thing for fuel but not for builder inventory because there's just one
-- controller node burning stuff, not multiple build heads drawing from inventories in turn. Much simpler.
digtron.burn = function(fuelstore_positions, target, test)
local current_burned = 0
for k, location in pairs(fuelstore_positions) do
if current_burned > target then
break
end
local inv = minetest.get_inventory({type="node", pos=location})
local invlist = inv:get_list("main")
for i, itemstack in pairs(invlist) do
local fuel_per_item = minetest.get_craft_result({method="fuel", width=1, items={itemstack:peek_item(1)}}).time
if fuel_per_item ~= 0 then
local actual_burned = math.min(
math.ceil((target - current_burned)/fuel_per_item ), -- burn this many, if we can.
itemstack:get_count() -- how many we have at most.
)
if test ~= true then
-- don't bother recording the items if we're just testing, nothing is actually being removed.
itemstack:set_count(itemstack:get_count() - actual_burned)
end
current_burned = current_burned + actual_burned * fuel_per_item
end
if current_burned > target then
break
end
end
if test ~= true then
-- only update the list if we're doing this for real.
inv:set_list("main", invlist)
end
end
return current_burned
end