From 3a40ab22293a3ed4009f9578de17ed6cda2ef044 Mon Sep 17 00:00:00 2001 From: Evert Date: Sun, 8 Apr 2018 12:39:06 +0300 Subject: [PATCH] FINALLY! A working system! --- items/storage_disk.lua | 156 +++++++++++++-------------- network.lua | 58 +++++++++- nodes.lua | 1 - nodes/common.lua | 11 +- nodes/crafting_grid.lua | 53 --------- nodes/disk_drive.lua | 119 ++++++++++++++++++-- nodes/grid.lua | 233 +++++++++++++++++++++++++++++++++++++++- 7 files changed, 483 insertions(+), 148 deletions(-) delete mode 100644 nodes/crafting_grid.lua diff --git a/items/storage_disk.lua b/items/storage_disk.lua index bd133b1..ccaa7f9 100644 --- a/items/storage_disk.lua +++ b/items/storage_disk.lua @@ -1,6 +1,7 @@ -- Storage disks storagetest.disks = {} +storagetest.disks.memcache = {} local function inv_to_table(inv) local t = {} @@ -24,12 +25,6 @@ local function table_to_inv(inv, t) end end -local function save_inv_itemstack(inv, stack) - local meta = stack:get_meta() - meta:set_string("storagetest_inventory", minetest.serialize(inv_to_table(inv))) - return stack -end - function storagetest.disks.register_disk(index, desc, capacity) local mod = minetest.get_current_modname() minetest.register_craftitem(mod..":storage_disk"..index, { @@ -40,91 +35,92 @@ function storagetest.disks.register_disk(index, desc, capacity) storagetest_name = "disk"..index, stack_max = 1, on_secondary_use = function (itemstack, user, pointed_thing) - local inv, stack = storagetest.disks.add_stack(itemstack, ItemStack("default:cobble 99")) - if not inv then print("full!"); return itemstack end return stack end }) end +local function create_invref(ptr, capacity) + local inv = minetest.create_detached_inventory(ptr, {}) + inv:set_size("main", capacity) + return inv +end + +function storagetest.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()].storagetest_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) + storagetest.disks.memcache[diskid] = create_invref(diskid, cap) + end + + return stack +end + +function storagetest.disks.load_disk_from_file(stack, diskptr) + local world = minetest.get_worldpath() + local directory = world.."/storagetest" + local cap = minetest.registered_items[stack:get_name()].storagetest_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 + storagetest.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)) + storagetest.disks.memcache[diskptr] = inv + return diskptr +end + +function storagetest.disks.save_disk_to_file(diskptr) + if not storagetest.disks.memcache[diskptr] then return nil end + + local world = minetest.get_worldpath() + local directory = world.."/storagetest" + local filetag = minetest.sha1(diskptr)..".invref" + + minetest.mkdir(directory) + + local inv = storagetest.disks.memcache[diskptr] + local data = minetest.serialize(inv_to_table(inv)) + + minetest.safe_file_write(directory.."/"..filetag, data) + return diskptr +end + +function storagetest.disks.save_disks_to_file() + for diskptr in pairs(storagetest.disks.memcache) do + storagetest.disks.save_disk_to_file(diskptr) + end +end + -- Make sure stack is disk function storagetest.disks.is_valid_disk(stack) local stack_name = stack:get_name() return minetest.get_item_group(stack_name, "storagetest_disk") > 0 end -function storagetest.disks.get_stack_inventory(stack) - if not storagetest.disks.is_valid_disk(stack) then return nil end - local stack_name = stack:get_name() - local meta = stack:get_meta() - local name = minetest.registered_items[stack_name].storagetest_name - local capacity = minetest.registered_items[stack_name].storagetest_capacity - - local inv = minetest.create_detached_inventory(name, { - - }) - inv:set_size("main", capacity) - local invmetastring = meta:get_string("storagetest_inventory") - - if invmetastring ~= "" then - table_to_inv(inv, minetest.deserialize(invmetastring)) - save_inv_itemstack(inv, stack) - end - - return inv, stack -end - -function storagetest.disks.save_stack_inventory(inv, stack) - if not storagetest.disks.is_valid_disk(stack) then return nil end - stack = save_inv_itemstack(inv, stack) - - local meta = stack:get_meta() - local capacity = minetest.registered_items[stack:get_name()].storagetest_capacity - local desc = minetest.registered_items[stack:get_name()].description - meta:set_string("description", desc.."\nContains "..storagetest.disks.get_stack_count(nil, inv).."/"..capacity) - - return inv, stack -end - -function storagetest.disks.get_stack_count(stack, invn) - local inv = invn or storagetest.disks.get_stack_inventory(stack) - if not inv then return 0 end - - local count = 0 - for _,v in pairs(inv:get_list("main")) do - if not v:is_empty() then - count = count + 1 - end - end - - return count -end - -function storagetest.disks.add_stack(stack, item) - local inv = storagetest.disks.get_stack_inventory(stack) - if not inv then return nil end - if not inv:room_for_item("main", item) then return nil end - - inv:add_item("main", item) - - return storagetest.disks.save_stack_inventory(inv, stack) -end - -function storagetest.disks.has_stack(stack, item) - local inv = storagetest.disks.get_stack_inventory(stack) - if not inv then return nil end - return inv:contains_item("main", item, true) -end - -function storagetest.disks.take_stack(stack, item) - local inv = storagetest.disks.get_stack_inventory(stack) - if not inv then return nil end - local item = inv:remove_item("main", item) - - inv, stack = storagetest.disks.save_stack_inventory(inv, stack) - - return item, stack -end +-- Save disks on shutdown +minetest.register_on_shutdown(function () + storagetest.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"} diff --git a/network.lua b/network.lua index 046d2df..b17c912 100644 --- a/network.lua +++ b/network.lua @@ -236,7 +236,6 @@ function storagetest.network.register_abm_controller(name) end dv_nodes, st_nodes = get_network(pos, ntwks) - local network_id = minetest.hash_node_position(pos) -- Run all the nodes local function run_nodes(list) @@ -248,7 +247,7 @@ function storagetest.network.register_abm_controller(name) nodedef = minetest.registered_nodes[node2.name] end if nodedef and nodedef.storagetest_run then - nodedef.storagetest_run(pos2, node2, network_id) + nodedef.storagetest_run(pos2, node2, pos) end end end @@ -399,3 +398,58 @@ function storagetest.network.register_abm_nodes() end, }) end + +----------------------- +-- Network Functions -- +----------------------- + +function storagetest.network.get_storage_devices(network_id) + local network = storagetest.network.networks[network_id] + if not network or not network.st_nodes then return {} end + return network.st_nodes +end + +function concat(t1,t2) + for i=1,#t2 do + t1[#t1+1] = t2[i] + end + return t1 +end + +function storagetest.network.get_storage_inventories(network_id) + local storage_nodes = storagetest.network.get_storage_devices(network_id) + local items = {} + + for _,pos in pairs(storage_nodes) do + local stacks = storagetest.stack_list(pos) + items = concat(items, stacks) + end + + return items +end + +function storagetest.network.insert_item(network_id, stack) + local storage_nodes = storagetest.network.get_storage_devices(network_id) + + for _,pos in pairs(storage_nodes) do + local success, leftover = storagetest.insert_stack(pos, stack) + if success then + return success, leftover + end + end + + return nil +end + +function storagetest.network.take_item(network_id, stack) + local storage_nodes = storagetest.network.get_storage_devices(network_id) + + for _,pos in pairs(storage_nodes) do + local success = storagetest.take_stack(pos, stack) + if success then + return success + end + end + + return nil +end diff --git a/nodes.lua b/nodes.lua index 84f68eb..2db6d3f 100644 --- a/nodes.lua +++ b/nodes.lua @@ -14,7 +14,6 @@ dofile(storagetest.modpath.."/nodes/disk_drive.lua") -- Grids dofile(storagetest.modpath.."/nodes/grid.lua") -dofile(storagetest.modpath.."/nodes/crafting_grid.lua") -- Start the network storagetest.network.register_abm_controller("storagetest:controller_active") diff --git a/nodes/common.lua b/nodes/common.lua index d60e352..f6cc873 100644 --- a/nodes/common.lua +++ b/nodes/common.lua @@ -10,9 +10,18 @@ function storagetest.helpers.swap_node(pos, noded) minetest.swap_node(pos, noded) end -function storagetest.helpers.grid_refresh(pos, n, network) +function storagetest.helpers.grid_refresh(pos, n, controller) local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos) local nodedef = minetest.registered_nodes[node.name] + local prev = meta:get_string("controller") + + meta:set_string("infotext", ("%s Active"):format(nodedef.description)) + meta:set_string("controller", minetest.pos_to_string(controller)) + + if not prev or prev == "" then + minetest.get_node_timer(pos):start(0.02) + end if nodedef.storagetest_enabled_name then node.name = nodedef.storagetest_enabled_name diff --git a/nodes/crafting_grid.lua b/nodes/crafting_grid.lua deleted file mode 100644 index 4f8b9c1..0000000 --- a/nodes/crafting_grid.lua +++ /dev/null @@ -1,53 +0,0 @@ --- Crafting Grid - -local function timer(pos, elapsed) - local refresh = false - local meta = minetest.get_meta(pos) - local node = minetest.get_node(pos) - - return refresh -end - -minetest.register_node("storagetest:crafting_grid", { - description = "Crafting Grid", - tiles = { - "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", - "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_crafting_grid.png", - }, - paramtype2 = "facedir", - on_timer = timer, - groups = { - cracky = 1, - storagetest_distributor = 1, - storagetest_device = 1, - }, - on_construct = function (pos) - storagetest.network.clear_networks(pos) - end, - on_destruct = storagetest.network.clear_networks, - storagetest_run = storagetest.helpers.grid_refresh, - storagetest_enabled_name = "storagetest:crafting_grid_active", -}) - -minetest.register_node("storagetest:crafting_grid_active", { - description = "Crafting Grid", - tiles = { - "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", - "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_crafting_grid_active.png", - }, - drop = "storagetest:crafting_grid", - paramtype2 = "facedir", - on_timer = timer, - groups = { - cracky = 1, - storagetest_distributor = 1, - storagetest_device = 1, - not_in_creative_inventory = 1 - }, - on_destruct = storagetest.network.clear_networks, - storagetest_run = storagetest.helpers.grid_refresh, - storagetest_disabled_name = "storagetest:crafting_grid", -}) - -storagetest.devices["storagetest:crafting_grid"] = true -storagetest.devices["storagetest:crafting_grid_active"] = true diff --git a/nodes/disk_drive.lua b/nodes/disk_drive.lua index 4ff067b..a247bce 100644 --- a/nodes/disk_drive.lua +++ b/nodes/disk_drive.lua @@ -43,7 +43,7 @@ local function allow_metadata_inventory_put (pos, listname, index, stack, player return 0 end - if minetest.get_item_group(stack:get_name(), "storagetest_disk") == 0 then + if not storagetest.disks.is_valid_disk(stack) then return 0 end @@ -64,18 +64,92 @@ local function allow_metadata_inventory_take (pos, listname, index, stack, playe return stack:get_count() end +local function sort_by_stack_name( ... ) + -- body +end + +function storagetest.stack_list(pos) + local invs = storagetest.get_all_inventories(pos) + if not invs then return {} end + local tabl = {} + + for _,diskptr in pairs(invs) do + local invref = storagetest.disks.memcache[diskptr] + if invref then + local stacks = invref:get_list("main") + for _,stack in pairs(stacks) do + if not stack:is_empty() then + table.insert(tabl, stack) + end + end + end + end + + --table.sort( tabl, sort_by_stack_name ) + return tabl +end + +function storagetest.insert_stack(pos, stack) + local invs = storagetest.get_all_inventories(pos) + if not invs then return {} end + local tabl = {} + local success = false + local leftover + + for _,diskptr in pairs(invs) do + local invref = storagetest.disks.memcache[diskptr] + if invref then + if invref:room_for_item("main", stack) then + leftover = invref:add_item("main", stack) + success = true + break + end + end + end + + return success, leftover +end + +function storagetest.take_stack(pos, stack) + local invs = storagetest.get_all_inventories(pos) + if not invs then return {} end + local tabl = {} + local success = false + + for _,diskptr in pairs(invs) do + local invref = storagetest.disks.memcache[diskptr] + if invref then + local list = invref:get_list("main") + for i, stacki in pairs(list) do + if stacki:get_name() == stack:get_name() and stacki:get_count() == stack:get_count() and stacki:get_wear() == stack:get_wear() then + success = true + stacki:clear() + list[i] = stacki + break + end + end + invref:set_list("main", list) + end + end + + return success +end + function storagetest.get_all_inventories(pos) local node = minetest.get_node(pos) - if minetest.get_item_group(node.name, "storagetest_storage") == 0 then return nil end + if minetest.get_item_group(node.name, "disk_drive") == 0 then return nil end local meta = minetest.get_meta(pos) local inv = meta:get_inventory() - local drives = inv:get_list("meta") + local drives = inv:get_list("main") local inventories = {} for i, v in pairs(drives) do if not v:is_empty() then - local inv1, stack = storagetest.disks.get_stack_inventory(v) - inventories[i] = {inventory = inv1, stack = stack} + local meta = v:get_meta() + local tag = meta:get_string("storage_tag") + if tag and tag ~= "" then + inventories[#inventories + 1] = tag + end end end @@ -88,6 +162,7 @@ local function register_disk_drive(index) storagetest_distributor = 1, storagetest_device = 1, storagetest_storage = 1, + disk_drive = 1, } local driveoverlay = "" @@ -123,7 +198,14 @@ local function register_disk_drive(index) on_metadata_inventory_move = function(pos) minetest.get_node_timer(pos):start(0.02) end, - on_metadata_inventory_put = function(pos) + on_metadata_inventory_put = function(pos, listname, index, stack, player) + stack = storagetest.disks.ensure_disk_inventory(stack, minetest.pos_to_string(pos)) + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + inv:set_stack(listname, index, stack) + minetest.get_node_timer(pos):start(0.02) end, on_metadata_inventory_take = function(pos) @@ -138,3 +220,28 @@ end for i = 0, 6 do register_disk_drive(i) end + +-- Create ABM for syncing disks +minetest.register_abm({ + label = "Storage Disk Synchronization", + nodenames = {"group:disk_drive"}, + neighbors = {"group:storagetest_distributor"}, + interval = 5, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + + local disks = inv:get_list("main") + for _,stack in pairs(disks) do + local meta = stack:get_meta() + local tag = meta:get_string("storage_tag") + if tag and tag ~= "" then + if not storagetest.disks.memcache[tag] then + print("loading drive",tag) + storagetest.disks.load_disk_from_file(stack, tag) + end + end + end + end +}) diff --git a/nodes/grid.lua b/nodes/grid.lua index d3c5ba7..01c254f 100644 --- a/nodes/grid.lua +++ b/nodes/grid.lua @@ -2,25 +2,142 @@ storagetest.grid = {} -function storagetest.grid.get_formspec(inventories, scroll_lvl, craft_inv) +function storagetest.grid.get_formspec(scroll_lvl, craft_inv) + local craft = "" + local title = "Grid" + local height = 6 + + if craft_inv then + title = "Crafting Grid" + height = 3 + craft = "list[current_player;craft;1.5,4.5;3,3;]".. + "image[4.5,5.5;1,1;gui_furnace_arrow_bg.png^[transformR270]".. + "list[current_player;craftpreview;5.5,5.5;1,1;]" + end + return "size[8,12]".. default.gui_bg.. default.gui_bg_img.. default.gui_slots.. - "label[0,0;Grid]".. - "list[context;main;0,0;1,1;]".. - "list[context;grid;0,1;7,6;]".. + "label[0,0;"..title.."]".. + "list[context;main;0,7;1,1;]".. + "list[context;grid;0,0.5;7,"..height..";]".. "list[current_player;main;0,8;8,1;]".. "list[current_player;main;0,9.2;8,3;8]".. + craft.. "listring[context;main]".. "listring[current_player;main]".. default.get_hotbar_bg(0, 8) end +function storagetest.grid.to_network(meta) + local ctrl = meta:get_string("controller") + if not ctrl or ctrl == "" then return nil end + local network = minetest.hash_node_position(minetest.string_to_pos(ctrl)) + return network +end + +function storagetest.grid.handle_grid(pos, meta, network, inv) + local refresh = false + local limited_items = {} + + local items = storagetest.network.get_storage_inventories(network) + local scroll = meta:get_int("scroll_len") or 0 + local grid = inv:get_size("grid") + + for i = (scroll * 7) + 1, grid + (scroll * 7) do + if items[i] then + limited_items[#limited_items + 1] = items[i] + end + end + + inv:set_list("grid", limited_items) + + -- Handle inputting items + local input = inv:get_stack("main", 1) + if not input:is_empty() then + local success, leftover = storagetest.network.insert_item(network, input) + if success then + inv:set_stack("main", 1, leftover) + refresh = true + end + end + + return refresh +end + +function storagetest.grid.allow_put(pos, listname, index, stack, player) + if minetest.is_protected(pos, player:get_player_name()) then + return 0 + end + + if listname == "grid" or listname == "craftpreview" then + return 0 + end + + return stack:get_count() +end + +function storagetest.grid.allow_move_active(pos, from_list, from_index, to_list, to_index, count, player) + if from_list == "grid" and to_list == "main" then + return 0 + end + + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(from_list, from_index) + + return storagetest.grid.allow_put(pos, to_list, to_index, stack, player) +end + +function storagetest.grid.on_disable(pos) + local meta = minetest.get_meta(pos) + local prev = meta:get_string("controller") + if prev and prev ~= "" then + meta:set_string("controller", "") + minetest.get_node_timer(pos):start(0.02) + end +end + +function storagetest.grid.on_move(pos, from_list, from_index, to_list, to_index, count, player) + if from_list == "grid" and to_list == "craft" then + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + local stack = inv:get_stack(to_list, to_index) + local meta = minetest.get_meta(pos) + local network = storagetest.grid.to_network(meta) + if network then + storagetest.network.take_item(network, stack) + end + end + + minetest.get_node_timer(pos):start(0.02) +end + +function storagetest.grid.on_take(pos, listname, index, stack, player) + if listname == "grid" then + local meta = minetest.get_meta(pos) + local network = storagetest.grid.to_network(meta) + if network then + storagetest.network.take_item(network, stack) + end + end + + minetest.get_node_timer(pos):start(0.02) +end + local function timer(pos, elapsed) local refresh = false local meta = minetest.get_meta(pos) local node = minetest.get_node(pos) + local inv = meta:get_inventory() + local network = storagetest.grid.to_network(meta) + + if not network then + inv:set_list("grid", {}) + else + refresh = storagetest.grid.handle_grid(pos, meta, network, inv) + end return refresh end @@ -41,15 +158,31 @@ minetest.register_node("storagetest:grid", { on_construct = function (pos) storagetest.network.clear_networks(pos) local meta = minetest.get_meta(pos) - meta:set_string("formspec", storagetest.grid.get_formspec(nil, 1)) + meta:set_string("formspec", storagetest.grid.get_formspec(0)) local inv = meta:get_inventory() inv:set_size("main", 1) inv:set_size("grid", 7*6) + + meta:set_int("scroll_len", 0) + end, + on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + minetest.get_node_timer(pos):start(0.02) + return itemstack end, on_destruct = storagetest.network.clear_networks, storagetest_run = storagetest.helpers.grid_refresh, + allow_metadata_inventory_move = function () + return 0 + end, + allow_metadata_inventory_put = function () + return 0 + end, + allow_metadata_inventory_take = function () + return 0 + end, storagetest_enabled_name = "storagetest:grid_active", + storagetest_on_disable = storagetest.grid.on_disable, }) minetest.register_node("storagetest:grid_active", { @@ -67,10 +200,100 @@ minetest.register_node("storagetest:grid_active", { storagetest_device = 1, not_in_creative_inventory = 1 }, + on_metadata_inventory_move = storagetest.grid.on_move, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.get_node_timer(pos):start(0.02) + end, + on_metadata_inventory_take = storagetest.grid.on_take, + on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + minetest.get_node_timer(pos):start(0.05) + return itemstack + end, on_destruct = storagetest.network.clear_networks, storagetest_run = storagetest.helpers.grid_refresh, storagetest_disabled_name = "storagetest:grid", + allow_metadata_inventory_move = storagetest.grid.allow_move_active, + allow_metadata_inventory_put = storagetest.grid.allow_put, +}) + +-- Crafting version + +minetest.register_node("storagetest:crafting_grid", { + description = "Crafting Grid", + tiles = { + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_crafting_grid.png", + }, + paramtype2 = "facedir", + on_timer = timer, + groups = { + cracky = 1, + storagetest_distributor = 1, + storagetest_device = 1, + }, + on_construct = function (pos) + storagetest.network.clear_networks(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", storagetest.grid.get_formspec(0, true)) + + local inv = meta:get_inventory() + inv:set_size("main", 1) + inv:set_size("grid", 7*3) + + meta:set_int("scroll_len", 0) + end, + on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + minetest.get_node_timer(pos):start(0.02) + return itemstack + end, + on_destruct = storagetest.network.clear_networks, + storagetest_run = storagetest.helpers.grid_refresh, + allow_metadata_inventory_move = function () + return 0 + end, + allow_metadata_inventory_put = function () + return 0 + end, + allow_metadata_inventory_take = function () + return 0 + end, + storagetest_enabled_name = "storagetest:crafting_grid_active", + storagetest_on_disable = storagetest.grid.on_disable, +}) + +minetest.register_node("storagetest:crafting_grid_active", { + description = "Crafting Grid", + tiles = { + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_crafting_grid_active.png", + }, + drop = "storagetest:crafting_grid", + paramtype2 = "facedir", + on_timer = timer, + groups = { + cracky = 1, + storagetest_distributor = 1, + storagetest_device = 1, + not_in_creative_inventory = 1 + }, + on_metadata_inventory_move = storagetest.grid.on_move, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + minetest.get_node_timer(pos):start(0.02) + end, + on_metadata_inventory_take = storagetest.grid.on_take, + on_rightclick = function (pos, node, clicker, itemstack, pointed_thing) + minetest.get_node_timer(pos):start(0.05) + return itemstack + end, + on_destruct = storagetest.network.clear_networks, + storagetest_run = storagetest.helpers.grid_refresh, + storagetest_disabled_name = "storagetest:crafting_grid", + allow_metadata_inventory_move = storagetest.grid.allow_move_active, + allow_metadata_inventory_put = storagetest.grid.allow_put, }) storagetest.devices["storagetest:grid"] = true storagetest.devices["storagetest:grid_active"] = true + +storagetest.devices["storagetest:crafting_grid"] = true +storagetest.devices["storagetest:crafting_grid_active"] = true