diff --git a/init.lua b/init.lua index bdbdd11..c6e6541 100644 --- a/init.lua +++ b/init.lua @@ -5,5 +5,10 @@ storagetest = rawget(_G, "storagetest") or {} local modpath = minetest.get_modpath(minetest.get_current_modname()) storagetest.modpath = modpath +storagetest.devices = {} + +-- Network +dofile(modpath.."/network.lua") + -- Nodes dofile(modpath.."/nodes.lua") diff --git a/network.lua b/network.lua new file mode 100644 index 0000000..eeadfbe --- /dev/null +++ b/network.lua @@ -0,0 +1,408 @@ +-- Storagetest Network +-- Some code borrowed from Technic (https://github.com/minetest-mods/technic/blob/master/technic/machines/switching_station.lua) + +storagetest.network = {} +storagetest.network.networks = {} +storagetest.network.devices = {} +storagetest.network.redundant_warn = {} + +function storagetest.get_or_load_node(pos) + local node = minetest.get_node_or_nil(pos) + if node then return node end + local vm = VoxelManip() + local MinEdge, MaxEdge = vm:read_from_map(pos, pos) + return nil +end + +local function get_item_group(name, grp) + return minetest.get_item_group(name, grp) > 0 +end + +function storagetest.network.is_network_conductor(name) + return get_item_group(name, "storagetest_distributor") +end + +function storagetest.network.is_network_device(name) + return get_item_group(name, "storagetest_device") +end + +----------------------- +-- Network traversal -- +----------------------- + +local function flatten(map) + local list = {} + for key, value in pairs(map) do + list[#list + 1] = value + end + return list +end + +-- Add a node to the network +local function add_network_node(nodes, pos, network_id) + local node_id = minetest.hash_node_position(pos) + storagetest.network.devices[node_id] = network_id + if nodes[node_id] then + return false + end + nodes[node_id] = pos + return true +end + +local function add_cable_node(nodes, pos, network_id, queue) + if add_network_node(nodes, pos, network_id) then + queue[#queue + 1] = pos + end +end + +local check_node_subp = function(dv_nodes, st_nodes, controllers, all_nodes, pos, devices, c_pos, network_id, queue) + storagetest.get_or_load_node(pos) + local meta = minetest.get_meta(pos) + local name = minetest.get_node(pos).name + + if storagetest.network.is_network_conductor(name) then + add_cable_node(all_nodes, pos, network_id, queue) + end + + if devices[name] then + meta:set_string("st_network", minetest.pos_to_string(c_pos)) + if get_item_group(name, "storagetest_controller") then + -- Another controller, disable it + add_network_node(controllers, pos, network_id) + meta:set_int("active", 0) + elseif get_item_group(name, "storagetest_storage") then + add_network_node(st_nodes, pos, network_id) + elseif storagetest.network.is_network_device(name) then + add_network_node(dv_nodes, pos, network_id) + end + + meta:set_int("nw_timeout", 2) + end +end + +-- Traverse a network given a list of machines and a cable type name +local traverse_network = function(dv_nodes, st_nodes, controllers, all_nodes, pos, devices, c_pos, network_id, queue) + local positions = { + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y+1, z=pos.z}, + {x=pos.x, y=pos.y-1, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z+1}, + {x=pos.x, y=pos.y, z=pos.z-1}} + for _, cur_pos in pairs(positions) do + check_node_subp(dv_nodes, st_nodes, controllers, all_nodes, cur_pos, devices, c_pos, network_id, queue) + end +end + +local touch_nodes = function(list) + for _, pos in ipairs(list) do + local meta = minetest.get_meta(pos) + meta:set_int("nw_timeout", 2) -- Touch node + end +end + +local function get_network(c_pos, positions) + local network_id = minetest.hash_node_position(c_pos) + local cached = storagetest.network.networks[network_id] + + if cached then + touch_nodes(cached.dv_nodes) + touch_nodes(cached.st_nodes) + for _, pos in ipairs(cached.controllers) do + local meta = minetest.get_meta(pos) + meta:set_int("active", 0) + meta:set_string("active_pos", minetest.serialize(c_pos)) + end + return cached.dv_nodes, cached.st_nodes + end + + local dv_nodes = {} + local st_nodes = {} + local controllers = {} + local all_nodes = {} + local queue = {} + + for pos in pairs(positions) do + queue = {} + + local node = minetest.get_node(pos) + if node and storagetest.network.is_network_conductor(node.name) and not storagetest.network.is_network_device(node.name) then + add_cable_node(all_nodes, pos, network_id, queue) + elseif node and storagetest.network.is_network_device(node.name) then + queue = {c_pos} + end + + while next(queue) do + local to_visit = {} + for _, posi in ipairs(queue) do + traverse_network(dv_nodes, st_nodes, controllers, all_nodes, + posi, storagetest.devices, c_pos, network_id, to_visit) + end + queue = to_visit + end + end + + dv_nodes = flatten(dv_nodes) + st_nodes = flatten(st_nodes) + controllers = flatten(controllers) + all_nodes = flatten(all_nodes) + + storagetest.network.networks[network_id] = {all_nodes = all_nodes, dv_nodes = dv_nodes, + st_nodes = st_nodes, controllers = controllers} + return dv_nodes, st_nodes +end + +-------------------- +-- Controller ABM -- +-------------------- + +storagetest.network.active_state = true + +minetest.register_chatcommand("storagectl", { + params = "state", + description = "Enables or disables Storagetest's storage controller ABM", + privs = { basic_privs = true }, + func = function(name, state) + if state == "on" then + storagetest.network.active_state = true + else + storagetest.network.active_state = false + end + end +}) + +local function concatinate(t1,t2) + for i=1,#t2 do + t1[#t1+1] = t2[i] + end + return t1 +end + +function storagetest.network.register_abm_controller(name) + minetest.register_abm({ + nodenames = {name}, + label = "Storage Controller", -- allows the mtt profiler to profile this abm individually + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + if not storagetest.network.active_state then return end + local meta = minetest.get_meta(pos) + local meta1 = nil + + local dv_nodes = {} + local st_nodes = {} + local device_name = "Storage Controller" + + local positions = { + {x=pos.x, y=pos.y-1, z=pos.z}, + {x=pos.x, y=pos.y+1, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z-1}, + {x=pos.x, y=pos.y, z=pos.z+1} + } + + local ntwks = {} + local errored = false + local nw_branches = 0 + for _,pos1 in pairs(positions) do + --Disable if necessary + if meta:get_int("active") ~= 1 then + minetest.forceload_free_block(pos) + minetest.forceload_free_block(pos1) + meta:set_string("infotext",("%s Already Present"):format(device_name)) + + local poshash = minetest.hash_node_position(pos) + + if not storagetest.network.redundant_warn[poshash] then + storagetest.network.redundant_warn[poshash] = true + print("[Storagetest] Warning: redundant controller found near "..minetest.pos_to_string(pos)) + end + errored = true + return + end + + local name = minetest.get_node(pos1).name + local networked = storagetest.network.is_network_conductor(name) + if networked then + ntwks[pos1] = true + nw_branches = nw_branches + 1 + end + end + + if errored then + return + end + + if nw_branches == 0 then + minetest.forceload_free_block(pos) + meta:set_string("infotext", ("%s Has No Network"):format(device_name)) + return + else + minetest.forceload_block(pos) + 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) + for _, pos2 in ipairs(list) do + storagetest.get_or_load_node(pos2) + local node2 = minetest.get_node(pos2) + local nodedef + if node2 and node2.name then + nodedef = minetest.registered_nodes[node2.name] + end + if nodedef and nodedef.storagetest_run then + nodedef.storagetest_run(pos2, node2, network_id) + end + end + end + + run_nodes(dv_nodes) + run_nodes(st_nodes) + + meta:set_string("infotext", ("%s Active"):format(device_name)) + end, + }) +end + +------------------------------------- +-- Update networks on block change -- +------------------------------------- + +local function check_connections(pos) + local machines = {} + for name in pairs(storagetest.devices) do + machines[name] = true + end + local connections = {} + local positions = { + {x=pos.x+1, y=pos.y, z=pos.z}, + {x=pos.x-1, y=pos.y, z=pos.z}, + {x=pos.x, y=pos.y+1, z=pos.z}, + {x=pos.x, y=pos.y-1, z=pos.z}, + {x=pos.x, y=pos.y, z=pos.z+1}, + {x=pos.x, y=pos.y, z=pos.z-1}} + for _,connected_pos in pairs(positions) do + local name = minetest.get_node(connected_pos).name + if machines[name] or storagetest.network.is_network_conductor(name) or get_item_group(name, "storagetest_controller") then + table.insert(connections,connected_pos) + end + end + return connections +end + +function storagetest.network.clear_networks(pos) + local node = minetest.get_node(pos) + local meta = minetest.get_meta(pos) + local name = node.name + local placed = name ~= "air" + local positions = check_connections(pos) + if #positions < 1 then return end + local dead_end = #positions == 1 + for _,connected_pos in pairs(positions) do + local net = storagetest.network.devices[minetest.hash_node_position(connected_pos)] or minetest.hash_node_position(connected_pos) + if net and storagetest.network.networks[net] then + if dead_end and placed then + -- Dead end placed, add it to the network + -- Get the network + local node_at = minetest.get_node(positions[1]) + local network_id = storagetest.network.devices[minetest.hash_node_position(positions[1])] or minetest.hash_node_position(positions[1]) + + if not network_id or not storagetest.network.networks[network_id] then + -- We're evidently not on a network, nothing to add ourselves to + return + end + local c_pos = minetest.get_position_from_hash(network_id) + local network = storagetest.network.networks[network_id] + + -- Actually add it to the (cached) network + -- This is similar to check_node_subp + storagetest.network.devices[minetest.hash_node_position(pos)] = network_id + pos.visited = 1 + + if storagetest.network.is_network_conductor(name) then + table.insert(network.all_nodes, pos) + end + + if storagetest.devices[name] then + meta:set_string("st_network", minetest.pos_to_string(c_pos)) + if get_item_group(name, "storagetest_controller") then + table.insert(network.controllers, pos) + elseif storagetest.network.is_network_device(name) then + table.insert(network.dv_nodes, pos) + end + end + elseif dead_end and not placed then + -- Dead end removed, remove it from the network + -- Get the network + local network_id = storagetest.network.devices[minetest.hash_node_position(positions[1])] or minetest.hash_node_position(positions[1]) + if not network_id or not storagetest.network.networks[network_id] then + -- We're evidently not on a network, nothing to remove ourselves from + return + end + local network = storagetest.network.networks[network_id] + + -- Search for and remove device + storagetest.network.devices[minetest.hash_node_position(pos)] = nil + for tblname,table in pairs(network) do + for devicenum,device in pairs(table) do + if device.x == pos.x + and device.y == pos.y + and device.z == pos.z then + table[devicenum] = nil + end + end + end + else + -- Not a dead end, so the whole network needs to be recalculated + for _,v in pairs(storagetest.network.networks[net].all_nodes) do + local pos1 = minetest.hash_node_position(v) + storagetest.network.devices[pos1] = nil + end + storagetest.network.networks[net] = nil + end + end + end +end + +-- Timeout ABM +-- Timeout for a node in case it was disconnected from the network +-- A node must be touched by the station continuously in order to function +local function controller_timeout_count(pos, tier) + local meta = minetest.get_meta(pos) + local timeout = meta:get_int("nw_timeout") + if timeout <= 0 then + return true + else + meta:set_int("nw_timeout", timeout - 1) + return false + end +end + +function storagetest.network.register_abm_nodes() + minetest.register_abm({ + label = "Devices: timeout check", + nodenames = {"group:storagetest_device"}, + interval = 1, + chance = 1, + action = function(pos, node, active_object_count, active_object_count_wider) + local meta = minetest.get_meta(pos) + if storagetest.devices[node.name] and controller_timeout_count(pos) then + local nodedef = minetest.registered_nodes[node.name] + if nodedef and nodedef.storagetest_disabled_name then + node.name = nodedef.storagetest_disabled_name + minetest.swap_node(pos, node) + elseif nodedef and nodedef.storagetest_on_disable then + nodedef.storagetest_on_disable(pos, node) + end + if nodedef then + local meta = minetest.get_meta(pos) + meta:set_string("infotext", ("%s Has No Network"):format(nodedef.description)) + end + end + end, + }) +end diff --git a/nodes.lua b/nodes.lua index cfa185d..84f68eb 100644 --- a/nodes.lua +++ b/nodes.lua @@ -1 +1,21 @@ -- Storagetest nodes + +-- Common registrations +dofile(storagetest.modpath.."/nodes/common.lua") + +-- Controller +dofile(storagetest.modpath.."/nodes/controller.lua") + +-- Cabling +dofile(storagetest.modpath.."/nodes/cable.lua") + +-- Disk drives +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") +storagetest.network.register_abm_nodes() diff --git a/nodes/cable.lua b/nodes/cable.lua new file mode 100644 index 0000000..9b589b2 --- /dev/null +++ b/nodes/cable.lua @@ -0,0 +1,47 @@ +-- Storagetest cabling + +minetest.register_node("storagetest:cable", { + description = "Storage Cable", + drawtype = "nodebox", + tiles = {"storagetest_cable.png"}, + node_box = { + type = "connected", + fixed = {{-1/8, -1/8, -1/8, 1/8, 1/8, 1/8}}, + connect_front = { + {-1/8, -1/8, -1/2, 1/8, 1/8, -1/8} + }, + connect_back = { + {-1/8, -1/8, 1/8, 1/8, 1/8, 1/2} + }, + connect_top = { + {-1/8, 1/8, -1/8, 1/8, 1/2, 1/8} + }, + connect_bottom = { + {-1/8, -1/2, -1/8, 1/8, -1/8, 1/8} + }, + connect_left = { + {-1/2, -1/8, -1/8, 1/8, 1/8, 1/8} + }, + connect_right = { + {1/8, -1/8, -1/8, 1/2, 1/8, 1/8} + }, + }, + paramtype = "light", + connect_sides = { "top", "bottom", "front", "left", "back", "right" }, + is_ground_content = false, + connects_to = { + "group:storagetest_controller", + "group:storagetest_distributor", + "group:storagetest_cable", + }, + groups = { + storagetest_distributor = 1, + storagetest_cable = 1, + cracky = 2, + oddly_breakable_by_hand = 2 + }, + on_construct = function (pos) + storagetest.network.clear_networks(pos) + end, + on_destruct = storagetest.network.clear_networks, +}) diff --git a/nodes/common.lua b/nodes/common.lua new file mode 100644 index 0000000..d60e352 --- /dev/null +++ b/nodes/common.lua @@ -0,0 +1,21 @@ +-- Storagetest commons + +storagetest.helpers = {} + +function storagetest.helpers.swap_node(pos, noded) + local node = minetest.get_node(pos) + if node.name == noded.name then + return + end + minetest.swap_node(pos, noded) +end + +function storagetest.helpers.grid_refresh(pos, n, network) + local node = minetest.get_node(pos) + local nodedef = minetest.registered_nodes[node.name] + + if nodedef.storagetest_enabled_name then + node.name = nodedef.storagetest_enabled_name + storagetest.helpers.swap_node(pos, node) + end +end diff --git a/nodes/controller.lua b/nodes/controller.lua new file mode 100644 index 0000000..4453016 --- /dev/null +++ b/nodes/controller.lua @@ -0,0 +1,47 @@ +-- Storagetest controller + +minetest.register_node("storagetest:controller", { + description = "Storage Controller", + tiles = {"storagetest_controller.png"}, + on_construct = function (pos) + local meta = minetest.get_meta(pos) + meta:set_string("infotext", "Storage Controller") + meta:set_string("active", 1) + meta:set_string("channel", "controller"..minetest.pos_to_string(pos)) + minetest.swap_node(pos, {name="storagetest:controller_active"}) + local poshash = minetest.hash_node_position(pos) + storagetest.network.redundant_warn[poshash] = nil + end, + after_dig_node = function(pos) + minetest.forceload_free_block(pos) + pos.y = pos.y - 1 + minetest.forceload_free_block(pos) + local poshash = minetest.hash_node_position(pos) + technic.redundant_warn[poshash] = nil + end, + groups = { + cracky = 1, + storagetest_controller = 1 + } +}) + +minetest.register_node("storagetest:controller_active", { + description = "Storage Controller", + tiles = { + { + name = "storagetest_controller_animated.png", + animation = { + type = "vertical_frames", + aspect_w = 16, + aspect_h = 16, + length = 5.0, + }, + } + }, + drop = "storagetest:controller", + groups = { + cracky = 1, + not_in_creative_inventory = 1, + storagetest_controller = 1 + } +}) diff --git a/nodes/crafting_grid.lua b/nodes/crafting_grid.lua new file mode 100644 index 0000000..4f8b9c1 --- /dev/null +++ b/nodes/crafting_grid.lua @@ -0,0 +1,53 @@ +-- 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 new file mode 100644 index 0000000..2747c93 --- /dev/null +++ b/nodes/disk_drive.lua @@ -0,0 +1,47 @@ +-- Disk Drive + +local function timer(pos, elapsed) + local refresh = false + local meta = minetest.get_meta(pos) + local node = minetest.get_node(pos) + + return refresh +end + +local function register_disk_drive(index) + local groups = { + cracky = 1, + storagetest_distributor = 1, + storagetest_device = 1, + storagetest_storage = 1, + } + + local driveoverlay = "" + if index ~= 0 then + groups["not_in_creative_inventory"] = 1 + driveoverlay = "^storagetest_drive_section"..index..".png" + end + + minetest.register_node("storagetest:disk_drive"..index, { + description = "Disk Drive", + tiles = { + "storagetest_drive_side.png", "storagetest_drive_side.png", "storagetest_drive_side.png", + "storagetest_drive_side.png", "storagetest_drive_side.png", "storagetest_drive.png"..driveoverlay, + }, + drop = "storagetest:disk_drive0", + paramtype2 = "facedir", + on_timer = timer, + groups = groups, + on_construct = function (pos) + storagetest.network.clear_networks(pos) + end, + on_destruct = storagetest.network.clear_networks, + }) + + storagetest.devices["storagetest:disk_drive"..index] = true +end + +-- Register 6 variants of the disk drive. +for i = 0, 6 do + register_disk_drive(i) +end diff --git a/nodes/grid.lua b/nodes/grid.lua new file mode 100644 index 0000000..cf61008 --- /dev/null +++ b/nodes/grid.lua @@ -0,0 +1,53 @@ +-- Storage 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:grid", { + description = "Grid", + tiles = { + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_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:grid_active", +}) + +minetest.register_node("storagetest:grid_active", { + description = "Grid", + tiles = { + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_machine_block.png", + "storagetest_machine_block.png", "storagetest_machine_block.png", "storagetest_grid_active.png", + }, + drop = "storagetest: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:grid", +}) + +storagetest.devices["storagetest:grid"] = true +storagetest.devices["storagetest:grid_active"] = true diff --git a/textures/storagetest_cable.png b/textures/storagetest_cable.png new file mode 100644 index 0000000..343a837 Binary files /dev/null and b/textures/storagetest_cable.png differ diff --git a/textures/storagetest_controller.png b/textures/storagetest_controller.png new file mode 100644 index 0000000..7680450 Binary files /dev/null and b/textures/storagetest_controller.png differ diff --git a/textures/storagetest_controller_animated.png b/textures/storagetest_controller_animated.png new file mode 100644 index 0000000..4a0f713 Binary files /dev/null and b/textures/storagetest_controller_animated.png differ diff --git a/textures/storagetest_crafting_grid.png b/textures/storagetest_crafting_grid.png new file mode 100644 index 0000000..5d9f1d5 Binary files /dev/null and b/textures/storagetest_crafting_grid.png differ diff --git a/textures/storagetest_crafting_grid_active.png b/textures/storagetest_crafting_grid_active.png new file mode 100644 index 0000000..39249f5 Binary files /dev/null and b/textures/storagetest_crafting_grid_active.png differ diff --git a/textures/storagetest_drive.png b/textures/storagetest_drive.png new file mode 100644 index 0000000..af6d559 Binary files /dev/null and b/textures/storagetest_drive.png differ diff --git a/textures/storagetest_drive_section1.png b/textures/storagetest_drive_section1.png new file mode 100644 index 0000000..fbcfe18 Binary files /dev/null and b/textures/storagetest_drive_section1.png differ diff --git a/textures/storagetest_drive_section2.png b/textures/storagetest_drive_section2.png new file mode 100644 index 0000000..151e1d6 Binary files /dev/null and b/textures/storagetest_drive_section2.png differ diff --git a/textures/storagetest_drive_section3.png b/textures/storagetest_drive_section3.png new file mode 100644 index 0000000..9993a54 Binary files /dev/null and b/textures/storagetest_drive_section3.png differ diff --git a/textures/storagetest_drive_section4.png b/textures/storagetest_drive_section4.png new file mode 100644 index 0000000..b7cc571 Binary files /dev/null and b/textures/storagetest_drive_section4.png differ diff --git a/textures/storagetest_drive_section5.png b/textures/storagetest_drive_section5.png new file mode 100644 index 0000000..b77d13b Binary files /dev/null and b/textures/storagetest_drive_section5.png differ diff --git a/textures/storagetest_drive_section6.png b/textures/storagetest_drive_section6.png new file mode 100644 index 0000000..a70be6c Binary files /dev/null and b/textures/storagetest_drive_section6.png differ diff --git a/textures/storagetest_drive_side.png b/textures/storagetest_drive_side.png new file mode 100644 index 0000000..a6d329b Binary files /dev/null and b/textures/storagetest_drive_side.png differ diff --git a/textures/storagetest_grid.png b/textures/storagetest_grid.png new file mode 100644 index 0000000..8b2b01c Binary files /dev/null and b/textures/storagetest_grid.png differ diff --git a/textures/storagetest_grid_active.png b/textures/storagetest_grid_active.png new file mode 100644 index 0000000..d739109 Binary files /dev/null and b/textures/storagetest_grid_active.png differ diff --git a/textures/storagetest_machine_block.png b/textures/storagetest_machine_block.png new file mode 100644 index 0000000..2436b5d Binary files /dev/null and b/textures/storagetest_machine_block.png differ