From 109f6e1aa650328c0c2fcc2b4302ad7e7bc178b4 Mon Sep 17 00:00:00 2001 From: Evert Date: Mon, 9 Apr 2018 23:43:15 +0300 Subject: [PATCH] Custom InvRef implementation for in-memory cache --- crafting.lua | 2 +- init.lua | 3 + items/storage_disk.lua | 99 ------------- masscache.lua | 233 ++++++++++++++++++++++++++++++ nodes/bus.lua | 1 - nodes/common.lua | 6 +- nodes/disk_drive.lua | 6 +- textures/holostorage_external.png | Bin 0 -> 472 bytes 8 files changed, 243 insertions(+), 107 deletions(-) create mode 100644 masscache.lua create mode 100644 textures/holostorage_external.png diff --git a/crafting.lua b/crafting.lua index 4c09f21..5cbdd41 100644 --- a/crafting.lua +++ b/crafting.lua @@ -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({ diff --git a/init.lua b/init.lua index 33fcd37..704454a 100644 --- a/init.lua +++ b/init.lua @@ -7,6 +7,9 @@ holostorage.modpath = modpath holostorage.devices = {} +-- Memory Storage +dofile(modpath.."/masscache.lua") + -- Network dofile(modpath.."/network.lua") diff --git a/items/storage_disk.lua b/items/storage_disk.lua index f86af57..1a088ce 100644 --- a/items/storage_disk.lua +++ b/items/storage_disk.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 diff --git a/masscache.lua b/masscache.lua new file mode 100644 index 0000000..7e561a2 --- /dev/null +++ b/masscache.lua @@ -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) diff --git a/nodes/bus.lua b/nodes/bus.lua index 7f62bfc..1b7854e 100644 --- a/nodes/bus.lua +++ b/nodes/bus.lua @@ -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 diff --git a/nodes/common.lua b/nodes/common.lua index 90a6f97..37c039b 100644 --- a/nodes/common.lua +++ b/nodes/common.lua @@ -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 diff --git a/nodes/disk_drive.lua b/nodes/disk_drive.lua index 6379c80..36fa9bb 100644 --- a/nodes/disk_drive.lua +++ b/nodes/disk_drive.lua @@ -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 diff --git a/textures/holostorage_external.png b/textures/holostorage_external.png new file mode 100644 index 0000000000000000000000000000000000000000..992ab70994c9f9cf87a1a1252a86f6ee34139ee9 GIT binary patch literal 472 zcmV;}0Vn>6P)WFU8GbZ8()Nlj2>E@cM*00BHnL_t(I%bk)l--?9iYXC7AjF84 zg<31MR**>J$e1$@^kqR3^E|)C!`wTgL~jkvGXM_c7y&Rd`ZTcsVuec_QsP_+!Of7w z!=FdKg5N)WVL*r}UA^&>uiL6Dgn;M60e8O!?E_xY-1&ZcOK^Akw!>iiox83D%