Mods in den Spieleordner reingeschoben. So richtig tief.
This commit is contained in:
parent
b4b6c08f4f
commit
f7bc25a670
1674 changed files with 56056 additions and 530 deletions
427
mods/drawers/lua/api.lua
Normal file
427
mods/drawers/lua/api.lua
Normal file
|
@ -0,0 +1,427 @@
|
|||
--[[
|
||||
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.
|
||||
]]
|
||||
|
||||
local S = minetest.get_translator('drawers')
|
||||
|
||||
drawers.node_box_simple = {
|
||||
{-0.5, -0.5, -0.4375, 0.5, 0.5, 0.5},
|
||||
{-0.5, -0.5, -0.5, -0.4375, 0.5, -0.4375},
|
||||
{0.4375, -0.5, -0.5, 0.5, 0.5, -0.4375},
|
||||
{-0.4375, 0.4375, -0.5, 0.4375, 0.5, -0.4375},
|
||||
{-0.4375, -0.5, -0.5, 0.4375, -0.4375, -0.4375},
|
||||
}
|
||||
|
||||
drawers.drawer_formspec = "size[9,7]" ..
|
||||
"list[context;upgrades;2,0.5;5,1;]" ..
|
||||
"list[current_player;main;0,3;9,4;]" ..
|
||||
"listring[context;upgrades]" ..
|
||||
"listring[current_player;main]" ..
|
||||
drawers.gui_bg ..
|
||||
drawers.gui_bg_img ..
|
||||
drawers.gui_slots ..
|
||||
drawers.get_upgrade_slots_bg(2, 0.5)
|
||||
|
||||
-- construct drawer
|
||||
function drawers.drawer_on_construct(pos)
|
||||
local node = core.get_node(pos)
|
||||
local ndef = core.registered_nodes[node.name]
|
||||
local drawerType = ndef.groups.drawer
|
||||
|
||||
local base_stack_max = core.nodedef_default.stack_max or 99
|
||||
local stack_max_factor = ndef.drawer_stack_max_factor or 24 -- 3x8
|
||||
stack_max_factor = math.floor(stack_max_factor / drawerType) -- drawerType => number of drawers in node
|
||||
|
||||
-- meta
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
local i = 1
|
||||
while i <= drawerType do
|
||||
local vid = i
|
||||
-- 1x1 drawers don't have numbers in the meta fields
|
||||
if drawerType == 1 then vid = "" end
|
||||
meta:set_string("name"..vid, "")
|
||||
meta:set_int("count"..vid, 0)
|
||||
meta:set_int("max_count"..vid, base_stack_max * stack_max_factor)
|
||||
meta:set_int("base_stack_max"..vid, base_stack_max)
|
||||
meta:set_string("entity_infotext"..vid, drawers.gen_info_text(S("Empty"), 0,
|
||||
stack_max_factor, base_stack_max))
|
||||
meta:set_int("stack_max_factor"..vid, stack_max_factor)
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
|
||||
-- spawn all visuals
|
||||
drawers.spawn_visuals(pos)
|
||||
|
||||
-- create drawer upgrade inventory
|
||||
meta:get_inventory():set_size("upgrades", 5)
|
||||
|
||||
-- set the formspec
|
||||
meta:set_string("formspec", drawers.drawer_formspec)
|
||||
end
|
||||
|
||||
-- destruct drawer
|
||||
function drawers.drawer_on_destruct(pos)
|
||||
drawers.remove_visuals(pos)
|
||||
|
||||
-- clean up visual cache
|
||||
if drawers.drawer_visuals[core.hash_node_position(pos)] then
|
||||
drawers.drawer_visuals[core.hash_node_position(pos)] = nil
|
||||
end
|
||||
end
|
||||
|
||||
-- drop all items
|
||||
function drawers.drawer_on_dig(pos, node, player)
|
||||
local drawerType = 1
|
||||
if core.registered_nodes[node.name] then
|
||||
drawerType = core.registered_nodes[node.name].groups.drawer
|
||||
end
|
||||
if core.is_protected(pos,player:get_player_name()) then
|
||||
core.record_protection_violation(pos,player:get_player_name())
|
||||
return 0
|
||||
end
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
local k = 1
|
||||
while k <= drawerType do
|
||||
-- don't add a number in meta fields for 1x1 drawers
|
||||
local vid = tostring(k)
|
||||
if drawerType == 1 then vid = "" end
|
||||
local count = meta:get_int("count"..vid)
|
||||
local name = meta:get_string("name"..vid)
|
||||
|
||||
-- drop the items
|
||||
local stack_max = ItemStack(name):get_stack_max()
|
||||
|
||||
local j = math.floor(count / stack_max) + 1
|
||||
local i = 1
|
||||
while i <= j do
|
||||
local rndpos = drawers.randomize_pos(pos)
|
||||
if i ~= j then
|
||||
core.add_item(rndpos, name .. " " .. stack_max)
|
||||
else
|
||||
core.add_item(rndpos, name .. " " .. count % stack_max)
|
||||
end
|
||||
i = i + 1
|
||||
end
|
||||
k = k + 1
|
||||
end
|
||||
|
||||
-- drop all drawer upgrades
|
||||
local upgrades = meta:get_inventory():get_list("upgrades")
|
||||
if upgrades then
|
||||
for _,itemStack in pairs(upgrades) do
|
||||
if itemStack:get_count() > 0 then
|
||||
local rndpos = drawers.randomize_pos(pos)
|
||||
core.add_item(rndpos, itemStack:get_name())
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- remove node
|
||||
core.node_dig(pos, node, player)
|
||||
end
|
||||
|
||||
function drawers.drawer_allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if core.is_protected(pos,player:get_player_name()) then
|
||||
core.record_protection_violation(pos,player:get_player_name())
|
||||
return 0
|
||||
end
|
||||
if listname ~= "upgrades" then
|
||||
return 0
|
||||
end
|
||||
if stack:get_count() > 1 then
|
||||
return 0
|
||||
end
|
||||
if core.get_item_group(stack:get_name(), "drawer_upgrade") < 1 then
|
||||
return 0
|
||||
end
|
||||
return 1
|
||||
end
|
||||
|
||||
function drawers.add_drawer_upgrade(pos, listname, index, stack, player)
|
||||
-- only do anything if adding to upgrades
|
||||
if listname ~= "upgrades" then return end
|
||||
|
||||
drawers.update_drawer_upgrades(pos)
|
||||
end
|
||||
|
||||
function drawers.remove_drawer_upgrade(pos, listname, index, stack, player)
|
||||
-- only do anything if adding to upgrades
|
||||
if listname ~= "upgrades" then return end
|
||||
|
||||
drawers.update_drawer_upgrades(pos)
|
||||
end
|
||||
|
||||
--[[
|
||||
Inserts an incoming stack into a specific slot of a drawer.
|
||||
]]
|
||||
function drawers.drawer_insert_object(pos, stack, visualid)
|
||||
local visual = drawers.get_visual(pos, visualid)
|
||||
if not visual then
|
||||
return stack
|
||||
end
|
||||
|
||||
return visual:try_insert_stack(stack, true)
|
||||
end
|
||||
|
||||
--[[
|
||||
Inserts an incoming stack into a drawer and uses all slots.
|
||||
]]
|
||||
function drawers.drawer_insert_object_from_tube(pos, node, stack, direction)
|
||||
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||
if not drawer_visuals then
|
||||
return stack
|
||||
end
|
||||
|
||||
-- first try to insert in the correct slot (if there are already items)
|
||||
local leftover = stack
|
||||
for _, visual in pairs(drawer_visuals) do
|
||||
if visual.itemName == stack:get_name() then
|
||||
leftover = visual:try_insert_stack(leftover, true)
|
||||
end
|
||||
end
|
||||
|
||||
-- if there's still something left, also use other slots
|
||||
if leftover:get_count() > 0 then
|
||||
for _, visual in pairs(drawer_visuals) do
|
||||
leftover = visual:try_insert_stack(leftover, true)
|
||||
end
|
||||
end
|
||||
return leftover
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns how much (count) of a stack can be inserted to a drawer slot.
|
||||
]]
|
||||
function drawers.drawer_can_insert_stack(pos, stack, visualid)
|
||||
local visual = drawers.get_visual(pos, visualid)
|
||||
if not visual then
|
||||
return 0
|
||||
end
|
||||
|
||||
return visual:can_insert_stack(stack)
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns whether a stack can be (partially) inserted to any slot of a drawer.
|
||||
]]
|
||||
function drawers.drawer_can_insert_stack_from_tube(pos, node, stack, direction)
|
||||
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||
if not drawer_visuals then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, visual in pairs(drawer_visuals) do
|
||||
if visual:can_insert_stack(stack) > 0 then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
function drawers.drawer_take_item(pos, itemstack)
|
||||
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||
|
||||
if not drawer_visuals then
|
||||
return ItemStack("")
|
||||
end
|
||||
|
||||
-- check for max count
|
||||
if itemstack:get_count() > itemstack:get_stack_max() then
|
||||
itemstack:set_count(itemstack:get_stack_max())
|
||||
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
|
||||
|
||||
--[[
|
||||
Returns the content of a drawer slot.
|
||||
]]
|
||||
function drawers.drawer_get_content(pos, visualid)
|
||||
local drawer_meta = core.get_meta(pos)
|
||||
|
||||
return {
|
||||
name = drawer_meta:get_string("name" .. visualid),
|
||||
count = drawer_meta:get_int("count" .. visualid),
|
||||
maxCount = drawer_meta:get_int("max_count" .. visualid)
|
||||
}
|
||||
end
|
||||
|
||||
function drawers.register_drawer(name, def)
|
||||
def.description = def.description or S("Wooden")
|
||||
def.drawtype = "nodebox"
|
||||
def.node_box = {type = "fixed", fixed = drawers.node_box_simple}
|
||||
def.collision_box = {type = "regular"}
|
||||
def.selection_box = {type = "fixed", fixed = drawers.node_box_simple}
|
||||
def.paramtype = "light"
|
||||
def.paramtype2 = "facedir"
|
||||
def.legacy_facedir_simple = true
|
||||
def.groups = def.groups or {}
|
||||
def.drawer_stack_max_factor = def.drawer_stack_max_factor or 24
|
||||
|
||||
-- events
|
||||
def.on_construct = drawers.drawer_on_construct
|
||||
def.on_destruct = drawers.drawer_on_destruct
|
||||
def.on_dig = drawers.drawer_on_dig
|
||||
def.allow_metadata_inventory_put = drawers.drawer_allow_metadata_inventory_put
|
||||
def.allow_metadata_inventory_take = drawers.drawer_allow_metadata_inventory_put
|
||||
def.on_metadata_inventory_put = drawers.add_drawer_upgrade
|
||||
def.on_metadata_inventory_take = drawers.remove_drawer_upgrade
|
||||
|
||||
if minetest.get_modpath("screwdriver") and screwdriver then
|
||||
def.on_rotate = def.on_rotate or screwdriver.disallow
|
||||
end
|
||||
|
||||
if minetest.get_modpath("pipeworks") and pipeworks then
|
||||
def.groups.tubedevice = 1
|
||||
def.groups.tubedevice_receiver = 1
|
||||
def.tube = def.tube or {}
|
||||
def.tube.insert_object = def.tube.insert_object or
|
||||
drawers.drawer_insert_object_from_tube
|
||||
def.tube.can_insert = def.tube.can_insert or
|
||||
drawers.drawer_can_insert_stack_from_tube
|
||||
|
||||
def.tube.connect_sides = {left = 1, right = 1, back = 1, top = 1,
|
||||
bottom = 1}
|
||||
def.after_place_node = pipeworks.after_place
|
||||
def.after_dig_node = pipeworks.after_dig
|
||||
end
|
||||
|
||||
local has_mesecons_mvps = minetest.get_modpath("mesecons_mvps")
|
||||
|
||||
if drawers.enable_1x1 then
|
||||
-- normal drawer 1x1 = 1
|
||||
local def1 = table.copy(def)
|
||||
def1.description = S("@1 Drawer", def.description)
|
||||
def1.tiles = def.tiles or def.tiles1
|
||||
def1.tiles1 = nil
|
||||
def1.tiles2 = nil
|
||||
def1.tiles4 = nil
|
||||
def1.groups.drawer = 1
|
||||
core.register_node(name .. "1", def1)
|
||||
core.register_alias(name, name .. "1") -- 1x1 drawer is the default one
|
||||
if has_mesecons_mvps then
|
||||
-- don't let drawers be moved by pistons, visual glitches and
|
||||
-- possible duplication bugs occur otherwise
|
||||
mesecon.register_mvps_stopper(name .. "1")
|
||||
end
|
||||
end
|
||||
|
||||
if drawers.enable_1x2 then
|
||||
-- 1x2 = 2
|
||||
local def2 = table.copy(def)
|
||||
def2.description = S("@1 Drawers (1x2)", def.description)
|
||||
def2.tiles = def.tiles2
|
||||
def2.tiles1 = nil
|
||||
def2.tiles2 = nil
|
||||
def2.tiles4 = nil
|
||||
def2.groups.drawer = 2
|
||||
core.register_node(name .. "2", def2)
|
||||
if has_mesecons_mvps then
|
||||
mesecon.register_mvps_stopper(name .. "2")
|
||||
end
|
||||
end
|
||||
|
||||
if drawers.enable_2x2 then
|
||||
-- 2x2 = 4
|
||||
local def4 = table.copy(def)
|
||||
def4.description = S("@1 Drawers (2x2)", def.description)
|
||||
def4.tiles = def.tiles4
|
||||
def4.tiles1 = nil
|
||||
def4.tiles2 = nil
|
||||
def4.tiles4 = nil
|
||||
def4.groups.drawer = 4
|
||||
core.register_node(name .. "4", def4)
|
||||
if has_mesecons_mvps then
|
||||
mesecon.register_mvps_stopper(name .. "4")
|
||||
end
|
||||
end
|
||||
|
||||
if (not def.no_craft) and def.material then
|
||||
if drawers.enable_1x1 then
|
||||
core.register_craft({
|
||||
output = name .. "1",
|
||||
recipe = {
|
||||
{def.material, def.material, def.material},
|
||||
{ "", drawers.CHEST_ITEMSTRING, "" },
|
||||
{def.material, def.material, def.material}
|
||||
}
|
||||
})
|
||||
end
|
||||
if drawers.enable_1x2 then
|
||||
core.register_craft({
|
||||
output = name .. "2 2",
|
||||
recipe = {
|
||||
{def.material, drawers.CHEST_ITEMSTRING, def.material},
|
||||
{def.material, def.material, def.material},
|
||||
{def.material, drawers.CHEST_ITEMSTRING, def.material}
|
||||
}
|
||||
})
|
||||
end
|
||||
if drawers.enable_2x2 then
|
||||
core.register_craft({
|
||||
output = name .. "4 4",
|
||||
recipe = {
|
||||
{drawers.CHEST_ITEMSTRING, def.material, drawers.CHEST_ITEMSTRING},
|
||||
{ def.material, def.material, def.material },
|
||||
{drawers.CHEST_ITEMSTRING, def.material, drawers.CHEST_ITEMSTRING}
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawers.register_drawer_upgrade(name, def)
|
||||
def.groups = def.groups or {}
|
||||
def.groups.drawer_upgrade = def.groups.drawer_upgrade or 100
|
||||
def.inventory_image = def.inventory_image or "drawers_upgrade_template.png"
|
||||
def.stack_max = 1
|
||||
|
||||
local recipe_item = def.recipe_item or "air"
|
||||
def.recipe_item = nil
|
||||
|
||||
core.register_craftitem(name, def)
|
||||
|
||||
if not def.no_craft then
|
||||
core.register_craft({
|
||||
output = name,
|
||||
recipe = {
|
||||
{recipe_item, "group:stick", recipe_item},
|
||||
{"group:stick", "drawers:upgrade_template", "group:stick"},
|
||||
{recipe_item, "group:stick", recipe_item}
|
||||
}
|
||||
})
|
||||
end
|
||||
end
|
||||
|
545
mods/drawers/lua/controller.lua
Normal file
545
mods/drawers/lua/controller.lua
Normal file
|
@ -0,0 +1,545 @@
|
|||
--[[
|
||||
Minetest Mod Storage Drawers - A Mod adding storage drawers
|
||||
|
||||
Copyright (C) 2017-2020 Linus Jahn <lnj@kaidan.im>
|
||||
Copyright (C) 2018 isaiah658
|
||||
|
||||
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.
|
||||
]]--
|
||||
|
||||
--[[ The gist of how the drawers mod stores data is that there are entities
|
||||
and the drawer node itself. The entities are needed to allow having multiple
|
||||
drawers in one node. The entities and node each store metadata about the item
|
||||
counts and such. It is necessary to change both at once otherwise in some cases
|
||||
the entity values are used and in other cases the node metadata is used.
|
||||
|
||||
The gist of how the controller works is this. The drawer controller scans the
|
||||
adjacent tiles and puts the item names and other info such as coordinates and
|
||||
the visualid of the entity in a table. That table is saved in the controllers
|
||||
metadata. The table is used to help prevent needing to scan all the drawers to
|
||||
deposit an item in certain situations. The table is only updated on an as needed
|
||||
basis, not by a specific time/interval. Controllers that have no items will not
|
||||
continue scanning drawers. ]]--
|
||||
|
||||
local S = minetest.get_translator('drawers')
|
||||
|
||||
local default_loaded = core.get_modpath("default") and default
|
||||
local mcl_loaded = core.get_modpath("mcl_core") and mcl_core
|
||||
local pipeworks_loaded = core.get_modpath("pipeworks") and pipeworks
|
||||
local digilines_loaded = core.get_modpath("digilines") and digilines
|
||||
local techage_loaded = core.get_modpath("techage") and techage
|
||||
|
||||
local function controller_formspec(pos)
|
||||
local formspec =
|
||||
"size[8,8.5]"..
|
||||
drawers.gui_bg..
|
||||
drawers.gui_bg_img..
|
||||
drawers.gui_slots..
|
||||
"label[0,0;" .. S("Drawer Controller") .. "]" ..
|
||||
"list[current_name;src;3.5,1.75;1,1;]"..
|
||||
"list[current_player;main;0,4.25;8,1;]"..
|
||||
"list[current_player;main;0,5.5;8,3;8]"..
|
||||
"listring[current_player;main]"..
|
||||
"listring[current_name;src]"..
|
||||
"listring[current_player;main]"
|
||||
|
||||
if digilines_loaded and pipeworks_loaded then
|
||||
formspec = formspec .. "field[1,3.5;4,1;digilineChannel;" .. S("Digiline Channel") .. ";${digilineChannel}]"
|
||||
formspec = formspec .. "button_exit[5,3.2;2,1;saveChannel;" .. S("Save") .. "]"
|
||||
end
|
||||
|
||||
return formspec
|
||||
end
|
||||
|
||||
local function is_valid_drawer_index_slot(net_index, item_name)
|
||||
return net_index and
|
||||
net_index[item_name] and
|
||||
net_index[item_name].drawer_pos and
|
||||
net_index[item_name].drawer_pos.x and
|
||||
net_index[item_name].drawer_pos.y and
|
||||
net_index[item_name].drawer_pos.z and
|
||||
net_index[item_name].visualid
|
||||
end
|
||||
|
||||
local function controller_index_slot(pos, visualid)
|
||||
return {
|
||||
drawer_pos = pos,
|
||||
visualid = visualid
|
||||
}
|
||||
end
|
||||
|
||||
local function compare_pos(pos1, pos2)
|
||||
return pos1.x == pos2.x and pos1.y == pos2.y and pos1.z == pos2.z
|
||||
end
|
||||
|
||||
local function contains_pos(list, p)
|
||||
for _,v in ipairs(list) do
|
||||
if compare_pos(v, p) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
return false
|
||||
end
|
||||
|
||||
-- iterator for iterating from 1 -> to
|
||||
local function range(to)
|
||||
local i = 0
|
||||
return function()
|
||||
if i == to then
|
||||
return nil
|
||||
end
|
||||
i = i + 1
|
||||
return i, i
|
||||
end
|
||||
end
|
||||
|
||||
local function pos_in_range(pos1, pos2)
|
||||
local diff = {
|
||||
pos1.x - pos2.x,
|
||||
pos1.y - pos2.y,
|
||||
pos1.z - pos2.z
|
||||
}
|
||||
for _,v in ipairs(diff) do
|
||||
if v < 0 then
|
||||
v = v * -1
|
||||
end
|
||||
if v > drawers.CONTROLLER_RANGE then
|
||||
return false
|
||||
end
|
||||
end
|
||||
return true
|
||||
end
|
||||
|
||||
local function add_drawer_to_inventory(controllerInventory, pos)
|
||||
-- the number of slots is saved as drawer group
|
||||
local slots = core.get_item_group(core.get_node(pos).name, "drawer")
|
||||
if not slots then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = core.get_meta(pos)
|
||||
if not meta then
|
||||
return
|
||||
end
|
||||
|
||||
local i = 1
|
||||
while i <= slots do
|
||||
-- nothing is appended in case the drawer has only one slot
|
||||
local slot_id = ""
|
||||
if slots ~= 1 then
|
||||
slot_id = tostring(i)
|
||||
end
|
||||
|
||||
local item_id = meta:get_string("name" .. slot_id)
|
||||
local drawer_meta_entity_infotext = meta:get_string("entity_infotext" .. slot_id)
|
||||
|
||||
if item_id == "" and not controllerInventory["empty"] then
|
||||
controllerInventory["empty"] = controller_index_slot(pos, slot_id)
|
||||
elseif item_id ~= "" then
|
||||
-- If we already indexed this item previously, check which drawer
|
||||
-- has the most space and have that one be the one indexed
|
||||
if controllerInventory[item_id] then
|
||||
local content = drawers.drawer_get_content(controllerInventory[item_id].drawer_pos, controllerInventory[item_id].visualid)
|
||||
local new_content = drawers.drawer_get_content(pos, slot_id)
|
||||
|
||||
-- If the already indexed drawer has less space, we override the
|
||||
-- table index for that item with the new drawer
|
||||
if (new_content.maxCount - new_content.count) > (content.maxCount - content.count) then
|
||||
controllerInventory[item_id] = controller_index_slot(pos, slot_id)
|
||||
end
|
||||
else
|
||||
controllerInventory[item_id] = controller_index_slot(pos, slot_id)
|
||||
end
|
||||
end
|
||||
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
local function find_connected_drawers(controller_pos, pos, foundPositions)
|
||||
foundPositions = foundPositions or {}
|
||||
pos = pos or controller_pos
|
||||
|
||||
local newPositions = core.find_nodes_in_area(
|
||||
{x = pos.x - 1, y = pos.y - 1, z = pos.z - 1},
|
||||
{x = pos.x + 1, y = pos.y + 1, z = pos.z + 1},
|
||||
{"group:drawer", "group:drawer_connector"}
|
||||
)
|
||||
|
||||
for _,p in ipairs(newPositions) do
|
||||
-- check that this node hasn't been scanned yet
|
||||
if not compare_pos(pos, p) and not contains_pos(foundPositions, p)
|
||||
and pos_in_range(controller_pos, pos) then
|
||||
-- add new position
|
||||
table.insert(foundPositions, p)
|
||||
-- search for other drawers from the new pos
|
||||
find_connected_drawers(controller_pos, p, foundPositions)
|
||||
end
|
||||
end
|
||||
|
||||
return foundPositions
|
||||
end
|
||||
|
||||
local function index_drawers(pos)
|
||||
--[[
|
||||
The pos parameter is the controllers position
|
||||
|
||||
We store the item name as a string key and the value is a table with position x,
|
||||
position y, position z, and visualid. Those are all strings as well with the
|
||||
values assigned to them that way we don't need to worry about the ordering of
|
||||
the table. The count and max count are not stored as those values have a high
|
||||
potential of being outdated quickly. It's better to grab the values from the
|
||||
drawer when needed so you know you are working with accurate numbers.
|
||||
]]
|
||||
|
||||
local controllerInventory = {}
|
||||
for _,drawerPos in ipairs(find_connected_drawers(pos)) do
|
||||
add_drawer_to_inventory(controllerInventory, drawerPos)
|
||||
end
|
||||
|
||||
return controllerInventory
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns a table of all stored itemstrings in the drawer network with their
|
||||
drawer position and visualid.
|
||||
|
||||
It uses the cached data, if possible, but if the itemstring is not contained
|
||||
the network is reindexed.
|
||||
]]
|
||||
local function controller_get_drawer_index(pos, itemstring)
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
-- If the index has not been created, the item isn't in the index, the
|
||||
-- item in the drawer is no longer the same item in the index, or the item
|
||||
-- is in the index but it's full, run the index_drawers function.
|
||||
local drawer_net_index = core.deserialize(meta:get_string("drawers_table_index"))
|
||||
|
||||
-- If the index has not been created
|
||||
-- If the item isn't in the index (or the index is corrupted)
|
||||
if not is_valid_drawer_index_slot(drawer_net_index, itemstring) then
|
||||
drawer_net_index = index_drawers(pos)
|
||||
meta:set_string("drawers_table_index", core.serialize(drawer_net_index))
|
||||
|
||||
-- There is a valid entry in the index: check that the entry is still up-to-date
|
||||
else
|
||||
local content = drawers.drawer_get_content(
|
||||
drawer_net_index[itemstring].drawer_pos,
|
||||
drawer_net_index[itemstring].visualid)
|
||||
|
||||
if content.name ~= itemstring or content.count >= content.maxCount then
|
||||
drawer_net_index = index_drawers(pos)
|
||||
meta:set_string("drawers_table_index", core.serialize(drawer_net_index))
|
||||
end
|
||||
end
|
||||
|
||||
return drawer_net_index
|
||||
end
|
||||
|
||||
local function controller_insert_to_drawers(pos, stack)
|
||||
-- Inizialize metadata
|
||||
local meta = core.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
local drawer_net_index = controller_get_drawer_index(pos, stack:get_name())
|
||||
|
||||
-- We check if there is a drawer with the item and it isn't full. We will
|
||||
-- put the items we can into it.
|
||||
if drawer_net_index[stack:get_name()] then
|
||||
local drawer_pos = drawer_net_index[stack:get_name()]["drawer_pos"]
|
||||
local visualid = drawer_net_index[stack:get_name()]["visualid"]
|
||||
local content = drawers.drawer_get_content(drawer_pos, visualid)
|
||||
|
||||
-- If the the item in the drawer is the same as the one we are trying to
|
||||
-- store, the drawer is not full, and the drawer entity is loaded, we
|
||||
-- will put the items in the drawer
|
||||
if content.name == stack:get_name() and
|
||||
content.count < content.maxCount and
|
||||
drawers.drawer_visuals[core.hash_node_position(drawer_pos)] then
|
||||
return drawers.drawer_insert_object(drawer_pos, stack, visualid)
|
||||
end
|
||||
elseif drawer_net_index["empty"] then
|
||||
local drawer_pos = drawer_net_index["empty"]["drawer_pos"]
|
||||
local visualid = drawer_net_index["empty"]["visualid"]
|
||||
local content = drawers.drawer_get_content(drawer_pos, visualid)
|
||||
|
||||
-- If the drawer is still empty and the drawer entity is loaded, we will
|
||||
-- put the items in the drawer
|
||||
if content.name == "" and drawers.drawer_visuals[core.hash_node_position(drawer_pos)] then
|
||||
local leftover = drawers.drawer_insert_object(drawer_pos, stack, visualid)
|
||||
|
||||
-- Add the item to the drawers table index and set the empty one to nil
|
||||
drawer_net_index["empty"] = nil
|
||||
drawer_net_index[stack:get_name()] = controller_index_slot(drawer_pos, visualid)
|
||||
|
||||
-- Set the controller metadata
|
||||
meta:set_string("drawers_table_index", core.serialize(drawer_net_index))
|
||||
|
||||
return leftover
|
||||
end
|
||||
end
|
||||
|
||||
return stack
|
||||
end
|
||||
|
||||
local function controller_can_dig(pos, player)
|
||||
local meta = core.get_meta(pos);
|
||||
local inv = meta:get_inventory()
|
||||
return inv:is_empty("src")
|
||||
end
|
||||
|
||||
local function controller_on_construct(pos)
|
||||
local meta = core.get_meta(pos)
|
||||
meta:set_string("drawers_table_index", "")
|
||||
meta:set_string("formspec", controller_formspec(pos))
|
||||
|
||||
meta:get_inventory():set_size("src", 1)
|
||||
end
|
||||
|
||||
local function controller_on_blast(pos)
|
||||
local drops = {}
|
||||
default.get_inventory_drops(pos, "src", drops)
|
||||
drops[#drops+1] = "drawers:controller"
|
||||
core.remove_node(pos)
|
||||
return drops
|
||||
end
|
||||
|
||||
local function controller_allow_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if (player and core.is_protected(pos, player:get_player_name())) or listname ~= "src" then
|
||||
return 0
|
||||
end
|
||||
|
||||
local drawer_net_index = controller_get_drawer_index(pos, stack:get_name())
|
||||
|
||||
if drawer_net_index[stack:get_name()] then
|
||||
local drawer = drawer_net_index[stack:get_name()]
|
||||
|
||||
if drawers.drawer_get_content(drawer.drawer_pos, drawer.visualid).name == stack:get_name() then
|
||||
return drawers.drawer_can_insert_stack(drawer.drawer_pos, stack, drawer["visualid"])
|
||||
end
|
||||
end
|
||||
|
||||
if drawer_net_index["empty"] then
|
||||
local drawer = drawer_net_index["empty"]
|
||||
|
||||
if drawers.drawer_get_content(drawer.drawer_pos, drawer.visualid).name == "" then
|
||||
return drawers.drawer_can_insert_stack(drawer.drawer_pos, stack, drawer.visualid)
|
||||
end
|
||||
end
|
||||
|
||||
return 0
|
||||
end
|
||||
|
||||
local function controller_allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
local meta = core.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
local stack = inv:get_stack(from_list, from_index)
|
||||
return controller_allow_metadata_inventory_put(pos, to_list, to_index, stack, player)
|
||||
end
|
||||
|
||||
local function controller_allow_metadata_inventory_take(pos, listname, index, stack, player)
|
||||
if core.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
local function controller_on_metadata_inventory_put(pos, listname, index, stack, player)
|
||||
if listname ~= "src" then
|
||||
return
|
||||
end
|
||||
|
||||
local inv = core.get_meta(pos):get_inventory()
|
||||
|
||||
local complete_stack = inv:get_stack("src", 1)
|
||||
local leftover = controller_insert_to_drawers(pos, complete_stack)
|
||||
inv:set_stack("src", 1, leftover)
|
||||
end
|
||||
|
||||
local function controller_on_digiline_receive(pos, _, channel, msg)
|
||||
local meta = core.get_meta(pos)
|
||||
|
||||
if channel ~= meta:get_string("digilineChannel") then
|
||||
return
|
||||
end
|
||||
|
||||
local item = ItemStack(msg)
|
||||
local drawers_index = controller_get_drawer_index(pos, item:get_name())
|
||||
|
||||
if not drawers_index[item:get_name()] then
|
||||
-- we can't do anything: the requested item doesn't exist
|
||||
return
|
||||
end
|
||||
|
||||
local taken_stack = drawers.drawer_take_item(
|
||||
drawers_index[item:get_name()]["drawer_pos"], item)
|
||||
local dir = core.facedir_to_dir(core.get_node(pos).param2)
|
||||
|
||||
-- prevent crash if taken_stack ended up with a nil value
|
||||
if taken_stack then
|
||||
pipeworks.tube_inject_item(pos, pos, dir, taken_stack:to_string())
|
||||
end
|
||||
end
|
||||
|
||||
local function controller_on_receive_fields(pos, formname, fields, sender)
|
||||
if core.is_protected(pos, sender:get_player_name()) then
|
||||
return
|
||||
end
|
||||
local meta = core.get_meta(pos)
|
||||
if fields.saveChannel then
|
||||
meta:set_string("digilineChannel", fields.digilineChannel)
|
||||
end
|
||||
end
|
||||
|
||||
-- Registers the drawer controller
|
||||
local function register_controller()
|
||||
-- Set the controller definition using a table to allow for pipeworks and
|
||||
-- potentially other mod support
|
||||
local def = {}
|
||||
|
||||
def.description = S("Drawer Controller")
|
||||
def.drawtype = "nodebox"
|
||||
def.node_box = { type = "fixed", fixed = drawers.node_box_simple }
|
||||
def.collision_box = { type = "regular" }
|
||||
def.selection_box = { type = "regular" }
|
||||
def.paramtype = "light"
|
||||
def.paramtype2 = "facedir"
|
||||
def.legacy_facedir_simple = true
|
||||
|
||||
-- add pipe connectors, if pipeworks is enabled
|
||||
if pipeworks_loaded then
|
||||
def.tiles = {
|
||||
"drawers_controller_top.png^pipeworks_tube_connection_metallic.png",
|
||||
"drawers_controller_top.png^pipeworks_tube_connection_metallic.png",
|
||||
"drawers_controller_side.png^pipeworks_tube_connection_metallic.png",
|
||||
"drawers_controller_side.png^pipeworks_tube_connection_metallic.png",
|
||||
"drawers_controller_top.png^pipeworks_tube_connection_metallic.png",
|
||||
"drawers_controller_front.png"
|
||||
}
|
||||
else
|
||||
def.tiles = {
|
||||
"drawers_controller_top.png",
|
||||
"drawers_controller_top.png",
|
||||
"drawers_controller_side.png",
|
||||
"drawers_controller_side.png",
|
||||
"drawers_controller_top.png",
|
||||
"drawers_controller_front.png"
|
||||
}
|
||||
end
|
||||
|
||||
-- MCL2 requires a few different groups and parameters that MTG does not
|
||||
if mcl_loaded then
|
||||
def.groups = {
|
||||
pickaxey = 1, stone = 1, building_block = 1, material_stone = 1
|
||||
}
|
||||
def._mcl_blast_resistance = 30
|
||||
def._mcl_hardness = 1.5
|
||||
else
|
||||
def.groups = {
|
||||
cracky = 3, level = 2
|
||||
}
|
||||
end
|
||||
|
||||
def.can_dig = controller_can_dig
|
||||
def.on_construct = controller_on_construct
|
||||
def.on_blast = controller_on_blast
|
||||
def.on_receive_fields = controller_on_receive_fields
|
||||
def.on_metadata_inventory_put = controller_on_metadata_inventory_put
|
||||
|
||||
def.allow_metadata_inventory_put = controller_allow_metadata_inventory_put
|
||||
def.allow_metadata_inventory_move = controller_allow_metadata_inventory_move
|
||||
def.allow_metadata_inventory_take = controller_allow_metadata_inventory_take
|
||||
|
||||
if pipeworks_loaded then
|
||||
def.groups.tubedevice = 1
|
||||
def.groups.tubedevice_receiver = 1
|
||||
|
||||
def.tube = {}
|
||||
def.tube.insert_object = function(pos, node, stack, tubedir)
|
||||
return controller_insert_to_drawers(pos, stack)
|
||||
end
|
||||
|
||||
def.tube.can_insert = function(pos, node, stack, tubedir)
|
||||
return controller_allow_metadata_inventory_put(pos, "src", nil, stack, nil) > 0
|
||||
end
|
||||
|
||||
def.tube.connect_sides = {
|
||||
left = 1, right = 1, back = 1, top = 1, bottom = 1
|
||||
}
|
||||
|
||||
def.after_place_node = pipeworks.after_place
|
||||
def.after_dig_node = pipeworks.after_dig
|
||||
end
|
||||
|
||||
if digilines_loaded and pipeworks_loaded then
|
||||
def.digiline = {
|
||||
receptor = {},
|
||||
effector = {
|
||||
action = controller_on_digiline_receive
|
||||
},
|
||||
}
|
||||
end
|
||||
|
||||
core.register_node("drawers:controller", def)
|
||||
|
||||
if techage_loaded then
|
||||
techage.register_node({"drawers:controller"}, {
|
||||
on_push_item = function(pos, in_dir, stack)
|
||||
return controller_insert_to_drawers(pos, stack)
|
||||
end
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- register drawer controller
|
||||
register_controller()
|
||||
|
||||
if default_loaded then
|
||||
core.register_craft({
|
||||
output = 'drawers:controller',
|
||||
recipe = {
|
||||
{'default:steel_ingot', 'default:diamond', 'default:steel_ingot'},
|
||||
{'default:tin_ingot', 'group:drawer', 'default:copper_ingot'},
|
||||
{'default:steel_ingot', 'default:diamond', 'default:steel_ingot'},
|
||||
}
|
||||
})
|
||||
elseif mcl_loaded then
|
||||
core.register_craft({
|
||||
output = 'drawers:controller',
|
||||
recipe = {
|
||||
{'mcl_core:iron_ingot', 'mcl_core:diamond', 'mcl_core:iron_ingot'},
|
||||
{'mcl_core:gold_ingot', 'group:drawer', 'mcl_core:gold_ingot'},
|
||||
{'mcl_core:iron_ingot', 'mcl_core:diamond', 'mcl_core:iron_ingot'},
|
||||
}
|
||||
})
|
||||
else
|
||||
-- Because the rest of the drawers mod doesn't have a hard depend on
|
||||
-- default, I changed the recipe to have an alternative
|
||||
core.register_craft({
|
||||
output = 'drawers:controller',
|
||||
recipe = {
|
||||
{'group:stone', 'group:stone', 'group:stone'},
|
||||
{'group:stone', 'group:drawer', 'group:stone'},
|
||||
{'group:stone', 'group:stone', 'group:stone'},
|
||||
}
|
||||
})
|
||||
end
|
||||
|
286
mods/drawers/lua/helpers.lua
Normal file
286
mods/drawers/lua/helpers.lua
Normal file
|
@ -0,0 +1,286 @@
|
|||
--[[
|
||||
Minetest Mod Storage Drawers - A Mod adding storage drawers
|
||||
|
||||
Copyright (C) 2017-2019 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.
|
||||
]]
|
||||
|
||||
local S = minetest.get_translator('drawers')
|
||||
|
||||
-- GUI
|
||||
function drawers.get_upgrade_slots_bg(x,y)
|
||||
local out = ""
|
||||
for i = 0, 4, 1 do
|
||||
out = out .."image["..x+i..","..y..";1,1;drawers_upgrade_slot_bg.png]"
|
||||
end
|
||||
return out
|
||||
end
|
||||
|
||||
function drawers.gen_info_text(basename, count, factor, stack_max)
|
||||
local maxCount = stack_max * factor
|
||||
local percent = count / maxCount * 100
|
||||
-- round the number (float -> int)
|
||||
percent = math.floor(percent + 0.5)
|
||||
|
||||
if count == 0 then
|
||||
return S("@1 (@2% full)", basename, tostring(percent))
|
||||
else
|
||||
return S("@1 @2 (@3% full)", tostring(count), basename, tostring(percent))
|
||||
end
|
||||
end
|
||||
|
||||
-- Get an image string from a tile definition
|
||||
local function tile_to_image(tile, fallback_image)
|
||||
if not tile then
|
||||
return fallback_image
|
||||
end
|
||||
local tile_type = type(tile)
|
||||
if tile_type == "string" then
|
||||
return tile
|
||||
end
|
||||
assert(tile_type == "table", "Tile definition is not a string or table")
|
||||
local image = tile.name or tile.image
|
||||
assert(image, "Tile definition has no image file specified")
|
||||
if tile.color then
|
||||
local colorstr = core.colorspec_to_colorstring(tile.color)
|
||||
if colorstr then
|
||||
return image .. "^[multiply:" .. colorstr
|
||||
end
|
||||
end
|
||||
return image
|
||||
end
|
||||
|
||||
function drawers.get_inv_image(name)
|
||||
local texture = "blank.png"
|
||||
local def = core.registered_items[name]
|
||||
if not def then return end
|
||||
|
||||
if def.inventory_image and #def.inventory_image > 0 then
|
||||
texture = def.inventory_image
|
||||
else
|
||||
if not def.tiles then return texture end
|
||||
local tiles = table.copy(def.tiles)
|
||||
local top = tile_to_image(tiles[1])
|
||||
local left = tile_to_image(tiles[3], top)
|
||||
local right = tile_to_image(tiles[5], left)
|
||||
texture = core.inventorycube(top, left, right)
|
||||
end
|
||||
|
||||
return texture
|
||||
end
|
||||
|
||||
function drawers.spawn_visuals(pos)
|
||||
local node = core.get_node(pos)
|
||||
local ndef = core.registered_nodes[node.name]
|
||||
local drawerType = ndef.groups.drawer
|
||||
|
||||
-- data for the new visual
|
||||
drawers.last_drawer_pos = pos
|
||||
drawers.last_drawer_type = drawerType
|
||||
|
||||
if drawerType == 1 then -- 1x1 drawer
|
||||
drawers.last_visual_id = ""
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name"))
|
||||
|
||||
local bdir = core.facedir_to_dir(node.param2)
|
||||
local fdir = vector.new(-bdir.x, 0, -bdir.z)
|
||||
local pos2 = vector.add(pos, vector.multiply(fdir, 0.45))
|
||||
|
||||
local obj = core.add_entity(pos2, "drawers:visual")
|
||||
if not obj then return end
|
||||
|
||||
if bdir.x < 0 then obj:set_yaw(0.5 * math.pi) end
|
||||
if bdir.z < 0 then obj:set_yaw(math.pi) end
|
||||
if bdir.x > 0 then obj:set_yaw(1.5 * math.pi) end
|
||||
|
||||
drawers.last_texture = nil
|
||||
elseif drawerType == 2 then
|
||||
local bdir = core.facedir_to_dir(node.param2)
|
||||
|
||||
local fdir1
|
||||
local fdir2
|
||||
if node.param2 == 2 or node.param2 == 0 then
|
||||
fdir1 = vector.new(-bdir.x, 0.5, -bdir.z)
|
||||
fdir2 = vector.new(-bdir.x, -0.5, -bdir.z)
|
||||
else
|
||||
fdir1 = vector.new(-bdir.x, 0.5, -bdir.z)
|
||||
fdir2 = vector.new(-bdir.x, -0.5, -bdir.z)
|
||||
end
|
||||
|
||||
local objs = {}
|
||||
|
||||
drawers.last_visual_id = 1
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name1"))
|
||||
local pos1 = vector.add(pos, vector.multiply(fdir1, 0.45))
|
||||
objs[1] = core.add_entity(pos1, "drawers:visual")
|
||||
|
||||
drawers.last_visual_id = 2
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name2"))
|
||||
local pos2 = vector.add(pos, vector.multiply(fdir2, 0.45))
|
||||
objs[2] = core.add_entity(pos2, "drawers:visual")
|
||||
|
||||
for i,obj in pairs(objs) do
|
||||
if bdir.x < 0 then obj:set_yaw(0.5 * math.pi) end
|
||||
if bdir.z < 0 then obj:set_yaw(math.pi) end
|
||||
if bdir.x > 0 then obj:set_yaw(1.5 * math.pi) end
|
||||
end
|
||||
else -- 2x2 drawer
|
||||
local bdir = core.facedir_to_dir(node.param2)
|
||||
|
||||
local fdir1
|
||||
local fdir2
|
||||
local fdir3
|
||||
local fdir4
|
||||
if node.param2 == 2 then
|
||||
fdir1 = vector.new(-bdir.x + 0.5, 0.5, -bdir.z)
|
||||
fdir2 = vector.new(-bdir.x - 0.5, 0.5, -bdir.z)
|
||||
fdir3 = vector.new(-bdir.x + 0.5, -0.5, -bdir.z)
|
||||
fdir4 = vector.new(-bdir.x - 0.5, -0.5, -bdir.z)
|
||||
elseif node.param2 == 0 then
|
||||
fdir1 = vector.new(-bdir.x - 0.5, 0.5, -bdir.z)
|
||||
fdir2 = vector.new(-bdir.x + 0.5, 0.5, -bdir.z)
|
||||
fdir3 = vector.new(-bdir.x - 0.5, -0.5, -bdir.z)
|
||||
fdir4 = vector.new(-bdir.x + 0.5, -0.5, -bdir.z)
|
||||
elseif node.param2 == 1 then
|
||||
fdir1 = vector.new(-bdir.x, 0.5, -bdir.z + 0.5)
|
||||
fdir2 = vector.new(-bdir.x, 0.5, -bdir.z - 0.5)
|
||||
fdir3 = vector.new(-bdir.x, -0.5, -bdir.z + 0.5)
|
||||
fdir4 = vector.new(-bdir.x, -0.5, -bdir.z - 0.5)
|
||||
else
|
||||
fdir1 = vector.new(-bdir.x, 0.5, -bdir.z - 0.5)
|
||||
fdir2 = vector.new(-bdir.x, 0.5, -bdir.z + 0.5)
|
||||
fdir3 = vector.new(-bdir.x, -0.5, -bdir.z - 0.5)
|
||||
fdir4 = vector.new(-bdir.x, -0.5, -bdir.z + 0.5)
|
||||
end
|
||||
|
||||
local objs = {}
|
||||
|
||||
drawers.last_visual_id = 1
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name1"))
|
||||
local pos1 = vector.add(pos, vector.multiply(fdir1, 0.45))
|
||||
objs[1] = core.add_entity(pos1, "drawers:visual")
|
||||
|
||||
drawers.last_visual_id = 2
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name2"))
|
||||
local pos2 = vector.add(pos, vector.multiply(fdir2, 0.45))
|
||||
objs[2] = core.add_entity(pos2, "drawers:visual")
|
||||
|
||||
drawers.last_visual_id = 3
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name3"))
|
||||
local pos3 = vector.add(pos, vector.multiply(fdir3, 0.45))
|
||||
objs[3] = core.add_entity(pos3, "drawers:visual")
|
||||
|
||||
drawers.last_visual_id = 4
|
||||
drawers.last_texture = drawers.get_inv_image(core.get_meta(pos):get_string("name4"))
|
||||
local pos4 = vector.add(pos, vector.multiply(fdir4, 0.45))
|
||||
objs[4] = core.add_entity(pos4, "drawers:visual")
|
||||
|
||||
|
||||
for i,obj in pairs(objs) do
|
||||
if bdir.x < 0 then obj:set_yaw(0.5 * math.pi) end
|
||||
if bdir.z < 0 then obj:set_yaw(math.pi) end
|
||||
if bdir.x > 0 then obj:set_yaw(1.5 * math.pi) end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function drawers.remove_visuals(pos)
|
||||
local objs = core.get_objects_inside_radius(pos, 0.56)
|
||||
if not objs then return end
|
||||
|
||||
for _, obj in pairs(objs) do
|
||||
if obj and obj:get_luaentity() and
|
||||
obj:get_luaentity().name == "drawers:visual" then
|
||||
obj:remove()
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
--[[
|
||||
Returns the visual object for the visualid of the drawer at pos.
|
||||
|
||||
visualid can be: "", "1", "2", ... or 1, 2, ...
|
||||
]]
|
||||
function drawers.get_visual(pos, visualid)
|
||||
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||
if not drawer_visuals then
|
||||
return nil
|
||||
end
|
||||
|
||||
-- not a real index (starts with 1)
|
||||
local index = tonumber(visualid)
|
||||
if visualid == "" then
|
||||
index = 1
|
||||
end
|
||||
|
||||
return drawer_visuals[index]
|
||||
end
|
||||
|
||||
function drawers.update_drawer_upgrades(pos)
|
||||
local node = core.get_node(pos)
|
||||
local ndef = core.registered_nodes[node.name]
|
||||
local drawerType = ndef.groups.drawer
|
||||
|
||||
-- default number of slots/stacks
|
||||
local stackMaxFactor = ndef.drawer_stack_max_factor
|
||||
|
||||
-- storage percent with all upgrades
|
||||
local storagePercent = 100
|
||||
|
||||
-- get info of all upgrades
|
||||
local inventory = core.get_meta(pos):get_inventory():get_list("upgrades")
|
||||
for _,itemStack in pairs(inventory) do
|
||||
local iname = itemStack:get_name()
|
||||
local idef = core.registered_items[iname]
|
||||
local addPercent = idef.groups.drawer_upgrade or 0
|
||||
|
||||
storagePercent = storagePercent + addPercent
|
||||
end
|
||||
|
||||
-- i.e.: 150% / 100 => 1.50
|
||||
stackMaxFactor = math.floor(stackMaxFactor * (storagePercent / 100))
|
||||
-- calculate stack_max factor for a single drawer
|
||||
stackMaxFactor = stackMaxFactor / drawerType
|
||||
|
||||
-- set the new stack max factor in all visuals
|
||||
local drawer_visuals = drawers.drawer_visuals[core.hash_node_position(pos)]
|
||||
if not drawer_visuals then return end
|
||||
|
||||
for _,visual in pairs(drawer_visuals) do
|
||||
visual:setStackMaxFactor(stackMaxFactor)
|
||||
end
|
||||
end
|
||||
|
||||
function drawers.randomize_pos(pos)
|
||||
local rndpos = table.copy(pos)
|
||||
local x = math.random(-50, 50) * 0.01
|
||||
local z = math.random(-50, 50) * 0.01
|
||||
rndpos.x = rndpos.x + x
|
||||
rndpos.y = rndpos.y + 0.25
|
||||
rndpos.z = rndpos.z + z
|
||||
return rndpos
|
||||
end
|
||||
|
||||
function drawers.node_tiles_front_other(front, other)
|
||||
return {other, other, other, other, other, front}
|
||||
end
|
463
mods/drawers/lua/visual.lua
Normal file
463
mods/drawers/lua/visual.lua
Normal file
|
@ -0,0 +1,463 @@
|
|||
--[[
|
||||
Minetest Mod Storage Drawers - A Mod adding storage drawers
|
||||
|
||||
Copyright (C) 2017-2019 Linus Jahn <lnj@kaidan.im>
|
||||
|
||||
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.
|
||||
]]
|
||||
|
||||
local S = minetest.get_translator('drawers')
|
||||
|
||||
core.register_entity("drawers:visual", {
|
||||
initial_properties = {
|
||||
hp_max = 1,
|
||||
physical = false,
|
||||
collide_with_objects = false,
|
||||
collisionbox = {-0.4374, -0.4374, 0, 0.4374, 0.4374, 0}, -- for param2 0, 2
|
||||
visual = "upright_sprite", -- "wielditem" for items without inv img?
|
||||
visual_size = {x = 0.6, y = 0.6},
|
||||
textures = {"blank.png"},
|
||||
spritediv = {x = 1, y = 1},
|
||||
initial_sprite_basepos = {x = 0, y = 0},
|
||||
is_visible = true,
|
||||
},
|
||||
|
||||
get_staticdata = function(self)
|
||||
return core.serialize({
|
||||
drawer_posx = self.drawer_pos.x,
|
||||
drawer_posy = self.drawer_pos.y,
|
||||
drawer_posz = self.drawer_pos.z,
|
||||
texture = self.texture,
|
||||
drawerType = self.drawerType,
|
||||
visualId = self.visualId
|
||||
})
|
||||
end,
|
||||
|
||||
on_activate = function(self, staticdata, dtime_s)
|
||||
-- Restore data
|
||||
local data = core.deserialize(staticdata)
|
||||
if data then
|
||||
self.drawer_pos = {
|
||||
x = data.drawer_posx,
|
||||
y = data.drawer_posy,
|
||||
z = data.drawer_posz,
|
||||
}
|
||||
self.texture = data.texture
|
||||
self.drawerType = data.drawerType or 1
|
||||
self.visualId = data.visualId or ""
|
||||
|
||||
-- backwards compatibility
|
||||
if self.texture == "drawers_empty.png" then
|
||||
self.texture = "blank.png"
|
||||
end
|
||||
else
|
||||
self.drawer_pos = drawers.last_drawer_pos
|
||||
self.texture = drawers.last_texture or "blank.png"
|
||||
self.visualId = drawers.last_visual_id
|
||||
self.drawerType = drawers.last_drawer_type
|
||||
end
|
||||
|
||||
local node = minetest.get_node(self.object:get_pos())
|
||||
if core.get_item_group(node.name, "drawer") == 0 then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
|
||||
-- add self to public drawer visuals
|
||||
-- this is needed because there is no other way to get this class
|
||||
-- only the underlying LuaEntitySAO
|
||||
-- PLEASE contact me, if this is wrong
|
||||
local vId = self.visualId
|
||||
if vId == "" then vId = 1 end
|
||||
local posstr = core.hash_node_position(self.drawer_pos)
|
||||
if not drawers.drawer_visuals[posstr] then
|
||||
drawers.drawer_visuals[posstr] = {[vId] = self}
|
||||
else
|
||||
drawers.drawer_visuals[posstr][vId] = self
|
||||
end
|
||||
|
||||
-- get meta
|
||||
self.meta = core.get_meta(self.drawer_pos)
|
||||
|
||||
-- collisionbox
|
||||
node = core.get_node(self.drawer_pos)
|
||||
local colbox
|
||||
if self.drawerType ~= 2 then
|
||||
if node.param2 == 1 or node.param2 == 3 then
|
||||
colbox = {0, -0.4374, -0.4374, 0, 0.4374, 0.4374}
|
||||
else
|
||||
colbox = {-0.4374, -0.4374, 0, 0.4374, 0.4374, 0} -- for param2 = 0 or 2
|
||||
end
|
||||
-- only half the size if it's a small drawer
|
||||
if self.drawerType > 1 then
|
||||
for i,j in pairs(colbox) do
|
||||
colbox[i] = j * 0.5
|
||||
end
|
||||
end
|
||||
else
|
||||
if node.param2 == 1 or node.param2 == 3 then
|
||||
colbox = {0, -0.2187, -0.4374, 0, 0.2187, 0.4374}
|
||||
else
|
||||
colbox = {-0.4374, -0.2187, 0, 0.4374, 0.2187, 0} -- for param2 = 0 or 2
|
||||
end
|
||||
end
|
||||
|
||||
-- visual size
|
||||
local visual_size = {x = 0.6, y = 0.6}
|
||||
if self.drawerType >= 2 then
|
||||
visual_size = {x = 0.3, y = 0.3}
|
||||
end
|
||||
|
||||
|
||||
-- drawer values
|
||||
local vid = self.visualId
|
||||
self.count = self.meta:get_int("count"..vid)
|
||||
self.itemName = self.meta:get_string("name"..vid)
|
||||
self.maxCount = self.meta:get_int("max_count"..vid)
|
||||
self.itemStackMax = self.meta:get_int("base_stack_max"..vid)
|
||||
self.stackMaxFactor = self.meta:get_int("stack_max_factor"..vid)
|
||||
|
||||
|
||||
-- infotext
|
||||
local infotext = self.meta:get_string("entity_infotext"..vid) .. "\n\n\n\n\n"
|
||||
|
||||
self.object:set_properties({
|
||||
collisionbox = colbox,
|
||||
infotext = infotext,
|
||||
textures = {self.texture},
|
||||
visual_size = visual_size
|
||||
})
|
||||
|
||||
-- make entity undestroyable
|
||||
self.object:set_armor_groups({immortal = 1})
|
||||
end,
|
||||
|
||||
on_rightclick = function(self, clicker)
|
||||
if core.is_protected(self.drawer_pos, clicker:get_player_name()) then
|
||||
core.record_protection_violation(self.drawer_pos, clicker:get_player_name())
|
||||
return
|
||||
end
|
||||
|
||||
-- used to check if we need to play a sound in the end
|
||||
local inventoryChanged = false
|
||||
|
||||
-- When the player uses the drawer with their bare hand all
|
||||
-- stacks from the inventory will be added to the drawer.
|
||||
if self.itemName ~= "" and
|
||||
clicker:get_wielded_item():get_name() == "" and
|
||||
not clicker:get_player_control().sneak then
|
||||
-- try to insert all items from inventory
|
||||
local i = 0
|
||||
local inv = clicker:get_inventory()
|
||||
|
||||
while i <= inv:get_size("main") do
|
||||
-- set current stack to leftover of insertion
|
||||
local leftover = self.try_insert_stack(
|
||||
self,
|
||||
inv:get_stack("main", i),
|
||||
true
|
||||
)
|
||||
|
||||
-- check if something was added
|
||||
if leftover:get_count() < inv:get_stack("main", i):get_count() then
|
||||
inventoryChanged = true
|
||||
end
|
||||
|
||||
-- set new stack
|
||||
inv:set_stack("main", i, leftover)
|
||||
i = i + 1
|
||||
end
|
||||
else
|
||||
-- try to insert wielded item only
|
||||
local leftover = self.try_insert_stack(
|
||||
self,
|
||||
clicker:get_wielded_item(),
|
||||
not clicker:get_player_control().sneak
|
||||
)
|
||||
|
||||
-- check if something was added
|
||||
if clicker:get_wielded_item():get_count() > leftover:get_count() then
|
||||
inventoryChanged = true
|
||||
end
|
||||
-- set the leftover as new wielded item for the player
|
||||
clicker:set_wielded_item(leftover)
|
||||
end
|
||||
|
||||
if inventoryChanged then
|
||||
self:play_interact_sound()
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(self, puncher, time_from_last_punch, tool_capabilities, dir)
|
||||
local node = minetest.get_node(self.object:get_pos())
|
||||
|
||||
if core.get_item_group(node.name, "drawer") == 0 then
|
||||
self.object:remove()
|
||||
return
|
||||
end
|
||||
local add_stack = not puncher:get_player_control().sneak
|
||||
if core.is_protected(self.drawer_pos, puncher:get_player_name()) then
|
||||
core.record_protection_violation(self.drawer_pos, puncher:get_player_name())
|
||||
return
|
||||
end
|
||||
local inv = puncher:get_inventory()
|
||||
if inv == nil then
|
||||
return
|
||||
end
|
||||
local spaceChecker = ItemStack(self.itemName)
|
||||
if add_stack then
|
||||
spaceChecker:set_count(spaceChecker:get_stack_max())
|
||||
end
|
||||
if not inv:room_for_item("main", spaceChecker) then
|
||||
return
|
||||
end
|
||||
|
||||
local stack
|
||||
if add_stack then
|
||||
stack = self:take_stack()
|
||||
else
|
||||
stack = self:take_items(1)
|
||||
end
|
||||
|
||||
if stack ~= nil then
|
||||
-- add removed stack to player's inventory
|
||||
inv:add_item("main", stack)
|
||||
|
||||
-- play the interact sound
|
||||
self:play_interact_sound()
|
||||
end
|
||||
end,
|
||||
|
||||
take_items = function(self, removeCount)
|
||||
local meta = core.get_meta(self.drawer_pos)
|
||||
|
||||
if self.count <= 0 then
|
||||
return
|
||||
end
|
||||
|
||||
if removeCount > self.count then
|
||||
removeCount = self.count
|
||||
end
|
||||
|
||||
local stack = ItemStack(self.itemName)
|
||||
stack:set_count(removeCount)
|
||||
|
||||
-- update the drawer count
|
||||
self.count = self.count - removeCount
|
||||
|
||||
self:updateInfotext()
|
||||
self:updateTexture()
|
||||
self:saveMetaData()
|
||||
|
||||
-- return the stack that was removed from the drawer
|
||||
return stack
|
||||
end,
|
||||
|
||||
take_stack = function(self)
|
||||
return self:take_items(ItemStack(self.itemName):get_stack_max())
|
||||
end,
|
||||
|
||||
can_insert_stack = function(self, stack)
|
||||
if stack:get_name() == "" or stack:get_count() <= 0 then
|
||||
return 0
|
||||
end
|
||||
|
||||
-- don't allow unstackable stacks
|
||||
if self.itemName == "" and stack:get_stack_max() ~= 1 then
|
||||
return stack:get_count()
|
||||
end
|
||||
|
||||
if self.itemName ~= stack:get_name() then
|
||||
return 0
|
||||
end
|
||||
|
||||
if (self.count + stack:get_count()) <= self.maxCount then
|
||||
return stack:get_count()
|
||||
end
|
||||
return self.maxCount - self.count
|
||||
end,
|
||||
|
||||
try_insert_stack = function(self, itemstack, insert_all)
|
||||
local stackCount = itemstack:get_count()
|
||||
local stackName = itemstack:get_name()
|
||||
|
||||
local insertCount = self:can_insert_stack(itemstack)
|
||||
|
||||
if insertCount == 0 then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- only add one, if player holding sneak key
|
||||
if not insert_all then
|
||||
insertCount = 1
|
||||
end
|
||||
|
||||
-- in case the drawer was empty, initialize count, itemName, maxCount
|
||||
if self.itemName == "" then
|
||||
self.count = 0
|
||||
self.itemName = itemstack:get_name()
|
||||
self.maxCount = itemstack:get_stack_max() * self.stackMaxFactor
|
||||
self.itemStackMax = itemstack:get_stack_max()
|
||||
end
|
||||
|
||||
-- update everything
|
||||
self.count = self.count + insertCount
|
||||
self:updateInfotext()
|
||||
self:updateTexture()
|
||||
self:saveMetaData()
|
||||
|
||||
-- return leftover
|
||||
itemstack:take_item(insertCount)
|
||||
if itemstack:get_count() == 0 then
|
||||
return ItemStack("")
|
||||
end
|
||||
return itemstack
|
||||
end,
|
||||
|
||||
updateInfotext = function(self)
|
||||
local itemDescription = ""
|
||||
if core.registered_items[self.itemName] then
|
||||
itemDescription = core.registered_items[self.itemName].description
|
||||
end
|
||||
|
||||
if self.count <= 0 then
|
||||
self.itemName = ""
|
||||
self.meta:set_string("name"..self.visualId, self.itemName)
|
||||
self.texture = "blank.png"
|
||||
itemDescription = S("Empty")
|
||||
end
|
||||
|
||||
local infotext = drawers.gen_info_text(itemDescription,
|
||||
self.count, self.stackMaxFactor, self.itemStackMax)
|
||||
self.meta:set_string("entity_infotext"..self.visualId, infotext)
|
||||
|
||||
self.object:set_properties({
|
||||
infotext = infotext .. "\n\n\n\n\n"
|
||||
})
|
||||
end,
|
||||
|
||||
updateTexture = function(self)
|
||||
-- texture
|
||||
self.texture = drawers.get_inv_image(self.itemName)
|
||||
|
||||
self.object:set_properties({
|
||||
textures = {self.texture}
|
||||
})
|
||||
end,
|
||||
|
||||
dropStack = function(self, itemStack)
|
||||
-- print warning if dropping higher stack counts than allowed
|
||||
if itemStack:get_count() > itemStack:get_stack_max() then
|
||||
core.log("warning", "[drawers] Dropping item stack with higher count than allowed")
|
||||
end
|
||||
-- find a position containing air
|
||||
local dropPos = core.find_node_near(self.drawer_pos, 1, {"air"}, false)
|
||||
-- if no pos found then drop on the top of the drawer
|
||||
if not dropPos then
|
||||
dropPos = self.object:get_pos()
|
||||
dropPos.y = dropPos.y + 1
|
||||
end
|
||||
-- drop the item stack
|
||||
core.item_drop(itemStack, nil, dropPos)
|
||||
end,
|
||||
|
||||
dropItemOverload = function(self)
|
||||
-- drop stacks until there are no more items than allowed
|
||||
while self.count > self.maxCount do
|
||||
-- remove the overflow
|
||||
local removeCount = self.count - self.maxCount
|
||||
-- if this is too much for a single stack, only take the
|
||||
-- stack limit
|
||||
if removeCount > self.itemStackMax then
|
||||
removeCount = self.itemStackMax
|
||||
end
|
||||
-- remove this count from the drawer
|
||||
self.count = self.count - removeCount
|
||||
-- create a new item stack having the size of the remove
|
||||
-- count
|
||||
local stack = ItemStack(self.itemName)
|
||||
stack:set_count(removeCount)
|
||||
print(stack:to_string())
|
||||
-- drop the stack
|
||||
self:dropStack(stack)
|
||||
end
|
||||
end,
|
||||
|
||||
setStackMaxFactor = function(self, stackMaxFactor)
|
||||
self.stackMaxFactor = stackMaxFactor
|
||||
self.maxCount = self.stackMaxFactor * self.itemStackMax
|
||||
|
||||
-- will drop possible overflowing items
|
||||
self:dropItemOverload()
|
||||
self:updateInfotext()
|
||||
self:saveMetaData()
|
||||
end,
|
||||
|
||||
play_interact_sound = function(self)
|
||||
core.sound_play("drawers_interact", {
|
||||
pos = self.object:get_pos(),
|
||||
max_hear_distance = 6,
|
||||
gain = 2.0
|
||||
})
|
||||
end,
|
||||
|
||||
saveMetaData = function(self, meta)
|
||||
self.meta:set_int("count"..self.visualId, self.count)
|
||||
self.meta:set_string("name"..self.visualId, self.itemName)
|
||||
self.meta:set_int("max_count"..self.visualId, self.maxCount)
|
||||
self.meta:set_int("base_stack_max"..self.visualId, self.itemStackMax)
|
||||
self.meta:set_int("stack_max_factor"..self.visualId, self.stackMaxFactor)
|
||||
end
|
||||
})
|
||||
|
||||
core.register_lbm({
|
||||
name = "drawers:restore_visual",
|
||||
nodenames = {"group:drawer"},
|
||||
run_at_every_load = true,
|
||||
action = function(pos, node)
|
||||
local meta = core.get_meta(pos)
|
||||
-- create drawer upgrade inventory
|
||||
meta:get_inventory():set_size("upgrades", 5)
|
||||
-- set the formspec
|
||||
meta:set_string("formspec", drawers.drawer_formspec)
|
||||
|
||||
-- count the drawer visuals
|
||||
local drawerType = core.registered_nodes[node.name].groups.drawer
|
||||
local foundVisuals = 0
|
||||
local objs = core.get_objects_inside_radius(pos, 0.56)
|
||||
if objs then
|
||||
for _, obj in pairs(objs) do
|
||||
if obj and obj:get_luaentity() and
|
||||
obj:get_luaentity().name == "drawers:visual" then
|
||||
foundVisuals = foundVisuals + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
-- if all drawer visuals were found, return
|
||||
if foundVisuals == drawerType then
|
||||
return
|
||||
end
|
||||
|
||||
-- not enough visuals found, remove existing and create new ones
|
||||
drawers.remove_visuals(pos)
|
||||
drawers.spawn_visuals(pos)
|
||||
end
|
||||
})
|
Loading…
Add table
Add a link
Reference in a new issue