working version
This commit is contained in:
parent
8411475612
commit
8dde8ec90b
33
init.lua
Normal file
33
init.lua
Normal file
@ -0,0 +1,33 @@
|
||||
|
||||
local S = minetest.get_translator("quickstack")
|
||||
local MP = minetest.get_modpath("quickstack")
|
||||
|
||||
local function get_settings(player)
|
||||
local str = player:get_meta():get("quickstack_settings")
|
||||
if not str then
|
||||
return {}
|
||||
end
|
||||
str = minetest.parse_json(str)
|
||||
return str or {}
|
||||
end
|
||||
|
||||
local function save_settings(player, settings)
|
||||
local str = minetest.write_json(settings)
|
||||
player:get_meta():set_string("quickstack_settings", str)
|
||||
end
|
||||
|
||||
local quickstack = loadfile(MP.."/quickstack.lua")(get_settings)
|
||||
|
||||
loadfile(MP.."/ui.lua")(quickstack, get_settings, save_settings)
|
||||
|
||||
minetest.register_chatcommand("qs", {
|
||||
description = S("Quick stack to nearby chests"),
|
||||
func = function(name)
|
||||
local player = minetest.get_player_by_name(name)
|
||||
if not player then
|
||||
return false
|
||||
end
|
||||
quickstack(player)
|
||||
return true
|
||||
end
|
||||
})
|
4
mod.conf
Normal file
4
mod.conf
Normal file
@ -0,0 +1,4 @@
|
||||
name = quickstack
|
||||
description = Adds Terraria's quick stack feature to Unified Inventory
|
||||
depends = unified_inventory
|
||||
min_minetest_version = 5.5.0
|
123
quickstack.lua
Normal file
123
quickstack.lua
Normal file
@ -0,0 +1,123 @@
|
||||
|
||||
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
|
BIN
sounds/quickstack_pop.ogg
Normal file
BIN
sounds/quickstack_pop.ogg
Normal file
Binary file not shown.
BIN
textures/quicksatck_locked.png
Normal file
BIN
textures/quicksatck_locked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.5 KiB |
BIN
textures/quicksatck_unlocked.png
Normal file
BIN
textures/quicksatck_unlocked.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 8.8 KiB |
BIN
textures/quickstack_button.png
Normal file
BIN
textures/quickstack_button.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 1.0 KiB |
BIN
textures/quickstack_lock_icon.png
Normal file
BIN
textures/quickstack_lock_icon.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 415 B |
BIN
textures/quickstack_lock_overlay.png
Normal file
BIN
textures/quickstack_lock_overlay.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 372 B |
BIN
textures/quickstack_settings.png
Normal file
BIN
textures/quickstack_settings.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 2.7 KiB |
115
ui.lua
Normal file
115
ui.lua
Normal file
@ -0,0 +1,115 @@
|
||||
|
||||
local S = minetest.get_translator("quickstack")
|
||||
local FS = function(...)
|
||||
return minetest.formspec_escape(S(...))
|
||||
end
|
||||
local floor, format, insert, concat = math.floor, string.format, table.insert, table.concat
|
||||
local quickstack, get_settings, save_settings = ...
|
||||
local ui = unified_inventory
|
||||
|
||||
ui.register_button("quickstack", {
|
||||
type = "image",
|
||||
image = "quickstack_button.png",
|
||||
tooltip = S("Quick stack to nearby chests"),
|
||||
action = quickstack,
|
||||
})
|
||||
|
||||
ui.register_button("quickstack_settings", {
|
||||
type = "image",
|
||||
image = "quickstack_settings.png",
|
||||
tooltip = S("Quick stack settings"),
|
||||
})
|
||||
|
||||
local function get_inventory_overlay(player, style)
|
||||
local settings = get_settings(player)
|
||||
if not settings.qs_show_locked then
|
||||
return ""
|
||||
end
|
||||
local overlay = {}
|
||||
for i=1, 32 do
|
||||
local x, y = (i-1)%8, floor((i-1)/8)
|
||||
if settings["qs_locked_"..i] then
|
||||
insert(overlay, format("image[%f,%f;1.25,1.25;quickstack_lock_overlay.png]",
|
||||
style.std_inv_x + x*1.25, style.std_inv_y + y*1.25))
|
||||
end
|
||||
end
|
||||
return concat(overlay)
|
||||
end
|
||||
|
||||
ui.register_page("quickstack_settings", {get_formspec = function(player, style)
|
||||
local settings = get_settings(player)
|
||||
local offset = style.is_lite_mode and 0.7 or 1.0
|
||||
local formspec = {
|
||||
style.standard_inv_bg,
|
||||
format("label[%f,%f;%s]", style.form_header_x, style.form_header_y, FS("Quick stack settings")),
|
||||
format("tooltip[%f,%f;6.7,3.3;%s]",
|
||||
style.std_inv_x + 0.1, offset, FS("Locked inventory slots are not quick stacked")),
|
||||
format("image_button[%f,%f;0.75,0.75;ui_locked.png;qs_lock_all;]tooltip[qs_lock_all;%s]",
|
||||
style.std_inv_x + 7.35, offset, FS("Lock all inventory slots")),
|
||||
format("image_button[%f,%f;0.75,0.75;ui_unlocked.png;qs_unlock_all;]tooltip[qs_unlock_all;%s]",
|
||||
style.std_inv_x + 8.2, offset, FS("Unlock all inventory slots")),
|
||||
}
|
||||
for i=1, 32 do
|
||||
local x, y = (i-1)%8, floor((i-1)/8)
|
||||
if settings["qs_locked_"..i] then
|
||||
insert(formspec, format("image_button[%f,%f;0.75,0.75;quickstack_lock_icon.png;%s;]",
|
||||
style.std_inv_x + 0.1 + x*0.85, offset + y*0.85, "qs_unlock_"..i))
|
||||
else
|
||||
insert(formspec, format("button[%f,%f;0.75,0.75;%s;]",
|
||||
style.std_inv_x + 0.1 + x*0.85, offset + y*0.85, "qs_lock_"..i))
|
||||
end
|
||||
end
|
||||
local checkboxes = {
|
||||
{"qs_lock_tools", FS("Lock tools"), FS("Tools are not quick stacked")},
|
||||
{"qs_exact_match", FS("Exact match"), FS("Only items with matching metadata are quick stacked")},
|
||||
{"qs_show_locked", FS("Show locked"), FS("Locked slots are shown in the inventory")},
|
||||
}
|
||||
for i, box in ipairs(checkboxes) do
|
||||
local checked = settings[box[1]] and "true" or "false"
|
||||
insert(formspec, format("checkbox[%f,%f;%s;%s;%s]tooltip[%s;%s]",
|
||||
style.std_inv_x + 7.35, offset + 1.2 + (i-1)*0.6, box[1], box[2], checked, box[1], box[3]))
|
||||
end
|
||||
return {formspec = concat(formspec)}
|
||||
end})
|
||||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
if not player or not fields or formname ~= "" then
|
||||
return
|
||||
end
|
||||
local settings = get_settings(player)
|
||||
local update_formspec = false
|
||||
for i=1, 32 do
|
||||
if (fields.qs_lock_all or fields["qs_lock_"..i]) and not settings["qs_locked_"..i] then
|
||||
settings["qs_locked_"..i] = true
|
||||
update_formspec = true
|
||||
elseif (fields.qs_unlock_all or fields["qs_unlock_"..i]) and settings["qs_locked_"..i] then
|
||||
settings["qs_locked_"..i] = nil
|
||||
update_formspec = true
|
||||
end
|
||||
end
|
||||
for _,box in pairs({"qs_lock_tools", "qs_exact_match", "qs_show_locked"}) do
|
||||
if fields[box] then
|
||||
settings[box] = fields[box] == "true" and true or nil
|
||||
update_formspec = true
|
||||
end
|
||||
end
|
||||
if update_formspec then
|
||||
save_settings(player, settings)
|
||||
minetest.sound_play("ui_click", {to_player=player:get_player_name(), gain = 0.1})
|
||||
ui.set_inventory_formspec(player, "quickstack_settings")
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_mods_loaded(function()
|
||||
for _,page in pairs(ui.pages) do
|
||||
local old_get_formspec = page.get_formspec
|
||||
page.get_formspec = function(player, style)
|
||||
local formspec = old_get_formspec(player, style)
|
||||
if formspec.draw_inventory ~= false then
|
||||
local overlay = get_inventory_overlay(player, style)
|
||||
formspec.formspec = formspec.formspec..overlay
|
||||
end
|
||||
return formspec
|
||||
end
|
||||
end
|
||||
end)
|
Loading…
x
Reference in New Issue
Block a user