Custom InvRef implementation for in-memory cache
This commit is contained in:
parent
dfc8e4adcc
commit
109f6e1aa6
@ -66,7 +66,7 @@ if quartz then
|
||||
minetest.register_craft({
|
||||
type = "cooking",
|
||||
output = "holostorage:silicon",
|
||||
recipe = "holostorage:quartz_iron"
|
||||
recipe = "quartz:quartz_crystal"
|
||||
})
|
||||
else
|
||||
minetest.register_craft({
|
||||
|
3
init.lua
3
init.lua
@ -7,6 +7,9 @@ holostorage.modpath = modpath
|
||||
|
||||
holostorage.devices = {}
|
||||
|
||||
-- Memory Storage
|
||||
dofile(modpath.."/masscache.lua")
|
||||
|
||||
-- Network
|
||||
dofile(modpath.."/network.lua")
|
||||
|
||||
|
@ -1,29 +1,6 @@
|
||||
-- Storage disks
|
||||
|
||||
holostorage.disks = {}
|
||||
holostorage.disks.memcache = {}
|
||||
|
||||
local function inv_to_table(inv)
|
||||
local t = {}
|
||||
for listname, list in pairs(inv:get_lists()) do
|
||||
local size = inv:get_size(listname)
|
||||
if size then
|
||||
t[listname] = {}
|
||||
for i = 1, size, 1 do
|
||||
t[listname][i] = inv:get_stack(listname, i):to_table()
|
||||
end
|
||||
end
|
||||
end
|
||||
return t
|
||||
end
|
||||
|
||||
local function table_to_inv(inv, t)
|
||||
for listname, list in pairs(t) do
|
||||
for i, stack in pairs(list) do
|
||||
inv:set_stack(listname, i, stack)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
function holostorage.disks.register_disk(index, desc, capacity)
|
||||
local mod = minetest.get_current_modname()
|
||||
@ -40,88 +17,12 @@ function holostorage.disks.register_disk(index, desc, capacity)
|
||||
})
|
||||
end
|
||||
|
||||
local function create_invref(ptr, capacity)
|
||||
local inv = minetest.create_detached_inventory(ptr, {})
|
||||
inv:set_size("main", capacity)
|
||||
return inv
|
||||
end
|
||||
|
||||
function holostorage.disks.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.disks.memcache[diskid] = create_invref(diskid, cap)
|
||||
end
|
||||
|
||||
return stack
|
||||
end
|
||||
|
||||
function holostorage.disks.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(diskptr, cap)
|
||||
minetest.mkdir(directory)
|
||||
|
||||
local filetag = minetest.sha1(diskptr)..".invref"
|
||||
local file = io.open(directory.."/"..filetag)
|
||||
|
||||
if not file then
|
||||
holostorage.disks.memcache[diskptr] = inv
|
||||
return diskptr
|
||||
end
|
||||
|
||||
local str = ""
|
||||
for line in file:lines() do
|
||||
str = str..line
|
||||
end
|
||||
|
||||
file:close()
|
||||
|
||||
table_to_inv(inv, minetest.deserialize(str))
|
||||
holostorage.disks.memcache[diskptr] = inv
|
||||
return diskptr
|
||||
end
|
||||
|
||||
function holostorage.disks.save_disk_to_file(diskptr)
|
||||
if not holostorage.disks.memcache[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.disks.memcache[diskptr]
|
||||
local data = minetest.serialize(inv_to_table(inv))
|
||||
|
||||
minetest.safe_file_write(directory.."/"..filetag, data)
|
||||
return diskptr
|
||||
end
|
||||
|
||||
function holostorage.disks.save_disks_to_file()
|
||||
for diskptr in pairs(holostorage.disks.memcache) do
|
||||
holostorage.disks.save_disk_to_file(diskptr)
|
||||
end
|
||||
end
|
||||
|
||||
-- Make sure stack is disk
|
||||
function holostorage.disks.is_valid_disk(stack)
|
||||
local stack_name = stack:get_name()
|
||||
return minetest.get_item_group(stack_name, "holostorage_disk") > 0
|
||||
end
|
||||
|
||||
-- Save disks on shutdown
|
||||
minetest.register_on_shutdown(function ()
|
||||
holostorage.disks.save_disks_to_file()
|
||||
end)
|
||||
|
||||
local capacities = {1000, 8000, 16000, 32000, 64000}
|
||||
local descriptions = {"1K Disk", "8K Disk", "16K Disk", "32K Disk", "64K Disk"}
|
||||
for i = 1, 5 do
|
||||
|
233
masscache.lua
Normal file
233
masscache.lua
Normal file
@ -0,0 +1,233 @@
|
||||
|
||||
-- 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
|
||||
for i,stc in pairs(system.stacks) do
|
||||
if not stc or stc:is_empty() then
|
||||
system[i] = stack
|
||||
break
|
||||
end
|
||||
|
||||
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
|
||||
else
|
||||
break
|
||||
end
|
||||
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)
|
@ -197,7 +197,6 @@ minetest.register_node("holostorage:export_bus", {
|
||||
meta:set_string("infotext", "Inventory full")
|
||||
end
|
||||
|
||||
|
||||
meta:set_string("infotext", "Exporting to Inventory at "..front_pos)
|
||||
|
||||
if can_take then
|
||||
|
@ -53,7 +53,7 @@ function holostorage.stack_list(pos)
|
||||
local tabl = {}
|
||||
|
||||
for _,diskptr in pairs(invs) do
|
||||
local invref = holostorage.disks.memcache[diskptr]
|
||||
local invref = holostorage.server_inventory.cache[diskptr]
|
||||
local inv_n = "main"
|
||||
local inv_p
|
||||
if diskptr:find("chest/") then
|
||||
@ -86,7 +86,7 @@ function holostorage.insert_stack(pos, stack)
|
||||
local leftover
|
||||
|
||||
for _,diskptr in pairs(invs) do
|
||||
local invref = holostorage.disks.memcache[diskptr]
|
||||
local invref = holostorage.server_inventory.cache[diskptr]
|
||||
local inv_n = "main"
|
||||
local inv_p
|
||||
if diskptr:find("chest/") then
|
||||
@ -116,7 +116,7 @@ function holostorage.take_stack(pos, stack)
|
||||
local success = false
|
||||
|
||||
for _,diskptr in pairs(invs) do
|
||||
local invref = holostorage.disks.memcache[diskptr]
|
||||
local invref = holostorage.server_inventory.cache[diskptr]
|
||||
local inv_n = "main"
|
||||
local inv_p
|
||||
if diskptr:find("chest/") then
|
||||
|
@ -111,7 +111,7 @@ local function register_disk_drive(index)
|
||||
minetest.get_node_timer(pos):start(0.02)
|
||||
end,
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
stack = holostorage.disks.ensure_disk_inventory(stack, minetest.pos_to_string(pos))
|
||||
stack = holostorage.server_inventory.ensure_disk_inventory(stack, minetest.pos_to_string(pos))
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
@ -149,9 +149,9 @@ minetest.register_abm({
|
||||
local meta = stack:get_meta()
|
||||
local tag = meta:get_string("storage_tag")
|
||||
if tag and tag ~= "" then
|
||||
if not holostorage.disks.memcache[tag] then
|
||||
if not holostorage.server_inventory.cache[tag] then
|
||||
print("loading drive",tag)
|
||||
holostorage.disks.load_disk_from_file(stack, tag)
|
||||
holostorage.server_inventory.load_disk_from_file(stack, tag)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
BIN
textures/holostorage_external.png
Normal file
BIN
textures/holostorage_external.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 472 B |
Loading…
Reference in New Issue
Block a user