holostorage/masscache.lua

235 lines
5.1 KiB
Lua

-- INVENTORY CACHE
holostorage.server_inventory = {
cache = {},
new = function (size)
local system = {
size = size,
stacks = {}
}
function system:get_size(abs)
return system.size
end
function system:get_stack(abs, index)
if not index then index = abs end
if system.stacks[index] then
return system.stacks[index]
end
return ItemStack(nil)
end
function system:set_stack(abs, index, stack)
if not stack then
stack = index
index = abs
end
if type(stack) == "table" or type(stack) == "string" then
stack = ItemStack(stack)
end
system.stacks[index] = stack
return stack
end
function system:get_list(abs)
return system.stacks
end
function system:set_list(abs, list)
if not list then list = abs end
system.stacks = list
end
function system:get_width(abs)
local size = 0
for _,v in pairs(system.stacks) do
if v and not v:is_empty() then
size = size + 1
end
end
return size
end
function system:first_empty_index()
local index = 0
local last = 0
for inx, stack in pairs(system.stacks) do
if stack:is_empty() then
index = inx
break
end
if last ~= inx - 1 then
index = inx - 1
break
end
last = inx
end
if index == 0 then
return #system.stacks + 1
end
return index
end
function system:room_for_item(abs, stack)
if not stack then stack = abs end
local matching = false
if system:get_width() < system.size then return true end
for _,stc in pairs(system.stacks) do
if not stc or stc:is_empty() then
matching = true
break
end
if stc:get_name() == stack:get_name() and
stc:get_meta() == stack:get_meta() then
if stc:item_fits(stack) then
matching = true
break
end
end
end
return matching
end
function system:add_item(abs, stack)
if not stack then stack = abs end
local leftover = nil
local first_empty_index = system:first_empty_index()
local added = false
for i, stc in pairs(system.stacks) do
if stc:get_name() == stack:get_name() and stc:get_meta() == stack:get_meta() then
if stc:get_count() == stack:get_stack_max() then
break
end
leftover = system.stacks[i]:add_item(stack)
if leftover and not leftover:is_empty() and system:room_for_item(leftover) then
leftover = system:add_item(leftover)
end
added = true
break
end
end
if added then return leftover end
if not leftover then
system.stacks[system:first_empty_index()] = stack
leftover = ItemStack(nil)
end
return leftover
end
return system
end,
from_table = function (inv, table)
if table["main"] then
table = table["main"]
end
for i, stack in pairs(table) do
inv:set_stack(i, stack)
end
return inv
end,
to_table = function (inv)
local t = {}
local size = inv:get_size()
if size then
for i = 1, size, 1 do
t[i] = inv:get_stack(i):to_table()
end
end
return t
end
}
local function create_invref(capacity)
return holostorage.server_inventory.new(capacity)
end
function holostorage.server_inventory.ensure_disk_inventory(stack, pstr)
local meta = stack:get_meta()
local tag = meta:get_string("storage_tag")
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
if not tag or tag == "" then
local rnd = PseudoRandom(os.clock())
local rndint = rnd.next(rnd)
local diskid = "d"..pstr.."-"..rndint
meta:set_string("storage_tag", diskid)
holostorage.server_inventory.cache[diskid] = create_invref(cap)
end
return stack
end
function holostorage.server_inventory.load_disk_from_file(stack, diskptr)
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local cap = minetest.registered_items[stack:get_name()].holostorage_capacity
local inv = create_invref(cap)
minetest.mkdir(directory)
local filetag = minetest.sha1(diskptr)..".invref"
local file = io.open(directory.."/"..filetag)
if not file then
holostorage.server_inventory.cache[diskptr] = inv
return diskptr
end
local str = ""
for line in file:lines() do
str = str..line
end
file:close()
holostorage.server_inventory.from_table(inv, minetest.deserialize(str))
holostorage.server_inventory.cache[diskptr] = inv
return diskptr
end
function holostorage.server_inventory.save_disk_to_file(diskptr)
if not holostorage.server_inventory.cache[diskptr] then return nil end
local world = minetest.get_worldpath()
local directory = world.."/holostorage"
local filetag = minetest.sha1(diskptr)..".invref"
minetest.mkdir(directory)
local inv = holostorage.server_inventory.cache[diskptr]
local data = minetest.serialize(holostorage.server_inventory.to_table(inv))
minetest.safe_file_write(directory.."/"..filetag, data)
return diskptr
end
function holostorage.server_inventory.save_disks_to_file()
for diskptr in pairs(holostorage.server_inventory.cache) do
holostorage.server_inventory.save_disk_to_file(diskptr)
end
end
-- Save disks on shutdown
minetest.register_on_shutdown(function ()
holostorage.server_inventory.save_disks_to_file()
end)