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. 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 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. 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 Structural Module
----------------- -----------------

@ -8,15 +8,31 @@ dofile( minetest.get_modpath( "digtron" ) .. "/node_controllers.lua" ) -- contro
dofile( minetest.get_modpath( "digtron" ) .."/recipes.lua" ) 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 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: -- digtron group numbers:
-- 1 - generic digtron node, nothing special is done with these. They're just dragged along. -- 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. -- 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 -- 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 -- 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({ minetest.register_lbm({
name = "digtron:sand_digger_upgrade", name = "digtron:sand_digger_upgrade",

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

@ -34,6 +34,12 @@ minetest.register_node("digtron:controller", {
fixed = controller_nodebox, 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) on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_string("waiting") == "true" then if meta:get_string("waiting") == "true" then
@ -63,6 +69,7 @@ minetest.register_node("digtron:controller", {
local nodes_dug = Pointset.create() local nodes_dug = Pointset.create()
local items_dropped = {} local items_dropped = {}
local digging_fuel_cost = 0
-- execute the execute_dig method on all digtron components that have one -- 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 -- 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 target = minetest.get_node(location)
local targetdef = minetest.registered_nodes[target.name] local targetdef = minetest.registered_nodes[target.name]
if targetdef.execute_dig ~= nil then 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 if dropped ~= nil then
for _, itemname in pairs(dropped) do for _, itemname in pairs(dropped) do
table.insert(items_dropped, itemname) table.insert(items_dropped, itemname)
end end
end end
digging_fuel_cost = digging_fuel_cost + fuel_cost
else 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)) 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 end
@ -96,9 +104,9 @@ minetest.register_node("digtron:controller", {
end end
if not can_move then 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.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory, minetest.after(digtron.cycle_time,
function (pos) function (pos)
minetest.get_meta(pos):set_string("waiting", nil) minetest.get_meta(pos):set_string("waiting", nil)
end, pos 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. -- 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 -- 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. -- 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 can_build = true
local test_build_return_code = nil local test_build_return_code = nil
local test_build_return_item = nil local test_build_return_item = nil
local test_items = {} local test_items = {}
local test_fuel_items = {}
local test_build_fuel_cost = 0
for k, location in pairs(layout.builders) do for k, location in pairs(layout.builders) do
local target = minetest.get_node(location) local target = minetest.get_node(location)
local targetdef = minetest.registered_nodes[target.name] local targetdef = minetest.registered_nodes[target.name]
@ -130,19 +141,34 @@ minetest.register_node("digtron:controller", {
end end
if test_build_return_code == 1 then if test_build_return_code == 1 then
table.insert(test_items, test_build_return_item) table.insert(test_items, test_build_return_item)
test_build_fuel_cost = test_build_fuel_cost + digtron.build_cost
end end
else 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)) 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
end end
for k, item_return in pairs(test_items) do
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 --Put everything back where it came from
for k, item_return in pairs(test_items) do
digtron.place_in_specific_inventory(item_return.item, item_return.location, layout.inventories, layout.controller) digtron.place_in_specific_inventory(item_return.item, item_return.location, layout.inventories, layout.controller)
end 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 if not can_build then
minetest.get_meta(pos):set_string("waiting", "true") minetest.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory, minetest.after(digtron.cycle_time,
function (pos) function (pos)
minetest.get_meta(pos):set_string("waiting", nil) minetest.get_meta(pos):set_string("waiting", nil)
end, pos end, pos
@ -181,18 +207,20 @@ minetest.register_node("digtron:controller", {
digtron.move_digtron(facing, layout.all, layout.extents, nodes_dug) digtron.move_digtron(facing, layout.all, layout.extents, nodes_dug)
local oldpos = {x=pos.x, y=pos.y, z=pos.z} local oldpos = {x=pos.x, y=pos.y, z=pos.z}
pos = digtron.find_new_pos(pos, facing) pos = digtron.find_new_pos(pos, facing)
meta = minetest.get_meta(pos)
if move_player then if move_player then
clicker:moveto(digtron.find_new_pos(player_pos, facing), true) clicker:moveto(digtron.find_new_pos(player_pos, facing), true)
end end
-- Start the delay before digtron can run again. Do this after moving the array or pos will be wrong. -- 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.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory, minetest.after(digtron.cycle_time,
function (pos) function (pos)
minetest.get_meta(pos):set_string("waiting", nil) minetest.get_meta(pos):set_string("waiting", nil)
end, pos end, pos
) )
local building_fuel_cost = 0
local strange_failure = false local strange_failure = false
-- execute_build on all digtron components that have one -- execute_build on all digtron components that have one
for k, location in pairs(layout.builders) do for k, location in pairs(layout.builders) do
@ -200,19 +228,36 @@ minetest.register_node("digtron:controller", {
local targetdef = minetest.registered_nodes[target.name] local targetdef = minetest.registered_nodes[target.name]
if targetdef.execute_build ~= nil then 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. --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 local build_return = targetdef.execute_build(location, clicker, layout.inventories, layout.protected, nodes_dug, controlling_coordinate, oldpos)
-- Don't interrupt the build cycle as a whole, we've already moved so might as well try to complete as much as possible. 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 strange_failure = true
elseif build_return == true then
building_fuel_cost = building_fuel_cost + digtron.build_cost
end end
else 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)) 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
end end
local status_text = ""
if strange_failure then 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("dingding", {gain=1.0, pos=pos})
minetest.sound_play("buzzer", {gain=0.5, 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 end
-- finally, dig out any nodes remaining to be dug. Some of these will have had their flag revoked because -- 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 end
if not can_move then 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") meta:set_string("waiting", "true")
minetest.after(digtron.refractory, minetest.after(digtron.cycle_time,
function (pos) function (pos)
minetest.get_meta(pos):set_string("waiting", nil) minetest.get_meta(pos):set_string("waiting", nil)
end, pos 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. -- 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.get_meta(pos):set_string("waiting", "true")
minetest.after(digtron.refractory, minetest.after(digtron.cycle_time,
function (pos) function (pos)
minetest.get_meta(pos):set_string("waiting", nil) minetest.get_meta(pos):set_string("waiting", nil)
end, pos end, pos

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

@ -58,16 +58,17 @@ minetest.register_node("digtron:inventory",
on_construct = function(pos) on_construct = function(pos)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
meta:set_string("formspec", meta:set_string("formspec",
"size[8,9]" .. "size[8,9.3]" ..
default.gui_bg .. default.gui_bg ..
default.gui_bg_img .. default.gui_bg_img ..
default.gui_slots .. default.gui_slots ..
"list[current_name;main;0,0.3;8,4;]" .. "label[0,0;Inventory items]" ..
"list[current_player;main;0,4.85;8,1;]" .. "list[current_name;main;0,0.6;8,4;]" ..
"list[current_player;main;0,6.08;8,3;8]" .. "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_name;main]" ..
"listring[current_player;main]" .. "listring[current_player;main]" ..
default.get_hotbar_bg(0,4.85) default.get_hotbar_bg(0,5.15)
) )
local inv = meta:get_inventory() local inv = meta:get_inventory()
inv:set_size("main", 8*4) inv:set_size("main", 8*4)
@ -79,3 +80,55 @@ minetest.register_node("digtron:inventory",
return inv:is_empty("main") return inv:is_empty("main")
end, 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()
return inv:is_empty("main")
end,
})

@ -66,6 +66,15 @@ minetest.register_craft({
} }
}) })
minetest.register_craft({
output = "digtron:fuelstore",
recipe = {
{"","default:furnace",""},
{"","digtron:digtron_core",""},
{"","",""}
}
})
minetest.register_craft({ minetest.register_craft({
output = "digtron:structure", output = "digtron:structure",
recipe = { 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 -- 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) -- 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. -- 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) local target = minetest.get_node(pos)
-- prevent digtrons from being marked for digging. -- prevent digtrons from being marked for digging.
if minetest.get_item_group(target.name, "digtron") ~= 0 then if minetest.get_item_group(target.name, "digtron") ~= 0 then
return nil return 0, nil
end end
local targetdef = minetest.registered_nodes[target.name] local targetdef = minetest.registered_nodes[target.name]
if targetdef.can_dig == nil or targetdef.can_dig(pos, player) then if targetdef.can_dig == nil or targetdef.can_dig(pos, player) then
nodes_dug:set(pos.x, pos.y, pos.z, true) nodes_dug:set(pos.x, pos.y, pos.z, true)
if target.name ~= "air" then 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
end end
return nil return 0, nil
end end
digtron.can_build_to = function(pos, protected_nodes, dug_nodes) digtron.can_build_to = function(pos, protected_nodes, dug_nodes)
@ -81,9 +99,11 @@ digtron.move_node = function(pos, newpos)
newinv:set_list("main", list) newinv:set_list("main", list)
newmeta:set_string("formspec", oldformspec) newmeta:set_string("formspec", oldformspec)
newmeta:set_string("offset", oldmeta:get_string("offset")) newmeta:set_int("offset", oldmeta:get_int("offset"))
newmeta:set_string("period", oldmeta:get_string("period")) newmeta:set_int("period", oldmeta:get_int("period"))
newmeta:set_string("build_facing", oldmeta:get_string("build_facing")) 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 -- remove node from old position
minetest.remove_node(pos) minetest.remove_node(pos)
@ -92,13 +112,12 @@ end
digtron.get_all_digtron_neighbours = function(pos, player) 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) -- 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 = {} 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 --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.traction = 0
layout.all = {} layout.all = {}
layout.inventories = {} layout.inventories = {}
layout.fuelstores = {}
layout.diggers = {} layout.diggers = {}
layout.builders = {} layout.builders = {}
layout.extents = {} layout.extents = {}
@ -148,7 +167,6 @@ digtron.get_all_digtron_neighbours = function(pos, player)
local group_number = minetest.get_item_group(node.name, "digtron") local group_number = minetest.get_item_group(node.name, "digtron")
if group_number > 0 then 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 --found one. Add it to the digtrons output
table.insert(layout.all, testpos) table.insert(layout.all, testpos)
@ -167,6 +185,8 @@ digtron.get_all_digtron_neighbours = function(pos, player)
table.insert(layout.diggers, testpos) table.insert(layout.diggers, testpos)
elseif group_number == 4 then elseif group_number == 4 then
table.insert(layout.builders, testpos) table.insert(layout.builders, testpos)
elseif group_number == 5 then
table.insert(layout.fuelstores, testpos)
end end
--queue up potential new test points adjacent to this digtron node --queue up potential new test points adjacent to this digtron node
@ -310,3 +330,39 @@ digtron.get_controlling_coordinate = function(pos, facedir)
return "y" return "y"
end end
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