EinsDreiDreiSieben/mods/quickstack/quickstack.lua

123 lines
3.2 KiB
Lua

local get_settings = ...
local chest_nodenames, cooldowns = {}, {}
local function can_quickstack(settings, index, stack)
if stack:is_empty() or settings["qs_locked_"..index] or
settings.qs_lock_tools and minetest.registered_tools[stack:get_name()] then
return false
end
return true
end
local function find_nearby_chests(player)
local pos = vector.round(player:get_pos())
local pos1 = vector.subtract(pos, vector.new(4, 3, 4))
local pos2 = vector.add(pos, vector.new(4, 3, 4))
return minetest.find_nodes_in_area(pos1, pos2, chest_nodenames, true)
end
local function stack_to_chest(settings, pos, player, items, allow_put)
local inv = minetest.get_meta(pos):get_inventory()
if inv:get_size("main") == 0 or inv:is_empty("main") then
return
end
local items_added = false
for _,stack in pairs(items) do
if inv:contains_item("main", stack:peek_item(1), settings.qs_exact_match) then
local count = stack:get_count()
if allow_put then
count = allow_put(pos, "main", nil, stack, player)
end
if count and count > 0 then
local to_add = stack:take_item(count)
local leftover = inv:add_item("main", to_add)
if leftover:get_count() < count then
items_added = true
end
stack:add_item(leftover)
end
end
end
return items_added
end
local function quickstack(player)
if not player then
return
end
local inv = player:get_inventory()
if inv:is_empty("main") then
return
end
local player_name = player:get_player_name()
local now = os.time()
if cooldowns[player_name] and now < cooldowns[player_name] then
return
end
cooldowns[player_name] = now + 3
local settings = get_settings(player)
local items = {}
for i, stack in pairs(inv:get_list("main")) do
if can_quickstack(settings, i, stack) then
items[i] = stack
end
end
if next(items) == nil then
return
end
local chests = find_nearby_chests(player)
if next(chests) == nil then
return
end
local items_added = false
for name, positions in pairs(chests) do
local def = minetest.registered_nodes[name]
if def then
local allow_put = def.allow_metadata_inventory_put
for _,pos in pairs(positions) do
if stack_to_chest(settings, pos, player, items, allow_put) then
items_added = true
end
end
end
end
if items_added then
for i, stack in pairs(items) do
inv:set_stack("main", i, stack)
end
minetest.sound_play("quickstack_pop", {to_player = player_name, gain = 0.1})
end
end
local function setting_to_table(setting)
local t = {}
local str = minetest.settings:get(setting)
if not str then
return t
end
for _,name in pairs(str:split(",")) do
name = name:trim()
if minetest.registered_nodes[name] then
t[name] = true
end
end
return t
end
minetest.register_on_mods_loaded(function()
local exclude_nodes = setting_to_table("quickstack_exclude_nodes")
local include_nodes = setting_to_table("quickstack_include_nodes")
for name, def in pairs(minetest.registered_nodes) do
if not exclude_nodes[name] then
if name:find("chest") or def.description and def.description:find("[Cc]hest") then
include_nodes[name] = true
end
end
end
for name in pairs(include_nodes) do
table.insert(chest_nodenames, name)
end
end)
return quickstack