mirror of
https://github.com/theFox6/microexpansion.git
synced 2024-11-29 18:33:51 +01:00
Checkpoint.
This commit is contained in:
parent
f5aee436d0
commit
9235b7bad1
134
api.lua
134
api.lua
@ -3,66 +3,66 @@ local BASENAME = "microexpansion"
|
|||||||
|
|
||||||
-- [function] Register Recipe
|
-- [function] Register Recipe
|
||||||
function microexpansion.register_recipe(output, recipe)
|
function microexpansion.register_recipe(output, recipe)
|
||||||
-- Check if disabled
|
-- Check if disabled
|
||||||
if recipe.disabled == true then
|
if recipe.disabled == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _,r in ipairs(recipe) do
|
for _,r in ipairs(recipe) do
|
||||||
local def = {
|
local def = {
|
||||||
type = type(r[2]) == "string" and r[2] or nil,
|
type = type(r[2]) == "string" and r[2] or nil,
|
||||||
output = output.." "..(r[1] or 1),
|
output = output.." "..(r[1] or 1),
|
||||||
recipe = r[3] or r[2]
|
recipe = r[3] or r[2]
|
||||||
}
|
}
|
||||||
minetest.register_craft(def)
|
minetest.register_craft(def)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [function] Register oredef
|
-- [function] Register oredef
|
||||||
function microexpansion.register_oredef(ore, defs)
|
function microexpansion.register_oredef(ore, defs)
|
||||||
-- Check if disabled
|
-- Check if disabled
|
||||||
if defs.disabled == true then
|
if defs.disabled == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
|
|
||||||
for _,d in ipairs(defs) do
|
for _,d in ipairs(defs) do
|
||||||
d.ore = "microexpansion:"..ore
|
d.ore = "microexpansion:"..ore
|
||||||
minetest.register_ore(d)
|
minetest.register_ore(d)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [local function] Choose description colour
|
-- [local function] Choose description colour
|
||||||
local function desc_colour(status, desc)
|
local function desc_colour(status, desc)
|
||||||
if status == "unstable" then
|
if status == "unstable" then
|
||||||
return minetest.colorize("orange", desc)
|
return minetest.colorize("orange", desc)
|
||||||
elseif status == "no" then
|
elseif status == "no" then
|
||||||
return minetest.colorize("red", desc)
|
return minetest.colorize("red", desc)
|
||||||
else
|
else
|
||||||
return minetest.colorize("white", desc)
|
return minetest.colorize("white", desc)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [function] Register Item
|
-- [function] Register Item
|
||||||
function microexpansion.register_item(itemstring, def)
|
function microexpansion.register_item(itemstring, def)
|
||||||
-- Check if disabled
|
-- Check if disabled
|
||||||
if def.disabled == true then
|
if def.disabled == true then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
-- Set usedfor
|
-- Set usedfor
|
||||||
if def.usedfor then
|
if def.usedfor then
|
||||||
def.description = def.description .. "\n"..minetest.colorize("grey", def.usedfor)
|
def.description = def.description .. "\n"..minetest.colorize("grey", def.usedfor)
|
||||||
end
|
end
|
||||||
-- Update inventory image
|
-- Update inventory image
|
||||||
if def.inventory_image then
|
if def.inventory_image then
|
||||||
def.inventory_image = BASENAME.."_"..def.inventory_image..".png"
|
def.inventory_image = BASENAME.."_"..def.inventory_image..".png"
|
||||||
else
|
else
|
||||||
def.inventory_image = BASENAME.."_"..itemstring..".png"
|
def.inventory_image = BASENAME.."_"..itemstring..".png"
|
||||||
end
|
end
|
||||||
-- Colour description
|
-- Colour description
|
||||||
def.description = desc_colour(def.status, def.description)
|
def.description = desc_colour(def.status, def.description)
|
||||||
|
|
||||||
-- Register craftitem
|
-- Register craftitem
|
||||||
minetest.register_craftitem(BASENAME..":"..itemstring, def)
|
minetest.register_craftitem(BASENAME..":"..itemstring, def)
|
||||||
|
|
||||||
-- if recipe, Register recipe
|
-- if recipe, Register recipe
|
||||||
if def.recipe then
|
if def.recipe then
|
||||||
@ -93,43 +93,43 @@ function microexpansion.register_node(itemstring, def)
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
-- Colour description
|
-- Colour description
|
||||||
def.description = desc_colour(def.status, def.description)
|
def.description = desc_colour(def.status, def.description)
|
||||||
-- Update connect_sides
|
-- Update connect_sides
|
||||||
if def.connect_sides == "nobottom" then
|
if def.connect_sides == "nobottom" then
|
||||||
def.connect_sides = { "top", "front", "left", "back", "right" }
|
def.connect_sides = { "top", "front", "left", "back", "right" }
|
||||||
elseif def.connect_sides == "machine" then
|
elseif def.connect_sides == "machine" then
|
||||||
def.connect_sides = { "top", "bottom", "left", "back", "right" }
|
def.connect_sides = { "top", "bottom", "left", "back", "right" }
|
||||||
end
|
end
|
||||||
|
|
||||||
-- Register node
|
-- Register node
|
||||||
minetest.register_node(BASENAME..":"..itemstring, def)
|
minetest.register_node(BASENAME..":"..itemstring, def)
|
||||||
|
|
||||||
-- if recipe, Register recipe
|
-- if recipe, Register recipe
|
||||||
if def.recipe then
|
if def.recipe then
|
||||||
microexpansion.register_recipe(BASENAME..":"..itemstring, def.recipe)
|
microexpansion.register_recipe(BASENAME..":"..itemstring, def.recipe)
|
||||||
end
|
end
|
||||||
|
|
||||||
-- if oredef, Register oredef
|
-- if oredef, Register oredef
|
||||||
if def.oredef then
|
if def.oredef then
|
||||||
microexpansion.register_oredef(BASENAME..":"..itemstring, def.oredef)
|
microexpansion.register_oredef(BASENAME..":"..itemstring, def.oredef)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get a node, if nessecary load it
|
-- get a node, if necessary load it
|
||||||
function microexpansion.get_node(pos)
|
function microexpansion.get_node(pos)
|
||||||
local node = minetest.get_node_or_nil(pos)
|
local node = minetest.get_node_or_nil(pos)
|
||||||
if node then return node end
|
if node then return node end
|
||||||
local vm = VoxelManip()
|
local vm = VoxelManip()
|
||||||
vm:read_from_map(pos, pos)
|
vm:read_from_map(pos, pos)
|
||||||
return minetest.get_node(pos)
|
return minetest.get_node(pos)
|
||||||
end
|
end
|
||||||
|
|
||||||
function microexpansion.update_node(pos,event)
|
function microexpansion.update_node(pos,event)
|
||||||
local node = microexpansion.get_node(pos)
|
local node = microexpansion.get_node(pos)
|
||||||
local def = minetest.registered_nodes[node.name]
|
local def = minetest.registered_nodes[node.name]
|
||||||
local ev = event or {type = "n/a"}
|
local ev = event or {type = "n/a"}
|
||||||
if def.me_update then
|
if def.me_update then
|
||||||
def.me_update(pos,node,ev)
|
def.me_update(pos,node,ev)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
2
mod.conf
2
mod.conf
@ -1,4 +1,4 @@
|
|||||||
name = microexpansion
|
name = microexpansion
|
||||||
description = A storage managing solution to get an overview over all your items.
|
description = A storage managing solution to get an overview over all your items.
|
||||||
depends = default
|
depends = default
|
||||||
optional_depends = pipeworks
|
optional_depends = pipeworks, drawers, technic_plus
|
||||||
|
477
modules/network/autocraft.lua
Normal file
477
modules/network/autocraft.lua
Normal file
@ -0,0 +1,477 @@
|
|||||||
|
local me = microexpansion
|
||||||
|
|
||||||
|
local pipeworks_craft_time = 1
|
||||||
|
|
||||||
|
function me.autocraft_next_start(net)
|
||||||
|
if net.pending then
|
||||||
|
-- start subsequent autocrafting jobs sequentially.
|
||||||
|
-- We really only need zero/not zero for build to queue actions or not
|
||||||
|
return net.pending.time[net.pending.max_index]
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.start_crafting(pos, step_time)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local timer = minetest.get_node_timer(pos)
|
||||||
|
timer:set(step_time, 0)
|
||||||
|
end
|
||||||
|
|
||||||
|
local function round(v)
|
||||||
|
return math.floor(v + 0.5)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- technic_plus doesn't export machine speed. We
|
||||||
|
-- use this to know exactly how long a machine will take to process
|
||||||
|
-- anything, after that time, we know it is done and we can grab the
|
||||||
|
-- outputs, no polling. We do this for efficiency.
|
||||||
|
me.speed = {
|
||||||
|
["default:furnace"] = 1,
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Use to wire in how long a machine takes to process something.
|
||||||
|
function me.set_speed(name, speed)
|
||||||
|
me.speed[name] = speed
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Sometimes the poor autocrafter doesn't have infinite input and output room
|
||||||
|
-- for a craft, break large ones up to fit.
|
||||||
|
-- Also machine inputs/outputs don't fit.
|
||||||
|
me.maximums = {
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Allow a maximum craft to be defined to avoid overrunning machine
|
||||||
|
-- inputs and outputs and the autocrafter inputs and output..
|
||||||
|
function me.register_max(name, count)
|
||||||
|
me.maximums[name] = count
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
local function build(net, cpos, inv, name, count, stack, sink, time)
|
||||||
|
-- The autocrafters nor the machines can take really large amounts
|
||||||
|
-- of things, help them out.
|
||||||
|
local max = me.maximums[name]
|
||||||
|
if not max then
|
||||||
|
-- If no explicit max, assume this is a pipeworks autocrafter and
|
||||||
|
-- it only has 12 outputs.
|
||||||
|
max = stack:get_stack_max()*12
|
||||||
|
end
|
||||||
|
if max and count > max then
|
||||||
|
local next_time = time
|
||||||
|
local built = true
|
||||||
|
while count > 1 and built do
|
||||||
|
local substack = ItemStack(stack)
|
||||||
|
max = math.min(max, count)
|
||||||
|
substack:set_count(max)
|
||||||
|
local step_time
|
||||||
|
built, step_time = build(net, cpos, inv, name, max, substack, sink, next_time)
|
||||||
|
if not built then
|
||||||
|
-- we are done, can't craft, so stop
|
||||||
|
else
|
||||||
|
next_time = math.max(next_time, next_time + step_time)
|
||||||
|
end
|
||||||
|
count = count - max
|
||||||
|
end
|
||||||
|
local step_time = next_time - time
|
||||||
|
return built, step_time
|
||||||
|
end
|
||||||
|
me.log("BUILD: count is "..count.." and stack size is "..stack:get_count(), "error")
|
||||||
|
local dat = {}
|
||||||
|
local second_output = nil
|
||||||
|
if net.process and net.process[name] then
|
||||||
|
dat.apos, dat.ipos = next(net.process[name])
|
||||||
|
dat.rinv = minetest.get_meta(dat.apos):get_inventory()
|
||||||
|
me.log("INT: looking up output "..name, "error")
|
||||||
|
local inputs = me.find_by_output(name)
|
||||||
|
local machine_name = minetest.get_node(dat.apos).name
|
||||||
|
local typename = me.block_to_typename_map[machine_name]
|
||||||
|
dat.recip = me.get_recipe(typename, inputs)
|
||||||
|
me.log("MACHINE: "..machine_name.." typename is "..typename.." and time is "..tostring(dat.recip.time), "error")
|
||||||
|
dat.recip.input = inputs
|
||||||
|
-- freezer can produce two outputs, we only care about the first.
|
||||||
|
if dat.recip.output[1] then
|
||||||
|
second_output = dat.recip.output[2]
|
||||||
|
dat.recip.output = dat.recip.output[1]
|
||||||
|
end
|
||||||
|
dat.ostack = ItemStack(dat.recip.output)
|
||||||
|
-- me.log("SEE: "..machine_name.." "..minetest.serialize(technic.recipes))
|
||||||
|
local speed = me.speed[machine_name]
|
||||||
|
local craft_count = dat.ostack:get_count()
|
||||||
|
local total = math.ceil(count/craft_count)
|
||||||
|
-- crafting 4 carbon plates misses taking 1 carbin plate on output, make this bigger
|
||||||
|
-- we'll try 1 for now, figure out right formula. 1 looks perfect
|
||||||
|
dat.recip.time = round((total+1)*dat.recip.time/speed)
|
||||||
|
if second_output then
|
||||||
|
second_output = ItemStack(second_output)
|
||||||
|
second_output:set_count(second_output:get_count()*total)
|
||||||
|
end
|
||||||
|
me.log("MACHINE: "..machine_name.." is speed "..speed.." and final time is "..dat.recip.time, "error")
|
||||||
|
elseif net.autocrafters[name] then
|
||||||
|
-- fill all recipe slots, wait, grab all output slots
|
||||||
|
-- "src" "dst" "recipe" "output"
|
||||||
|
dat.apos, dat.ipos = next(net.autocrafters[name])
|
||||||
|
-- TODO: If we set up pipeworks ac, then we remove interface for it and craft
|
||||||
|
-- it goes to ac, and dies here. Flush net.autocrafters for all the
|
||||||
|
-- attached inventories during interface removal.
|
||||||
|
dat.rinv = minetest.get_meta(dat.apos):get_inventory()
|
||||||
|
if dat.rinv == nil then
|
||||||
|
me.log("no inventory", "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
dat.ostack = dat.rinv:get_stack("output", 1)
|
||||||
|
if dat.ostack:get_name() ~= name then
|
||||||
|
-- invalidate it
|
||||||
|
net.autocrafters[name][dat.apos] = nil
|
||||||
|
-- me.log("invalidating autocrafter", "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
else
|
||||||
|
me.log("can't craft a "..name, "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
dat.isink = function(sstack)
|
||||||
|
me.log("TIMER: prep inputs, moving "..sstack:get_count().." "..sstack:get_name(), "error")
|
||||||
|
return dat.rinv:add_item("src", sstack)
|
||||||
|
end
|
||||||
|
local craft_count = dat.ostack:get_count()
|
||||||
|
-- These will be returned to the me system
|
||||||
|
local extra = ItemStack(name)
|
||||||
|
local total = math.ceil(count/craft_count)
|
||||||
|
extra:set_count(total*craft_count - count)
|
||||||
|
me.log("AC: count "..count.." craft_count "..craft_count.." extra "..extra:get_count(), "error");
|
||||||
|
-- we craft a minimum of count, to the multiple of the crafting count
|
||||||
|
count = total
|
||||||
|
me.log("AC: numcount "..count, "error");
|
||||||
|
|
||||||
|
local consume = {}
|
||||||
|
if net.process and net.process[name] then
|
||||||
|
for i = 1, #dat.recip.input do
|
||||||
|
local inp = dat.recip.input[i]
|
||||||
|
me.log("MID: consuming "..inp:get_name().." count: "..count.." inp:getcount: "..inp:get_count(), "error")
|
||||||
|
consume[inp:get_name()] = (consume[inp:get_name()] or 0) + count*inp:get_count()
|
||||||
|
end
|
||||||
|
else
|
||||||
|
for i = 1, 9 do
|
||||||
|
local inp = dat.rinv:get_stack("recipe", i)
|
||||||
|
if inp and not inp:is_empty() then
|
||||||
|
consume[inp:get_name()] = (consume[inp:get_name()] or 0) + count*inp:get_count()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local replace = true
|
||||||
|
local next_time = time
|
||||||
|
me.log("PREP: pre count is "..count, "error")
|
||||||
|
-- prepwork
|
||||||
|
me.log("PREP: count is "..count, "error")
|
||||||
|
local prepworkbits = {}
|
||||||
|
local previous_ac_size = inv:get_size("ac")
|
||||||
|
me.log("PREP: ac size at top is "..previous_ac_size, "error")
|
||||||
|
for name, count in pairs(consume) do
|
||||||
|
local istack = ItemStack(name)
|
||||||
|
if count >= math.pow(2,16) then
|
||||||
|
replace = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Don't consume the last item by autocrafting
|
||||||
|
istack:set_count(count+1)
|
||||||
|
local hasit = inv:contains_item("main", istack)
|
||||||
|
istack:set_count(count)
|
||||||
|
me.log("ac checking "..name, "error")
|
||||||
|
if hasit then
|
||||||
|
me.log("ac grabbing "..name, "error")
|
||||||
|
local grabbed = me.remove_item(net, inv, "main", istack)
|
||||||
|
if grabbed then
|
||||||
|
me.log("ac grabbed "..name, "error")
|
||||||
|
local slot = inv:get_size("ac")+1
|
||||||
|
inv:set_size("ac", slot)
|
||||||
|
inv:set_stack("ac", slot, grabbed)
|
||||||
|
-- and later we do this:
|
||||||
|
prepworkbits[function()
|
||||||
|
me.log("PREP: about to move "..name, "error")
|
||||||
|
local stack = inv:get_stack("ac", slot)
|
||||||
|
me.log("PREP: before move actual content of slot "..slot.." is "..stack:get_count().." "..stack:get_name(), "error")
|
||||||
|
local leftovers = dat.rinv:add_item("src", stack)
|
||||||
|
me.log("PREP: post move into real inventory "..leftovers:get_count().." leftovers", "error")
|
||||||
|
me.log("PREP: did move "..name, "error")
|
||||||
|
inv:set_stack("ac", slot, leftovers)
|
||||||
|
end] = name
|
||||||
|
-- and then something moves the size of ac back to before we started
|
||||||
|
end
|
||||||
|
else
|
||||||
|
-- Try and autocraft it
|
||||||
|
me.log("AC: recursive crafting "..count.." "..istack:get_count(), "error")
|
||||||
|
local built, step_time = build(net, cpos, inv, name, count, istack, dat.isink, time)
|
||||||
|
if built then
|
||||||
|
hasit = true
|
||||||
|
next_time = math.max(next_time, time + step_time)
|
||||||
|
else
|
||||||
|
me.log("can't craft "..istack:get_count().." "..istack:get_name(), "error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
replace = replace and hasit
|
||||||
|
end
|
||||||
|
local prepwork = function ()
|
||||||
|
-- Do all the little bits of prepwork
|
||||||
|
for func, name in pairs(prepworkbits) do
|
||||||
|
me.log("PREPing: before "..name, "error")
|
||||||
|
func()
|
||||||
|
me.log("PREPing: done "..name, "error")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- end of prepwork
|
||||||
|
if not replace then
|
||||||
|
-- If we don't have everything, and can't craft it, we're stuck,
|
||||||
|
-- do as much as we can, then nothing else
|
||||||
|
me.log("missing items", "error")
|
||||||
|
-- Existing items are already loaded.
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local main_action_time = count * pipeworks_craft_time + 1
|
||||||
|
if net.process and net.process[name] then
|
||||||
|
main_action_time = dat.recip.time + 1
|
||||||
|
end
|
||||||
|
local main_action = function()
|
||||||
|
me.log("ACTION: prep for "..stack:get_name(), "error")
|
||||||
|
prepwork()
|
||||||
|
-- and once we are done with all the postponed work, we can reduce "ac"
|
||||||
|
-- lifetimes are more complex than you can imagine.
|
||||||
|
-- We use a simple rule. When all done, there is nothing left. At that point,
|
||||||
|
-- we can put any leftovers back into the main inventory.
|
||||||
|
-- Even this might be too soon, if we have multiple independent crafts going, we
|
||||||
|
-- need the last one.
|
||||||
|
if previous_ac_size == 0 then
|
||||||
|
for i = 1,inv:get_size("ac") do
|
||||||
|
local stack = inv:get_stack("ac", i)
|
||||||
|
if stack:get_count() ~= 0 then
|
||||||
|
me.log("AC: putting "..stack:get_count().." "..stack:get_name().." back into main inventory", "error")
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
if leftovers:get_count() > 0 then
|
||||||
|
-- drop on floor, todo: play sound
|
||||||
|
minetest.add_item(cpos, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
me.log("PREP: ac size is now down to "..previous_ac_size, "error")
|
||||||
|
inv:set_size("ac", previous_ac_size)
|
||||||
|
end
|
||||||
|
me.log("ACTION: main for "..stack:get_name(), "error")
|
||||||
|
local rmeta = minetest.get_meta(dat.apos)
|
||||||
|
|
||||||
|
-- Let's start up the crafter since we loaded it up to run
|
||||||
|
if (net.process and net.process[name]) or rmeta:get_int("enabled") == 1 then
|
||||||
|
local timer = minetest.get_node_timer(dat.apos)
|
||||||
|
if not timer:is_started() then
|
||||||
|
me.log("TIMER: starting ac now for "..stack:get_name(), "error")
|
||||||
|
timer:start(pipeworks_craft_time)
|
||||||
|
end
|
||||||
|
me.log("TIMER: registering timer for "..stack:get_name(), "error")
|
||||||
|
local action_time_step = count * pipeworks_craft_time + 1
|
||||||
|
if net.process and net.process[name] then
|
||||||
|
action_time_step = dat.recip.time + 1
|
||||||
|
end
|
||||||
|
local action = function(net)
|
||||||
|
me.log("ACTION: post craft for "..stack:get_name(), "error")
|
||||||
|
me.log("TIMER: moving "..stack:get_count().." "..stack:get_name(), "error")
|
||||||
|
-- deal with output and replacements
|
||||||
|
local dst_stack = dat.rinv:remove_item("dst", stack)
|
||||||
|
if dst_stack:get_count() ~= stack:get_count() then
|
||||||
|
me.log("wow, missing items that should have been crafted "..stack:get_name(), "error")
|
||||||
|
-- me.log("saw "..dst_stack:get_count().." items instead of "..stack:get_count().." items", "error")
|
||||||
|
end
|
||||||
|
if not dst_stack:is_empty() then
|
||||||
|
me.log("TIMER: inserting "..dst_stack:get_count().." "..dst_stack:get_name(), "error")
|
||||||
|
local leftovers = sink(dst_stack)
|
||||||
|
if leftovers and not leftovers:is_empty() then
|
||||||
|
me.log("autocrafter overflow, backpressuring", "error")
|
||||||
|
-- If any don't fit, back pressure on the crafter, we don't
|
||||||
|
-- mean to do this, and want to chunk the crafting items smaller
|
||||||
|
dat.rinv:add_item("dst", leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if not extra:is_empty() then
|
||||||
|
dst_stack = dat.rinv:remove_item("dst", extra)
|
||||||
|
if dst_stack:get_count() ~= extra:get_count() then
|
||||||
|
me.log("wow, missing items that should have been crafted "..stack:get_name(), "error")
|
||||||
|
me.log("saw "..dst_stack:get_count().." items instead of "..extra:get_count().." items", "error")
|
||||||
|
end
|
||||||
|
if not dst_stack:is_empty() then
|
||||||
|
local leftovers = me.insert_item(dst_stack, net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
|
if leftovers and not leftovers:is_empty() then
|
||||||
|
me.log("autocrafter overflow, backpressuring", "error")
|
||||||
|
-- If any don't fit, back pressure on the crafter, we don't
|
||||||
|
-- mean to do this, and want to chunk the crafting items smaller
|
||||||
|
dat.rinv:add_item("dst", leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if second_output then
|
||||||
|
local second = dat.rinv:remove_item("dst", second_output)
|
||||||
|
if second and not second:is_empty() then
|
||||||
|
local leftovers = sink(second)
|
||||||
|
if leftovers and not leftovers:is_empty() then
|
||||||
|
me.log("autocrafter overflow, backpressuring", "error")
|
||||||
|
-- If any don't fit, back pressure on the crafter, we don't
|
||||||
|
-- mean to do this, and want to chunk the crafting items smaller
|
||||||
|
dat.rinv:add_item("dst", leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
me.log("ACTION: done post craft for "..stack:get_name(), "error")
|
||||||
|
end
|
||||||
|
local net,cpos = me.get_connected_network(dat.ipos)
|
||||||
|
me.later(net, cpos, action, next_time + action_time_step)
|
||||||
|
end
|
||||||
|
me.log("ACTION: main done for "..stack:get_name(), "error")
|
||||||
|
end
|
||||||
|
|
||||||
|
local net,cpos = me.get_connected_network(dat.ipos)
|
||||||
|
-- queue main action for later
|
||||||
|
me.log("LATER: main action for "..stack:get_name().." in "..next_time.." seconds", "error")
|
||||||
|
me.later(net, cpos, main_action, next_time)
|
||||||
|
|
||||||
|
-- The step time is the prep time and the main_action_time
|
||||||
|
local step_time = next_time - time + main_action_time
|
||||||
|
return true, step_time
|
||||||
|
end
|
||||||
|
|
||||||
|
-- time is absolute, starting from 0 from the front of a craft or
|
||||||
|
-- non-zero if a previous craft was running.
|
||||||
|
function me.later(net, cpos, action, time)
|
||||||
|
if not net.pending then
|
||||||
|
net.pending = {}
|
||||||
|
net.pending.time = {}
|
||||||
|
end
|
||||||
|
local i = (net.pending.max_index or 0) + 1
|
||||||
|
net.pending.max_index = i
|
||||||
|
net.pending[i] = action
|
||||||
|
net.pending.time[i] = time
|
||||||
|
if not net.pending.index then
|
||||||
|
net.pending.index = 1
|
||||||
|
end
|
||||||
|
if i == 1 then
|
||||||
|
me.log("TIMER: starting timer to fire at "..time.." seconds", "error")
|
||||||
|
me.start_crafting(cpos, time+0.1)
|
||||||
|
else
|
||||||
|
-- me.log("TIMER: did not start timer for later, index "..i.." at time "..time, "error")
|
||||||
|
-- bubble sort the entry back to the right spot
|
||||||
|
while i > 1 do
|
||||||
|
-- me.log("TIME ds: "..i.." "..net.pending.time[i].." "..net.pending.time[i-1], "error")
|
||||||
|
if net.pending.time[i] < net.pending.time[i-1] then
|
||||||
|
-- if out of order, swap. This works as previously the list was sorted
|
||||||
|
local t = net.pending.time[i-1]
|
||||||
|
net.pending.time[i-1] = net.pending.time[i]
|
||||||
|
net.pending.time[i] = t
|
||||||
|
t = net.pending[i-1]
|
||||||
|
net.pending[i-1] = net.pending[i]
|
||||||
|
net.pending[i] = t
|
||||||
|
if i == 2 then
|
||||||
|
me.start_crafting(cpos, net.pending.time[1]+0.1)
|
||||||
|
end
|
||||||
|
else
|
||||||
|
break
|
||||||
|
end
|
||||||
|
i = i - 1
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.autocraft(autocrafterCache, cpos, net, linv, inv, count)
|
||||||
|
local ostack = linv:get_stack("output", 1)
|
||||||
|
local name = ostack:get_name()
|
||||||
|
me.log("crafting "..name.." "..tostring(count), "error")
|
||||||
|
|
||||||
|
local stack = ItemStack(name)
|
||||||
|
local craft_count = ostack:get_count()
|
||||||
|
me.log("auto: craft_count "..craft_count.." count "..count, "error")
|
||||||
|
-- we craft a minimum of count, to the multiple of the crafting count
|
||||||
|
count = math.ceil(count/craft_count)
|
||||||
|
me.log("auto: count is now "..count, "error")
|
||||||
|
stack:set_count(count*craft_count)
|
||||||
|
me.log("auto: stack size is now "..stack:get_count(), "error")
|
||||||
|
me.log("auto: and build count is "..(count*craft_count), "error")
|
||||||
|
|
||||||
|
-- me.log("autocrafters: "..minetest.serialize(net.autocrafters), "error")
|
||||||
|
|
||||||
|
if not net.process then
|
||||||
|
-- rewalk the interfaces on the network to rebuild the machines.
|
||||||
|
net:reload_network()
|
||||||
|
end
|
||||||
|
if net.autocrafters[name] or net.process[name] then
|
||||||
|
me.log("using pipeworks autocrafter", "error")
|
||||||
|
local sink = function(stack)
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
|
return leftovers
|
||||||
|
end
|
||||||
|
local start_time = me.autocraft_next_start(net)
|
||||||
|
local built, step_time = build(net, cpos, inv, name, count*craft_count, stack, sink, start_time)
|
||||||
|
if built then
|
||||||
|
me.log("crafting "..stack:get_count().." "..stack:get_name().." in "..step_time.." seconds", "error")
|
||||||
|
else
|
||||||
|
me.log("can't craft "..stack:get_count().." "..stack:get_name(), "error")
|
||||||
|
end
|
||||||
|
return
|
||||||
|
end
|
||||||
|
|
||||||
|
me.log("using microexpansion autocrafter", "error")
|
||||||
|
local consume = {}
|
||||||
|
for i = 1, 9 do
|
||||||
|
local inp = linv:get_stack("recipe", i)
|
||||||
|
if inp and inp:get_name() ~= "" then
|
||||||
|
consume[inp:get_name()] = (consume[inp:get_name()] or 0) + count*inp:get_count()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local replace = true
|
||||||
|
for name, count in pairs(consume) do
|
||||||
|
local stack = ItemStack(name)
|
||||||
|
if count >= math.pow(2,16) then
|
||||||
|
replace = false
|
||||||
|
break
|
||||||
|
end
|
||||||
|
-- Don't consume the last item by autocrafting
|
||||||
|
stack:set_count(count+1)
|
||||||
|
replace = replace and inv:contains_item("main", stack)
|
||||||
|
end
|
||||||
|
if replace then
|
||||||
|
for name, count in pairs(consume) do
|
||||||
|
local stack = ItemStack(name)
|
||||||
|
stack:set_count(count)
|
||||||
|
me.log("REMOVE: "..count.." "..stack:get_name(), "error")
|
||||||
|
if not inv:contains_item("main", stack) then
|
||||||
|
fixme1()
|
||||||
|
end
|
||||||
|
local ret = me.remove_item(net, inv, "main", stack)
|
||||||
|
if ret:get_count() ~= stack:get_count() then
|
||||||
|
me.log("AUTO: found "..(ret:get_count()).." "..(stack:get_name()).." but wanted "..stack:get_count(), "error")
|
||||||
|
-- fixme2()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
if leftovers:get_count() > 0 then
|
||||||
|
-- Ick, no room, just drop on the floor. Maybe player inventory?
|
||||||
|
minetest.add_item(cpos, leftovers)
|
||||||
|
end
|
||||||
|
net:set_storage_space(true)
|
||||||
|
-- deal with replacements
|
||||||
|
local hash = minetest.hash_node_position(cpos)
|
||||||
|
local craft = autocrafterCache[hash] or me.get_craft(cpos, linv, hash)
|
||||||
|
for i = 1, 9 do
|
||||||
|
if (craft.decremented_input.items[i]:get_count() ~= linv:get_stack("recipe", i):get_count()
|
||||||
|
or craft.decremented_input.items[i]:get_name() ~= linv:get_stack("recipe", i):get_name())
|
||||||
|
and not craft.decremented_input.items[i]:is_empty() then
|
||||||
|
local leftovers = me.insert_item(craft.decremented_input.items[i], net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
|
if leftovers:get_count() > 0 then
|
||||||
|
-- Ick, no room, just drop on the floor. Maybe player inventory?
|
||||||
|
minetest.add_item(cpos, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if replace then
|
||||||
|
linv:set_stack("output", 1, craft.output.item)
|
||||||
|
else
|
||||||
|
linv:set_list("output", {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
@ -7,50 +7,50 @@ local network = me.network
|
|||||||
|
|
||||||
-- [register node] Controller
|
-- [register node] Controller
|
||||||
me.register_node("ctrl", {
|
me.register_node("ctrl", {
|
||||||
description = "ME Controller",
|
description = "ME Controller",
|
||||||
tiles = {
|
tiles = {
|
||||||
"ctrl_sides",
|
"ctrl_sides",
|
||||||
"ctrl_bottom",
|
"ctrl_bottom",
|
||||||
"ctrl_sides",
|
"ctrl_sides",
|
||||||
"ctrl_sides",
|
"ctrl_sides",
|
||||||
"ctrl_sides",
|
"ctrl_sides",
|
||||||
"ctrl_sides"
|
"ctrl_sides"
|
||||||
},
|
},
|
||||||
recipe = {
|
recipe = {
|
||||||
{ 1, {
|
{ 1, {
|
||||||
{"default:steel_ingot", "microexpansion:steel_infused_obsidian_ingot", "default:steel_ingot"},
|
{"default:steel_ingot", "microexpansion:steel_infused_obsidian_ingot", "default:steel_ingot"},
|
||||||
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
|
||||||
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
|
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
node_box = {
|
node_box = {
|
||||||
type = "fixed",
|
type = "fixed",
|
||||||
fixed = {
|
fixed = {
|
||||||
{-0.375, -0.375, -0.375, 0.375, 0.375, 0.375}, -- Core
|
{-0.375, -0.375, -0.375, 0.375, 0.375, 0.375}, -- Core
|
||||||
{0.1875, -0.5, -0.5, 0.5, 0.5, -0.1875}, -- Corner1
|
{0.1875, -0.5, -0.5, 0.5, 0.5, -0.1875}, -- Corner1
|
||||||
{-0.5, -0.5, -0.5, -0.1875, 0.5, -0.1875}, -- Corner2
|
{-0.5, -0.5, -0.5, -0.1875, 0.5, -0.1875}, -- Corner2
|
||||||
{-0.5, -0.5, 0.1875, -0.1875, 0.5, 0.5}, -- Corner3
|
{-0.5, -0.5, 0.1875, -0.1875, 0.5, 0.5}, -- Corner3
|
||||||
{0.1875, -0.5, 0.1875, 0.5, 0.5, 0.5}, -- Corner4
|
{0.1875, -0.5, 0.1875, 0.5, 0.5, 0.5}, -- Corner4
|
||||||
{-0.5, -0.4375, -0.5, 0.5, -0.1875, 0.5}, -- Bottom
|
{-0.5, -0.4375, -0.5, 0.5, -0.1875, 0.5}, -- Bottom
|
||||||
{-0.5, 0.1875, -0.5, 0.5, 0.5, -0.1875}, -- Top1
|
{-0.5, 0.1875, -0.5, 0.5, 0.5, -0.1875}, -- Top1
|
||||||
{0.1875, 0.1875, -0.5, 0.5, 0.5, 0.5}, -- Top2
|
{0.1875, 0.1875, -0.5, 0.5, 0.5, 0.5}, -- Top2
|
||||||
{-0.5, 0.1875, -0.5, -0.1875, 0.5, 0.5}, -- Top3
|
{-0.5, 0.1875, -0.5, -0.1875, 0.5, 0.5}, -- Top3
|
||||||
{-0.5, 0.1875, 0.1875, 0.5, 0.5, 0.5}, -- Top4
|
{-0.5, 0.1875, 0.1875, 0.5, 0.5, 0.5}, -- Top4
|
||||||
{-0.1875, -0.5, -0.1875, 0.1875, -0.25, 0.1875}, -- Bottom2
|
{-0.1875, -0.5, -0.1875, 0.1875, -0.25, 0.1875}, -- Bottom2
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
groups = { cracky = 1, me_connect = 1, },
|
groups = { cracky = 1, me_connect = 1, },
|
||||||
connect_sides = "nobottom",
|
connect_sides = "nobottom",
|
||||||
me_update = function(pos,_,ev)
|
me_update = function(pos,_,ev)
|
||||||
local cnet = me.get_network(pos)
|
local net = me.get_network(pos)
|
||||||
if cnet == nil then
|
if net == nil then
|
||||||
microexpansion.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error")
|
me.log("no network for ctrl at pos "..minetest.pos_to_string(pos),"error")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
cnet:update()
|
net:update()
|
||||||
end,
|
end,
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
@ -60,13 +60,13 @@ me.register_node("ctrl", {
|
|||||||
|
|
||||||
meta:set_string("infotext", "Network Controller")
|
meta:set_string("infotext", "Network Controller")
|
||||||
end,
|
end,
|
||||||
after_place_node = function(pos, player)
|
after_place_node = function(pos, player)
|
||||||
local name = player:get_player_name()
|
local name = player:get_player_name()
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("infotext", "Network Controller (owned by "..name..")")
|
meta:set_string("infotext", "Network Controller (owned by "..name..")")
|
||||||
meta:set_string("owner", name)
|
meta:set_string("owner", name)
|
||||||
end,
|
end,
|
||||||
on_destruct = function(pos)
|
on_destruct = function(pos)
|
||||||
local net,idx = me.get_network(pos)
|
local net,idx = me.get_network(pos)
|
||||||
--disconnect all those who need the network
|
--disconnect all those who need the network
|
||||||
me.send_event(pos,"disconnect",{net=net})
|
me.send_event(pos,"disconnect",{net=net})
|
||||||
@ -78,61 +78,93 @@ me.register_node("ctrl", {
|
|||||||
end
|
end
|
||||||
--disconnect all those that haven't realized the network is gone
|
--disconnect all those that haven't realized the network is gone
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
--disconnect all those that haven't realized the controller was disconnected
|
--disconnect all those that haven't realized the controller was disconnected
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
machine = {
|
machine = {
|
||||||
type = "controller",
|
type = "controller",
|
||||||
},
|
},
|
||||||
|
on_timer = function(pos, elapsed)
|
||||||
|
::top::
|
||||||
|
me.log("TIMER: starting service", "error")
|
||||||
|
local net = me.get_network(pos)
|
||||||
|
if not net then return false end
|
||||||
|
if not net.pending then return false end
|
||||||
|
local i = net.pending.index
|
||||||
|
local action = net.pending[i]
|
||||||
|
-- me.log("TIMER: doing service", "error")
|
||||||
|
if not action then
|
||||||
|
net.pending = nil
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
local prev_time = net.pending.time[i]
|
||||||
|
action(net)
|
||||||
|
net.pending[i] = nil
|
||||||
|
net.pending.time[i] = nil
|
||||||
|
net.pending.index = i + 1
|
||||||
|
if net.pending[i+1] then
|
||||||
|
local next_action_time = net.pending.time[i+1]
|
||||||
|
local step_time = next_action_time - prev_time
|
||||||
|
me.log("TIMER: starting next timer for "..step_time.." seconds", "error")
|
||||||
|
if step_time == 0 then
|
||||||
|
goto top
|
||||||
|
end
|
||||||
|
me.start_crafting(pos, step_time)
|
||||||
|
else
|
||||||
|
-- me.log("TIMER: ending service", "error")
|
||||||
|
net.pending = nil
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end,
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [register node] Cable
|
-- [register node] Cable
|
||||||
me.register_machine("cable", {
|
me.register_machine("cable", {
|
||||||
description = "ME Cable",
|
description = "ME Cable",
|
||||||
tiles = {
|
tiles = {
|
||||||
"cable",
|
"cable",
|
||||||
},
|
},
|
||||||
recipe = {
|
recipe = {
|
||||||
{ 12, "shapeless", {
|
{ 12, "shapeless", {
|
||||||
"microexpansion:steel_infused_obsidian_ingot", "microexpansion:machine_casing"
|
"microexpansion:steel_infused_obsidian_ingot", "microexpansion:machine_casing"
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
drawtype = "nodebox",
|
drawtype = "nodebox",
|
||||||
node_box = {
|
node_box = {
|
||||||
type = "connected",
|
type = "connected",
|
||||||
fixed = {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25},
|
fixed = {-0.25, -0.25, -0.25, 0.25, 0.25, 0.25},
|
||||||
connect_top = {-0.25, -0.25, -0.25, 0.25, 0.5, 0.25}, -- y+
|
connect_top = {-0.25, -0.25, -0.25, 0.25, 0.5, 0.25}, -- y+
|
||||||
connect_bottom = {-0.25, -0.5, -0.25, 0.25, 0.25, 0.25}, -- y-
|
connect_bottom = {-0.25, -0.5, -0.25, 0.25, 0.25, 0.25}, -- y-
|
||||||
connect_front = {-0.25, -0.25, -0.5, 0.25, 0.25, 0.25}, -- z-
|
connect_front = {-0.25, -0.25, -0.5, 0.25, 0.25, 0.25}, -- z-
|
||||||
connect_back = {-0.25, -0.25, 0.25, 0.25, 0.25, 0.5 }, -- z+
|
connect_back = {-0.25, -0.25, 0.25, 0.25, 0.25, 0.5 }, -- z+
|
||||||
connect_left = {-0.5, -0.25, -0.25, 0.25, 0.25, 0.25}, -- x-
|
connect_left = {-0.5, -0.25, -0.25, 0.25, 0.25, 0.25}, -- x-
|
||||||
connect_right = {-0.25, -0.25, -0.25, 0.5, 0.25, 0.25}, -- x+
|
connect_right = {-0.25, -0.25, -0.25, 0.5, 0.25, 0.25}, -- x+
|
||||||
},
|
},
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
groups = { crumbly = 1, },
|
groups = { crumbly = 1, },
|
||||||
--TODO: move these functions into the registration
|
--TODO: move these functions into the registration
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
me.send_event(pos,"connect")
|
me.send_event(pos,"connect")
|
||||||
end,
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
me_update = function(pos,_,ev)
|
me_update = function(pos,_,ev)
|
||||||
if ev then
|
if ev then
|
||||||
if ev.type ~= "disconnect" then return end
|
if ev.type ~= "disconnect" then return end
|
||||||
end
|
end
|
||||||
--maybe this shouldn't be called on every update
|
--maybe this shouldn't be called on every update
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
if me.get_connected_network(pos) then
|
if me.get_connected_network(pos) then
|
||||||
meta:set_string("infotext", "Network connected")
|
meta:set_string("infotext", "Network connected")
|
||||||
else
|
else
|
||||||
meta:set_string("infotext", "No Network")
|
meta:set_string("infotext", "No Network")
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
machine = {
|
machine = {
|
||||||
type = "conductor",
|
type = "conductor",
|
||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
me.networks = {}
|
me.networks = {}
|
||||||
local networks = me.networks
|
local networks = me.networks
|
||||||
local path = microexpansion.get_module_path("network")
|
local path = me.get_module_path("network")
|
||||||
|
|
||||||
--deprecated: use ItemStack(x) instead
|
--deprecated: use ItemStack(x) instead
|
||||||
--[[
|
--[[
|
||||||
@ -30,98 +30,397 @@ local function split_stack_values(stack)
|
|||||||
end
|
end
|
||||||
--]]
|
--]]
|
||||||
|
|
||||||
function me.insert_item(stack, inv, listname)
|
local annotate_large_stack = function(stack, count)
|
||||||
if me.settings.huge_stacks == false then
|
local description = minetest.registered_items[stack:get_name()]
|
||||||
return inv:add_item(listname, stack)
|
if description then
|
||||||
end
|
-- steel is an alias and won't be found in here, skip it
|
||||||
local to_insert = type(stack) == "userdata" and stack or ItemStack(stack)
|
description = description.description
|
||||||
local found = false
|
--stack:set_count(1)
|
||||||
for i = 0, inv:get_size(listname) do
|
--This screw up everything, autocrafting, item removal and more
|
||||||
local inside = inv:get_stack(listname, i)
|
--stack:get_meta():set_string("description", description.." "..count)
|
||||||
if inside:get_name() == to_insert:get_name() and inside:get_wear() == to_insert:get_wear() then
|
stack:get_meta():set_string("description", "")
|
||||||
if inside:get_meta():equals(to_insert:get_meta()) then
|
|
||||||
local total_count = inside:get_count() + to_insert:get_count()
|
|
||||||
-- bigger item count is not possible, we only have unsigned 16 bit
|
|
||||||
if total_count <= math.pow(2,16) then
|
|
||||||
if not inside:set_count(total_count) then
|
|
||||||
microexpansion.log("adding items to stack in microexpansion network failed","error")
|
|
||||||
print("stack is now " .. inside:to_string())
|
|
||||||
end
|
|
||||||
inv:set_stack(listname, i, inside)
|
|
||||||
found = true
|
|
||||||
break;
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
if not found then
|
|
||||||
return inv:add_item(listname, stack)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
function me.insert_item(stack, net, inv, listname, bias)
|
||||||
|
if stack == nil then
|
||||||
|
foobar()
|
||||||
|
return ItemStack(), 0
|
||||||
|
end
|
||||||
|
stack = type(stack) == "userdata" and stack or ItemStack(stack)
|
||||||
|
if stack:get_name() == "" then
|
||||||
|
-- foobar() -- TODO: can trip, ignore for now
|
||||||
|
return ItemStack(), 0
|
||||||
|
end
|
||||||
|
local slot
|
||||||
|
assert(net, not stack:is_empty())
|
||||||
|
local found = false
|
||||||
|
if not net.byname then
|
||||||
|
net.byname = {}
|
||||||
|
end
|
||||||
|
if not net.byname[listname] then
|
||||||
|
net.byname[listname] = {}
|
||||||
|
end
|
||||||
|
if not net.byname[listname][stack:get_name()] then
|
||||||
|
net.byname[listname][stack:get_name()] = {}
|
||||||
|
end
|
||||||
|
--if not net.byname[listname][stack:get_name()][stack:get_wear()] then
|
||||||
|
-- net.byname[listname][stack:get_name()][stack:get_wear()] = {}
|
||||||
|
--end
|
||||||
|
local meta = stack:get_meta()
|
||||||
|
-- slot = net.byname[listname][stack:get_name()][stack:get_wear()][meta]
|
||||||
|
-- assert(net, minetest.serialize(meta))
|
||||||
|
::was_empty::
|
||||||
|
slot = net.byname[listname][stack:get_name()][stack:get_wear()]
|
||||||
|
-- me.log("checking "..listname.." slot "..tostring(slot).." has "..stack:get_name().." in it", "error")
|
||||||
|
if not slot then
|
||||||
|
local ret = inv:add_item(listname, stack) -- TODO: fix to use set_stack, careful capacity
|
||||||
|
slot = inv:get_size(listname)
|
||||||
|
-- me.log(listname.." slot "..tostring(slot).." should now have "..stack:get_name().." in it", "error")
|
||||||
|
-- me.log(listname.." slot "..tostring(slot).." has "..inv:get_stack(listname, slot):get_name().." in it", "error")
|
||||||
|
if inv:get_stack(listname, slot):get_name() ~= stack:get_name() then
|
||||||
|
return ret, 0
|
||||||
|
--net:sync_main(inv)
|
||||||
|
-- TODO: infinite loop on full?
|
||||||
|
--goto was_empty
|
||||||
|
end
|
||||||
|
-- net.byname[listname][stack:get_name()][stack:get_wear()][meta] = slot
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = slot
|
||||||
|
-- me.log("byname is "..minetest.serialize(net.byname), "error")
|
||||||
|
if bias then
|
||||||
|
if not net.bias then
|
||||||
|
net.bias = {}
|
||||||
|
end
|
||||||
|
if not net.bias[listname] then
|
||||||
|
net.bias[listname] = {}
|
||||||
|
end
|
||||||
|
if not net.bias[listname][stack:get_name()] then
|
||||||
|
net.bias[listname][stack:get_name()] = 0
|
||||||
|
end
|
||||||
|
net.bias[listname][stack:get_name()] = net.bias[listname][stack:get_name()] + bias
|
||||||
|
me.log("LARGE: init insert_item bias "..bias.." for "..stack:get_name(), "error")
|
||||||
|
local mstack = inv:get_stack(listname, slot)
|
||||||
|
annotate_large_stack(mstack, mstack:get_count()+net.bias[listname][stack:get_name()])
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
end
|
||||||
|
return ret, slot
|
||||||
|
end
|
||||||
|
local mstack = inv:get_stack(listname, slot)
|
||||||
|
-- me.log(listname.." slot "..tostring(slot).." has "..mstack:get_name().." in it", "error")
|
||||||
|
if mstack:is_empty() then
|
||||||
|
-- me.log("adding items to stack in microexpansion network was going to fail, fixing", "error")
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
goto was_empty
|
||||||
|
end
|
||||||
|
-- me.log("init insert_item "..stack:get_name(), "error")
|
||||||
|
-- me.log("init insert_item "..mstack:get_name(), "error")
|
||||||
|
if mstack:get_name() ~= stack:get_name() then
|
||||||
|
-- me.log("adding items to stack in microexpansion network was going to fail, wrong item, fixing", "error")
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
goto was_empty
|
||||||
|
end
|
||||||
|
local mbias = (net.bias and net.bias[listname] and net.bias[listname][stack:get_name()]) or 0
|
||||||
|
local total_count = mstack:get_count() + mbias + stack:get_count() + (bias or 0)
|
||||||
|
-- me.log("insert_item "..mstack:get_name().." "..tostring(total_count), "error")
|
||||||
|
-- bigger item count is not possible, we only have unsigned 16 bit
|
||||||
|
if total_count > math.pow(2,15) then
|
||||||
|
-- We handle overflows by storing the excess stores into a bias number for the slot.
|
||||||
|
-- This give us lua max int (2^48 or so) for the actual count.
|
||||||
|
if not net.bias then
|
||||||
|
net.bias = {}
|
||||||
|
end
|
||||||
|
if not net.bias[listname] then
|
||||||
|
net.bias[listname] = {}
|
||||||
|
end
|
||||||
|
if not net.bias[listname][stack:get_name()] then
|
||||||
|
net.bias[listname][stack:get_name()] = 0
|
||||||
|
end
|
||||||
|
net.bias[listname][stack:get_name()] = total_count - math.pow(2,15)
|
||||||
|
me.log("LARGE: overflow bias "..stack:get_count().." for "..stack:get_name(), "error")
|
||||||
|
total_count = math.pow(2,15)
|
||||||
|
end
|
||||||
|
local addition_real_loaned = total_count - mstack:get_count()
|
||||||
|
mstack:set_count(total_count)
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
-- if there is one or more loans for the item, add stack:get_count()
|
||||||
|
-- + (bias or 0) to them and update those inventories, if they have room
|
||||||
|
local remaining = stack:get_count() + (bias or 0)
|
||||||
|
local loan_slot = net:find_loan(inv, stack)
|
||||||
|
if loan_slot then
|
||||||
|
me.loan.bump_loan(net, inv, loan_slot, remaining, addition_real_loaned)
|
||||||
|
end
|
||||||
|
return ItemStack(), slot
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.add_capacity(ipos, count)
|
||||||
|
local int_meta = minetest.get_meta(ipos)
|
||||||
|
local prev = int_meta:get_int("capacity") or 0
|
||||||
|
int_meta:set_int("capacity", prev + count)
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.remove_item(net, inv, listname, stack)
|
||||||
|
if not stack then return ItemStack() end
|
||||||
|
if stack == "" then return ItemStack() end
|
||||||
|
if type(stack) == string then
|
||||||
|
me.log("REMOVE: converting "..stack, "error")
|
||||||
|
stack = ItemStack(stack)
|
||||||
|
end
|
||||||
|
-- stack = ItemStack(stack):set_count(stack:get_count())
|
||||||
|
-- this can dump...
|
||||||
|
me.log("type is "..type(stack), "error")
|
||||||
|
-- me.log("serial is "..minetest.serialize(stack), "error")
|
||||||
|
if stack:get_count() == 0 then return ItemStack() end
|
||||||
|
me.log("me.remove_item "..listname, "error")
|
||||||
|
me.log("me.remove_item "..listname.." "..stack:get_count().." "..stack:get_name(), "error")
|
||||||
|
-- me.log("me.remove_item "..listname.." "..stack:get_wear(), "error")
|
||||||
|
if listname ~= "main" then
|
||||||
|
foobar()
|
||||||
|
return inv:remove_item(listname, stack)
|
||||||
|
end
|
||||||
|
if not net.byname[listname] or not net.byname[listname][stack:get_name()] then
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local slot = net.byname[listname][stack:get_name()][stack:get_wear()]
|
||||||
|
if not slot then
|
||||||
|
me.log("wanted to remove "..stack:get_name().." from "..listname..", but didn't find anything", "error")
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local mstack = inv:get_stack(listname, slot)
|
||||||
|
me.log("init remove item "..tostring(stack:get_count()).." "..stack:get_name(), "error")
|
||||||
|
if stack:get_name() ~= mstack:get_name()
|
||||||
|
or stack:get_wear() ~= mstack:get_wear()
|
||||||
|
or not stack:get_meta():equals(mstack:get_meta()) then
|
||||||
|
me.log("wanted to remove "..stack:get_name().." from "..listname..", but had "..mstack:get_name().." in slot "..slot, "error")
|
||||||
|
-- foobar()
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local mbias = 0
|
||||||
|
if net.bias and net.bias[listname] then
|
||||||
|
mbias = net.bias[listname][stack:get_name()] or 0
|
||||||
|
end
|
||||||
|
local on_loan = net.counts[stack:get_name()]
|
||||||
|
local remaining = mstack:get_count() + mbias - stack:get_count()
|
||||||
|
me.log("init me.remove_item has "..(on_loan or 0).." on loan and "..remaining.." remaining", "error")
|
||||||
|
if on_loan and remaining < on_loan then
|
||||||
|
me.log("init me.remove_item has "..on_loan.." on loan and "..remaining.." remaining", "error")
|
||||||
|
local loan_slot = net:find_loan(inv, stack)
|
||||||
|
-- find_loan can update main, refetch
|
||||||
|
mstack = inv:get_stack(listname, slot)
|
||||||
|
if not loan_slot then
|
||||||
|
-- someone updated the real inventories, there are no more of these
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local lstack = me.loan.get_stack(net, inv, loan_slot)
|
||||||
|
if lstack:is_empty() then
|
||||||
|
return ItemStack()
|
||||||
|
end
|
||||||
|
local ref = me.network.get_ref(lstack)
|
||||||
|
local real_count = nil
|
||||||
|
if ref.drawer then
|
||||||
|
local c = drawers.drawer_get_content(ref.pos, ref.slot)
|
||||||
|
c.count = math.max(c.count-1,0) -- Poor man's locking
|
||||||
|
local count = math.min(stack:get_count(), c.count)
|
||||||
|
me.log("init removing "..count.." items from drawer", "error")
|
||||||
|
stack:set_count(count)
|
||||||
|
local take = stack
|
||||||
|
drawers.drawer_take_large_item(ref.pos, take)
|
||||||
|
c.count = c.count - count
|
||||||
|
real_count = c.count
|
||||||
|
if real_count > math.pow(2,15) then
|
||||||
|
real_count = math.pow(2,15)
|
||||||
|
end
|
||||||
|
-- me.log("CAPACITY: drawer "..-count, "error")
|
||||||
|
-- me.add_capacity(ref.ipos, -count)
|
||||||
|
else
|
||||||
|
local rinv = minetest.get_meta(ref.pos):get_inventory()
|
||||||
|
local real_stack = rinv:get_stack(ref.invname, ref.slot)
|
||||||
|
local count = math.min(stack:get_count(), real_stack:get_count())
|
||||||
|
me.log("init removing "..count.." items from chest", "error")
|
||||||
|
stack:set_count(count)
|
||||||
|
real_count = real_stack:get_count()-count
|
||||||
|
real_stack:set_count(real_count)
|
||||||
|
rinv:set_stack(ref.invname, ref.slot, real_stack)
|
||||||
|
-- me.log("CAPACITY: chest "..-count, "error")
|
||||||
|
-- me.add_capacity(ref.ipos, -count)
|
||||||
|
end
|
||||||
|
me.log("init now down to "..real_count.." items", "error")
|
||||||
|
local lcount = lstack:get_count() -- it was mc 1 excess 0 lcount 1 rc 1
|
||||||
|
local excess = real_count - lcount -- it was mc 1 excess -1 lcount 2 rc 1
|
||||||
|
me.log("it was "..mstack:get_count().." "..excess.." "..lcount.." "..real_count, "error") -- fails with: 1 -1
|
||||||
|
if real_count == 0 then
|
||||||
|
me.log("init me.remove_item before remove_loan chest", "error")
|
||||||
|
net:remove_loan(ref.pos, inv, lstack, loan_slot, ref)
|
||||||
|
elseif excess ~= 0 then
|
||||||
|
-- update loan and main with new excess
|
||||||
|
lstack:set_count(lcount + excess)
|
||||||
|
me.log("LOAN: me.remove_item loan to "..lstack:get_count(), "error")
|
||||||
|
me.loan.set_stack(net, inv, loan_slot, lstack)
|
||||||
|
mstack:set_count(mstack:get_count() + excess)
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
if mstack:is_empty() then
|
||||||
|
me.maybemove(net, inv, listname, slot, stack)
|
||||||
|
end
|
||||||
|
-- TODO: Think this is wrong, only adjust by excess no stack:get_count()
|
||||||
|
--net.counts[lstack:get_name()] = net.counts[lstack:get_name()] - stack:get_count()
|
||||||
|
--me.add_capacity(ref.ipos, -stack:get_count())
|
||||||
|
me.log("CAPACITY: is "..excess, "error")
|
||||||
|
net.counts[lstack:get_name()] = net.counts[lstack:get_name()] + excess
|
||||||
|
me.add_capacity(ref.ipos, excess)
|
||||||
|
end
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
if remaining > 0 then
|
||||||
|
if remaining > math.pow(2,15) then
|
||||||
|
if not net.bias then
|
||||||
|
net.bias = {}
|
||||||
|
end
|
||||||
|
if not net.bias[listname] then
|
||||||
|
net.bias[listname] = {}
|
||||||
|
end
|
||||||
|
me.log("LARGE: total count "..remaining.." for "..stack:get_name(), "error")
|
||||||
|
annotate_large_stack(mstack, remaining)
|
||||||
|
net.bias[listname][stack:get_name()] = remaining - math.pow(2,15)
|
||||||
|
remaining = math.pow(2,15)
|
||||||
|
end
|
||||||
|
mstack:set_count(remaining)
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
if remaining < 0 then
|
||||||
|
me.log("init wow, missing "..tostring(-remaining).." "..stack:get_name().." during removal, taking less", "error")
|
||||||
|
-- take fewer
|
||||||
|
stack:set_count(mstack:get_count() + mbias)
|
||||||
|
remaining = 0
|
||||||
|
end
|
||||||
|
mstack:set_count(remaining)
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
me.log("init me.remove_item bottom before", "error")
|
||||||
|
me.maybemove(net, inv, listname, slot, stack)
|
||||||
|
me.log("init me.remove_item bottom after", "error")
|
||||||
|
return stack
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.maybemove(net, inv, listname, slot, stack)
|
||||||
|
if stack == nil then
|
||||||
|
-- me.log("init nil stack", "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if net == nil then
|
||||||
|
-- me.log("init nil net", "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if inv == nil then
|
||||||
|
-- me.log("init nil inv", "error")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
-- me.log("init maybemove "..stack:get_name(), "error")
|
||||||
|
if not net.byname or not net.byname[listname] or not net.byname[listname][stack:get_name()] then
|
||||||
|
me.log("byname on "..listname.." is already nil", "error")
|
||||||
|
else
|
||||||
|
-- slot has been completely removed, deindex it
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
end
|
||||||
|
if net.bias and net.bias[listname] then
|
||||||
|
net.bias[listname][stack:get_name()] = nil
|
||||||
|
end
|
||||||
|
-- Move the last or the second to the last if the last is empty,
|
||||||
|
-- back to the hole left by the removed items
|
||||||
|
local main_size = inv:get_size(listname)
|
||||||
|
-- me.log("CALC main_size"..main_size.." slot "..slot, "error")
|
||||||
|
if slot < main_size and main_size > 1 then
|
||||||
|
local orig_slot = main_size
|
||||||
|
local mstack = inv:get_stack(listname, orig_slot)
|
||||||
|
-- me.log("CALC count "..mstack:get_count().." orig_slot-1 "..orig_slot-1, "error")
|
||||||
|
if mstack:is_empty() and slot < orig_slot-1 and orig_slot-1 > 1 then
|
||||||
|
orig_slot = orig_slot-1
|
||||||
|
mstack = inv:get_stack(listname, orig_slot)
|
||||||
|
end
|
||||||
|
if not mstack:is_empty() then
|
||||||
|
inv:set_stack(listname, orig_slot, ItemStack())
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
-- [meta]
|
||||||
|
-- me.log("CALC not empty, old "..stack:get_name().." new "..mstack:get_name(), "error")
|
||||||
|
if net.byname and net.byname[listname] and net.byname[listname][stack:get_name()] then
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
end
|
||||||
|
net.byname[listname][mstack:get_name()][mstack:get_wear()] = slot
|
||||||
|
else
|
||||||
|
inv:set_stack(listname, slot, mstack)
|
||||||
|
-- me.log("CALC empty, old "..stack:get_name(), "error")
|
||||||
|
if net.byname and net.byname[listname] and net.byname[listname][stack:get_name()] then
|
||||||
|
net.byname[listname][stack:get_name()][stack:get_wear()] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
inv:set_size(listname, main_size-1)
|
||||||
|
end
|
||||||
|
|
||||||
|
dofile(path.."/loan.lua") -- Loan Management
|
||||||
dofile(path.."/network.lua") -- Network Management
|
dofile(path.."/network.lua") -- Network Management
|
||||||
|
dofile(path.."/autocraft.lua") -- Autocrafting
|
||||||
|
|
||||||
-- generate iterator to find all connected nodes
|
-- generate iterator to find all connected nodes
|
||||||
function me.connected_nodes(start_pos,include_ctrl)
|
function me.connected_nodes(start_pos,include_ctrl)
|
||||||
-- nodes to be checked
|
-- nodes to be checked
|
||||||
local open_list = {{pos = start_pos}}
|
local open_list = {{pos = start_pos}}
|
||||||
-- nodes that were checked
|
-- nodes that were checked
|
||||||
local closed_set = {}
|
local closed_set = {}
|
||||||
-- local connected nodes function to reduce table lookups
|
-- local connected nodes function to reduce table lookups
|
||||||
local adjacent_connected_nodes = me.network.adjacent_connected_nodes
|
local adjacent_connected_nodes = me.network.adjacent_connected_nodes
|
||||||
-- return the generated iterator
|
-- return the generated iterator
|
||||||
return function ()
|
return function ()
|
||||||
-- start looking for next pos
|
-- start looking for next pos
|
||||||
local open = false
|
local open = false
|
||||||
-- pos to be checked
|
-- pos to be checked
|
||||||
local current
|
local current
|
||||||
-- find next unclosed
|
-- find next unclosed
|
||||||
while not open do
|
while not open do
|
||||||
-- get unchecked pos
|
-- get unchecked pos
|
||||||
current = table.remove(open_list)
|
current = table.remove(open_list)
|
||||||
-- none are left
|
-- none are left
|
||||||
if current == nil then return end
|
if current == nil then return end
|
||||||
-- assume it's open
|
-- assume it's open
|
||||||
open = true
|
open = true
|
||||||
-- check the closed positions
|
-- check the closed positions
|
||||||
for _,closed in pairs(closed_set) do
|
for _,closed in pairs(closed_set) do
|
||||||
-- if current is unclosed
|
-- if current is unclosed
|
||||||
if vector.equals(closed,current.pos) then
|
if vector.equals(closed,current.pos) then
|
||||||
--found one was closed
|
--found one was closed
|
||||||
open = false
|
open = false
|
||||||
end
|
|
||||||
end
|
|
||||||
end
|
|
||||||
-- get all connected nodes
|
|
||||||
local nodes = adjacent_connected_nodes(current.pos,include_ctrl)
|
|
||||||
-- iterate through them
|
|
||||||
for _,n in pairs(nodes) do
|
|
||||||
-- mark position to be checked
|
|
||||||
table.insert(open_list,n)
|
|
||||||
end
|
|
||||||
-- add this one to the closed set
|
|
||||||
table.insert(closed_set,current.pos)
|
|
||||||
-- return the one to be checked
|
|
||||||
return current.pos,current.name
|
|
||||||
end
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- get all connected nodes
|
||||||
|
local nodes = adjacent_connected_nodes(current.pos,include_ctrl)
|
||||||
|
-- iterate through them
|
||||||
|
for _,n in pairs(nodes) do
|
||||||
|
-- mark position to be checked
|
||||||
|
table.insert(open_list,n)
|
||||||
|
end
|
||||||
|
-- add this one to the closed set
|
||||||
|
table.insert(closed_set,current.pos)
|
||||||
|
-- return the one to be checked
|
||||||
|
return current.pos,current.name
|
||||||
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- get network connected to position
|
-- get network connected to position
|
||||||
function me.get_connected_network(start_pos)
|
function me.get_connected_network(start_pos)
|
||||||
for npos,nn in me.connected_nodes(start_pos,true) do
|
for npos,nn in me.connected_nodes(start_pos,true) do
|
||||||
if nn == "microexpansion:ctrl" then
|
if nn == "microexpansion:ctrl" then
|
||||||
local network = me.get_network(npos)
|
local net = me.get_network(npos)
|
||||||
if network then
|
if net then
|
||||||
return network,npos
|
return net,npos
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function me.update_connected_machines(start_pos,event,include_start)
|
function me.update_connected_machines(start_pos,event,include_start)
|
||||||
microexpansion.log("updating connected machines","action")
|
me.log("updating connected machines", "action")
|
||||||
local ev = event or {type = "n/a"}
|
local ev = event or {type = "n/a"}
|
||||||
local sn = microexpansion.get_node(start_pos)
|
local sn = me.get_node(start_pos)
|
||||||
local sd = minetest.registered_nodes[sn.name]
|
local sd = minetest.registered_nodes[sn.name]
|
||||||
local sm = sd.machine or {}
|
local sm = sd.machine or {}
|
||||||
ev.origin = {
|
ev.origin = {
|
||||||
@ -134,7 +433,7 @@ function me.update_connected_machines(start_pos,event,include_start)
|
|||||||
if include_start or not vector.equals(npos,start_pos) then
|
if include_start or not vector.equals(npos,start_pos) then
|
||||||
me.update_node(npos,ev)
|
me.update_node(npos,ev)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
function me.send_event(spos,type,data)
|
function me.send_event(spos,type,data)
|
||||||
@ -148,31 +447,31 @@ function me.send_event(spos,type,data)
|
|||||||
end
|
end
|
||||||
|
|
||||||
function me.get_network(pos)
|
function me.get_network(pos)
|
||||||
for i,net in pairs(networks) do
|
for i,net in pairs(networks) do
|
||||||
if net.controller_pos then
|
if net.controller_pos then
|
||||||
if vector.equals(pos, net.controller_pos) then
|
if vector.equals(pos, net.controller_pos) then
|
||||||
return net,i
|
return net,i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
dofile(path.."/ctrl.lua") -- Controller/wires
|
dofile(path.."/ctrl.lua") -- Controller/wires
|
||||||
|
|
||||||
-- load networks
|
-- load networks
|
||||||
function me.load()
|
function me.load()
|
||||||
local f = io.open(me.worldpath.."/microexpansion_networks", "r")
|
local f = io.open(me.worldpath.."/microexpansion_networks", "r")
|
||||||
if f then
|
if f then
|
||||||
local res = minetest.deserialize(f:read("*all"))
|
local res = minetest.deserialize(f:read("*all"))
|
||||||
f:close()
|
f:close()
|
||||||
if type(res) == "table" then
|
if type(res) == "table" then
|
||||||
for _,n in pairs(res) do
|
for _,n in pairs(res) do
|
||||||
local net = me.network.new(n)
|
local net = me.network.new(n)
|
||||||
net:load()
|
net:load()
|
||||||
table.insert(me.networks,net)
|
table.insert(me.networks,net)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- load now
|
-- load now
|
||||||
@ -181,12 +480,17 @@ me.load()
|
|||||||
-- save networks
|
-- save networks
|
||||||
function me.save()
|
function me.save()
|
||||||
local data = {}
|
local data = {}
|
||||||
for _,v in pairs(me.networks) do
|
for _,net in pairs(me.networks) do
|
||||||
table.insert(data,v:serialize())
|
-- We rebuild this data by walking as they contain non-serializable content.
|
||||||
|
-- All other data is serialized and survives.
|
||||||
|
net.autocrafters = nil
|
||||||
|
net.autocrafters_by_pos = nil
|
||||||
|
net.process = nil
|
||||||
|
table.insert(data,net:serialize())
|
||||||
end
|
end
|
||||||
local f = io.open(me.worldpath.."/microexpansion_networks", "w")
|
local f = io.open(me.worldpath.."/microexpansion_networks", "w")
|
||||||
f:write(minetest.serialize(data))
|
f:write(minetest.serialize(data))
|
||||||
f:close()
|
f:close()
|
||||||
end
|
end
|
||||||
|
|
||||||
-- save on server shutdown
|
-- save on server shutdown
|
||||||
|
108
modules/network/loan.lua
Normal file
108
modules/network/loan.lua
Normal file
@ -0,0 +1,108 @@
|
|||||||
|
local me = microexpansion
|
||||||
|
local loan = {
|
||||||
|
}
|
||||||
|
me.loan = loan
|
||||||
|
|
||||||
|
function me.loan.get_stack(net, inv, loan_slot)
|
||||||
|
local lstack = inv:get_stack("loan", loan_slot)
|
||||||
|
return lstack
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.loan.set_stack(net, inv, loan_slot, lstack)
|
||||||
|
inv:set_stack("loan", loan_slot, lstack)
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.loan.get_size(net, inv)
|
||||||
|
return inv:get_size("loan")
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.loan.set_size(net, inv, size)
|
||||||
|
return inv:set_size("loan", size)
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.loan.bump_loan(net, inv, loan_slot, remaining, addition_real_loaned)
|
||||||
|
local lstack = me.loan.get_stack(net, inv, loan_slot)
|
||||||
|
local ref
|
||||||
|
local real_count
|
||||||
|
if lstack:is_empty() then
|
||||||
|
-- TODO: should never happen, verify and remove
|
||||||
|
return
|
||||||
|
end
|
||||||
|
ref = me.network.get_ref(lstack)
|
||||||
|
real_count = nil
|
||||||
|
local prev_lstack_count = lstack:get_count()
|
||||||
|
if ref.drawer then
|
||||||
|
local stack = ItemStack(lstack)
|
||||||
|
-- the drawer api only allow up to 2^16-1, ask them for a better api, 2^48 max
|
||||||
|
local count = math.pow(2,16)-1
|
||||||
|
-- ensure that lstack:get_count() + spare below is at most 2^16-1
|
||||||
|
count = math.min(count, math.pow(2,16)-1 - lstack:get_count())
|
||||||
|
-- ensure at most 2^16-1 as the stack api doesn't allow more
|
||||||
|
count = math.min(count, remaining)
|
||||||
|
-- if the loan size is already maximal, then we can't update the loan any
|
||||||
|
if count > 0 then
|
||||||
|
stack:set_count(count)
|
||||||
|
|
||||||
|
-- bump up the actual inventory, spare is how many fit
|
||||||
|
local excess = drawers.drawer_insert_object(ref.pos, stack, ref.slot)
|
||||||
|
local spare = count - excess:get_count()
|
||||||
|
|
||||||
|
-- bump loan by spare
|
||||||
|
lstack:set_count(lstack:get_count() + spare)
|
||||||
|
me.log("LOAN: bump_loan to "..lstack:get_count(), "error")
|
||||||
|
me.loan.set_stack(net, inv, loan_slot, lstack)
|
||||||
|
net.counts[lstack:get_name()] = net.counts[lstack:get_name()] + spare
|
||||||
|
me.log("COUNT: loan now to "..net.counts[lstack:get_name()].." "..lstack:get_name()..", "..spare.." more", "error")
|
||||||
|
me.log("LOAN: adril "..addition_real_loaned.." loan "..prev_lstack_count.." and adjustment(spare) "..spare, "error")
|
||||||
|
addition_real_loaned = math.min(addition_real_loaned, spare)
|
||||||
|
me.add_capacity(ref.ipos, addition_real_loaned)
|
||||||
|
|
||||||
|
-- reduce remaining by spare
|
||||||
|
remaining = remaining - spare
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local rinv = minetest.get_meta(ref.pos):get_inventory()
|
||||||
|
local real_stack = rinv:get_stack(ref.invname, ref.slot)
|
||||||
|
local max = real_stack:get_stack_max()
|
||||||
|
if real_stack:get_count() < max then
|
||||||
|
local spare = max - real_stack:get_count()
|
||||||
|
spare = math.min(spare, remaining)
|
||||||
|
-- me.log("bumping "..lstack:get_name().." by "..spare, "error")
|
||||||
|
|
||||||
|
-- bump up the actual inventory by spare
|
||||||
|
real_stack:set_count(real_stack:get_count() + spare)
|
||||||
|
rinv:set_stack(ref.invname, ref.slot, real_stack)
|
||||||
|
|
||||||
|
-- bump loan by spare
|
||||||
|
lstack:set_count(lstack:get_count() + spare)
|
||||||
|
-- me.log("bumping "..lstack:get_name().." to "..lstack:get_count(), "error")
|
||||||
|
me.log("LOAN: bump_loan to "..lstack:get_count(), "error")
|
||||||
|
me.loan.set_stack(net, inv, loan_slot, lstack)
|
||||||
|
-- me.log("COUNTS: "..minetest.serialize(net.counts), "error")
|
||||||
|
net.counts[lstack:get_name()] = net.counts[lstack:get_name()] + spare
|
||||||
|
me.log("COUNT: bump_loan loan now to "..net.counts[lstack:get_name()].." "..lstack:get_name()..", "..spare.." more", "error")
|
||||||
|
me.log("LOAN: adril "..addition_real_loaned.." loan "..prev_lstack_count.." and adjustment(spare) "..spare, "error")
|
||||||
|
addition_real_loaned = math.min(addition_real_loaned, spare)
|
||||||
|
me.add_capacity(ref.ipos, addition_real_loaned)
|
||||||
|
|
||||||
|
-- reduce remaining by spare
|
||||||
|
remaining = remaining - spare
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- This code is misguided. We've already added them as real, we can
|
||||||
|
-- only add them to a loan if those items are added to that
|
||||||
|
-- inventory being loaded. This is only possible if there is room.
|
||||||
|
if false and remaining > 0 then
|
||||||
|
if not net.bias then
|
||||||
|
net.bias = {}
|
||||||
|
end
|
||||||
|
if not net.bias["loan"] then
|
||||||
|
net.bias["loan"] = {}
|
||||||
|
end
|
||||||
|
if not net.bias["loan"][loan_slot] then
|
||||||
|
net.bias["loan"][loan_slot] = 0
|
||||||
|
end
|
||||||
|
net.bias["loan"][loan_slot] = net.bias["loan"][loan_slot] + remaining
|
||||||
|
me.log("LARGE: bump_loan bias is "..net.bias["loan"][loan_slot].." "..lstack:get_name()..", "..remaining.." more", "error")
|
||||||
|
end
|
||||||
|
end
|
File diff suppressed because it is too large
Load Diff
@ -48,7 +48,7 @@ function microexpansion.int_to_pagenum(int)
|
|||||||
end
|
end
|
||||||
|
|
||||||
-- [function] Move items from inv to inv
|
-- [function] Move items from inv to inv
|
||||||
function microexpansion.move_inv(inv1, inv2, max)
|
function microexpansion.move_inv(net, inv1, inv2, max)
|
||||||
if max <= 0 then return end
|
if max <= 0 then return end
|
||||||
local finv, tinv = inv1.inv, inv2.inv
|
local finv, tinv = inv1.inv, inv2.inv
|
||||||
local fname, tname = inv1.name, inv2.name
|
local fname, tname = inv1.name, inv2.name
|
||||||
@ -66,14 +66,14 @@ function microexpansion.move_inv(inv1, inv2, max)
|
|||||||
end
|
end
|
||||||
if tinv and tinv:room_for_item(tname, v) then
|
if tinv and tinv:room_for_item(tname, v) then
|
||||||
if huge then
|
if huge then
|
||||||
microexpansion.insert_item(v, tinv, tname)
|
microexpansion.insert_item(v, net, tinv, tname)
|
||||||
finv:remove_item(fname, v)
|
finv:remove_item(fname, v)
|
||||||
else
|
else
|
||||||
local leftover = tinv:add_item(tname, v)
|
local leftovers = tinv:add_item(tname, v)
|
||||||
finv:remove_item(fname, v)
|
finv:remove_item(fname, v)
|
||||||
if leftover and not(leftover:is_empty()) then
|
if leftovers and not leftovers:is_empty() then
|
||||||
microexpansion.log("leftover items when transferring inventory","warning")
|
microexpansion.log("leftover items when transferring inventory", "warning")
|
||||||
finv:add_item(fname, leftover)
|
finv:add_item(fname, leftovers)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
inserted = inserted + v:get_count()
|
inserted = inserted + v:get_count()
|
||||||
|
756
modules/storage/cterminal.lua
Normal file
756
modules/storage/cterminal.lua
Normal file
@ -0,0 +1,756 @@
|
|||||||
|
-- crafting terminal
|
||||||
|
-- microexpansion/cterminal.lua
|
||||||
|
|
||||||
|
-- TODO: Bugs, can't craft sticks, oil extract by using the
|
||||||
|
-- output. Does work when updating the recipe. Groups are hanky. We
|
||||||
|
-- only use the last recipe registered. Would be nice to be able to
|
||||||
|
-- cycle trough them. We handle this by merely requiring the user to
|
||||||
|
-- select the input recipe they want.
|
||||||
|
|
||||||
|
-- TODO: Bugs in original, if you remove controller, this wipes all drives
|
||||||
|
-- Spacing sucks.
|
||||||
|
|
||||||
|
-- The search list doesn't update when main updates or when autocrafting updates.
|
||||||
|
|
||||||
|
local autocrafterCache = {} -- caches some recipe data to avoid to call the slow function minetest.get_craft_result() every second
|
||||||
|
|
||||||
|
local me = microexpansion
|
||||||
|
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
||||||
|
|
||||||
|
-- [me chest] Get formspec
|
||||||
|
local function chest_formspec(pos, start_id, listname, page_max, q)
|
||||||
|
local list
|
||||||
|
local page_number = ""
|
||||||
|
local buttons = ""
|
||||||
|
local query = q or ""
|
||||||
|
local net,cpos = me.get_connected_network(pos)
|
||||||
|
|
||||||
|
if cpos then
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
if listname and (inv:get_size(listname) > 0 or net:get_item_capacity() > 0) then
|
||||||
|
local ctrlinvname = net:get_inventory_name()
|
||||||
|
if listname == "main" then
|
||||||
|
list = "list[detached:"..ctrlinvname..";"
|
||||||
|
.. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
||||||
|
else
|
||||||
|
list = "list[context;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
||||||
|
end
|
||||||
|
if minetest.get_modpath("i3") then
|
||||||
|
list = list .. [[
|
||||||
|
list[current_player;main;0,8.5;9,4;]
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
list = list .. [[
|
||||||
|
list[current_player;main;0,8.5;8,1;]
|
||||||
|
list[current_player;main;0,9.73;8,3;8]
|
||||||
|
]]
|
||||||
|
end
|
||||||
|
list = list .. [[
|
||||||
|
list[context;recipe;0.22,5.22;3,3;]
|
||||||
|
list[context;output;4,6.22;1,1;]
|
||||||
|
]]
|
||||||
|
list = list .. [[
|
||||||
|
listring[current_player;main]
|
||||||
|
listring[detached:]]..ctrlinvname..[[;main]
|
||||||
|
listring[current_player;main]
|
||||||
|
listring[context;recipe]
|
||||||
|
listring[current_player;main]
|
||||||
|
listring[context;output]
|
||||||
|
listring[current_player;main]
|
||||||
|
]]
|
||||||
|
buttons = [[
|
||||||
|
button[3.56,4.35;1.8,0.9;tochest;To Drive]
|
||||||
|
tooltip[tochest;Move everything from your inventory to the ME network.]
|
||||||
|
button[5.4,4.35;0.8,0.9;prev;<]
|
||||||
|
button[7.25,4.35;0.8,0.9;next;>]
|
||||||
|
tooltip[prev;Previous]
|
||||||
|
tooltip[next;Next]
|
||||||
|
field[0.29,4.6;2.2,1;filter;;]]..query..[[]
|
||||||
|
button[2.1,4.5;0.8,0.5;search;?]
|
||||||
|
button[2.75,4.5;0.8,0.5;clear;X]
|
||||||
|
tooltip[search;Search]
|
||||||
|
tooltip[clear;Reset]
|
||||||
|
field[6,5.42;2,1;autocraft;;1]
|
||||||
|
tooltip[autocraft;Number of items to Craft]
|
||||||
|
]]
|
||||||
|
else
|
||||||
|
list = "label[3,2;" .. minetest.colorize("red", "No connected storage!") .. "]"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
list = "label[3,2;" .. minetest.colorize("red", "No connected network!") .. "]"
|
||||||
|
end
|
||||||
|
if page_max then
|
||||||
|
page_number = "label[6.15,4.5;" .. math.floor((start_id / 32)) + 1 ..
|
||||||
|
"/" .. page_max .."]"
|
||||||
|
end
|
||||||
|
|
||||||
|
return [[
|
||||||
|
size[9,12.5]
|
||||||
|
]]..
|
||||||
|
microexpansion.gui_bg ..
|
||||||
|
microexpansion.gui_slots ..
|
||||||
|
list ..
|
||||||
|
[[
|
||||||
|
label[0,-0.23;ME Crafting Terminal]
|
||||||
|
field_close_on_enter[filter;false]
|
||||||
|
field_close_on_enter[autocraft;false]
|
||||||
|
]]..
|
||||||
|
page_number ..
|
||||||
|
buttons
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update_chest(pos,_,ev)
|
||||||
|
--for now all events matter
|
||||||
|
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
if net == nil then
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local size = net:get_item_capacity()
|
||||||
|
local page_max = me.int_to_pagenum(size) + 1
|
||||||
|
|
||||||
|
meta:set_string("inv_name", "main")
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
|
end
|
||||||
|
|
||||||
|
-- From pipeworks/autocrafter.lua
|
||||||
|
local function count_index(invlist)
|
||||||
|
local index = {}
|
||||||
|
for _, stack in pairs(invlist) do
|
||||||
|
if not stack:is_empty() then
|
||||||
|
local stack_name = stack:get_name()
|
||||||
|
index[stack_name] = (index[stack_name] or 0) + stack:get_count()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return index
|
||||||
|
end
|
||||||
|
|
||||||
|
-- From pipeworks/autocrafter.lua
|
||||||
|
function me.get_craft(pos, inventory, hash)
|
||||||
|
local hash = hash or minetest.hash_node_position(pos)
|
||||||
|
local craft = autocrafterCache[hash]
|
||||||
|
if not craft then
|
||||||
|
local recipe = inventory:get_list("recipe")
|
||||||
|
for i = 1, 9 do
|
||||||
|
if recipe[i]:get_count() > 1 then
|
||||||
|
recipe[i] = ItemStack(recipe[i]:get_name())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local output, decremented_input = minetest.get_craft_result({method = "normal", width = 3, items = recipe})
|
||||||
|
craft = {recipe = recipe, consumption=count_index(recipe), output = output, decremented_input = decremented_input}
|
||||||
|
autocrafterCache[hash] = craft
|
||||||
|
end
|
||||||
|
return craft
|
||||||
|
end
|
||||||
|
|
||||||
|
-- From pipeworks/autocrafter.lua
|
||||||
|
-- note, that this function assumes allready being updated to virtual items
|
||||||
|
-- and doesn't handle recipes with stacksizes > 1
|
||||||
|
local function after_recipe_change(pos, inventory)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
-- if we emptied the grid, there's no point in keeping it running or cached
|
||||||
|
if inventory:is_empty("recipe") then
|
||||||
|
autocrafterCache[minetest.hash_node_position(pos)] = nil
|
||||||
|
inventory:set_stack("output", 1, "")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local recipe = inventory:get_list("recipe")
|
||||||
|
|
||||||
|
local hash = minetest.hash_node_position(pos)
|
||||||
|
local craft = autocrafterCache[hash]
|
||||||
|
|
||||||
|
if craft then
|
||||||
|
-- check if it changed
|
||||||
|
local cached_recipe = craft.recipe
|
||||||
|
for i = 1, 9 do
|
||||||
|
if recipe[i]:get_name() ~= cached_recipe[i]:get_name() then
|
||||||
|
autocrafterCache[hash] = nil -- invalidate recipe
|
||||||
|
craft = nil
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
craft = craft or me.get_craft(pos, inventory, hash)
|
||||||
|
local output_item = craft.output.item
|
||||||
|
inventory:set_stack("output", 1, output_item)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- From pipeworks/autocrafter.lua
|
||||||
|
-- clean out unknown items and groups, which would be handled like unknown items in the crafting grid
|
||||||
|
-- if minetest supports query by group one day, this might replace them
|
||||||
|
-- with a canonical version instead
|
||||||
|
local function normalize(item_list)
|
||||||
|
for i = 1, #item_list do
|
||||||
|
local name = item_list[i]
|
||||||
|
if not minetest.registered_items[name] then
|
||||||
|
item_list[i] = ""
|
||||||
|
if name == "group:stick" then
|
||||||
|
item_list[i] = "default:stick"
|
||||||
|
elseif name == "group:glass" then
|
||||||
|
item_list[i] = "default:glass"
|
||||||
|
elseif name == "group:wood" then
|
||||||
|
name = "moretrees:oak_planks"
|
||||||
|
if minetest.registered_items[name] then
|
||||||
|
item_list[i] = name
|
||||||
|
else
|
||||||
|
item_list[i] = "default:wood"
|
||||||
|
end
|
||||||
|
elseif name == "group:wood" then
|
||||||
|
item_list[i] = "moretrees:oak_trunk"
|
||||||
|
elseif name == "group:wool" then
|
||||||
|
item_list[i] = "wool:white"
|
||||||
|
elseif name == "group:sand" then
|
||||||
|
item_list[i] = "default:sand"
|
||||||
|
elseif name == "group:stone" then
|
||||||
|
item_list[i] = "default:cobble"
|
||||||
|
elseif name == "group:leaves" then
|
||||||
|
name = "moretrees:sequoia_leaves"
|
||||||
|
if minetest.registered_items[name] then
|
||||||
|
item_list[i] = name
|
||||||
|
else
|
||||||
|
item_list[i] = "default:leaves"
|
||||||
|
end
|
||||||
|
elseif name == "group:coal" then
|
||||||
|
item_list[i] = "default:coal"
|
||||||
|
elseif name == "group:tree" then
|
||||||
|
item_list[i] = "default:tree"
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return item_list
|
||||||
|
end
|
||||||
|
|
||||||
|
-- 0 to 34
|
||||||
|
function me.uranium_dust(p)
|
||||||
|
return "technic:uranium"..(p == 7 and "" or p).."_dust"
|
||||||
|
end
|
||||||
|
for pa = 0, 34 do
|
||||||
|
-- uranium_dust(pa)
|
||||||
|
-- me.uranium_dust(pa-1).." 2"
|
||||||
|
-- No, this would require a billion uranium to do this. :-(
|
||||||
|
-- Make a uranium centrifuge controller and have it be smart.
|
||||||
|
--me.register_output_by_typename("separating", "")
|
||||||
|
end
|
||||||
|
|
||||||
|
me.output_by_typename = {
|
||||||
|
-- aka me.register_output_by_typename("cooking", "default:stone")
|
||||||
|
["cooking"] = { "default:stone" }
|
||||||
|
}
|
||||||
|
|
||||||
|
-- Used to register what machine types (typename) produce which outputs.
|
||||||
|
-- Used to figure out what machine to use to create the given output.
|
||||||
|
-- If multiple outputs are produced, only use the main output, not the
|
||||||
|
-- incidental output.
|
||||||
|
function me.register_output_by_typename(typename, output)
|
||||||
|
if not me.output_by_typename[typename] then
|
||||||
|
me.output_by_typename[typename] = {}
|
||||||
|
end
|
||||||
|
table.insert(me.output_by_typename[typename], output)
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
function me.register_output_to_inputs(output, inputs)
|
||||||
|
me.log("REG: output "..output.." from inputs "..dump(inputs))
|
||||||
|
me.map_output_to_inputs[output] = inputs
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
me.map_output_to_inputs = {
|
||||||
|
-- furnace ("cooking")
|
||||||
|
["default:stone"] = { ItemStack("default:cobble") },
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
function me.find_by_output(name)
|
||||||
|
-- TODO: we'd love to be able to look this stuff up in the recipes.
|
||||||
|
-- technic.recipes["technic:doped_silicon_wafer"].alloy.recipes[4].input[1]
|
||||||
|
return me.map_output_to_inputs[name]
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.register_inventory(name, func)
|
||||||
|
-- me.log("INVENTORY: registering "..name, "error")
|
||||||
|
if not me.registered_inventory then
|
||||||
|
me.registered_inventory = {}
|
||||||
|
end
|
||||||
|
me.registered_inventory[name] = func
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Allow any type of machine process to be registered. For example,
|
||||||
|
-- "alloy" for an alloy furnace for example. These must be done
|
||||||
|
-- before specific me.register_inventory calls, as that one needs to
|
||||||
|
-- override this call.
|
||||||
|
function me.register_typename(name, typename)
|
||||||
|
me.block_to_typename_map[name] = typename
|
||||||
|
me.register_inventory(name, function() end)
|
||||||
|
end
|
||||||
|
|
||||||
|
me.block_to_typename_map = {
|
||||||
|
}
|
||||||
|
|
||||||
|
-- default wiring
|
||||||
|
me.register_typename("default:furnace", "cooking")
|
||||||
|
|
||||||
|
function me.get_recipe(typename, inputs)
|
||||||
|
return technic.get_recipe(typename, inputs)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- TODO: Removing an output when the recipe is empty that is in
|
||||||
|
-- net.autocrafters should not be allowed as the output in that case
|
||||||
|
-- is virtual. It can be removed if rinv:"output" has the item iff
|
||||||
|
-- that item is removed from the autocrafter's output.
|
||||||
|
local function on_output_change(pos, linv, stack)
|
||||||
|
local name = stack:get_name()
|
||||||
|
-- me.log("PROCESS: "..name.." was found0", "error")
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local has_enough = true
|
||||||
|
local function clear_recipe()
|
||||||
|
local has_enough = true
|
||||||
|
for i = 1, 9 do
|
||||||
|
local prev = linv:get_stack("recipe", i)
|
||||||
|
if prev and prev:get_name() ~= "" and not inv:room_for_item("main", prev) then
|
||||||
|
-- full, no room to remove
|
||||||
|
has_enough = false
|
||||||
|
elseif prev and prev:get_name() ~= "" and me.insert_item(prev, net, inv, "main"):get_count() > 0 then
|
||||||
|
net:set_storage_space(true)
|
||||||
|
-- full, no room to remove
|
||||||
|
-- push into player inventory?
|
||||||
|
-- Don't have to worry about this happening until minetest is fully multithreaded
|
||||||
|
has_enough = false
|
||||||
|
else
|
||||||
|
net:set_storage_space(true)
|
||||||
|
linv:set_stack("recipe", i, ItemStack(""))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return has_enough
|
||||||
|
end
|
||||||
|
if not net.process then
|
||||||
|
-- rewalk the interfaces on the network to rebuild loans and machines.
|
||||||
|
net:reload_network()
|
||||||
|
end
|
||||||
|
if net and net.process[name] then
|
||||||
|
-- me.log("PROCESS: "..name.." was found1", "error")
|
||||||
|
has_enough = clear_recipe()
|
||||||
|
local pos,ipos = next(net.process[name])
|
||||||
|
if has_enough and pos then
|
||||||
|
-- me.log("PROCESS: "..name.." was found2", "error")
|
||||||
|
local inputs = me.find_by_output(name)
|
||||||
|
-- me.log("PROCESS: inputs are "..dump(inputs), "error")
|
||||||
|
local machine_name = minetest.get_node(pos).name
|
||||||
|
local typename = me.block_to_typename_map[machine_name]
|
||||||
|
local recip = typename and me.get_recipe(typename, inputs)
|
||||||
|
if recip and recip.output then
|
||||||
|
recip.intput = inputs
|
||||||
|
-- me.log("PROCESS: "..name.." was found for "..typename.." on a "..machine_name, "error")
|
||||||
|
-- freezer can produce two outputs, we only care about the first.
|
||||||
|
if recip.output[1] then
|
||||||
|
recip.output = recip.output[1]
|
||||||
|
end
|
||||||
|
stack = ItemStack(recip.output)
|
||||||
|
linv:set_stack("output", 1, stack)
|
||||||
|
-- me.log("PROCESS: and the output is "..minetest.serialize(recip.output), "error")
|
||||||
|
-- me.log("PROCESS: and the output is "..stack:get_name(), "error")
|
||||||
|
else
|
||||||
|
me.log("PROCESS: "..name.." was missing from recipe on a "..machine_name, "error")
|
||||||
|
linv:set_stack("output", 1, ItemStack())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
elseif net and net.autocrafters[name] then
|
||||||
|
has_enough = clear_recipe()
|
||||||
|
if has_enough then
|
||||||
|
local pos,ipos = next(net.autocrafters[name])
|
||||||
|
if pos then
|
||||||
|
local rinv = minetest.get_meta(pos):get_inventory()
|
||||||
|
stack = ItemStack(rinv:get_stack("output", 1))
|
||||||
|
linv:set_stack("output", 1, stack)
|
||||||
|
else
|
||||||
|
-- me.log("pos in autocrafters was missing", "error")
|
||||||
|
linv:set_stack("output", 1, ItemStack())
|
||||||
|
end
|
||||||
|
else
|
||||||
|
linv:set_stack("output", 1, ItemStack())
|
||||||
|
end
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
local input = minetest.get_craft_recipe(name)
|
||||||
|
if not input.items or input.type ~= "normal" then return 0 end
|
||||||
|
local items, width = normalize(input.items), input.width
|
||||||
|
local item_idx, width_idx = 1, 1
|
||||||
|
for i = 1, 9 do
|
||||||
|
local prev = linv:get_stack("recipe", i)
|
||||||
|
if prev and prev:get_name() ~= "" and not inv:room_for_item("main", prev) then
|
||||||
|
-- full, no room to remove
|
||||||
|
has_enough = false
|
||||||
|
if width_idx <= width then
|
||||||
|
item_idx = item_idx + 1
|
||||||
|
end
|
||||||
|
elseif prev and prev:get_name() ~= "" and me.insert_item(prev, net, inv, "main"):get_count() > 0 then
|
||||||
|
net:set_storage_space(true)
|
||||||
|
-- full, no room to remove
|
||||||
|
-- push into player inventory?
|
||||||
|
-- Don't have to worry about this happening until minetest is fully multithreaded
|
||||||
|
has_enough = false
|
||||||
|
if width_idx <= width then
|
||||||
|
item_idx = item_idx + 1
|
||||||
|
end
|
||||||
|
elseif width_idx <= width then
|
||||||
|
net:set_storage_space(true)
|
||||||
|
if inv:contains_item("main", items[item_idx]) then
|
||||||
|
me.remove_item(net, inv, "main", ItemStack(items[item_idx]))
|
||||||
|
linv:set_stack("recipe", i, items[item_idx])
|
||||||
|
else
|
||||||
|
has_enough = false
|
||||||
|
linv:set_stack("recipe", i, ItemStack(""))
|
||||||
|
end
|
||||||
|
item_idx = item_idx + 1
|
||||||
|
else
|
||||||
|
linv:set_stack("recipe", i, ItemStack(""))
|
||||||
|
end
|
||||||
|
width_idx = (width_idx < 3) and (width_idx + 1) or 1
|
||||||
|
end
|
||||||
|
-- we'll set the output slot in after_recipe_change to the actual result of the new recipe
|
||||||
|
after_recipe_change(pos, linv)
|
||||||
|
return 0
|
||||||
|
end
|
||||||
|
|
||||||
|
-- [me cterminal] Register node
|
||||||
|
me.register_node("cterminal", {
|
||||||
|
description = "ME Crafting Terminal",
|
||||||
|
usedfor = "Can interact with storage cells in ME networks",
|
||||||
|
tiles = {
|
||||||
|
"chest_top",
|
||||||
|
"chest_top",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"chest_front",
|
||||||
|
},
|
||||||
|
recipe = {
|
||||||
|
{ 1, {
|
||||||
|
{"microexpansion:term", "default:chest"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 },
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
me_update = update_chest,
|
||||||
|
on_construct = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1))
|
||||||
|
meta:set_string("inv_name", "none")
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
|
||||||
|
local own_inv = meta:get_inventory()
|
||||||
|
own_inv:set_size("src", 1)
|
||||||
|
own_inv:set_size("recipe", 3*3)
|
||||||
|
own_inv:set_size("output", 1)
|
||||||
|
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
me.send_event(pos,"connect",{net=net})
|
||||||
|
if net then
|
||||||
|
update_chest(pos)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
after_destruct = function(pos)
|
||||||
|
me.send_event(pos,"disconnect")
|
||||||
|
end,
|
||||||
|
can_dig = function(pos, player)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
return inv:is_empty("recipe")
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
me.log("Allow a move from "..from_list.." to "..to_list, "error")
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
if to_list == "search" then
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local stack = linv:get_stack(from_list, from_index)
|
||||||
|
stack:set_count(count)
|
||||||
|
-- local meta = minetest.get_meta(pos)
|
||||||
|
-- meta:set_string("infotext", "allow moving: "..stack:get_name())
|
||||||
|
-- TODO: Check capacity? Test.
|
||||||
|
me.insert_item(stack, net, inv, "main")
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
if to_list == "recipe" and from_list == "search" then
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local stack = linv:get_stack(from_list, from_index)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
count = math.min(count, stack:get_stack_max())
|
||||||
|
stack:set_count(count)
|
||||||
|
me.remove_item(net, inv, "main", stack)
|
||||||
|
return count
|
||||||
|
end
|
||||||
|
if to_list == "output" then
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
local stack = linv:get_stack(from_list, from_index)
|
||||||
|
return on_output_change(pos, linv, stack)
|
||||||
|
end
|
||||||
|
return count
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||||
|
-- This is used for removing items from "search", "recipe" and "output".
|
||||||
|
--me.log("Allow a take from "..listname, "error")
|
||||||
|
local count = stack:get_count()
|
||||||
|
if listname == "search" or listname == "recipe" then
|
||||||
|
count = math.min(count, stack:get_stack_max())
|
||||||
|
end
|
||||||
|
--[[if listname == "main" then
|
||||||
|
-- This should be unused, we don't have a local inventory called main.
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local ret = me.remove_item(net, inv, "main", stack)
|
||||||
|
me.log("REMOVE: after remove count is "..ret:get_count(), "error")
|
||||||
|
return ret:get_count()
|
||||||
|
end
|
||||||
|
]]
|
||||||
|
return count
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
if listname == "output" then
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
return on_output_change(pos, linv, stack)
|
||||||
|
elseif listname == "search" or listname == "main" then
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
-- TODO: Check full inv, should be fixed now, confirm.
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
return stack:get_count() - leftovers:get_count()
|
||||||
|
end
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_put = function(pos, listname, _, stack)
|
||||||
|
if listname == "recipe" then
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
after_recipe_change(pos, linv)
|
||||||
|
elseif listname == "search" or listname == "main" then
|
||||||
|
-- done above in allow, nothing left to do here
|
||||||
|
elseif listname == output then
|
||||||
|
-- done above
|
||||||
|
else
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
if leftovers:get_count() > 0 then
|
||||||
|
fixme()
|
||||||
|
end
|
||||||
|
net:set_storage_space(true)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_take = function(pos, listname, index, stack)
|
||||||
|
me.log("A taking of "..stack:get_name().." from "..listname, "error")
|
||||||
|
if listname == "output" then
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
local num_left = linv:get_stack("output", 1):get_count()
|
||||||
|
-- We only need to consume the recipe if there are no more items
|
||||||
|
-- if num_left ~= 0 then return end
|
||||||
|
if num_left > 1 then return end
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local replace = true
|
||||||
|
-- This assumes that all inputs are only just 1 item, always true?
|
||||||
|
for i = 1, 9 do
|
||||||
|
local inp = linv:get_stack("recipe", i)
|
||||||
|
if inp and inp:get_name() ~= "" then
|
||||||
|
local consume = ItemStack(inp:get_name())
|
||||||
|
replace = replace and (inp:get_count() > 1 or inv:contains_item("main", consume))
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, 9 do
|
||||||
|
local inp = linv:get_stack("recipe", i)
|
||||||
|
if inp and inp:get_name() ~= "" then
|
||||||
|
if inp:get_count() == 1 then
|
||||||
|
if inv:contains_item("main", inp) then
|
||||||
|
local r = me.remove_item(net, inv, "main", inp)
|
||||||
|
if r:get_count() ~= 1 then
|
||||||
|
linv:set_stack("recipe", i, ItemStack(""))
|
||||||
|
replace = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
linv:set_stack("recipe", i, ItemStack(""))
|
||||||
|
replace = false
|
||||||
|
end
|
||||||
|
else
|
||||||
|
local stack_copy = ItemStack(inp)
|
||||||
|
stack_copy:set_count(inp:get_count()-1)
|
||||||
|
linv:set_stack("recipe", i, stack_copy)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- deal with replacements
|
||||||
|
local hash = minetest.hash_node_position(pos)
|
||||||
|
local craft = autocrafterCache[hash] or me.get_craft(pos, linv, hash)
|
||||||
|
for i = 1, 9 do
|
||||||
|
if (craft.decremented_input.items[i]:get_count() ~= linv:get_stack("recipe", i):get_count()
|
||||||
|
or craft.decremented_input.items[i]:get_name() ~= linv:get_stack("recipe", i):get_name())
|
||||||
|
and not craft.decremented_input.items[i]:is_empty() then
|
||||||
|
local leftovers = me.insert_item(craft.decremented_input.items[i], net, inv, "main")
|
||||||
|
if leftovers:get_count() > 0 then
|
||||||
|
-- Ick, no room, just drop on the floor. Maybe player inventory?
|
||||||
|
minetest.add_item(pos, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if replace then
|
||||||
|
linv:set_stack("output", 1, craft.output.item)
|
||||||
|
else
|
||||||
|
linv:set_list("output", {})
|
||||||
|
end
|
||||||
|
end
|
||||||
|
elseif listname == "recipe" then
|
||||||
|
local linv = minetest.get_meta(pos):get_inventory()
|
||||||
|
after_recipe_change(pos, linv)
|
||||||
|
elseif listname ~= "main" then
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
me.remove_item(net, inv, "main", stack)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||||
|
me.log("A move from "..from_list.." to "..to_list, "error")
|
||||||
|
if to_list == "recipe" or from_list == "recipe" then
|
||||||
|
local inv = minetest.get_meta(pos):get_inventory()
|
||||||
|
after_recipe_change(pos, inv)
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
tube = {
|
||||||
|
can_insert = function(pos, _, stack) --pos, node, stack, direction
|
||||||
|
-- TODO: update to use capacity_cache?
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local max_slots = inv:get_size("main")
|
||||||
|
local max_items = net.capacity_cache
|
||||||
|
|
||||||
|
local slots, items = 0, 0
|
||||||
|
-- Get amount of items in drive
|
||||||
|
for i = 1, max_slots do
|
||||||
|
local dstack = inv:get_stack("main", i)
|
||||||
|
if dstack:get_name() ~= "" then
|
||||||
|
slots = slots + 1
|
||||||
|
local num = dstack:get_count()
|
||||||
|
if num == 0 then num = 1 end
|
||||||
|
items = items + num
|
||||||
|
end
|
||||||
|
end
|
||||||
|
items = items + stack:get_count()
|
||||||
|
return max_items > items
|
||||||
|
end,
|
||||||
|
insert_object = function(pos, _, stack)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
|
return leftovers
|
||||||
|
end,
|
||||||
|
connect_sides = {left=1, right=1, front=1, back=1, top=1, bottom=1},
|
||||||
|
},
|
||||||
|
after_place_node = pipeworks_enabled and pipeworks.after_place,
|
||||||
|
after_dig_node = pipeworks_enabled and pipeworks.after_dig,
|
||||||
|
on_receive_fields = function(pos, _, fields, sender)
|
||||||
|
local net,cpos = me.get_connected_network(pos)
|
||||||
|
if net then
|
||||||
|
if cpos then
|
||||||
|
me.log("network and ctrl_pos","info")
|
||||||
|
else
|
||||||
|
me.log("network but no ctrl_pos","warning")
|
||||||
|
end
|
||||||
|
else
|
||||||
|
if cpos then
|
||||||
|
me.log("no network but ctrl_pos","warning")
|
||||||
|
else
|
||||||
|
me.log("no network and no ctrl_pos","info")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local page = meta:get_int("page")
|
||||||
|
local inv_name = meta:get_string("inv_name")
|
||||||
|
local own_inv = meta:get_inventory()
|
||||||
|
local ctrl_inv
|
||||||
|
if cpos then
|
||||||
|
ctrl_inv = net:get_inventory()
|
||||||
|
else
|
||||||
|
me.log("no network connected","warning")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local inv
|
||||||
|
if inv_name == "main" then
|
||||||
|
inv = ctrl_inv
|
||||||
|
assert(inv,"no control inv")
|
||||||
|
else
|
||||||
|
inv = own_inv
|
||||||
|
assert(inv,"no own inv")
|
||||||
|
end
|
||||||
|
local page_max = math.floor(inv:get_size(inv_name) / 32) + 1
|
||||||
|
if inv_name == "none" then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
if fields.next then
|
||||||
|
if page + 32 > inv:get_size(inv_name) then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
meta:set_int("page", page + 32)
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, page + 32, inv_name, page_max))
|
||||||
|
elseif fields.prev then
|
||||||
|
if page - 32 < 1 then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
meta:set_int("page", page - 32)
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, page - 32, inv_name, page_max))
|
||||||
|
elseif fields.search or fields.key_enter_field == "filter" then
|
||||||
|
own_inv:set_size("search", 0)
|
||||||
|
if fields.filter == "" then
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
meta:set_string("inv_name", "main")
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
|
else
|
||||||
|
local tab = {}
|
||||||
|
for i = 1, ctrl_inv:get_size("main") do
|
||||||
|
local match = ctrl_inv:get_stack("main", i):get_name():find(fields.filter)
|
||||||
|
if match then
|
||||||
|
tab[#tab + 1] = ctrl_inv:get_stack("main", i)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
own_inv:set_list("search", tab)
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
meta:set_string("inv_name", "search")
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1, "search", page_max, fields.filter))
|
||||||
|
end
|
||||||
|
elseif fields.clear then
|
||||||
|
own_inv:set_size("search", 0)
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
meta:set_string("inv_name", "main")
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
|
elseif fields.tochest then
|
||||||
|
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
|
||||||
|
-- TODO: test and fix, net:set_storage_space(pinv:get_size("main"))
|
||||||
|
local space = net:get_item_capacity()
|
||||||
|
local contents = ctrl_inv:get_list("main") or {}
|
||||||
|
for _,s in pairs(contents) do
|
||||||
|
if not s:is_empty() then
|
||||||
|
space = space - s:get_count()
|
||||||
|
end
|
||||||
|
end
|
||||||
|
me.move_inv(net, { inv=pinv, name="main" }, { inv=ctrl_inv, name="main", huge=true }, space)
|
||||||
|
net:set_storage_space(true)
|
||||||
|
elseif fields.autocraft or fields.key_enter_field == "autocraft" then
|
||||||
|
if fields.autocraft ~= "" and tonumber(fields.autocraft) ~= nil then
|
||||||
|
local count = tonumber(fields.autocraft)
|
||||||
|
fields.autocraft = nil
|
||||||
|
if not own_inv:get_stack("output", 1):is_empty() and count < math.pow(2,16) then
|
||||||
|
me.autocraft(autocrafterCache, pos, net, own_inv, ctrl_inv, count)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
})
|
42
modules/storage/drawer-api.lua
Normal file
42
modules/storage/drawer-api.lua
Normal file
@ -0,0 +1,42 @@
|
|||||||
|
--[[
|
||||||
|
Minetest Mod Storage Drawers - A Mod adding storage drawers
|
||||||
|
|
||||||
|
Copyright (C) 2017-2020 Linus Jahn <lnj@kaidan.im>
|
||||||
|
Copyright (C) 2016 Mango Tango <mtango688@gmail.com>
|
||||||
|
|
||||||
|
MIT License
|
||||||
|
|
||||||
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
of this software and associated documentation files (the "Software"), to deal
|
||||||
|
in the Software without restriction, including without limitation the rights
|
||||||
|
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
copies of the Software, and to permit persons to whom the Software is
|
||||||
|
furnished to do so, subject to the following conditions:
|
||||||
|
|
||||||
|
The above copyright notice and this permission notice shall be included in all
|
||||||
|
copies or substantial portions of the Software.
|
||||||
|
|
||||||
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||||
|
SOFTWARE.
|
||||||
|
]]
|
||||||
|
|
||||||
|
function drawers.drawer_take_large_item(pos, itemstack)
|
||||||
|
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||||
|
|
||||||
|
if not drawer_visuals then
|
||||||
|
return ItemStack("")
|
||||||
|
end
|
||||||
|
|
||||||
|
for _, visual in pairs(drawer_visuals) do
|
||||||
|
if visual.itemName == itemstack:get_name() then
|
||||||
|
return visual:take_items(itemstack:get_count())
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return ItemStack()
|
||||||
|
end
|
39
modules/storage/drawer-interop.lua
Normal file
39
modules/storage/drawer-interop.lua
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
-- Interoperability file for drawers support.
|
||||||
|
local me = microexpansion
|
||||||
|
|
||||||
|
me.register_inventory("drawers:wood1", function(net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
if not doinventories then return end
|
||||||
|
local c = drawers.drawer_get_content(n.pos, "")
|
||||||
|
if c.name ~= "" and c.count > 1 then
|
||||||
|
-- A poor man's locking system will have us never remove the last item from a drawer.
|
||||||
|
c.count = c.count-1
|
||||||
|
local stack = ItemStack(c.name)
|
||||||
|
local bias = nil
|
||||||
|
if c.count > math.pow(2,15) then -- assumes me.settings.huge_stacks == true
|
||||||
|
bias = c.count - math.pow(2,15)
|
||||||
|
c.count = math.pow(2,15)
|
||||||
|
end
|
||||||
|
stack:set_count(c.count)
|
||||||
|
net:create_loan(stack, {pos=n.pos, drawer=true, slot="", ipos=pos}, ctrl_inv, int_meta, bias)
|
||||||
|
end
|
||||||
|
-- local rest = drawers.drawer_insert_object(n.pos, ItemStack("default:stone"), "")
|
||||||
|
-- meta:set_int("count", meta:get_int("count")+1)
|
||||||
|
-- drawers.remove_visuals(n.pos)
|
||||||
|
-- drawers.spawn_visuals(n.pos)
|
||||||
|
end)
|
||||||
|
|
||||||
|
me.register_inventory("drawers:wood2", function(net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
if not doinventories then return end
|
||||||
|
-- local c = drawers.drawer_get_content(n.pos, "")
|
||||||
|
-- local rest = drawers.drawer_insert_object(n.pos, ItemStack("default:stone"), "")
|
||||||
|
end)
|
||||||
|
|
||||||
|
me.register_inventory("drawers:wood4", function(net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
if not doinventories then return end
|
||||||
|
-- local c = drawers.drawer_get_content(n.pos, "")
|
||||||
|
-- local rest = drawers.drawer_insert_object(n.pos, ItemStack("default:stone"), "")
|
||||||
|
end)
|
||||||
|
|
||||||
|
me.register_inventory("drawers:controller", function(net, ctrl_inv, int_meta, n, pos)
|
||||||
|
-- inv:add_item("src", ItemStack("default:stone"))
|
||||||
|
end)
|
@ -39,7 +39,7 @@ local function get_drive_controller(pos)
|
|||||||
for i,d in pairs(netdrives) do
|
for i,d in pairs(netdrives) do
|
||||||
if d.dpos then
|
if d.dpos then
|
||||||
if vector.equals(pos, d.dpos) then
|
if vector.equals(pos, d.dpos) then
|
||||||
return d,i
|
return d,i
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@ -51,10 +51,10 @@ local function set_drive_controller(dpos,setd,cpos,i)
|
|||||||
local dt = netdrives[i]
|
local dt = netdrives[i]
|
||||||
if dt then
|
if dt then
|
||||||
if setd then
|
if setd then
|
||||||
dt.dpos = dpos
|
dt.dpos = dpos
|
||||||
end
|
end
|
||||||
if cpos ~= nil then
|
if cpos ~= nil then
|
||||||
dt.cpos = cpos
|
dt.cpos = cpos
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
netdrives[i] = {dpos = dpos, cpos = cpos}
|
netdrives[i] = {dpos = dpos, cpos = cpos}
|
||||||
@ -63,10 +63,10 @@ local function set_drive_controller(dpos,setd,cpos,i)
|
|||||||
local dt = get_drive_controller(dpos)
|
local dt = get_drive_controller(dpos)
|
||||||
if dt then
|
if dt then
|
||||||
if setd then
|
if setd then
|
||||||
dt.dpos = dpos
|
dt.dpos = dpos
|
||||||
end
|
end
|
||||||
if cpos ~= nil then
|
if cpos ~= nil then
|
||||||
dt.cpos = cpos
|
dt.cpos = cpos
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
table.insert(netdrives,{dpos = dpos, cpos = cpos})
|
table.insert(netdrives,{dpos = dpos, cpos = cpos})
|
||||||
@ -75,26 +75,26 @@ local function set_drive_controller(dpos,setd,cpos,i)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function write_to_cell(cell, items, item_count)
|
local function write_to_cell(cell, items, item_count)
|
||||||
local size = microexpansion.get_cell_size(cell:get_name())
|
local size = microexpansion.get_cell_size(cell:get_name())
|
||||||
local item_meta = cell:get_meta()
|
local item_meta = cell:get_meta()
|
||||||
--print(dump2(items,"cell_items"))
|
--print(dump2(items,"cell_items"))
|
||||||
item_meta:set_string("items", minetest.serialize(items))
|
item_meta:set_string("items", minetest.serialize(items))
|
||||||
local base_desc = minetest.registered_craftitems[cell:get_name()].microexpansion.base_desc
|
local base_desc = minetest.registered_craftitems[cell:get_name()].microexpansion.base_desc
|
||||||
-- Calculate Percentage
|
-- Calculate Percentage
|
||||||
local percent = math.floor(item_count / size * 100)
|
local percent = math.floor(item_count / size * 100)
|
||||||
-- Update description
|
-- Update description
|
||||||
item_meta:set_string("description", base_desc.."\n"..
|
item_meta:set_string("description", base_desc.."\n"..
|
||||||
minetest.colorize("grey", tostring(item_count).."/"..tostring(size).." Items ("..tostring(percent).."%)"))
|
minetest.colorize("grey", tostring(item_count).."/"..tostring(size).." Items ("..tostring(percent).."%)"))
|
||||||
return cell
|
return cell
|
||||||
end
|
end
|
||||||
|
|
||||||
local function write_drive_cells(pos,network)
|
local function write_drive_cells(pos, net)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local own_inv = meta:get_inventory()
|
local own_inv = meta:get_inventory()
|
||||||
if network == nil then
|
if net == nil then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local ctrl_inv = network:get_inventory()
|
local ctrl_inv = net:get_inventory()
|
||||||
local cells = {}
|
local cells = {}
|
||||||
for i = 1, own_inv:get_size("main") do
|
for i = 1, own_inv:get_size("main") do
|
||||||
local cell = own_inv:get_stack("main", i)
|
local cell = own_inv:get_stack("main", i)
|
||||||
@ -111,40 +111,83 @@ local function write_drive_cells(pos,network)
|
|||||||
local items_in_cell_count = 0
|
local items_in_cell_count = 0
|
||||||
local cell_items = {}
|
local cell_items = {}
|
||||||
|
|
||||||
|
net:update_counts()
|
||||||
|
if not net.counts then
|
||||||
|
net.counts = {}
|
||||||
|
end
|
||||||
for i = 1, ctrl_inv:get_size("main") do
|
for i = 1, ctrl_inv:get_size("main") do
|
||||||
local stack_inside = ctrl_inv:get_stack("main", i)
|
local stack = ctrl_inv:get_stack("main", i)
|
||||||
local item_string = stack_inside:to_string()
|
local item_string = stack:to_string()
|
||||||
if item_string ~= "" then
|
if item_string ~= "" then
|
||||||
item_string = item_string:split(" ")
|
item_string = item_string:split(" ")
|
||||||
local item_count = stack_inside:get_count()
|
lbias = (net.counts and net.counts[stack:get_name()]) or 0
|
||||||
|
local mbias = (net.bias and net.bias["main"] and net.bias["main"][stack:get_name()]) or 0
|
||||||
|
if mbias > lbias and lbias > 0 then
|
||||||
|
mbias = mbias - lbias
|
||||||
|
lbias = 0
|
||||||
|
net.bias["main"][stack:get_name()] = mbias
|
||||||
|
net.counts[stack:get_name()] = nil
|
||||||
|
elseif lbias > mbias and mbias > 0 then
|
||||||
|
lbias = lbias - mbias
|
||||||
|
mbias = 0
|
||||||
|
net.counts[stack:get_name()] = lbias
|
||||||
|
net.bias["main"][stack:get_name()] = nil
|
||||||
|
elseif mbias == lbias and mbias > 0 then
|
||||||
|
net.bias["main"][stack:get_name()] = nil
|
||||||
|
net.counts[stack:get_name()] = nil
|
||||||
|
end
|
||||||
|
local item_count = stack:get_count() + mbias
|
||||||
|
-- TODO: on_loan includes the >32k bias in it, so, therefore the
|
||||||
|
-- stack:get_count() + mbias should have it in it.
|
||||||
|
local on_loan = net.counts[stack:get_name()] or 0
|
||||||
|
item_count = item_count - on_loan
|
||||||
|
if item_count < 0 then
|
||||||
|
me.log("LOAN: drive "..item_count.." "..stack:get_name().." "..on_loan.." on loan", "error")
|
||||||
|
-- TODO: we need to update the count faster and we need to update counts from actual inventories
|
||||||
|
-- and not allow taking unless there is an actual item there, mostly done now
|
||||||
|
-- TODO: In theory this should be impossible now, but we have
|
||||||
|
-- bugs with cell removal and insert, see wow
|
||||||
|
me.log("wow, free items "..stack:get_name().." during drive write, "..tostring(-item_count).." extra, with a loan of "..on_loan, "error")
|
||||||
|
item_count = 0
|
||||||
|
if mbias > 0 then
|
||||||
|
net.bias["main"][stack:get_name()] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
if item_count > 1 and item_string[2] ~= tostring(item_count) then
|
if item_count > 1 and item_string[2] ~= tostring(item_count) then
|
||||||
microexpansion.log("stack count differs from second field of the item string","warning")
|
me.log("stack count differs from second field of the item string","warning")
|
||||||
end
|
end
|
||||||
while item_count ~= 0 and cell_idx ~= nil do
|
while item_count ~= 0 and cell_idx ~= nil do
|
||||||
--print(("stack to store: %q"):format(table.concat(item_string," ")))
|
--print(("stack to store: %q"):format(table.concat(item_string," ")))
|
||||||
if size < items_in_cell_count + item_count then
|
|
||||||
local space = size - items_in_cell_count
|
|
||||||
item_string[2] = tostring(space)
|
|
||||||
table.insert(cell_items,table.concat(item_string," "))
|
|
||||||
items_in_cell_count = items_in_cell_count + space
|
|
||||||
|
|
||||||
own_inv:set_stack("main", cell_idx, write_to_cell(cells[cell_idx],cell_items,items_in_cell_count))
|
-- TODO: This should fail if we write 64k items onto a 64k
|
||||||
cell_idx = next(cells, cell_idx)
|
-- drive (or larger). Fix by writting the number first, that's
|
||||||
if cell_idx == nil then
|
-- the bias and then the name. This requires that no node in
|
||||||
--there may be other drives within the network
|
-- the storage system starts with a number. Then in read,
|
||||||
microexpansion.log("too many items to store in drive","info")
|
-- support that.
|
||||||
break
|
|
||||||
end
|
if size < items_in_cell_count + item_count then
|
||||||
size = microexpansion.get_cell_size(cells[cell_idx]:get_name())
|
local space = size - items_in_cell_count
|
||||||
items_in_cell_count = 0
|
item_string[2] = tostring(space)
|
||||||
cell_items = {}
|
table.insert(cell_items,table.concat(item_string," "))
|
||||||
item_count = item_count - space
|
items_in_cell_count = items_in_cell_count + space
|
||||||
else
|
|
||||||
items_in_cell_count = items_in_cell_count + item_count
|
own_inv:set_stack("main", cell_idx, write_to_cell(cells[cell_idx],cell_items,items_in_cell_count))
|
||||||
item_string[2] = tostring(item_count)
|
cell_idx = next(cells, cell_idx)
|
||||||
table.insert(cell_items,table.concat(item_string," "))
|
if cell_idx == nil then
|
||||||
item_count = 0
|
--there may be other drives within the network
|
||||||
end
|
me.log("too many items to store in drive","info")
|
||||||
|
break
|
||||||
|
end
|
||||||
|
size = microexpansion.get_cell_size(cells[cell_idx]:get_name())
|
||||||
|
items_in_cell_count = 0
|
||||||
|
cell_items = {}
|
||||||
|
item_count = item_count - space
|
||||||
|
else
|
||||||
|
items_in_cell_count = items_in_cell_count + item_count
|
||||||
|
item_string[2] = tostring(item_count)
|
||||||
|
table.insert(cell_items,table.concat(item_string," "))
|
||||||
|
item_count = 0
|
||||||
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
if cell_idx == nil then
|
if cell_idx == nil then
|
||||||
@ -162,6 +205,7 @@ local function write_drive_cells(pos,network)
|
|||||||
end
|
end
|
||||||
|
|
||||||
local function take_all(pos,net)
|
local function take_all(pos,net)
|
||||||
|
-- me.log("take_all", "error")
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local own_inv = meta:get_inventory()
|
local own_inv = meta:get_inventory()
|
||||||
local ctrl_inv = net:get_inventory()
|
local ctrl_inv = net:get_inventory()
|
||||||
@ -172,21 +216,25 @@ local function take_all(pos,net)
|
|||||||
if name ~= "" then
|
if name ~= "" then
|
||||||
local its = minetest.deserialize(stack:get_meta():get_string("items"))
|
local its = minetest.deserialize(stack:get_meta():get_string("items"))
|
||||||
for _,s in pairs(its) do
|
for _,s in pairs(its) do
|
||||||
table.insert(items,s)
|
table.insert(items,s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
for _,ostack in pairs(items) do
|
for _,ostack in pairs(items) do
|
||||||
--this returns 99 (max count) even if it removes more
|
--this returns 99 (max count) even if it removes more
|
||||||
ctrl_inv:remove_item("main", ostack)
|
--ctrl_inv:remove_item("main", ostack)
|
||||||
print(ostack)
|
local postack = ItemStack(ostack)
|
||||||
|
-- me.log("drive take_all remove_item "..minetest.serialize(ostack), "error")
|
||||||
|
me.log("DRIVE: take_all remove_item "..tostring(postack:get_count()).." "..postack:get_name(), "error")
|
||||||
|
me.remove_item(net, ctrl_inv, "main", postack)
|
||||||
end
|
end
|
||||||
|
|
||||||
net:update()
|
net:update()
|
||||||
me.send_event(pos,"items")
|
me.send_event(pos,"items")
|
||||||
end
|
end
|
||||||
|
|
||||||
local function add_all(pos,net)
|
local function add_all(pos,net)
|
||||||
|
-- me.log("add_all", "error")
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local own_inv = meta:get_inventory()
|
local own_inv = meta:get_inventory()
|
||||||
local ctrl_inv = net:get_inventory()
|
local ctrl_inv = net:get_inventory()
|
||||||
@ -197,23 +245,22 @@ local function add_all(pos,net)
|
|||||||
if name ~= "" then
|
if name ~= "" then
|
||||||
local its = minetest.deserialize(stack:get_meta():get_string("items"))
|
local its = minetest.deserialize(stack:get_meta():get_string("items"))
|
||||||
if its then
|
if its then
|
||||||
for _,s in pairs(its) do
|
for _,s in pairs(its) do
|
||||||
table.insert(items,s)
|
table.insert(items,s)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
|
||||||
for _,ostack in pairs(items) do
|
|
||||||
me.insert_item(ostack, ctrl_inv, "main")
|
|
||||||
print(ostack)
|
|
||||||
end
|
end
|
||||||
|
for _,ostack in pairs(items) do
|
||||||
|
me.insert_item(ostack, net, ctrl_inv, "main")
|
||||||
|
end
|
||||||
|
|
||||||
net:update()
|
net:update()
|
||||||
me.send_event(pos,"items",{net = net})
|
me.send_event(pos,"items",{net = net})
|
||||||
end
|
end
|
||||||
|
|
||||||
function me.disconnect_drive(pos,ncpos)
|
function me.disconnect_drive(pos,ncpos)
|
||||||
microexpansion.log("disconnecting drive at "..minetest.pos_to_string(pos),"action")
|
me.log("disconnecting drive at "..minetest.pos_to_string(pos),"action")
|
||||||
local fc,i = get_drive_controller(pos)
|
local fc,i = get_drive_controller(pos)
|
||||||
if not fc.cpos then
|
if not fc.cpos then
|
||||||
return
|
return
|
||||||
@ -228,7 +275,7 @@ function me.disconnect_drive(pos,ncpos)
|
|||||||
if fnet then
|
if fnet then
|
||||||
take_all(pos,fnet)
|
take_all(pos,fnet)
|
||||||
else
|
else
|
||||||
microexpansion.log("drive couldn't take items from its former network","warning")
|
me.log("drive couldn't take items from its former network","warning")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
@ -240,141 +287,146 @@ local function update_drive(pos,_,ev)
|
|||||||
local cnet = ev.net or me.get_connected_network(pos)
|
local cnet = ev.net or me.get_connected_network(pos)
|
||||||
if cnet then
|
if cnet then
|
||||||
if not fc then
|
if not fc then
|
||||||
microexpansion.log("connecting drive at "..minetest.pos_to_string(pos),"action")
|
me.log("connecting drive at "..minetest.pos_to_string(pos), "action")
|
||||||
set_drive_controller(pos,true,cnet.controller_pos,i)
|
set_drive_controller(pos,true,cnet.controller_pos,i)
|
||||||
add_all(pos,cnet)
|
add_all(pos,cnet)
|
||||||
elseif not fc.cpos then
|
elseif not fc.cpos then
|
||||||
microexpansion.log("connecting drive at "..minetest.pos_to_string(pos),"action")
|
me.log("connecting drive at "..minetest.pos_to_string(pos), "action")
|
||||||
set_drive_controller(pos,false,cnet.controller_pos,i)
|
set_drive_controller(pos,false,cnet.controller_pos,i)
|
||||||
add_all(pos,cnet)
|
add_all(pos,cnet)
|
||||||
elseif not vector.equals(fc.cpos,cnet.controller_pos) then
|
elseif not vector.equals(fc.cpos,cnet.controller_pos) then
|
||||||
microexpansion.log("reconnecting drive at "..minetest.pos_to_string(pos),"action")
|
me.log("reconnecting drive at "..minetest.pos_to_string(pos), "action")
|
||||||
write_drive_cells(pos,me.get_network(fc.cpos))
|
write_drive_cells(pos,me.get_network(fc.cpos))
|
||||||
set_drive_controller(pos,false,cnet.controller_pos,i)
|
set_drive_controller(pos,false,cnet.controller_pos,i)
|
||||||
add_all(pos,cnet)
|
add_all(pos,cnet)
|
||||||
me.disconnect_drive(pos,cnet.controller_pos)
|
me.disconnect_drive(pos,cnet.controller_pos)
|
||||||
else
|
else
|
||||||
if ev.origin.name == "microexpansion:ctrl" then
|
if ev.origin.name == "microexpansion:ctrl" then
|
||||||
me.disconnect_drive(pos,false)
|
me.disconnect_drive(pos,false)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
else
|
elseif fc then
|
||||||
if fc then
|
if fc.cpos then
|
||||||
if fc.cpos then
|
me.disconnect_drive(pos,false)
|
||||||
me.disconnect_drive(pos,false)
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [me chest] Register node
|
-- [me chest] Register node
|
||||||
microexpansion.register_node("drive", {
|
microexpansion.register_node("drive", {
|
||||||
description = "ME Drive",
|
description = "ME Drive",
|
||||||
usedfor = "Stores items into ME storage cells",
|
usedfor = "Stores items into ME storage cells",
|
||||||
tiles = {
|
tiles = {
|
||||||
"chest_top",
|
"chest_top",
|
||||||
"chest_top",
|
"chest_top",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"drive_full",
|
"drive_full",
|
||||||
},
|
},
|
||||||
recipe = {
|
recipe = {
|
||||||
{ 1, {
|
{ 1, {
|
||||||
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
|
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
|
||||||
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
|
||||||
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
|
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
groups = { cracky = 1, me_connect = 1 },
|
groups = { cracky = 1, me_connect = 1 },
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
me_update = update_drive,
|
me_update = update_drive,
|
||||||
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[9,9.5]"..
|
"size[9,7.5]"..
|
||||||
microexpansion.gui_bg ..
|
microexpansion.gui_bg ..
|
||||||
microexpansion.gui_slots ..
|
microexpansion.gui_slots ..
|
||||||
[[
|
[[
|
||||||
label[0,-0.23;ME Drive]
|
label[0,-0.23;ME Drive]
|
||||||
list[context;main;0,0.3;8,4]
|
list[context;main;0,0.3;5,2]
|
||||||
list[current_player;main;0,5.5;8,1;]
|
list[current_player;main;0,3.5;8,1;]
|
||||||
list[current_player;main;0,6.73;8,3;8]
|
list[current_player;main;0,4.73;8,3;8]
|
||||||
listring[current_name;main]
|
listring[current_name;main]
|
||||||
listring[current_player;main]
|
listring[current_player;main]
|
||||||
field_close_on_enter[filter;false]
|
field_close_on_enter[filter;false]
|
||||||
]])
|
]])
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
inv:set_size("main", 10)
|
inv:set_size("main", 10)
|
||||||
me.send_event(pos,"connect")
|
me.send_event(pos,"connect")
|
||||||
end,
|
end,
|
||||||
can_dig = function(pos, player)
|
can_dig = function(pos, player)
|
||||||
if minetest.is_protected(pos, player) then
|
if minetest.is_protected(pos, player) then
|
||||||
return false
|
return false
|
||||||
end
|
end
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local inv = meta:get_inventory()
|
local inv = meta:get_inventory()
|
||||||
return inv:is_empty("main")
|
return inv:is_empty("main")
|
||||||
end,
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
end,
|
end,
|
||||||
allow_metadata_inventory_put = function(_, _, _, stack)
|
allow_metadata_inventory_put = function(pos, _, _, stack, player)
|
||||||
if minetest.is_protected(pos, player) or minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then
|
if minetest.is_protected(pos, player)
|
||||||
return 0
|
or minetest.get_item_group(stack:get_name(), "microexpansion_cell") == 0 then
|
||||||
else
|
return 0
|
||||||
return 1
|
end
|
||||||
end
|
return 1
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_put = function(pos, _, _, stack)
|
on_metadata_inventory_put = function(pos, _, _, stack)
|
||||||
me.send_event(pos,"item_cap")
|
me.send_event(pos,"item_cap")
|
||||||
local network = me.get_connected_network(pos)
|
local network = me.get_connected_network(pos)
|
||||||
if network == nil then
|
if network == nil then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local ctrl_inv = network:get_inventory()
|
local ctrl_inv = network:get_inventory()
|
||||||
local items = minetest.deserialize(stack:get_meta():get_string("items"))
|
local items = minetest.deserialize(stack:get_meta():get_string("items"))
|
||||||
if items == nil then
|
if items == nil then
|
||||||
print("no items")
|
print("no items")
|
||||||
me.send_event(pos,"items",{net=network})
|
me.send_event(pos,"items",{net=network})
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
network:set_storage_space(#items)
|
-- network:set_storage_space(#items)
|
||||||
for _,s in pairs(items) do
|
for _,stack in pairs(items) do
|
||||||
me.insert_item(s, ctrl_inv, "main")
|
network:set_storage_space(true)
|
||||||
end
|
me.insert_item(stack, network, ctrl_inv, "main")
|
||||||
me.send_event(pos,"items",{net=network})
|
end
|
||||||
end,
|
network:set_storage_space(true)
|
||||||
allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player
|
me.send_event(pos,"items",{net=network})
|
||||||
if minetest.is_protected(pos, player) then
|
end,
|
||||||
return 0
|
allow_metadata_inventory_take = function(pos,_,_,stack, player) --args: pos, listname, index, stack, player
|
||||||
end
|
if minetest.is_protected(pos, player) then
|
||||||
local network = me.get_connected_network(pos)
|
return 0
|
||||||
write_drive_cells(pos,network)
|
end
|
||||||
return stack:get_count()
|
local network = me.get_connected_network(pos)
|
||||||
end,
|
write_drive_cells(pos,network)
|
||||||
on_metadata_inventory_take = function(pos, _, _, stack)
|
return stack:get_count()
|
||||||
local network = me.get_connected_network(pos)
|
end,
|
||||||
if network == nil then
|
on_metadata_inventory_take = function(pos, _, _, stack)
|
||||||
return
|
local network = me.get_connected_network(pos)
|
||||||
end
|
if network == nil then
|
||||||
me.send_event(pos,"item_cap",{net=network})
|
return
|
||||||
local ctrl_inv = network:get_inventory()
|
end
|
||||||
local items = minetest.deserialize(stack:get_meta():get_string("items"))
|
me.send_event(pos,"item_cap",{net=network})
|
||||||
if items == nil then
|
local ctrl_inv = network:get_inventory()
|
||||||
network:update()
|
local items = minetest.deserialize(stack:get_meta():get_string("items"))
|
||||||
return
|
if items == nil then
|
||||||
end
|
network:update()
|
||||||
for _,ostack in pairs(items) do
|
return
|
||||||
--this returns 99 (max count) even if it removes more
|
end
|
||||||
ctrl_inv:remove_item("main", ostack)
|
for _,ostack in pairs(items) do
|
||||||
end
|
local postack = ItemStack(ostack)
|
||||||
--print(stack:to_string())
|
-- me.log("drive meta_inv_take remove_item "..tostring(postack:get_count()).." "..postack:get_name(), "error")
|
||||||
|
-- TODO: this was here, but did nothing? me.remove_item(network, ctrl_inv, "main", postack)
|
||||||
|
-- No, this is the main item removal on cell removal from drive
|
||||||
|
me.remove_item(network, ctrl_inv, "main", postack)
|
||||||
|
--this returns 99 (max count) even if it removes more
|
||||||
|
--ctrl_inv:remove_item("main", ostack)
|
||||||
|
end
|
||||||
|
--print(stack:to_string())
|
||||||
|
|
||||||
network:update()
|
network:update()
|
||||||
me.send_event(pos,"items",{net=network})
|
me.send_event(pos,"items",{net=network})
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
@ -13,3 +13,18 @@ dofile(module_path.."/storage.lua")
|
|||||||
-- Load machines
|
-- Load machines
|
||||||
dofile(module_path.."/drive.lua")
|
dofile(module_path.."/drive.lua")
|
||||||
dofile(module_path.."/terminal.lua")
|
dofile(module_path.."/terminal.lua")
|
||||||
|
dofile(module_path.."/cterminal.lua")
|
||||||
|
dofile(module_path.."/interface.lua")
|
||||||
|
local drawers_enabled = minetest.get_modpath("drawers") and true or false
|
||||||
|
if drawers_enabled then
|
||||||
|
dofile(module_path.."/drawer-api.lua") -- Extra Drawer api
|
||||||
|
dofile(module_path.."/drawer-interop.lua")
|
||||||
|
end
|
||||||
|
local technic_enabled = minetest.get_modpath("technic") and true or false
|
||||||
|
if technic_enabled then
|
||||||
|
dofile(module_path.."/technic-interop.lua")
|
||||||
|
end
|
||||||
|
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
||||||
|
if pipeworks_enabled then
|
||||||
|
dofile(module_path.."/pipeworks-interop.lua")
|
||||||
|
end
|
||||||
|
313
modules/storage/interface.lua
Normal file
313
modules/storage/interface.lua
Normal file
@ -0,0 +1,313 @@
|
|||||||
|
-- interface
|
||||||
|
-- microexpansion/interface.lua
|
||||||
|
|
||||||
|
local me = microexpansion
|
||||||
|
local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
||||||
|
|
||||||
|
-- Interfaces work by walking all connected blocks. We walk machines and inventories.
|
||||||
|
-- This explains which nodes are connected.
|
||||||
|
-- Missing from technic_plus, the generators, might be nice to be able
|
||||||
|
-- to feed them wood when the power is low.
|
||||||
|
-- Odd machines like the reactor or the force field aren't supported.
|
||||||
|
-- We'd have to figure out what we'd want to do with them.
|
||||||
|
local function can_connect(name)
|
||||||
|
if me.registered_inventory[name] then
|
||||||
|
return true
|
||||||
|
end
|
||||||
|
return false
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.walk_connected(pos)
|
||||||
|
local nodes = {}
|
||||||
|
local visited = {}
|
||||||
|
visited[pos.x] = {}
|
||||||
|
visited[pos.x][pos.y] = {}
|
||||||
|
visited[pos.x][pos.y][pos.z] = true
|
||||||
|
local to_visit = {pos}
|
||||||
|
while #to_visit > 0 do
|
||||||
|
local pos = table.remove(to_visit)
|
||||||
|
local adjacent = {
|
||||||
|
{x=pos.x+1, y=pos.y, z=pos.z},
|
||||||
|
{x=pos.x-1, y=pos.y, z=pos.z},
|
||||||
|
{x=pos.x, y=pos.y+1, z=pos.z},
|
||||||
|
{x=pos.x, y=pos.y-1, z=pos.z},
|
||||||
|
{x=pos.x, y=pos.y, z=pos.z+1},
|
||||||
|
{x=pos.x, y=pos.y, z=pos.z-1},
|
||||||
|
}
|
||||||
|
for _,apos in pairs(adjacent) do
|
||||||
|
if not visited[apos.x] then
|
||||||
|
visited[apos.x] = {}
|
||||||
|
end
|
||||||
|
if not visited[apos.x][apos.y] then
|
||||||
|
visited[apos.x][apos.y] = {}
|
||||||
|
end
|
||||||
|
if visited[apos.x][apos.y][apos.z] ~= true then
|
||||||
|
visited[apos.x][apos.y][apos.z] = true
|
||||||
|
local napos = minetest.get_node(apos)
|
||||||
|
local nn = napos.name
|
||||||
|
if can_connect(nn) then
|
||||||
|
table.insert(nodes, {pos=apos, name=nn})
|
||||||
|
table.insert(to_visit, apos)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
return nodes
|
||||||
|
end
|
||||||
|
|
||||||
|
local function update(pos,_,ev)
|
||||||
|
if ev.type == "connect" then
|
||||||
|
-- net.update_counts()
|
||||||
|
elseif ev.type == "disconnect" then
|
||||||
|
--
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.reload_inventory(name, net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
local func = me.registered_inventory and me.registered_inventory[name]
|
||||||
|
if func then
|
||||||
|
func(net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
function me.chest_reload(net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
if not doinventories then return end
|
||||||
|
local meta = minetest.get_meta(n.pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
for i = 1, inv:get_size("main") do
|
||||||
|
local stack = inv:get_stack("main", i)
|
||||||
|
if not stack:is_empty() then
|
||||||
|
net:create_loan(stack, {pos=n.pos, invname="main", slot=i, ipos=pos}, ctrl_inv, int_meta)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
me.register_inventory("default:chest", me.chest_reload)
|
||||||
|
|
||||||
|
-- This never rewalks connected machines. To do that add a gui
|
||||||
|
-- rewalk and/or remove, replace.
|
||||||
|
function me.reload_interface(net, pos, doinventories)
|
||||||
|
if not net then return end
|
||||||
|
local ctrl_inv = net:get_inventory()
|
||||||
|
local int_meta = minetest.get_meta(pos)
|
||||||
|
local inv = int_meta:get_inventory()
|
||||||
|
local inventories = minetest.deserialize(int_meta:get_string("connected"))
|
||||||
|
-- not appropriate
|
||||||
|
-- me.send_event(pos,"connect")
|
||||||
|
int_meta:set_string("infotext", "chests: "..#inventories)
|
||||||
|
if not net.counts then
|
||||||
|
net.counts = {}
|
||||||
|
end
|
||||||
|
if not net.autocrafters then
|
||||||
|
net.autocrafters = {}
|
||||||
|
end
|
||||||
|
if not net.autocrafters_by_pos then
|
||||||
|
net.autocrafters_by_pos = {}
|
||||||
|
end
|
||||||
|
if not net.process then
|
||||||
|
net.process = {}
|
||||||
|
end
|
||||||
|
for _, n in pairs(inventories) do
|
||||||
|
local node = minetest.get_node(n.pos)
|
||||||
|
local name = node.name
|
||||||
|
-- me.log("INT: found a "..name, "error")
|
||||||
|
local outputs = me.output_by_typename[me.block_to_typename_map[name]]
|
||||||
|
if outputs then
|
||||||
|
for _, name in pairs(outputs) do
|
||||||
|
if not net.process[name] then
|
||||||
|
net.process[name] = {}
|
||||||
|
end
|
||||||
|
-- me.log("INT: registering "..name.." for the "..node.name, "error")
|
||||||
|
net.process[name][n.pos] = pos
|
||||||
|
end
|
||||||
|
else
|
||||||
|
me.reload_inventory(name, net, ctrl_inv, int_meta, n, pos, doinventories)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- me.send_event(pos,...
|
||||||
|
end
|
||||||
|
|
||||||
|
-- [me chest] Register node
|
||||||
|
me.register_node("interface", {
|
||||||
|
description = "ME Interface",
|
||||||
|
usedfor = "Interface for ME system",
|
||||||
|
tiles = {
|
||||||
|
"chest_top",
|
||||||
|
"chest_top",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side",
|
||||||
|
"chest_side", -- TODO: Maybe customize it?
|
||||||
|
},
|
||||||
|
recipe = {
|
||||||
|
{ 1, {
|
||||||
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
|
||||||
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot" },
|
||||||
|
{"default:steel_ingot", "default:chest", "default:steel_ingot" },
|
||||||
|
},
|
||||||
|
}
|
||||||
|
},
|
||||||
|
is_ground_content = false,
|
||||||
|
groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 },
|
||||||
|
paramtype = "light",
|
||||||
|
paramtype2 = "facedir",
|
||||||
|
me_update = update,
|
||||||
|
on_construct = function(pos)
|
||||||
|
local int_meta = minetest.get_meta(pos)
|
||||||
|
int_meta:set_string("formspec",
|
||||||
|
"size[9,7.5]"..
|
||||||
|
microexpansion.gui_bg ..
|
||||||
|
microexpansion.gui_slots ..
|
||||||
|
[[
|
||||||
|
label[0,-0.23;ME Interface]
|
||||||
|
list[context;import;0,0.3;9,1]
|
||||||
|
list[context;export;0,0.3;9,1]
|
||||||
|
list[current_player;main;0,3.5;8,1;]
|
||||||
|
list[current_player;main;0,4.73;8,3;8]
|
||||||
|
listring[current_name;import]
|
||||||
|
listring[current_player;main]
|
||||||
|
field_close_on_enter[filter;false]
|
||||||
|
]])
|
||||||
|
local inv = int_meta:get_inventory()
|
||||||
|
inv:set_size("export", 3)
|
||||||
|
inv:set_size("import", 3)
|
||||||
|
local inventories = me.walk_connected(pos)
|
||||||
|
int_meta:set_string("connected", minetest.serialize(inventories))
|
||||||
|
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
if net == nil then
|
||||||
|
int_meta:set_string("infotext", "No Network")
|
||||||
|
return
|
||||||
|
end
|
||||||
|
me.reload_interface(net, pos, true)
|
||||||
|
end,
|
||||||
|
can_dig = function(pos)
|
||||||
|
local meta = minetest.get_meta(pos)
|
||||||
|
local inv = meta:get_inventory()
|
||||||
|
return inv:is_empty("import")
|
||||||
|
end,
|
||||||
|
on_destruct = function(pos)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
if net == nil then return end
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
|
||||||
|
local int_meta = minetest.get_meta(pos)
|
||||||
|
local inventories = minetest.deserialize(int_meta:get_string("connected"))
|
||||||
|
int_meta:set_string("infotext", "")
|
||||||
|
|
||||||
|
local to_remove = {}
|
||||||
|
for _, n in pairs(inventories) do
|
||||||
|
local pos = n.pos
|
||||||
|
if not to_remove[pos.x] then
|
||||||
|
to_remove[pos.x] = {}
|
||||||
|
end
|
||||||
|
if not to_remove[pos.x][pos.y] then
|
||||||
|
to_remove[pos.x][pos.y] = {}
|
||||||
|
end
|
||||||
|
if not to_remove[pos.x][pos.y][pos.z] then
|
||||||
|
to_remove[pos.x][pos.y][pos.z] = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
net:update_counts()
|
||||||
|
local loan_slot = me.loan.get_size(net, inv)
|
||||||
|
local ref
|
||||||
|
while loan_slot > 0 do
|
||||||
|
local lstack = me.loan.get_stack(net, inv, loan_slot)
|
||||||
|
if lstack:is_empty() then
|
||||||
|
-- TODO: Don't think this can happen now, update_counts
|
||||||
|
-- me.log("interface empty loan at "..loan_slot, "error")
|
||||||
|
goto continue
|
||||||
|
foobar()
|
||||||
|
end
|
||||||
|
-- me.log("interface removing loan at "..loan_slot, "error")
|
||||||
|
ref = me.network.get_ref(lstack)
|
||||||
|
if ref and to_remove[ref.pos.x] and to_remove[ref.pos.x][ref.pos.y] and to_remove[ref.pos.x][ref.pos.y][ref.pos.z] then
|
||||||
|
net:remove_loan(ref.pos, inv, lstack, loan_slot, ref)
|
||||||
|
end
|
||||||
|
::continue::
|
||||||
|
loan_slot = loan_slot - 1
|
||||||
|
end
|
||||||
|
net:update_counts()
|
||||||
|
|
||||||
|
-- pos is a table and does not have value semantics.
|
||||||
|
if net.autocrafters_by_pos then
|
||||||
|
for k, v in pairs(net.autocrafters_by_pos) do
|
||||||
|
if k.x == pos.x and k.y == pos.y and k.z == pos.z then
|
||||||
|
pos = k
|
||||||
|
break
|
||||||
|
end
|
||||||
|
end
|
||||||
|
if net.autocrafters_by_pos[pos] then
|
||||||
|
for name, apos in pairs(net.autocrafters_by_pos[pos]) do
|
||||||
|
-- deindex these upon removal of the interface controlling them
|
||||||
|
net.autocrafters_by_pos[pos][name] = nil
|
||||||
|
net.autocrafters[name][apos] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end,
|
||||||
|
after_destruct = function(pos)
|
||||||
|
me.send_event(pos,"disconnect")
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_put = function(pos, listname, index, stack)
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_put = function(pos, _, _, stack)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
if net == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ctrl_inv = net:get_inventory()
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_take = function(pos,_,_,stack) --args: pos, listname, index, stack, player
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
return stack:get_count()
|
||||||
|
end,
|
||||||
|
on_metadata_inventory_take = function(pos, _, _, stack)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
if net == nil then
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local ctrl_inv = net:get_inventory()
|
||||||
|
end,
|
||||||
|
-- tube connection
|
||||||
|
tube = {
|
||||||
|
can_insert = function(pos, _, stack) --pos, node, stack, direction
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
|
||||||
|
local max_slots = inv:get_size("main")
|
||||||
|
local max_items = net.capacity_cache
|
||||||
|
|
||||||
|
local slots, items = 0, 0
|
||||||
|
-- Get amount of items in drive
|
||||||
|
for i = 1, max_slots do
|
||||||
|
local mstack = inv:get_stack("main", i)
|
||||||
|
if mstack:get_name() ~= "" then
|
||||||
|
slots = slots + 1
|
||||||
|
local num = mstack:get_count()
|
||||||
|
if num == 0 then num = 1 end
|
||||||
|
items = items + num
|
||||||
|
end
|
||||||
|
end
|
||||||
|
items = items + stack:get_count()
|
||||||
|
return max_items > items
|
||||||
|
end,
|
||||||
|
insert_object = function(pos, _, stack)
|
||||||
|
local net = me.get_connected_network(pos)
|
||||||
|
local leftovers = stack
|
||||||
|
if net then
|
||||||
|
local inv = net:get_inventory()
|
||||||
|
leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
|
end
|
||||||
|
return leftovers
|
||||||
|
end,
|
||||||
|
connect_sides = {left=1, right=1, front=1, back=1, top=1, bottom=1},
|
||||||
|
},
|
||||||
|
after_place_node = pipeworks_enabled and pipeworks.after_place,
|
||||||
|
after_dig_node = pipeworks_enabled and pipeworks.after_dig,
|
||||||
|
})
|
25
modules/storage/pipeworks-interop.lua
Normal file
25
modules/storage/pipeworks-interop.lua
Normal file
@ -0,0 +1,25 @@
|
|||||||
|
-- Interoperability file for pipework support.
|
||||||
|
local me = microexpansion
|
||||||
|
|
||||||
|
me.register_inventory("pipeworks:autocrafter", function(net, ctrl_inv, int_meta, n, pos)
|
||||||
|
local meta = minetest.get_meta(n.pos)
|
||||||
|
local rinv = meta:get_inventory()
|
||||||
|
-- Autoinsert all the outputs
|
||||||
|
--for i = 1, rinv:get_size("dst")
|
||||||
|
-- local stack = rinv:get_stack("dst", i)
|
||||||
|
-- local leftovers = me.insert_item(stack, net, ctrl_inv, "main")
|
||||||
|
-- rinv:set_stack("dst", i, leftovers)
|
||||||
|
--end
|
||||||
|
-- register the crafted items so the autocrafter can use them
|
||||||
|
local craft = rinv:get_stack("output", 1)
|
||||||
|
if not craft:is_empty() then
|
||||||
|
if not net.autocrafters_by_pos[pos] then
|
||||||
|
net.autocrafters_by_pos[pos] = {}
|
||||||
|
end
|
||||||
|
net.autocrafters_by_pos[pos][craft:get_name()] = n.pos
|
||||||
|
if not net.autocrafters[craft:get_name()] then
|
||||||
|
net.autocrafters[craft:get_name()] = {}
|
||||||
|
end
|
||||||
|
net.autocrafters[craft:get_name()][n.pos] = pos
|
||||||
|
end
|
||||||
|
end)
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
--TODO: use storagecomp for crafting
|
--TODO: use storagecomp for crafting
|
||||||
|
|
||||||
-- [drive] 8k
|
-- [drive] 1k
|
||||||
microexpansion.register_cell("cell_1k", {
|
microexpansion.register_cell("cell_1k", {
|
||||||
description = "1k ME Storage Cell",
|
description = "1k ME Storage Cell",
|
||||||
capacity = 1000,
|
capacity = 1000,
|
||||||
@ -16,7 +16,7 @@ microexpansion.register_cell("cell_1k", {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [drive] 8k
|
-- [drive] 2k
|
||||||
microexpansion.register_cell("cell_2k", {
|
microexpansion.register_cell("cell_2k", {
|
||||||
description = "2k ME Storage Cell",
|
description = "2k ME Storage Cell",
|
||||||
capacity = 2000,
|
capacity = 2000,
|
||||||
@ -31,7 +31,7 @@ microexpansion.register_cell("cell_2k", {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [drive] 16k
|
-- [drive] 4k
|
||||||
microexpansion.register_cell("cell_4k", {
|
microexpansion.register_cell("cell_4k", {
|
||||||
description = "4k ME Storage Cell",
|
description = "4k ME Storage Cell",
|
||||||
capacity = 4000,
|
capacity = 4000,
|
||||||
@ -44,7 +44,7 @@ microexpansion.register_cell("cell_4k", {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [drive] 16k
|
-- [drive] 8k
|
||||||
microexpansion.register_cell("cell_8k", {
|
microexpansion.register_cell("cell_8k", {
|
||||||
description = "8k ME Storage Cell",
|
description = "8k ME Storage Cell",
|
||||||
capacity = 8000,
|
capacity = 8000,
|
||||||
@ -53,7 +53,7 @@ microexpansion.register_cell("cell_8k", {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
|
|
||||||
-- [drive] 32k
|
-- [drive] 16k
|
||||||
microexpansion.register_cell("cell_16k", {
|
microexpansion.register_cell("cell_16k", {
|
||||||
description = "16k ME Storage Cell",
|
description = "16k ME Storage Cell",
|
||||||
capacity = 16000,
|
capacity = 16000,
|
||||||
|
234
modules/storage/technic-interop.lua
Normal file
234
modules/storage/technic-interop.lua
Normal file
@ -0,0 +1,234 @@
|
|||||||
|
-- Interoperability file for technic and technic_plus support.
|
||||||
|
local me = microexpansion
|
||||||
|
|
||||||
|
|
||||||
|
-- technic_plus doesn't export machine speed, so wire it in here. We
|
||||||
|
-- use this to know exactly how long a machine will take to process
|
||||||
|
-- anything, after that time, we know it is done and we can grab the
|
||||||
|
-- outputs, no polling. We do this for efficiency.
|
||||||
|
|
||||||
|
-- The speeds of the various machines:
|
||||||
|
me.set_speed("technic:electric_furnace", 2)
|
||||||
|
me.set_speed("technic:mv_electric_furnace", 4)
|
||||||
|
me.set_speed("technic:hv_electric_furnace", 12)
|
||||||
|
me.set_speed("technic:lv_alloy_furnace", 1)
|
||||||
|
me.set_speed("technic:mv_alloy_furnace", 1.5)
|
||||||
|
me.set_speed("technic:lv_compressor", 1)
|
||||||
|
me.set_speed("technic:mv_compressor", 2)
|
||||||
|
me.set_speed("technic:hv_compressor", 5)
|
||||||
|
me.set_speed("technic:lv_extractor", 1)
|
||||||
|
me.set_speed("technic:mv_extractor", 2)
|
||||||
|
me.set_speed("technic:lv_grinder", 1)
|
||||||
|
me.set_speed("technic:mv_grinder", 2)
|
||||||
|
me.set_speed("technic:hv_grinder", 5)
|
||||||
|
me.set_speed("technic:mv_centrifuge", 2)
|
||||||
|
me.set_speed("technic:mv_freezer", 0.5)
|
||||||
|
|
||||||
|
-- ======================================================================== --
|
||||||
|
|
||||||
|
|
||||||
|
-- Register maximal output sizes for all the ingredients we produce.
|
||||||
|
-- We also break up deeply recursive crafts that would blow a pipeworks
|
||||||
|
|
||||||
|
-- autocrafter if it tried to make something.
|
||||||
|
-- might not be necessary, but maybe it is. It might limit
|
||||||
|
-- oversupply of inputs to batteries.
|
||||||
|
me.register_max("technic:lv_battery_box0", 3)
|
||||||
|
me.register_max("technic:battery", 12)
|
||||||
|
|
||||||
|
-- HV furnace only has 4 output slots
|
||||||
|
me.register_max("technic:cast_iron_ingot", 20)
|
||||||
|
me.register_max("mesecons_materials:glue", 380)
|
||||||
|
me.register_max("mesecons_materials:fiber", 380)
|
||||||
|
me.register_max("default:stone", 20)
|
||||||
|
me.register_max("basic_materials:plastic_sheet", 380)
|
||||||
|
me.register_max("basic_materials:paraffin", 380)
|
||||||
|
|
||||||
|
-- HV grinder only has 4 output slots
|
||||||
|
me.register_max("technic:coal_dust", 380)
|
||||||
|
me.register_max("technic:gold_dust", 380)
|
||||||
|
me.register_max("technic:sulfur_dust", 380)
|
||||||
|
me.register_max("technic:stone_dust", 380)
|
||||||
|
me.register_max("default:gravel", 380)
|
||||||
|
me.register_max("default:sand", 380)
|
||||||
|
me.register_max("default:snowblock", 380)
|
||||||
|
me.register_max("technic:rubber_tree_grindings", 380)
|
||||||
|
|
||||||
|
-- MV alloy furnace only has 4 output slots
|
||||||
|
me.register_max("technic:doped_silicon_wafer", 380)
|
||||||
|
me.register_max("technic:silicon_wafer", 380)
|
||||||
|
me.register_max("basic_materials:brass_ingot", 380)
|
||||||
|
me.register_max("default:bronze_ingot", 380)
|
||||||
|
me.register_max("technic:stainless_steel_ingot", 380)
|
||||||
|
me.register_max("technic:rubber", 380)
|
||||||
|
me.register_max("bucket:bucket_lava", 4)
|
||||||
|
me.register_max("technic:carbon_steel_ingot", 380)
|
||||||
|
|
||||||
|
-- LV extractor only has 4 output slots
|
||||||
|
me.register_max("technic:raw_latex", 380)
|
||||||
|
|
||||||
|
-- HV compressor only has 4 output slots
|
||||||
|
me.register_max("technic:composite_plate", 380)
|
||||||
|
me.register_max("technic:copper_plate", 380)
|
||||||
|
me.register_max("technic:graphite", 380)
|
||||||
|
me.register_max("technic:carbon_plate", 380)
|
||||||
|
me.register_max("technic:uranium_fuel", 380)
|
||||||
|
me.register_max("default:diamond", 380)
|
||||||
|
|
||||||
|
-- freezer only has 4 output slots
|
||||||
|
me.register_max("default:ice", 380)
|
||||||
|
|
||||||
|
-- ======================================================================== --
|
||||||
|
|
||||||
|
|
||||||
|
-- The type of machines all the machines are: We have to list these
|
||||||
|
-- before me.register_inventory.
|
||||||
|
me.register_typename("technic:electric_furnace", "cooking")
|
||||||
|
me.register_typename("technic:mv_electric_furnace", "cooking")
|
||||||
|
me.register_typename("technic:hv_electric_furnace", "cooking")
|
||||||
|
me.register_typename("technic:lv_grinder", "grinding")
|
||||||
|
me.register_typename("technic:mv_grinder", "grinding")
|
||||||
|
me.register_typename("technic:hv_grinder", "grinding")
|
||||||
|
me.register_typename("technic:coal_alloy_furnace", "alloy")
|
||||||
|
me.register_typename("technic:lv_alloy_furnace", "alloy")
|
||||||
|
me.register_typename("technic:mv_alloy_furnace", "alloy")
|
||||||
|
me.register_typename("technic:lv_extractor", "extracting")
|
||||||
|
me.register_typename("technic:mv_extractor", "extracting")
|
||||||
|
me.register_typename("technic:lv_compressor", "compressing")
|
||||||
|
me.register_typename("technic:mv_compressor", "compressing")
|
||||||
|
me.register_typename("technic:hv_compressor", "compressing")
|
||||||
|
me.register_typename("technic:mv_centrifuge", "separating")
|
||||||
|
me.register_typename("technic:mv_freezer", "freezing")
|
||||||
|
|
||||||
|
-- ======================================================================== --
|
||||||
|
|
||||||
|
|
||||||
|
-- The various blocks and how to interface to them:
|
||||||
|
me.register_inventory("technic:gold_chest", me.chest_reload)
|
||||||
|
me.register_inventory("technic:mithril_chest", me.chest_reload)
|
||||||
|
|
||||||
|
me.register_inventory("technic:quarry", function(net, ctrl_inv, int_meta, n, pos)
|
||||||
|
local meta = minetest.get_meta(n.pos)
|
||||||
|
local rinv = meta:get_inventory()
|
||||||
|
for i = 1, rinv:get_size("cache") do
|
||||||
|
local stack = rinv:get_stack("cache", i)
|
||||||
|
if not stack:is_empty() then
|
||||||
|
local leftovers = me.insert_item(stack, net, ctrl_inv, "main")
|
||||||
|
rinv:set_stack("cache", i, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
-- we can set up a timer to recheck the cache every 30 seconds and
|
||||||
|
-- clean it out for example.
|
||||||
|
end)
|
||||||
|
|
||||||
|
me.register_inventory("technic:mv_centrifuge", function(net, ctrl_inv, int_meta, n, pos)
|
||||||
|
local meta = minetest.get_meta(n.pos)
|
||||||
|
local rinv = meta:get_inventory()
|
||||||
|
for i = 1, rinv:get_size("dst") do
|
||||||
|
local stack = rinv:get_stack("dst", i)
|
||||||
|
if not stack:is_empty() then
|
||||||
|
local leftovers = me.insert_item(stack, net, ctrl_inv, "main")
|
||||||
|
rinv:set_stack("dst", i, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
for i = 1, rinv:get_size("dst2") do
|
||||||
|
local stack = rinv:get_stack("dst2", i)
|
||||||
|
if not stack:is_empty() then
|
||||||
|
local leftovers = me.insert_item(stack, net, ctrl_inv, "main")
|
||||||
|
rinv:set_stack("dst2", i, leftovers)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end)
|
||||||
|
|
||||||
|
-- ======================================================================== --
|
||||||
|
|
||||||
|
|
||||||
|
-- The various outputs the various machine types can generate:
|
||||||
|
me.register_output_by_typename("cooking", "technic:cast_iron_ingot")
|
||||||
|
me.register_output_by_typename("cooking", "mesecons_materials:glue")
|
||||||
|
me.register_output_by_typename("cooking", "mesecons_materials:fiber")
|
||||||
|
me.register_output_by_typename("cooking", "basic_materials:plastic_sheet")
|
||||||
|
me.register_output_by_typename("cooking", "basic_materials:paraffin")
|
||||||
|
|
||||||
|
me.register_output_by_typename("grinding", "technic:coal_dust")
|
||||||
|
me.register_output_by_typename("grinding", "technic:gold_dust")
|
||||||
|
me.register_output_by_typename("grinding", "technic:sulfur_dust")
|
||||||
|
me.register_output_by_typename("grinding", "technic:stone_dust")
|
||||||
|
me.register_output_by_typename("grinding", "default:gravel")
|
||||||
|
me.register_output_by_typename("grinding", "default:sand")
|
||||||
|
me.register_output_by_typename("grinding", "default:snowblock")
|
||||||
|
me.register_output_by_typename("grinding", "technic:rubber_tree_grindings")
|
||||||
|
|
||||||
|
me.register_output_by_typename("alloy", "technic:doped_silicon_wafer")
|
||||||
|
me.register_output_by_typename("alloy", "technic:silicon_wafer")
|
||||||
|
me.register_output_by_typename("alloy", "basic_materials:brass_ingot")
|
||||||
|
me.register_output_by_typename("alloy", "default:bronze_ingot")
|
||||||
|
me.register_output_by_typename("alloy", "technic:stainless_steel_ingot")
|
||||||
|
me.register_output_by_typename("alloy", "technic:rubber")
|
||||||
|
me.register_output_by_typename("alloy", "bucket:bucket_lava")
|
||||||
|
me.register_output_by_typename("alloy", "technic:carbon_steel_ingot")
|
||||||
|
|
||||||
|
me.register_output_by_typename("extracting", "technic:raw_latex")
|
||||||
|
|
||||||
|
me.register_output_by_typename("compressing", "technic:composite_plate")
|
||||||
|
me.register_output_by_typename("compressing", "technic:copper_plate")
|
||||||
|
me.register_output_by_typename("compressing", "technic:graphite")
|
||||||
|
me.register_output_by_typename("compressing", "technic:carbon_plate")
|
||||||
|
me.register_output_by_typename("compressing", "technic:uranium_fuel")
|
||||||
|
me.register_output_by_typename("compressing", "default:diamond")
|
||||||
|
|
||||||
|
-- Any of these worth doing? TODO: Uranium, sure.
|
||||||
|
--me.register_output_by_typename("separating", "")
|
||||||
|
|
||||||
|
me.register_output_by_typename("freezing", "default:ice")
|
||||||
|
|
||||||
|
-- ======================================================================== --
|
||||||
|
|
||||||
|
-- The inputs required for the given output. The inputs are exact count, the output it just
|
||||||
|
-- for 1. We'll figure out how many are actually produced later. For multiple outputs
|
||||||
|
-- only list the more interesting one.
|
||||||
|
-- furnace ("cooking")
|
||||||
|
me.register_output_to_inputs("technic:cast_iron_ingot", { ItemStack("default:steel_ingot") })
|
||||||
|
me.register_output_to_inputs("mesecons_materials:glue", { ItemStack("technic:raw_latex") })
|
||||||
|
me.register_output_to_inputs("mesecons_materials:fiber", { ItemStack("mesecons_materials:glue") })
|
||||||
|
me.register_output_to_inputs("basic_materials:plastic_sheet", { ItemStack("basic_materials:paraffin") })
|
||||||
|
me.register_output_to_inputs("basic_materials:paraffin", { ItemStack("basic_materials:oil_extract") })
|
||||||
|
|
||||||
|
-- grinder ("grinding")
|
||||||
|
me.register_output_to_inputs("technic:coal_dust", { ItemStack("default:coal_lump") })
|
||||||
|
me.register_output_to_inputs("technic:gold_dust", { ItemStack("default:gold_lump") })
|
||||||
|
me.register_output_to_inputs("technic:sulfur_dust", { ItemStack("technic:sulfur_lump") })
|
||||||
|
me.register_output_to_inputs("technic:stone_dust", { ItemStack("default:stone") })
|
||||||
|
me.register_output_to_inputs("default:gravel", { ItemStack("default:cobble") })
|
||||||
|
me.register_output_to_inputs("default:sand", { ItemStack("default:gravel") })
|
||||||
|
me.register_output_to_inputs("default:snowblock", { ItemStack("default:ice") })
|
||||||
|
-- TODO: Something about this doesn't work: recheck, think it is fixed now
|
||||||
|
me.register_output_to_inputs("technic:rubber_tree_grindings", { ItemStack("moretrees:rubber_tree_trunk") })
|
||||||
|
|
||||||
|
-- alloy_furnace ("alloy")
|
||||||
|
-- The most useful alloy recipes. We don't do the less useful ones as we don't yet have
|
||||||
|
-- a way for the user to say, no, don't do that.
|
||||||
|
me.register_output_to_inputs("technic:doped_silicon_wafer", { ItemStack("technic:gold_dust"), ItemStack("technic:silicon_wafer") })
|
||||||
|
me.register_output_to_inputs("technic:silicon_wafer", { ItemStack("default:sand 2"), ItemStack("technic:coal_dust 2") })
|
||||||
|
me.register_output_to_inputs("basic_materials:brass_ingot", { ItemStack("default:copper_ingot 2"), ItemStack("technic:zinc_ingot") })
|
||||||
|
me.register_output_to_inputs("default:bronze_ingot", { ItemStack("default:copper_ingot 7"), ItemStack("default:tin_ingot") })
|
||||||
|
me.register_output_to_inputs("technic:stainless_steel_ingot", { ItemStack("technic:carbon_steel_ingot 4"), ItemStack("technic:chromium_ingot") })
|
||||||
|
me.register_output_to_inputs("technic:rubber", { ItemStack("technic:raw_latex 4"), ItemStack("technic:coal_dust 2") })
|
||||||
|
me.register_output_to_inputs("bucket:bucket_lava", { ItemStack("default:obsidian"), ItemStack("bucket:bucket_empty") })
|
||||||
|
me.register_output_to_inputs("technic:carbon_steel_ingot", { ItemStack("default:steel_ingot 2"), ItemStack("technic:coal_dust") })
|
||||||
|
|
||||||
|
-- extractor ("extracting")
|
||||||
|
me.register_output_to_inputs("technic:raw_latex", { ItemStack("technic:rubber_tree_grindings 4") })
|
||||||
|
|
||||||
|
-- compressor ("compressing")
|
||||||
|
me.register_output_to_inputs("technic:composite_plate", { ItemStack("technic:mixed_metal_ingot") })
|
||||||
|
me.register_output_to_inputs("technic:copper_plate", { ItemStack("default:copper_ingot 5") })
|
||||||
|
me.register_output_to_inputs("technic:graphite", { ItemStack("technic:coal_dust 4") })
|
||||||
|
me.register_output_to_inputs("technic:carbon_plate", { ItemStack("technic:carbon_cloth") })
|
||||||
|
me.register_output_to_inputs("technic:uranium_fuel", { ItemStack("technic:uranium35_ingot 5") })
|
||||||
|
me.register_output_to_inputs("default:diamond", { ItemStack("technic:graphite 25") })
|
||||||
|
|
||||||
|
-- centrifuge ("separating")
|
||||||
|
|
||||||
|
-- freezer ("freezing")
|
||||||
|
me.register_output_to_inputs("default:ice", { ItemStack("bucket:bucket_water") })
|
@ -1,3 +1,4 @@
|
|||||||
|
-- terminal
|
||||||
-- microexpansion/machines.lua
|
-- microexpansion/machines.lua
|
||||||
|
|
||||||
local me = microexpansion
|
local me = microexpansion
|
||||||
@ -5,136 +6,149 @@ local pipeworks_enabled = minetest.get_modpath("pipeworks") and true or false
|
|||||||
|
|
||||||
-- [me chest] Get formspec
|
-- [me chest] Get formspec
|
||||||
local function chest_formspec(pos, start_id, listname, page_max, q)
|
local function chest_formspec(pos, start_id, listname, page_max, q)
|
||||||
local list
|
local list
|
||||||
local page_number = ""
|
local page_number = ""
|
||||||
local buttons = ""
|
local buttons = ""
|
||||||
local query = q or ""
|
local query = q or ""
|
||||||
local net,cp = me.get_connected_network(pos)
|
local net,cp = me.get_connected_network(pos)
|
||||||
|
|
||||||
if cp then
|
if cp then
|
||||||
if listname and net:get_item_capacity() > 0 then
|
if listname and net:get_item_capacity() > 0 then
|
||||||
local ctrlinvname = net:get_inventory_name()
|
local ctrlinvname = net:get_inventory_name()
|
||||||
if listname == "main" then
|
if listname == "main" then
|
||||||
list = "list[detached:"..ctrlinvname..";"
|
list = "list[detached:"..ctrlinvname..";"
|
||||||
.. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
.. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
||||||
else
|
else
|
||||||
list = "list[context;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
list = "list[context;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]"
|
||||||
end
|
end
|
||||||
list = list .. [[
|
if minetest.get_modpath("i3") then
|
||||||
list[current_player;main;0,5.5;8,1;]
|
list = list .. [[
|
||||||
list[current_player;main;0,6.73;8,3;8]
|
list[current_player;main;0,5.5;9,4;]
|
||||||
listring[detached:]]..ctrlinvname..[[;main]
|
]]
|
||||||
listring[current_player;main]
|
else
|
||||||
]]
|
list = list .. [[
|
||||||
buttons = [[
|
list[current_player;main;0,5.5;8,1;]
|
||||||
button[3.56,4.35;1.8,0.9;tochest;To Drive]
|
list[current_player;main;0,6.73;8,3;8]
|
||||||
tooltip[tochest;Move everything from your inventory to the ME network.]
|
]]
|
||||||
button[5.4,4.35;0.8,0.9;prev;<]
|
end
|
||||||
button[7.25,4.35;0.8,0.9;next;>]
|
list = list .. [[
|
||||||
tooltip[prev;Previous]
|
listring[detached:]]..ctrlinvname..[[;main]
|
||||||
tooltip[next;Next]
|
listring[current_player;main]
|
||||||
field[0.29,4.6;2.2,1;filter;;]]..query..[[]
|
]]
|
||||||
button[2.1,4.5;0.8,0.5;search;?]
|
buttons = [[
|
||||||
button[2.75,4.5;0.8,0.5;clear;X]
|
button[3.56,4.35;1.8,0.9;tochest;To Drive]
|
||||||
tooltip[search;Search]
|
tooltip[tochest;Move everything from your inventory to the ME network.]
|
||||||
tooltip[clear;Reset]
|
button[5.4,4.35;0.8,0.9;prev;<]
|
||||||
]]
|
button[7.25,4.35;0.8,0.9;next;>]
|
||||||
else
|
tooltip[prev;Previous]
|
||||||
list = "label[3,2;" .. minetest.colorize("red", "No connected drives!") .. "]"
|
tooltip[next;Next]
|
||||||
end
|
field[0.29,4.6;2.2,1;filter;;]]..query..[[]
|
||||||
else
|
button[2.1,4.5;0.8,0.5;search;?]
|
||||||
list = "label[3,2;" .. minetest.colorize("red", "No connected network!") .. "]"
|
button[2.75,4.5;0.8,0.5;clear;X]
|
||||||
end
|
tooltip[search;Search]
|
||||||
if page_max then
|
tooltip[clear;Reset]
|
||||||
page_number = "label[6.15,4.5;" .. math.floor((start_id / 32)) + 1 ..
|
]]
|
||||||
"/" .. page_max .."]"
|
else
|
||||||
end
|
list = "label[3,2;" .. minetest.colorize("red", "No connected storage!") .. "]"
|
||||||
|
end
|
||||||
|
else
|
||||||
|
list = "label[3,2;" .. minetest.colorize("red", "No connected network!") .. "]"
|
||||||
|
end
|
||||||
|
if page_max then
|
||||||
|
page_number = "label[6.15,4.5;" .. math.floor((start_id / 32)) + 1 ..
|
||||||
|
"/" .. page_max .."]"
|
||||||
|
end
|
||||||
|
|
||||||
return [[
|
return [[
|
||||||
size[9,9.5]
|
size[9,9.5]
|
||||||
]]..
|
]]..
|
||||||
microexpansion.gui_bg ..
|
microexpansion.gui_bg ..
|
||||||
microexpansion.gui_slots ..
|
microexpansion.gui_slots ..
|
||||||
list ..
|
list ..
|
||||||
[[
|
[[
|
||||||
label[0,-0.23;ME Terminal]
|
label[0,-0.23;ME Terminal]
|
||||||
field_close_on_enter[filter;false]
|
field_close_on_enter[filter;false]
|
||||||
]]..
|
]]..
|
||||||
page_number ..
|
page_number ..
|
||||||
buttons
|
buttons
|
||||||
end
|
end
|
||||||
|
|
||||||
local function update_chest(pos,_,ev)
|
local function update_chest(pos,_,ev)
|
||||||
--for now all events matter
|
--for now all events matter
|
||||||
|
|
||||||
local network = me.get_connected_network(pos)
|
|
||||||
local meta = minetest.get_meta(pos)
|
|
||||||
if network == nil then
|
|
||||||
meta:set_int("page", 1)
|
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1))
|
|
||||||
return
|
|
||||||
end
|
|
||||||
local size = network:get_item_capacity()
|
|
||||||
local page_max = me.int_to_pagenum(size) + 1
|
|
||||||
|
|
||||||
meta:set_string("inv_name", "main")
|
local network = me.get_connected_network(pos)
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
local meta = minetest.get_meta(pos)
|
||||||
|
if network == nil then
|
||||||
|
meta:set_int("page", 1)
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1))
|
||||||
|
return
|
||||||
|
end
|
||||||
|
local size = network:get_item_capacity()
|
||||||
|
local page_max = me.int_to_pagenum(size) + 1
|
||||||
|
|
||||||
|
meta:set_string("inv_name", "main")
|
||||||
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
end
|
end
|
||||||
|
|
||||||
-- [me chest] Register node
|
-- [me chest] Register node
|
||||||
microexpansion.register_node("term", {
|
me.register_node("term", {
|
||||||
description = "ME Terminal",
|
description = "ME Terminal",
|
||||||
usedfor = "Can interact with storage cells in ME networks",
|
usedfor = "Can interact with storage cells in ME networks",
|
||||||
tiles = {
|
tiles = {
|
||||||
"chest_top",
|
"chest_top",
|
||||||
"chest_top",
|
"chest_top",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"chest_side",
|
"chest_side",
|
||||||
"chest_front",
|
"chest_front",
|
||||||
},
|
},
|
||||||
recipe = {
|
recipe = {
|
||||||
{ 1, {
|
{ 1, {
|
||||||
{"default:steel_ingot", "default:chest", "default:steel_ingot"},
|
{"default:steel_ingot", "default:chest", "default:steel_ingot"},
|
||||||
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
|
{"default:steel_ingot", "microexpansion:machine_casing", "default:steel_ingot"},
|
||||||
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
|
{"default:steel_ingot", "microexpansion:cable", "default:steel_ingot"},
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
is_ground_content = false,
|
is_ground_content = false,
|
||||||
groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 },
|
groups = { cracky = 1, me_connect = 1, tubedevice = 1, tubedevice_receiver = 1 },
|
||||||
paramtype = "light",
|
paramtype = "light",
|
||||||
paramtype2 = "facedir",
|
paramtype2 = "facedir",
|
||||||
me_update = update_chest,
|
me_update = update_chest,
|
||||||
on_construct = function(pos)
|
on_construct = function(pos)
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1))
|
meta:set_string("formspec", chest_formspec(pos, 1))
|
||||||
meta:set_string("inv_name", "none")
|
meta:set_string("inv_name", "none")
|
||||||
meta:set_int("page", 1)
|
meta:set_int("page", 1)
|
||||||
|
|
||||||
local own_inv = meta:get_inventory()
|
local own_inv = meta:get_inventory()
|
||||||
own_inv:set_size("src", 1)
|
own_inv:set_size("src", 1)
|
||||||
|
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
me.send_event(pos,"connect",{net=net})
|
me.send_event(pos,"connect",{net=net})
|
||||||
if net then
|
if net then
|
||||||
update_chest(pos)
|
update_chest(pos)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
after_destruct = function(pos)
|
after_destruct = function(pos)
|
||||||
me.send_event(pos,"disconnect")
|
me.send_event(pos,"disconnect")
|
||||||
|
end,
|
||||||
|
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||||
|
-- TODO: Check capacity, only allow if room
|
||||||
|
return stack:get_count()
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_put = function(pos, listname, _, stack)
|
on_metadata_inventory_put = function(pos, listname, _, stack)
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
local inv = net:get_inventory()
|
local inv = net:get_inventory()
|
||||||
me.insert_item(stack, inv, "main")
|
me.insert_item(stack, net, inv, "main")
|
||||||
|
net:set_storage_space(true)
|
||||||
end,
|
end,
|
||||||
on_metadata_inventory_take = function(pos, listname, _, stack)
|
on_metadata_inventory_take = function(pos, listname, _, stack)
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
local inv = net:get_inventory()
|
local inv = net:get_inventory()
|
||||||
inv:remove_item("main", stack)
|
me.remove_item(net, inv, "main", stack)
|
||||||
end,
|
end,
|
||||||
tube = {
|
tube = {
|
||||||
can_insert = function(pos, _, stack) --pos, node, stack, direction
|
can_insert = function(pos, _, stack) --pos, node, stack, direction
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
local inv = net:get_inventory()
|
local inv = net:get_inventory()
|
||||||
@ -144,13 +158,13 @@ microexpansion.register_node("term", {
|
|||||||
local slots, items = 0, 0
|
local slots, items = 0, 0
|
||||||
-- Get amount of items in drive
|
-- Get amount of items in drive
|
||||||
for i = 1, max_slots do
|
for i = 1, max_slots do
|
||||||
local dstack = inv:get_stack("main", i)
|
local dstack = inv:get_stack("main", i)
|
||||||
if dstack:get_name() ~= "" then
|
if dstack:get_name() ~= "" then
|
||||||
slots = slots + 1
|
slots = slots + 1
|
||||||
local num = dstack:get_count()
|
local num = dstack:get_count()
|
||||||
if num == 0 then num = 1 end
|
if num == 0 then num = 1 end
|
||||||
items = items + num
|
items = items + num
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
items = items + stack:get_count()
|
items = items + stack:get_count()
|
||||||
return max_items > items
|
return max_items > items
|
||||||
@ -158,101 +172,100 @@ microexpansion.register_node("term", {
|
|||||||
insert_object = function(pos, _, stack)
|
insert_object = function(pos, _, stack)
|
||||||
local net = me.get_connected_network(pos)
|
local net = me.get_connected_network(pos)
|
||||||
local inv = net:get_inventory()
|
local inv = net:get_inventory()
|
||||||
me.insert_item(stack, inv, "main")
|
local leftovers = me.insert_item(stack, net, inv, "main")
|
||||||
net:set_storage_space(true)
|
net:set_storage_space(true)
|
||||||
--TODO: leftover
|
return leftovers
|
||||||
return ItemStack()
|
|
||||||
end,
|
end,
|
||||||
connect_sides = {left=1, right=1, front=1, back=1, top=1, bottom=1},
|
connect_sides = {left=1, right=1, front=1, back=1, top=1, bottom=1},
|
||||||
},
|
},
|
||||||
after_place_node = pipeworks_enabled and pipeworks.after_place,
|
after_place_node = pipeworks_enabled and pipeworks.after_place,
|
||||||
after_dig_node = pipeworks_enabled and pipeworks.after_dig,
|
after_dig_node = pipeworks_enabled and pipeworks.after_dig,
|
||||||
on_receive_fields = function(pos, _, fields, sender)
|
on_receive_fields = function(pos, _, fields, sender)
|
||||||
local net,cp = me.get_connected_network(pos)
|
local net,cp = me.get_connected_network(pos)
|
||||||
if net then
|
if net then
|
||||||
if cp then
|
if cp then
|
||||||
microexpansion.log("network and ctrl_pos","info")
|
me.log("network and ctrl_pos","info")
|
||||||
else
|
else
|
||||||
microexpansion.log("network but no ctrl_pos","warning")
|
me.log("network but no ctrl_pos","warning")
|
||||||
end
|
end
|
||||||
else
|
else
|
||||||
if cp then
|
if cp then
|
||||||
microexpansion.log("no network but ctrl_pos","warning")
|
me.log("no network but ctrl_pos","warning")
|
||||||
else
|
else
|
||||||
microexpansion.log("no network and no ctrl_pos","info")
|
me.log("no network and no ctrl_pos","info")
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
local meta = minetest.get_meta(pos)
|
local meta = minetest.get_meta(pos)
|
||||||
local page = meta:get_int("page")
|
local page = meta:get_int("page")
|
||||||
local inv_name = meta:get_string("inv_name")
|
local inv_name = meta:get_string("inv_name")
|
||||||
local own_inv = meta:get_inventory()
|
local own_inv = meta:get_inventory()
|
||||||
local ctrl_inv
|
local ctrl_inv
|
||||||
if cp then
|
if cp then
|
||||||
ctrl_inv = net:get_inventory()
|
ctrl_inv = net:get_inventory()
|
||||||
else
|
else
|
||||||
microexpansion.log("no network connected","warning")
|
me.log("no network connected","warning")
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
local inv
|
local inv
|
||||||
if inv_name == "main" then
|
if inv_name == "main" then
|
||||||
inv = ctrl_inv
|
inv = ctrl_inv
|
||||||
assert(inv,"no control inv")
|
assert(inv,"no control inv")
|
||||||
else
|
else
|
||||||
inv = own_inv
|
inv = own_inv
|
||||||
assert(inv,"no own inv")
|
assert(inv,"no own inv")
|
||||||
end
|
end
|
||||||
local page_max = math.floor(inv:get_size(inv_name) / 32) + 1
|
local page_max = math.floor(inv:get_size(inv_name) / 32) + 1
|
||||||
if inv_name == "none" then
|
if inv_name == "none" then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
if fields.next then
|
if fields.next then
|
||||||
if page + 32 > inv:get_size(inv_name) then
|
if page + 32 > inv:get_size(inv_name) then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
meta:set_int("page", page + 32)
|
meta:set_int("page", page + 32)
|
||||||
meta:set_string("formspec", chest_formspec(pos, page + 32, inv_name, page_max))
|
meta:set_string("formspec", chest_formspec(pos, page + 32, inv_name, page_max))
|
||||||
elseif fields.prev then
|
elseif fields.prev then
|
||||||
if page - 32 < 1 then
|
if page - 32 < 1 then
|
||||||
return
|
return
|
||||||
end
|
end
|
||||||
meta:set_int("page", page - 32)
|
meta:set_int("page", page - 32)
|
||||||
meta:set_string("formspec", chest_formspec(pos, page - 32, inv_name, page_max))
|
meta:set_string("formspec", chest_formspec(pos, page - 32, inv_name, page_max))
|
||||||
elseif fields.search or fields.key_enter_field == "filter" then
|
elseif fields.search or fields.key_enter_field == "filter" then
|
||||||
own_inv:set_size("search", 0)
|
own_inv:set_size("search", 0)
|
||||||
if fields.filter == "" then
|
if fields.filter == "" then
|
||||||
meta:set_int("page", 1)
|
meta:set_int("page", 1)
|
||||||
meta:set_string("inv_name", "main")
|
meta:set_string("inv_name", "main")
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
else
|
else
|
||||||
local tab = {}
|
local tab = {}
|
||||||
for i = 1, ctrl_inv:get_size("main") do
|
for i = 1, ctrl_inv:get_size("main") do
|
||||||
local match = ctrl_inv:get_stack("main", i):get_name():find(fields.filter)
|
local match = ctrl_inv:get_stack("main", i):get_name():find(fields.filter)
|
||||||
if match then
|
if match then
|
||||||
tab[#tab + 1] = ctrl_inv:get_stack("main", i)
|
tab[#tab + 1] = ctrl_inv:get_stack("main", i)
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
own_inv:set_list("search", tab)
|
own_inv:set_list("search", tab)
|
||||||
meta:set_int("page", 1)
|
meta:set_int("page", 1)
|
||||||
meta:set_string("inv_name", "search")
|
meta:set_string("inv_name", "search")
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1, "search", page_max, fields.filter))
|
meta:set_string("formspec", chest_formspec(pos, 1, "search", page_max, fields.filter))
|
||||||
end
|
end
|
||||||
elseif fields.clear then
|
elseif fields.clear then
|
||||||
own_inv:set_size("search", 0)
|
own_inv:set_size("search", 0)
|
||||||
meta:set_int("page", 1)
|
meta:set_int("page", 1)
|
||||||
meta:set_string("inv_name", "main")
|
meta:set_string("inv_name", "main")
|
||||||
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max))
|
||||||
elseif fields.tochest then
|
elseif fields.tochest then
|
||||||
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
|
local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()})
|
||||||
net:set_storage_space(pinv:get_size("main"))
|
-- TODO: test and fix, net:set_storage_space(pinv:get_size("main"))
|
||||||
local space = net:get_item_capacity()
|
local space = net:get_item_capacity()
|
||||||
local contents = ctrl_inv:get_list("main") or {}
|
local contents = ctrl_inv:get_list("main") or {}
|
||||||
for _,s in pairs(contents) do
|
for _,s in pairs(contents) do
|
||||||
if not s:is_empty() then
|
if not s:is_empty() then
|
||||||
space = space - s:get_count()
|
space = space - s:get_count()
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
microexpansion.move_inv({ inv=pinv, name="main" }, { inv=ctrl_inv, name="main",huge=true }, space)
|
me.move_inv(net, { inv=pinv, name="main" }, { inv=ctrl_inv, name="main", huge=true }, space)
|
||||||
net:set_storage_space(true)
|
net:set_storage_space(true)
|
||||||
end
|
end
|
||||||
end,
|
end,
|
||||||
})
|
})
|
||||||
|
Loading…
Reference in New Issue
Block a user