Add cache to quarry

Adds a cache to the quarry in order to reduce load and send larger stacks through pipes instead of just single items. Coin tossing ensures the cache gets purged around every 200 seconds. The interval isn't fixed in order to prevent material spikes from multiple quarries which got loaded simultaneously. When the cache is full, or the quarry finished, it is purged too.
This commit is contained in:
est31 2015-01-24 11:46:47 +01:00
parent c38da0945c
commit 86dd5852aa
1 changed files with 87 additions and 15 deletions

View File

@ -15,23 +15,25 @@ local quarry_demand = 10000
local function set_quarry_formspec(meta) local function set_quarry_formspec(meta)
local radius = meta:get_int("size") local radius = meta:get_int("size")
local formspec = "size[6,2.5]".. local formspec = "size[6,4.3]"..
"item_image[0,0;1,1;technic:quarry]".. "list[context;cache;0,1;4,3;]"..
"label[1,0;"..S("%s Quarry"):format("HV").."]".. "item_image[4.8,0;1,1;technic:quarry]"..
"field[0.3,1.5;2,1;size;"..S("Radius:")..";"..radius.."]" "label[0,0.2;"..S("%s Quarry"):format("HV").."]"..
"field[4.3,3.5;2,1;size;"..S("Radius:")..";"..radius.."]"
if meta:get_int("enabled") == 0 then if meta:get_int("enabled") == 0 then
formspec = formspec.."button[4,1.2;2,1;enable;"..S("Disabled").."]" formspec = formspec.."button[4,1;2,1;enable;"..S("Disabled").."]"
else else
formspec = formspec.."button[4,1.2;2,1;disable;"..S("Enabled").."]" formspec = formspec.."button[4,1;2,1;disable;"..S("Enabled").."]"
end end
local diameter = radius*2 + 1 local diameter = radius*2 + 1
local nd = meta:get_int("dug") local nd = meta:get_int("dug")
local rel_y = quarry_dig_above_nodes - math.floor(nd / (diameter*diameter)) local rel_y = quarry_dig_above_nodes - math.floor(nd / (diameter*diameter))
formspec = formspec.."label[0,2;"..minetest.formspec_escape( formspec = formspec.."label[0,4;"..minetest.formspec_escape(
nd == 0 and S("Digging not started") or nd == 0 and S("Digging not started") or
(rel_y < -quarry_max_depth and S("Digging finished") or (rel_y < -quarry_max_depth and S("Digging finished") or
(meta:get_int("purge_on") == 1 and S("Purging cache") or
S("Digging %d m "..(rel_y > 0 and "above" or "below").." machine") S("Digging %d m "..(rel_y > 0 and "above" or "below").." machine")
:format(math.abs(rel_y))) :format(math.abs(rel_y))))
).."]" ).."]"
formspec = formspec.."button[4,2;2,1;restart;"..S("Restart").."]" formspec = formspec.."button[4,2;2,1;restart;"..S("Restart").."]"
meta:set_string("formspec", formspec) meta:set_string("formspec", formspec)
@ -41,8 +43,8 @@ local function set_quarry_demand(meta)
local radius = meta:get_int("size") local radius = meta:get_int("size")
local diameter = radius*2 + 1 local diameter = radius*2 + 1
local machine_name = S("%s Quarry"):format("HV") local machine_name = S("%s Quarry"):format("HV")
if meta:get_int("enabled") == 0 then if meta:get_int("enabled") == 0 or meta:get_int("purge_on") == 1 then
meta:set_string("infotext", S("%s Disabled"):format(machine_name)) meta:set_string("infotext", S(meta:get_int("purge_on") == 1 and "%s purging cache" or "%s Disabled"):format(machine_name))
meta:set_int("HV_EU_demand", 0) meta:set_int("HV_EU_demand", 0)
elseif meta:get_int("dug") == diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) then elseif meta:get_int("dug") == diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) then
meta:set_string("infotext", S("%s Finished"):format(machine_name)) meta:set_string("infotext", S("%s Finished"):format(machine_name))
@ -64,14 +66,47 @@ local function quarry_receive_fields(pos, formname, fields, sender)
end end
if fields.enable then meta:set_int("enabled", 1) end if fields.enable then meta:set_int("enabled", 1) end
if fields.disable then meta:set_int("enabled", 0) end if fields.disable then meta:set_int("enabled", 0) end
if fields.restart then meta:set_int("dug", 0) end if fields.restart then
meta:set_int("dug", 0)
meta:set_int("purge_on", 1)
end
set_quarry_formspec(meta) set_quarry_formspec(meta)
set_quarry_demand(meta) set_quarry_demand(meta)
end end
local function quarry_handle_purge(pos)
local meta = minetest.get_meta(pos)
local inv = meta:get_inventory()
local i = 0
for _,stack in ipairs(inv:get_list("cache")) do
i = i + 1
if stack then
local item = stack:to_table()
if item then
technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), item)
stack:clear()
inv:set_stack("cache", i, stack)
break
end
end
end
if inv:is_empty("cache") then
meta:set_int("purge_on", 0)
end
end
local function quarry_run(pos, node) local function quarry_run(pos, node)
local meta = minetest.get_meta(pos) local meta = minetest.get_meta(pos)
if meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand then local inv = meta:get_inventory()
-- initialize cache for the case we load an older world
inv:set_size("cache", 12)
-- toss a coin whether we do an automatic purge. Chance 1:200
local purge_rand = math.random()
if purge_rand <= 0.005 then
meta:set_int("purge_on", 1)
end
if meta:get_int("enabled") and meta:get_int("HV_EU_input") >= quarry_demand and meta:get_int("purge_on") == 0 then
local pdir = minetest.facedir_to_dir(node.param2) local pdir = minetest.facedir_to_dir(node.param2)
local qdir = pdir.x == 1 and vector.new(0,0,-1) or local qdir = pdir.x == 1 and vector.new(0,0,-1) or
(pdir.z == -1 and vector.new(-1,0,0) or (pdir.z == -1 and vector.new(-1,0,0) or
@ -133,18 +168,42 @@ local function quarry_run(pos, node)
nd = nd + 1 nd = nd + 1
if can_dig then if can_dig then
minetest.remove_node(digpos) minetest.remove_node(digpos)
for _, item in ipairs(minetest.get_node_drops(dignode.name, "")) do local drops = minetest.get_node_drops(dignode.name, "")
technic.tube_inject_item(pos, pos, vector.new(0, 1, 0), item) for _, dropped_item in ipairs(drops) do
local left = inv:add_item("cache", dropped_item)
while not left:is_empty() do
meta:set_int("purge_on", 1)
quarry_handle_purge(pos)
left = inv:add_item("cache", left)
end
end end
break break
end end
end end
if nd == diameter*diameter * (quarry_dig_above_nodes+1+quarry_max_depth) then
-- if a quarry is finished, we enable purge mode
meta:set_int("purge_on", 1)
end
meta:set_int("dug", nd) meta:set_int("dug", nd)
else
-- if a quarry is disabled or has no power, we enable purge mode
meta:set_int("purge_on", 1)
end
-- if something triggered a purge, we handle it
if meta:get_int("purge_on") == 1 then
quarry_handle_purge(pos)
end end
set_quarry_formspec(meta) set_quarry_formspec(meta)
set_quarry_demand(meta) set_quarry_demand(meta)
end end
local function send_move_error(player)
minetest.chat_send_player(player:get_player_name(),
S("Manually taking/removing from cache by hand is not possible. "..
"If you can't wait, restart or disable the quarry to start automatic purge."))
return 0
end
minetest.register_node("technic:quarry", { minetest.register_node("technic:quarry", {
description = S("%s Quarry"):format("HV"), description = S("%s Quarry"):format("HV"),
tiles = {"technic_carbon_steel_block.png", "technic_carbon_steel_block.png", tiles = {"technic_carbon_steel_block.png", "technic_carbon_steel_block.png",
@ -167,10 +226,23 @@ minetest.register_node("technic:quarry", {
meta:set_string("owner", placer:get_player_name()) meta:set_string("owner", placer:get_player_name())
pipeworks.scan_for_tube_objects(pos) pipeworks.scan_for_tube_objects(pos)
end, end,
can_dig = function(pos,player)
local meta = minetest.get_meta(pos);
local inv = meta:get_inventory()
return inv:is_empty("cache")
end,
after_dig_node = pipeworks.scan_for_tube_objects, after_dig_node = pipeworks.scan_for_tube_objects,
on_receive_fields = quarry_receive_fields, on_receive_fields = quarry_receive_fields,
technic_run = quarry_run, technic_run = quarry_run,
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
return send_move_error(player)
end,
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
return send_move_error(player)
end,
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
return send_move_error(player)
end
}) })
technic.register_machine("HV", "technic:quarry", technic.receiver) technic.register_machine("HV", "technic:quarry", technic.receiver)