--[[ TechPack Warehouse ================== Copyright (C) 2019 Joachim Stolberg LGPLv2.1+ See LICENSE.txt for more information common.lua ]]-- --- for lazy programmers local S = function(pos) if pos then return minetest.pos_to_string(pos) end end local P = minetest.string_to_pos local M = minetest.get_meta local STANDBY_TICKS = 4 local COUNTDOWN_TICKS = 2 local CYCLE_TIME = 2 local Cache = {} techpack_warehouse.Box = {} techpack_warehouse.Turn180 = {F="B", L="R", B="F", R="L", U="D", D="U"} local function formspec(self, pos, meta) return "size[10,9]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. "image_button[0,0;1,1;techpack_warehouse_arrow_inv.png;shift;;true;false;]".. "list[context;shift;1,0;7,1;]".. "image_button[9,0;1,1;techpack_warehouse_arrow_inv.png;shift;;true;false;]".. "image_button[8,0;1,1;".. self:get_state_button_image(meta) ..";state_button;]".. "image_button[0,1.4;1,1;techpack_warehouse_filter_inv.png;filter;;true;false;]".. "list[context;filter;1,1.4;8,1;]".. "image_button[9,1.4;1,1;techpack_warehouse_filter_inv.png;filter;;true;false;]".. "image_button[0,2.5;1,1;techpack_warehouse_inventory_inv.png;storage;;true;false;]".. "list[context;main;1,2.5;8,1;]".. "image_button[9,2.5;1,1;techpack_warehouse_inventory_inv.png;storage;;true;false;]".. "image_button[0,3.6;1,1;techpack_warehouse_input_inv.png;input;;true;false;]".. "list[context;input;1,3.6;8,1;]".. "image_button[9,3.6;1,1;techpack_warehouse_input_inv.png;input;;true;false;]".. "tooltip[shift;Pass-through storage for unconfigured items (turn on/off)]".. "tooltip[filter;Filter: To configure the 8 storages]".. "tooltip[storage;Storage: All items will be stored here]".. "tooltip[input;Input: Put items will be moved to the storage, if configured]".. "list[current_player;main;1,5.3;8,4;]".. "listring[context;shift]".. "listring[current_player;main]".. "listring[context;input]" end local function move_to_main(pos, index) local inv = M(pos):get_inventory() local main_stack = inv:get_stack("main", index) local inp_stack = inv:get_stack("input", index) if inp_stack:get_name() ~= "" then local stack = ItemStack(inp_stack:get_name()) stack:set_count(inp_stack:get_count() + main_stack:get_count()) inp_stack:clear() inv:set_stack("main", index, stack) inv:set_stack("input", index, inp_stack) end end local function move_to_player_inv(player_name, pos, index) local node_inv = M(pos):get_inventory() local main_stack = node_inv:get_stack("main", index) local player_inv = minetest.get_inventory({type="player", name=player_name}) local num = main_stack:get_count() if num > 99 then num = 99 end local leftover = player_inv:add_item("main", ItemStack(main_stack:get_name().." "..num)) main_stack:set_count(main_stack:get_count() - num + leftover:get_count()) node_inv:set_stack("main", index, main_stack) end function techpack_warehouse.tiles(background_img) return { -- up, down, right, left, back, front 'tubelib_pusher1.png^tubelib_addons3_node_frame4.png', 'tubelib_pusher1.png^tubelib_addons3_node_frame4.png', background_img..'^techpack_warehouse_box_side.png', background_img..'^techpack_warehouse_box_side.png', background_img..'^techpack_warehouse_box_back.png', background_img..'^techpack_warehouse_box_front.png', } end function techpack_warehouse.tiles_active(background_img) return { -- up, down, right, left, back, front { image = "tubelib_addons3_pusher_active.png", backface_culling = false, animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = 2.0, }, }, { image = "tubelib_addons3_pusher_active.png", backface_culling = false, animation = { type = "vertical_frames", aspect_w = 32, aspect_h = 32, length = 2.0, }, }, background_img..'^techpack_warehouse_box_side.png', background_img..'^techpack_warehouse_box_side.png', background_img..'^techpack_warehouse_box_back.png', background_img..'^techpack_warehouse_box_front.png', } end function techpack_warehouse.tiles_defect(background_img) return { -- up, down, right, left, back, front 'tubelib_pusher1.png^tubelib_addons3_node_frame4.png', 'tubelib_pusher1.png^tubelib_addons3_node_frame4.png', background_img..'^techpack_warehouse_box_side.png^tubelib_defect.png', background_img..'^techpack_warehouse_box_side.png^tubelib_defect.png', background_img..'^techpack_warehouse_box_back.png^tubelib_defect.png', background_img..'^techpack_warehouse_box_front.png^tubelib_defect.png', } end function techpack_warehouse.Box:new(attr) local o = { node_name = attr.node_name, description = attr.description, inv_size = attr.inv_size, background_img = attr.background_img, } o.State = tubelib.NodeStates:new({ node_name_passive = attr.node_name, node_name_active = attr.node_name.."_active", node_name_defect = attr.node_name.."_defect", infotext_name = attr.description, cycle_time = CYCLE_TIME, standby_ticks = STANDBY_TICKS, has_item_meter = true, aging_factor = 50, formspec_func = formspec, }) setmetatable(o, self) self.__index = self return o end function techpack_warehouse.numbers_to_shift(self, meta, item) -- check cache local number = meta:get_string("tubelib_number") local item_name = item:get_name() if not Cache[number] then local inv = meta:get_inventory() Cache[number] = {} for idx,items in ipairs(inv:get_list("filter")) do Cache[number][idx] = items:get_name() end end -- determine number to shift local num_items = item:get_count() local inv_size = meta:get_int("inv_size") local inv = meta:get_inventory() for idx, name in ipairs(Cache[number]) do if item_name == name then local stack_size = inv:get_stack("main", idx):get_count() if stack_size == self.inv_size then -- full? Cache[number][idx] = "" -- delete for searching elseif (stack_size + num_items) > self.inv_size then -- limit will be reached? inv:set_stack("main", idx, ItemStack({name = item_name, count = self.inv_size})) Cache[number][idx] = "" -- delete for searching -- search with the rest for further slots num_items = num_items - (self.inv_size - stack_size) else inv:set_stack("main", idx, ItemStack({name = item_name, count = stack_size + num_items})) return 0 end end end return num_items end function techpack_warehouse.allow_metadata_inventory_put(self, pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 elseif stack:get_wear() ~= 0 then return 0 elseif stack:get_stack_max() == 1 then return 0 end local inv = M(pos):get_inventory() local main_stack = inv:get_stack("main", index) local item_name = inv:get_stack("filter", index):get_name() if listname == "input" and item_name == stack:get_name() then return math.min(stack:get_count(), self.inv_size - main_stack:get_count()) elseif listname == "filter" and item_name == main_stack:get_name() then local number = M(pos):get_string("tubelib_number") Cache[number] = nil return 1 elseif listname == "shift" then return stack:get_count() end return 0 end function techpack_warehouse.on_metadata_inventory_put(pos, listname, index, stack, player) if listname == "input" then local number = M(pos):get_string("tubelib_number") Cache[number] = nil minetest.after(0.5, move_to_main, pos, index) end end function techpack_warehouse.allow_metadata_inventory_take(pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 end local inv = M(pos):get_inventory() local main_stack = inv:get_stack("main", index) local number = M(pos):get_string("tubelib_number") if listname == "main" then Cache[number] = nil minetest.after(0.1, move_to_player_inv, player:get_player_name(), pos, index) return 0 elseif listname == "filter" and main_stack:is_empty() then Cache[number] = nil return 1 elseif listname == "shift" then Cache[number] = nil return stack:get_count() end return 0 end function techpack_warehouse.allow_metadata_inventory_move(pos, listname, index, stack, player) return 0 end function techpack_warehouse.on_receive_fields(self, pos, formname, fields, player) if minetest.is_protected(pos, player:get_player_name()) then return end local number = M(pos):get_string("tubelib_number") Cache[number] = nil self.State:state_button_event(pos, fields) end function techpack_warehouse.after_place_node(self, pos, placer, itemstack) local meta = M(pos) local number = tubelib.add_node(pos, self.node_name) self.State:node_init(pos, number) meta:set_string("player_name", placer:get_player_name()) local inv = meta:get_inventory() inv:set_size('shift', 7) inv:set_size('filter', 8) inv:set_size('main', 8) inv:set_size('input', 8) end function techpack_warehouse.on_timer(self, pos, elapsed) if tubelib.data_not_corrupted(pos) then local meta = M(pos) local inv = meta:get_inventory() if not inv:is_empty("shift") then --local number = meta:get_string("tubelib_number") local player_name = meta:get_string("player_name") local offs = meta:get_int("offs") local push_dir = meta:get_string("push_dir") if push_dir == "" then push_dir = "L" end meta:set_int("offs", offs + 1) for i = 0,7 do local idx = ((i + offs) % 8) + 1 local stack = inv:get_stack("shift", idx) if stack:get_count() > 0 then if tubelib.push_items(pos, push_dir, stack, player_name) then -- The effort is needed here for the case the -- pusher pushes into its own chest. local num = stack:get_count() stack = inv:get_stack("shift", idx) stack:take_item(num) inv:set_stack("shift", idx, stack) self.State:keep_running(pos, meta, COUNTDOWN_TICKS) break else self.State:blocked(pos, meta) end end end else self.State:idle(pos, meta) end return self.State:is_active(meta) end return false end function techpack_warehouse.can_dig(self, pos) local inv = M(pos):get_inventory() return inv:is_empty("main") and inv:is_empty("shift") end function techpack_warehouse.on_dig_node(self, pos, node, digger) tubelib.remove_node(pos) if node.name == self.node_name then -- not for defect nodes self.State:on_dig_node(pos, node, digger) end end function techpack_warehouse.get_num_items(meta, index) index = index and tonumber(index) if index < 1 then index = 1 end if index > 8 then index = 8 end local inv = meta:get_inventory() return inv:get_stack("main", index):get_count() end