da66780a56
(exactly as last supplied there, updates to these mods will follow later)
246 lines
7.0 KiB
Lua
246 lines
7.0 KiB
Lua
--------------------------------------------------------
|
|
-- supporting junk
|
|
|
|
|
|
function min(a,b)
|
|
if a < b then
|
|
return a
|
|
else
|
|
return b
|
|
end
|
|
end
|
|
|
|
if not string.starts then
|
|
function string.starts(String,Start)
|
|
return string.sub(String,1,string.len(Start))==Start
|
|
end
|
|
end
|
|
|
|
--------------------------------------------------------
|
|
|
|
function sortInventory(inv,sorter)
|
|
local tabl = inv:get_list("main")
|
|
if(tabl == nil) then
|
|
-- we don't sort furnaces!
|
|
return false
|
|
end
|
|
|
|
table.sort(tabl,sorter)
|
|
-- note take_item will set the name to '' when empty
|
|
-- NEVER reduce the inventory array size for chests
|
|
inv:set_list('main',tabl)
|
|
return true
|
|
end
|
|
|
|
sorters = {
|
|
wise = function(a,b)
|
|
-- XXX: this needs to have stricter ordering!
|
|
-- (why is air scoring higher than the end?)
|
|
if(a == nil) then
|
|
if b == nil then
|
|
return true
|
|
else
|
|
return false
|
|
end
|
|
elseif b == nil then
|
|
return true
|
|
end
|
|
|
|
local aname = a:get_name()
|
|
local bname = b:get_name()
|
|
-- make sure empty slots go at the end
|
|
|
|
if(string.len(aname) == 0) then
|
|
return false
|
|
end
|
|
if(string.len(bname) == 0) then
|
|
return true
|
|
end
|
|
|
|
-- if the nodes are entirely different, sorted
|
|
if (aname ~= bname) then
|
|
return aname < bname
|
|
end
|
|
|
|
-- same node types
|
|
-- may need to collapse the two together!
|
|
local bothmax = a:get_stack_max()
|
|
if bothmax == 1 then
|
|
-- it's unstackable
|
|
local awear = a:get_wear()
|
|
local bwear = b:get_wear()
|
|
return awear < bwear
|
|
end
|
|
local acount = a:get_count()
|
|
local bcount = b:get_count()
|
|
if(acount == bothmax) then
|
|
--print('same?',acount,bcount,bothmax)
|
|
return bcount ~= bothmax
|
|
elseif (bcount == bothmax) then
|
|
--print('bcount bothmax derp')
|
|
return false
|
|
end
|
|
local num = min(bcount,bothmax-acount)
|
|
a:add_item(b:take_item(num))
|
|
-- nothing can have both count AND wear, right?
|
|
-- now a:count > b:count so a should go first
|
|
--print('numnum',num)
|
|
return true
|
|
end,
|
|
amount = function(a,b)
|
|
return a:get_count() > b:get_count()
|
|
end,
|
|
wear = function(a,b)
|
|
return a:get_wear() < b:get_wear()
|
|
end,
|
|
-- etc...
|
|
}
|
|
|
|
function registerWand(method,sorter)
|
|
if method == nil then
|
|
name = "inventory_sorter:wand"
|
|
sorter = sorters.wise
|
|
assert(sorter ~= nil)
|
|
desc = 'Chest Sorter'
|
|
image = 'inventory_sorter_wand.png'
|
|
else
|
|
name = "inventory_sorter:wand_"..method
|
|
desc = "Chest Sorter ("..method..')'
|
|
image = 'inventory_sorter_wand_'..method..'.png'
|
|
end
|
|
|
|
minetest.register_tool(name, {
|
|
description = desc,
|
|
inventory_image = image,
|
|
wield_image = image,
|
|
stack_max = 1,
|
|
tool_capabilities = {
|
|
full_punch_interval=0,
|
|
max_drop_level=0
|
|
},
|
|
on_use = function(self,user,punched)
|
|
local pos = minetest.get_pointed_thing_position(punched)
|
|
if pos==nil then
|
|
return
|
|
end
|
|
local meta = minetest.get_meta(pos)
|
|
local inv = meta:get_inventory()
|
|
if(inv == nil) then
|
|
minetest.chat_send_player(user:get_player_name(),"That can't be sorted.","Sorter -!-")
|
|
return
|
|
end
|
|
-- this isn't exported, but default locked chest does this
|
|
local owner = meta:get_string("owner")
|
|
if(owner ~= nil and string.len(owner) ~= 0 and user:get_player_name() ~= owner) then
|
|
minetest.chat_send_player(user:get_player_name(),"That's not yours!","Sorter -!-")
|
|
return
|
|
end
|
|
-- Sokomine's shared chest locks
|
|
if locks ~= nil then
|
|
if punched == nil or punched.name == nil then
|
|
punched = minetest.get_node(pos)
|
|
end
|
|
if punched and punched.name:starts('locks:') and not locks:lock_allow_use(pos,user) then
|
|
-- the error has already been reported (yay side effects)
|
|
return
|
|
end
|
|
end
|
|
|
|
if(sortInventory(inv,sorter)) then
|
|
minetest.chat_send_player(user:get_player_name(),"Chest sorted.","Sorter -!-")
|
|
end
|
|
end
|
|
})
|
|
end
|
|
|
|
function debugSorter(a,b)
|
|
result = sorters.wise(a,b)
|
|
function derp(a)
|
|
return a:get_name()..":"..a:get_count()..":"..a:get_wear()
|
|
end
|
|
if a then
|
|
a = derp(a)
|
|
end
|
|
if b then
|
|
b = derp(b)
|
|
end
|
|
if result then
|
|
print('a goes first',a,b)
|
|
else
|
|
print('b goes first',a,b)
|
|
end
|
|
return result
|
|
end
|
|
function test()
|
|
function thingy(name,stack_max)
|
|
return {
|
|
get_name=function(self) return name end,
|
|
get_stack_max=function(self) return stack_max end,
|
|
get_count=function(self) return stack_max end,
|
|
get_wear=function(self) return 1/stack_max end,
|
|
take_item=function() end,
|
|
add_item=function() end,
|
|
derp=function()
|
|
return name..', '..tostring(stack_max)
|
|
end
|
|
}
|
|
end
|
|
tabl = {thingy('thing1',1),thingy('hting2',1),nil,thingy('thing1',2),thingy('thing1',4),thingy('thing1',10)}
|
|
table.sort(tabl,sorter)
|
|
for n,v in pairs(tabl) do
|
|
print(n,v:get_name(),v:get_count())
|
|
end
|
|
end
|
|
-- test()
|
|
-- print('yay')
|
|
-- error('...')
|
|
|
|
for name,sorter in pairs(sorters) do
|
|
registerWand(name,sorter)
|
|
end
|
|
|
|
registerWand()
|
|
|
|
minetest.register_craft({
|
|
output = 'inventory_sorter:wand',
|
|
recipe = {
|
|
{'default:stick','default:stick',''},
|
|
{'default:stick','default:stick',''},
|
|
{'','default:stick',''}
|
|
}
|
|
})
|
|
|
|
-- is this one automatic...?
|
|
|
|
minetest.register_craft({
|
|
output = 'inventory_sorter:wand',
|
|
recipe = {
|
|
{'','default:stick','default:stick'},
|
|
{'','default:stick','default:stick'},
|
|
{'','','default:stick'}
|
|
}
|
|
})
|
|
|
|
minetest.register_chatcommand('sort',{
|
|
params = '[optional algorithm: amount,wear]',
|
|
description = 'Sort your inventory! No takebacks.',
|
|
privs={interact=true},
|
|
func = function(name,param)
|
|
local sorter = sorters.wise;
|
|
if string.len(param) > 0 then
|
|
sorter = sorters[param];
|
|
if sorter == nil then
|
|
minetest.chat_send_player(name,"/sort [algorithm]","Sorter -!-")
|
|
minetest.chat_send_player(name,"Valid algorithms:","Sorter -!-")
|
|
for n,v in pairs(sorters) do
|
|
minetest.chat_send_player(name,' '..n,"Sorter -!-")
|
|
end
|
|
return;
|
|
end
|
|
end
|
|
if(sortInventory(minetest.get_player_by_name(name):get_inventory(),sorter)) then
|
|
minetest.chat_send_player(name,"Sorted.","Sorter -!-")
|
|
end
|
|
end
|
|
})
|