From bca53b0b55b4cf5bccd4eb51ee43be5056d0a023 Mon Sep 17 00:00:00 2001 From: BlockMen Date: Tue, 12 Aug 2014 16:36:38 +0200 Subject: [PATCH] Initial commit --- README.txt | 34 +++++ depends.txt | 1 + init.lua | 262 +++++++++++++++++++++++++++++++++ sounds/invtweak_tool_break.ogg | Bin 0 -> 10374 bytes 4 files changed, 297 insertions(+) create mode 100644 README.txt create mode 100644 depends.txt create mode 100644 init.lua create mode 100644 sounds/invtweak_tool_break.ogg diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..0bf68db --- /dev/null +++ b/README.txt @@ -0,0 +1,34 @@ +Minetest mod "Inventory Tweaks" +=============================== +version: 2.0 + +License of source code: WTFPL +----------------------------- +Written 2013-2014 by BlockMen + +This program is free software. It comes without any warranty, to +the extent permitted by applicable law. You can redistribute it +and/or modify it under the terms of the Do What The Fuck You Want +To Public License, Version 2, as published by Sam Hocevar. See +http://sam.zoy.org/wtfpl/COPYING for more details. + +License of sounds: +------------------ +invtweak_break_tool.ogg by EdgardEdition (CC BY 3.0), http://www.freesound.org/people/EdgardEdition + + +~About~ +------- +This mod add different new functions to Minetest. + +First: This mod adds 3 different buttons to player inventory. With those buttons you can sort your inventory easily. +"›•"-Button concernates all stacks to their maximum size. +"^"-Button sorts all items in an ascending order +"v"-Button sorts all items in an descending order + +Furthermore this mod has the ability to refill your wielded items automaticly. For example your current tool +break and you have one more of the same type (e.g. a stone pickaxe) this mod put it right in you hand +and you can keep digging our placing nodes without opening the inventory. +You can disable this setting by adding/changing following to your minetest.conf file: "invtweak_autorefill = false" + +As a small gimic it adds also a sound when a tool breaks, to improve the atmosphere of the gameplay. diff --git a/depends.txt b/depends.txt new file mode 100644 index 0000000..4ad96d5 --- /dev/null +++ b/depends.txt @@ -0,0 +1 @@ +default diff --git a/init.lua b/init.lua new file mode 100644 index 0000000..60f159c --- /dev/null +++ b/init.lua @@ -0,0 +1,262 @@ +local auto_refill = minetest.setting_getbool("invtweak_auto_refill") or true + +local tweak = {} +tweak.formspec = {} + +tweak.buttons = { +--sort_asc +"0.55,0.6;sort_asc;^]", +--sort_desc +"0.55,0.6;sort_desc;v]", +--concatenate +"0.65,0.6;sort;›•]" +} + +local function get_formspec_size(formspec) + local w = 8 + local h = 7.5 + local sstring = string.find(formspec,"size[",1,true) + if sstring ~= nil then + sstring = string.sub(formspec, sstring+5) + local p = string.find(sstring,",") + w = string.sub(sstring,1,p-1) + sstring = string.sub(sstring,p+1,string.find(sstring,"]")+2) + p = string.find(sstring,",") + if p == nil then p = string.find(sstring,"]") end + h = string.sub(sstring,1,p-1) + end + return w,h +end + +local function add_buttons(player) + local name = player:get_player_name() + local formspec = player:get_inventory_formspec() + local w,h = get_formspec_size(formspec) + for i=1,#tweak.buttons do + formspec = formspec .. "button["..w-2+(i*0.5)..",-0.2;" .. tweak.buttons[i] + end + player:set_inventory_formspec(formspec) +end + +minetest.register_on_joinplayer(function(player) + minetest.after(0.65,function() + add_buttons(player) + end) +end) + + +local function comp_asc(w1,w2) + if w1.name < w2.name then + return true + end +end + +local function comp_desc(w1,w2) + if w1.name > w2.name then + return true + end +end + +minetest.register_on_player_receive_fields(function(player, formname, fields) + if fields.sort_asc then + tweak.sort(player, comp_asc) + end + if fields.sort_desc then + tweak.sort(player, comp_desc) + end + if fields.sort then + tweak.sort(player, comp_asc, true) + end + + -- player inventory + if minetest.setting_getbool("creative_mode") then + add_buttons(player) + end +end) + +-- sort asc without mod prefix +local function comp_in(w1, w2) + local w11 = string.find(w1.name, ":") + local w22 = string.find(w2.name, ":") + if w11 ~= nil then + w11 = string.sub(w1.name,w11) + else + w11 = w1.name + end + if w22 ~= nil then + w22 = string.sub(w2.name,w22) + else + w22 = w2.name + end + if w11 < w22 then + return true + end +end + +tweak.concatenate = function(list) + local last = nil + local last_cnt = 100 + local refresh = false + for _,stack in ipairs(list) do + local i = _ + if refresh then + refresh = false + table.sort(list, comp_asc) + list = tweak.concatenate(list) + break + end + if stack.name ~= "zztmpsortname" and last == stack.name then + if last_cnt < stack.max then + local diff = stack.max - last_cnt + local add = stack.count + if stack.count > diff then + stack.count = stack.count - diff + add = diff + else + stack.name = "zztmpsortname" + refresh = true + end + list[i-1].count = list[i-1].count + add + end + end + last = stack.name + last_cnt = stack.count + end + return list +end + +tweak.sort = function(player, mode, con) + local inv = player:get_inventory() + if inv then + local list = inv:get_list("main") + local tmp_list = {} + + --write whole list as table + for _,stack in ipairs(list) do + local tbl_stack = stack:to_table() + if tbl_stack == nil then tbl_stack = {name="zztmpsortname"} end + tbl_stack.max = stack:get_stack_max() + tmp_list[_]=tbl_stack + end + + -- sort asc/desc + table.sort(tmp_list, mode) + + if con then + tmp_list = tweak.concatenate(tmp_list) + table.sort(tmp_list, comp_in) + end + + --write back to inventory + for _,stack in ipairs(tmp_list) do + stack.max = nil + if stack.name ~= "zztmpsortname" then + inv:set_stack("main", _, ItemStack(stack)) + else + inv:set_stack("main", _, ItemStack(nil)) + end + end + end +end + + +-- tool break sound + autorefill +function refill(player, stck_name, index) + local inv = player:get_inventory() + for i,stack in ipairs(inv:get_list("main")) do + if stack:get_name() == stck_name then + inv:set_stack("main", index, stack) + stack:clear() + inv:set_stack("main", i, stack) + minetest.log("action", "Inventory Tweaks: refilled stack("..stck_name..") of " .. player:get_player_name() ) + return + end + end +end + +if auto_refill == true then + minetest.register_on_placenode(function(pos, newnode, placer, oldnode) + if not placer then return end + local index = placer:get_wield_index() + local cnt = placer:get_wielded_item():get_count()-1 + if minetest.setting_getbool("creative_mode") then + return true + else + if cnt == 0 then + minetest.after(0.01, refill, placer, newnode.name, index) + end + end + end) +end + +local wielded = {} +wielded.name = {} +wielded.wear = {} + +minetest.register_on_punchnode(function(pos, node, puncher) + if not puncher or minetest.setting_getbool("creative_mode") then + return + end + local name = puncher:get_player_name() + + local item = puncher:get_wielded_item() + local tname = item:get_name() + local def = minetest.registered_tools[tname] + + wielded.name[name] = tname + + if not item or not tname or tname == "" or not def then + return + end + local typ = def.type + if not typ or typ ~= "tool" then + return + end + wielded.wear[name] = item:get_wear() + -- TODO: re-add for costum tools like lighter +end) + +minetest.register_on_dignode(function(pos, oldnode, digger) + if not digger then return end + + local name = digger:get_player_name() + local item = digger:get_wielded_item() + local index = digger:get_wield_index() + local tname = item:get_name() + local def = minetest.registered_tools[tname] + + + if not item then + return + end + if tname ~= "" then + if not def then + return + end + end + + local old_name = wielded.name[name] + if tname == old_name and tname == "" then + return + end + + local old = wielded.wear[name] + if not old and tname == "" then + old = 0 + end + local new = item:get_wear() + + if old ~= new then + if old > 0 and new == 0 then + wielded.wear[name] = new + minetest.sound_play("invtweak_tool_break", { + pos = digger:getpos(), + gain = 0.9, + max_hear_distance = 5 + }) + if auto_refill == true then + minetest.after(0.01, refill, digger, old_name, index) + end + end + end +end) diff --git a/sounds/invtweak_tool_break.ogg b/sounds/invtweak_tool_break.ogg new file mode 100644 index 0000000000000000000000000000000000000000..c68522cde3da623ef714957c3357de4166bc0319 GIT binary patch literal 10374 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