diff --git a/api.lua b/api.lua index 61a55e9..aa909a6 100644 --- a/api.lua +++ b/api.lua @@ -116,7 +116,7 @@ function microexpansion.register_node(itemstring, def) def.description = def.description .. "\n"..minetest.colorize("grey", def.usedfor) end -- Update texture - if auto_complete ~= false then + if def.auto_complete ~= false then for _,i in ipairs(def.tiles) do if #def.tiles[_]:split("^") <= 1 then local prefix = "" @@ -150,3 +150,20 @@ function microexpansion.register_node(itemstring, def) microexpansion.register_oredef(BASENAME..":"..itemstring, def.oredef) end end + +-- get a node, if nessecary load it +function microexpansion.get_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 minetest.get_node(pos) +end + +function microexpansion.update_node(pos) + local node = microexpansion.get_node(pos) + local def = minetest.registered_nodes[node.name] + if def.me_update then + def.me_update(pos,node) + end +end diff --git a/doc/api.md b/doc/api.md index be924d1..175b5b0 100644 --- a/doc/api.md +++ b/doc/api.md @@ -56,4 +56,9 @@ This API function accepts the same parameters in the definition table as does `m #### `register_node(itemstring, def)` __Usage:__ `microexpansion.register_node(, ` -This API function accepts the same parameters in the definition table as does `minetest.register_craftitem`, however, it makes several modifications to the parameters before passing them on. A new parameter, `usedfor`, is introduced, which if provided is appened on a new line in grey to the item description, a good way to specify what the item does or include more information about it. The `tiles` table is modified so as to simplify the definition when registering the node. Each texture in the `tiles` table has `microexpansion_` added to the beginning and `.png` to the end. This means that rather than specifying something like `microexpansion_chest_top.png`, only `chest_top` is required. __Note:__ the texture path "autocomplete" functionality can be disabled by settings `auto_complete` to `false` in the definition (useful if using textures from another mod). One final extra parameter is `status`, which if set to `no` the description is red, if set to `unstable` the description is `orange`, and if anything else the description is red. The recipe can be automatically registered and defined right in the item definition with the `recipe` table. See `microexpansion.register_recipe` for more information. You can also automatically register ore definitions for the current node with `microexpansion.register_oredef`. \ No newline at end of file +This API function accepts the same parameters in the definition table as does `minetest.register_craftitem`, however, it makes several modifications to the parameters before passing them on. +A new parameter, `usedfor`, is introduced, which if provided is appened on a new line in grey to the item description, a good way to specify what the item does or include more information about it. +The `tiles` table is modified so as to simplify the definition when registering the node. Each texture in the `tiles` table has `microexpansion_` added to the beginning and `.png` to the end. +This means that rather than specifying something like `microexpansion_chest_top.png`, only `chest_top` is required. __Note:__ the texture path "autocomplete" functionality can be disabled by setting `auto_complete` to `false` in the definition (useful if using textures from another mod). +One final extra parameter is `status`, which if set to `no` the description is red, if set to `unstable` the description is `orange`, and if anything else the description is red. +The recipe can be automatically registered and defined right in the item definition with the `recipe` table. See `microexpansion.register_recipe` for more information. You can also automatically register ore definitions for the current node with `microexpansion.register_oredef`. \ No newline at end of file diff --git a/modules/power/ctrl.lua b/modules/network/ctrl.lua similarity index 81% rename from modules/power/ctrl.lua rename to modules/network/ctrl.lua index ec6f0a7..67fc6ca 100644 --- a/modules/power/ctrl.lua +++ b/modules/network/ctrl.lua @@ -1,11 +1,11 @@ -- power/ctrl.lua local me = microexpansion -local power = me.power +local network = me.network -- [register node] Controller me.register_node("ctrl", { - description = "ME Drive", + description = "ME Controller", tiles = { "ctrl_sides", "ctrl_bottom", @@ -39,27 +39,24 @@ me.register_node("ctrl", { after_place_node = function(pos, player) local name = player:get_player_name() local meta = minetest.get_meta(pos) - local id = power.new_id() + table.insert(me.networks,network:new({controller_pos = pos})) + me.update_connected_machines(pos) - meta:set_string("infotext", "Network Controller (owned by "..name..")" - .."\nNetwork ID: "..id) - meta:set_string("network_id", id) + meta:set_string("infotext", "Network Controller (owned by "..name..")") meta:set_string("owner", name) - - me.networks[id] = {pos = pos} - - -- Trace Network - power.trace(pos) end, on_destruct = function(pos, player) local meta = minetest.get_meta(pos) - local id = meta:get_string("network_id") - me.networks[id] = nil - - -- Remove unit from network - --me.network_remove(pos) - -- Trace/clear network - power.trace(pos) + local net,idx = me.get_network(pos) + if net then + net.controller_pos = nil + end + if idx then + table.remove(me.networks,idx) + end + end, + after_dig_node = function(pos) + me.update_connected_machines(pos) end, machine = { type = "transporter", @@ -86,6 +83,8 @@ me.register_machine("cable", { paramtype = "light", groups = { crumbly = 1, }, status = "unstable", + after_place_node = me.update_connected_machines, + after_dig_node = me.update_connected_machines, machine = { type = "transporter", }, diff --git a/modules/network/init.lua b/modules/network/init.lua index e7e1ca6..aa2fbaf 100644 --- a/modules/network/init.lua +++ b/modules/network/init.lua @@ -3,15 +3,6 @@ me.networks = {} local networks = me.networks local path = microexpansion.get_module_path("network") --- get a node, if nessecary load it -function me.get_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 minetest.get_node(pos) -end - -- load Resources dofile(path.."/network.lua") -- Network Management @@ -27,21 +18,23 @@ function me.connected_nodes(start_pos) -- return the generated iterator return function () -- start looking for next pos - local found = false + local open = false -- pos to be checked local current_pos -- find next unclosed - while not found do + while not open do -- get unchecked pos current_pos = table.remove(open_list) -- none are left if current_pos == nil then return end + -- assume it's open + open = true -- check the closed positions for _,closed in pairs(closed_set) do -- if current is unclosed - if not vector.equals(closed,current_pos) then - --found next unclosed - found = true + if vector.equals(closed,current_pos) then + --found one was closed + open = false end end end @@ -50,7 +43,7 @@ function me.connected_nodes(start_pos) -- iterate through them for _,p in pairs(next_pos) do -- mark position to be checked - table.insert(open_set,p) + table.insert(open_list,p) end -- add this one to the closed set table.insert(closed_set,current_pos) @@ -60,18 +53,36 @@ function me.connected_nodes(start_pos) end -- get network connected to position -function me.get_network(start_pos) +function me.get_connected_network(start_pos) for npos in me.connected_nodes(start_pos) do if me.get_node(npos).name == "microexpansion:ctrl" then - for _,net in pairs(networks) do - if vector.equals(npos, net.pos) then - return net - end + local network = me.get_network(npos) + if network then + return network end end end end +function me.update_connected_machines(start_pos) + --print("updating connected machines") + for npos in me.connected_nodes(start_pos) do + me.update_node(npos) + end +end + +function me.get_network(pos) + for i,net in pairs(networks) do + if net.controller_pos then + if vector.equals(pos, net.controller_pos) then + return net,i + end + end + end +end + +dofile(path.."/ctrl.lua") -- Controller/wires + -- load networks function me.load() local res = io.open(me.worldpath.."/microexpansion.txt", "r") diff --git a/modules/network/network.lua b/modules/network/network.lua index f4a7de9..1756060 100644 --- a/modules/network/network.lua +++ b/modules/network/network.lua @@ -3,9 +3,13 @@ -- @field #table controller_pos the position of the controller -- @field #number power_load the power currently provided to the network -- @field #number power_storage the power that can be stored for the next tick +-- @field #table items the itemstacks stored in the networks drives +-- @field #number item_capacity the amount of items that can be stored in the networks drives local network = { power_load = 0, - power_storage = 0 + power_storage = 0, + --for testing it's at 3200 will be set to 0 when the drives work + item_capacity = 3200, } microexpansion.network = network @@ -14,7 +18,7 @@ microexpansion.network = network -- @param #table o the object to become a network or nil function network:new(o) local n = setmetatable(o or {}, {__index = self}) - o.machines = {} + o.items = {} return o end @@ -23,7 +27,7 @@ end -- @param #table pos the position of the node to be checked -- @return #boolean whether this node has the group me_connect function network.can_connect(pos) - local node = me.get_node(pos) + local node = microexpansion.get_node(pos) return minetest.get_item_group(node.name, "me_connect") > 0 end @@ -47,7 +51,7 @@ function network.adjacent_connected_nodes(pos, include_ctrl) for _,pos in pairs(adjacent) do if network.can_connect(pos) then if include_ctrl == false then - if not me.get_node(pos).name == "microexpansion:ctrl" then + if not microexpansion.get_node(pos).name == "microexpansion:ctrl" then table.insert(nodes, pos) end else diff --git a/modules/power/init.lua b/modules/power/init.lua index e5ce41a..fa82cd7 100644 --- a/modules/power/init.lua +++ b/modules/power/init.lua @@ -12,5 +12,5 @@ local power = me.power dofile(path.."/network.lua") -- Network Management dofile(path.."/register.lua") -- Machine Registration -dofile(path.."/ctrl.lua") -- Controller/wires +--dofile(path.."/ctrl.lua") -- Controller/wires dofile(path.."/gen.lua") -- Generators diff --git a/modules/power/register.lua b/modules/power/register.lua index ebb2d10..0dd5efe 100644 --- a/modules/power/register.lua +++ b/modules/power/register.lua @@ -8,13 +8,14 @@ local power = me.power -- [function] Register machine function me.register_machine(itemstring, def) -- Set after_place_node + local def_afterplace = def.after_place_node def.after_place_node = function(pos, player) - if def.after_place_node then - def.after_place_node(pos, player) + if def_afterplace then + def_afterplace(pos, player) end local meta = minetest.get_meta(pos) - local nodes = me.get_connected_nodes(pos) + local nodes = me.network.adjacent_connected_nodes(pos) meta:set_string("infotext", def.description.."\nNo Network") @@ -40,9 +41,10 @@ function me.register_machine(itemstring, def) end end -- Set on_destruct + local def_destruct = def.on_destruct def.on_destruct = function(pos, player) - if def.on_destruct then - def.on_destruct(pos, player) + if def_destruct then + def_destruct(pos, player) end local meta = minetest.get_meta(pos) diff --git a/modules/storage/chest.lua b/modules/storage/chest.lua new file mode 100644 index 0000000..2b46148 --- /dev/null +++ b/modules/storage/chest.lua @@ -0,0 +1,216 @@ +-- microexpansion/machines.lua + +local me = microexpansion + +-- [me chest] Get formspec +local function chest_formspec(pos, start_id, listname, page_max, query) + local list + local page_number = "" + local buttons = "" + local query = query or "" + + if not listname then + list = "label[3,2;" .. minetest.colorize("red", "No drive!") .. "]" + else + list = "list[current_name;" .. listname .. ";0,0.3;8,4;" .. (start_id - 1) .. "]" + buttons = [[ + button[3.56,4.35;1.8,0.9;tochest;To Drive] + tooltip[tochest;Move everything from your inventory to the ME network.] + button[5.4,4.35;0.8,0.9;prev;<] + button[7.25,4.35;0.8,0.9;next;>] + tooltip[prev;Previous] + tooltip[next;Next] + field[0.29,4.6;2.2,1;filter;;]]..query..[[] + button[2.1,4.5;0.8,0.5;search;?] + button[2.75,4.5;0.8,0.5;clear;X] + tooltip[search;Search] + tooltip[clear;Reset] + ]] + end + if page_max then + page_number = "label[6.15,4.5;" .. math.floor((start_id / 32)) + 1 .. + "/" .. page_max .."]" + end + + return [[ + size[9,9.5] + ]].. + microexpansion.gui_bg .. + microexpansion.gui_slots .. + list .. + [[ + label[0,-0.23;ME Chest] + list[current_player;main;0,5.5;8,1;] + list[current_player;main;0,6.73;8,3;8] + listring[current_name;main] + listring[current_player;main] + field_close_on_enter[filter;false] + ]].. + page_number .. + buttons +end + +local function update_chest(pos) + local network = me.get_connected_network(pos) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + if network == nil then + inv:set_size("main", 0) + meta:set_int("page", 1) + meta:set_string("formspec", chest_formspec(pos, 1)) + return + end + local items = network.items + local size = network.item_capacity + local page_max = me.int_to_pagenum(size) + 1 + inv:set_size("main", me.int_to_stacks(size)) + if items then + inv:set_list("main", items) + end + meta:set_string("inv_name", "main") + meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max)) +end + +-- [me chest] Register node +microexpansion.register_node("chest", { + description = "ME Chest", + usedfor = "Can interact with storage cells in ME networks", + tiles = { + "chest_top", + "chest_top", + "chest_side", + "chest_side", + "chest_side", + "chest_front", + }, + is_ground_content = false, + groups = { cracky = 1, me_connect = 1 }, + paramtype = "light", + paramtype2 = "facedir", + me_update = update_chest, + on_construct = function(pos) + local meta = minetest.get_meta(pos) + meta:set_string("formspec", chest_formspec(pos, 1)) + meta:set_string("inv_name", "none") + meta:set_int("page", 1) + local net = me.get_connected_network(pos) + if net then + update_chest(pos) + end + end, + can_dig = function(pos, player) + local meta = minetest.get_meta(pos) + local inv = meta:get_inventory() + return inv:is_empty("main") + end, + allow_metadata_inventory_put = function(pos, listname, index, stack, player) + if listname == "main" then + local inv = minetest.get_meta(pos):get_inventory() + local max_slots = inv:get_size(listname) + local max_items = math.floor(max_slots * 99) + + local slots, items = 0, 0 + -- Get amount of items in drive + for i = 1, max_items do + local stack = inv:get_stack("main", i) + local item = stack:get_name() + if item ~= "" then + slots = slots + 1 + local num = stack:get_count() + if num == 0 then num = 1 end + items = items + num + end + end + + return math.min(stack:get_count(),max_items-items) + else + return 0 + end + end, + on_metadata_inventory_put = function(pos, listname, index, stack, player) + if listname == "main" then + local inv = minetest.get_meta(pos):get_inventory() + inv:remove_item(listname, stack) + local stackname = stack:get_name() + local found = false + for i = 0, inv:get_size(listname) do + local inside = inv:get_stack(listname, i) + if inside:get_name() == stackname then + inside:set_count(inside:get_count() + stack:get_count()) + inv:set_stack(listname, i, inside) + found = true + break; + end + end + if not found then + inv:add_item(listname, stack) + end + local network = me.get_connected_network(pos) + network.items = inv:get_list("main") + me.update_connected_machines(pos) + end + end, + allow_metadata_inventory_take = function(pos, listname, index, stack, player) + return math.min(stack:get_count(),stack:get_stack_max()) + end, + on_metadata_inventory_take = function(pos, listname, index, stack, player) + local inv = minetest.get_meta(pos):get_inventory() + if listname == "search" then + inv:remove_item("main", stack) + end + local network = me.get_connected_network(pos) + network.items = inv:get_list("main") + me.update_connected_machines(pos) + end, + on_receive_fields = function(pos, formname, fields, sender) + local meta = minetest.get_meta(pos) + local page = meta:get_int("page") + local inv_name = meta:get_string("inv_name") + local inv = meta:get_inventory() + local page_max = math.floor(inv:get_size("main") / 32) + 1 + local network = me.get_connected_network(pos) + if inv_name == "none" then + return + end + if fields.next then + if page + 32 > inv:get_size(inv_name) then + return + end + meta:set_int("page", page + 32) + meta:set_string("formspec", chest_formspec(pos, page + 32, inv_name, page_max)) + elseif fields.prev then + if page - 32 < 1 then + return + end + meta:set_int("page", page - 32) + meta:set_string("formspec", chest_formspec(pos, page - 32, inv_name, page_max)) + elseif fields.search or fields.key_enter_field == "filter" then + inv:set_size("search", 0) + if fields.filter == "" then + meta:set_int("page", 1) + meta:set_string("inv_name", "main") + meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max)) + else + local tab = {} + for i = 1, inv:get_size("main") do + local match = inv:get_stack("main", i):get_name():find(fields.filter) + if match then + tab[#tab + 1] = inv:get_stack("main", i) + end + end + inv:set_list("search", tab) + meta:set_int("page", 1) + meta:set_string("inv_name", "search") + meta:set_string("formspec", chest_formspec(pos, 1, "search", page_max, fields.filter)) + end + elseif fields.clear then + inv:set_size("search", 0) + meta:set_int("page", 1) + meta:set_string("inv_name", "main") + meta:set_string("formspec", chest_formspec(pos, 1, "main", page_max)) + elseif fields.tochest then + local pinv = minetest.get_inventory({type="player", name=sender:get_player_name()}) + microexpansion.move_inv({ inv=pinv, name="main" }, { inv=inv, name="main" }) + end + end, +}) diff --git a/modules/storage/machines.lua b/modules/storage/drive.lua similarity index 100% rename from modules/storage/machines.lua rename to modules/storage/drive.lua diff --git a/modules/storage/init.lua b/modules/storage/init.lua index 58f5052..6151207 100644 --- a/modules/storage/init.lua +++ b/modules/storage/init.lua @@ -2,6 +2,8 @@ local module_path = microexpansion.get_module_path("storage") +microexpansion.require_module("network") + -- Load API dofile(module_path.."/api.lua") @@ -9,4 +11,5 @@ dofile(module_path.."/api.lua") dofile(module_path.."/storage.lua") -- Load machines -dofile(module_path.."/machines.lua") +--dofile(module_path.."/drive.lua") +dofile(module_path.."/chest.lua")