-- Machine definitions local pw = minetest.get_modpath("pipeworks") ~= nil local mc = minetest.get_modpath("mesecons") ~= nil local tl = minetest.get_modpath("tubelib") ~= nil --[[ Groups: ele_machine Any machine that does something with power ele_provider Any machine that can provide power (generator, storage, etc) ele_user Any machine that uses power ele_storage Any machine that stores power ele_conductor A node that is used to connect ele_machine nodes together Custom nodedef variables: ele_capacity = 12000 Static capacitor for nodes. ** Can be overridden by metadata: `capacity` ele_inrush = 32 Decides how much power can be inserted into this machine's internal capacitor. ** Can be overridden by metadata: `inrush` ele_output = 64 Decides how much power a `ele_provider` node can output. ** SHOULD be overridden by metadata: `output` ele_sides = nil All sides of providers currently output power. All sides of other nodes accept power. ** SHOULD be overridden by metadata: `sides` ele_usage = 16 How much power this machine uses or generates. ** Can be overridden by metadata: `usage` ele_active_node = nil Set to true or a string to also register an active variant of this node. If the parameter is a boolean, "_active" will be appended to the `node_name` ele_active_nodedef = nil If set, the `ele_active_node` will have this table in its nodedef. Intended use: to set textures or light output. ]] local function can_dig(pos, player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:is_empty("dst") and inv:is_empty("src") end ele.default = {} function ele.default.allow_metadata_inventory_put(pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 end if listname == "dst" then return 0 end return stack:get_count() end function ele.default.allow_metadata_inventory_move(pos, from_list, from_index, to_list, to_index, count, player) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local stack = inv:get_stack(from_list, from_index) return ele.default.allow_metadata_inventory_put(pos, to_list, to_index, stack, player) end function ele.default.allow_metadata_inventory_take(pos, listname, index, stack, player) if minetest.is_protected(pos, player:get_player_name()) then return 0 end return stack:get_count() end ele.default.metadata_inventory_changed = ele.helpers.start_timer -- State machine descriptions ele.default.states = { [0] = {s = "on", d = "Always on", e = "toggle"}, {s = "off", d = "Always off", e = "toggle"}, {s = "signal", d = "Enable by Mesecons signal", e = "mesecons"}, {s = "interrupt", d = "Disable by Mesecons signal", e = "mesecons"}, } -- Preserve power storage in the item stack dropped local function preserve_metadata(pos, oldnode, oldmeta, drops) local meta = minetest.get_meta(pos) local storage = ele.helpers.get_node_property(meta, pos, "storage") local capacity = ele.helpers.get_node_property(meta, pos, "capacity") local nodedesc = minetest.registered_nodes[oldnode.name].description local partsstr = meta:get_string("components") if storage == 0 and partsstr == "" then return drops end for i,stack in pairs(drops) do local stack_meta = stack:get_meta() stack_meta:set_int("storage", storage) local desc = ele.capacity_text(capacity, storage) if partsstr ~= "" then stack_meta:set_string("components", partsstr) desc = desc .. "\n" .. minetest.colorize("#9647ff", "Modified Device") end stack_meta:set_string("description", nodedesc .. "\n" .. desc) drops[i] = stack end return drops end -- Retrieve power storage from itemstack when placed local function retrieve_metadata(pos, placer, itemstack, pointed_thing) local item_meta = itemstack:get_meta() local storage = item_meta:get_int("storage") local partsstr = item_meta:get_string("components") if storage > 0 or partsstr ~= "" then local meta = minetest.get_meta(pos) meta:set_int("storage", storage) if partsstr ~= "" then meta:set_string("components", partsstr) if elepm then elepm.handle_machine_upgrades(pos) end else ele.helpers.start_timer(pos) end end return false end function ele.capacity_text(capacity, storage) return ("Charge: %s / %s %s"):format(ele.helpers.comma_value(storage), ele.helpers.comma_value(capacity), ele.unit) end -- API support local tube = { insert_object = function(pos, node, stack, direction) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() ele.helpers.start_timer(pos) return inv:add_item("src", stack) end, can_insert = function(pos, node, stack, direction) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() if meta:get_int("splitstacks") == 1 then stack = stack:peek_item(1) end return inv:room_for_item("src", stack) end, input_inventory = "dst", connect_sides = {left = 1, right = 1, back = 1, top = 1, bottom = 1}, } local tubelib_tube = { on_pull_item = function(pos, side, player_name) local meta = minetest.get_meta(pos) ele.helpers.start_timer(pos) return tubelib.get_item(meta, "dst") end, on_push_item = function(pos, side, item, player_name) local meta = minetest.get_meta(pos) ele.helpers.start_timer(pos) return tubelib.put_item(meta, "src", item) end, on_unpull_item = function(pos, side, item, player_name) local meta = minetest.get_meta(pos) ele.helpers.start_timer(pos) return tubelib.put_item(meta, "dst", item) end, } local mesecons_def = { effector = { action_on = function (pos, node) local meta = minetest.get_meta(pos) meta:set_int("signal_interrupt", 1) end, action_off = function (pos, node) local meta = minetest.get_meta(pos) meta:set_int("signal_interrupt", 0) end, action_change = ele.helpers.start_timer, } } -- Functions local function switch_state(pos, state_def) local meta = minetest.get_meta(pos) local state = meta:get_int("state") local states = {} for id,state in pairs(ele.default.states) do if state_def[state.e] then states[#states + 1] = id end end if #states == 0 then return end state = state + 1 if state >= #states then state = 0 end state = states[state + 1] meta:set_int("state", state) ele.helpers.start_timer(pos) end -- Patch a table local function apply_patches (table, patches) for k,v in pairs(patches) do if table[k] and type(table[k]) == "table" then apply_patches(table[k], v) else table[k] = v end end end -- Register a base device function ele.register_base_device(nodename, nodedef) local tlsupp = tl and nodedef.groups and (nodedef.groups["tubedevice"] or nodedef.groups["tube"]) -- Override construct callback local original_on_construct = nodedef.on_construct nodedef.on_construct = function (pos) if nodedef.groups and nodedef.groups["ele_machine"] then local meta = minetest.get_meta(pos) meta:set_int("storage", 0) end ele.clear_networks(pos) if original_on_construct then original_on_construct(pos) end end -- Override destruct callback local original_after_destruct = nodedef.after_destruct nodedef.after_destruct = function (pos) ele.clear_networks(pos) if original_after_destruct then original_after_destruct(pos) end end -- Save storage amount when picked up local original_preserve_metadata = nodedef.preserve_metadata nodedef.preserve_metadata = function (pos, oldnode, oldmeta, drops) drops = preserve_metadata(pos, oldnode, oldmeta, drops) if original_preserve_metadata then drops = original_preserve_metadata(pos, oldnode, oldmeta, drops) end return drops end local original_after_place_node = nodedef.after_place_node nodedef.after_place_node = function(pos, placer, itemstack, pointed_thing) local ret = retrieve_metadata(pos, placer, itemstack, pointed_thing) if tlsupp then tubelib.add_node(pos, nodename) end if original_after_place_node then ret = original_after_place_node(pos, placer, itemstack, pointed_thing) end return ret end local original_after_dig_node = nodedef.after_dig_node nodedef.after_dig_node = function(pos, placer, itemstack, pointed_thing) if tlsupp then tubelib.remove_node(pos) end if original_after_dig_node then return original_after_dig_node(pos, placer, itemstack, pointed_thing) end end -- Prevent digging when there's items inside if not nodedef.can_dig then nodedef.can_dig = can_dig end -- Explicitly allow the disabling of the state machine if nodedef.groups["state_machine"] ~= 0 and not nodedef["states"] then nodedef.states = {toggle = true} end -- Pipeworks support if pw and nodedef.groups and (nodedef.groups["tubedevice"] or nodedef.groups["tube"]) then if nodedef['tube'] == false then nodedef['tube'] = nil nodedef.groups["tubedevice"] = 0 nodedef.groups["tube"] = 0 elseif nodedef['tube'] then for key,val in pairs(tube) do if not nodedef['tube'][key] then nodedef['tube'][key] = val end end else nodedef['tube'] = tube end if nodedef.groups['tubedevice_receiver'] ~= 0 and nodedef['tube'] then nodedef.groups.tubedevice_receiver = 1 end end -- Node IO Support if nodedef.groups["tubedevice"] or nodedef.groups["tube"] then nodedef.node_io_can_put_item = function(pos, node, side) return true end nodedef.node_io_room_for_item = function(pos, node, side, itemstack, count) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local istack_real = ItemStack(itemstack) istack_real:set_count(count) return inv:room_for_item("src", istack_real) end nodedef.node_io_put_item = function(pos, node, side, putter, itemstack) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() ele.helpers.start_timer(pos) return inv:add_item("src", itemstack) end nodedef.node_io_can_take_item = function(pos, node, side) return true end nodedef.node_io_get_item_size = function(pos, node, side) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:get_size("dst") end nodedef.node_io_get_item_name = function(pos, node, side, index) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:get_stack("dst", index):get_name() end nodedef.node_io_get_item_stack = function(pos, node, side, index) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() return inv:get_stack("dst", index) end nodedef.node_io_take_item = function(pos, node, side, taker, want_item, want_count) local meta = minetest.get_meta(pos) local inv = meta:get_inventory() local stack = ItemStack(want_item) stack:set_count(want_count) ele.helpers.start_timer(pos) return inv:take_item("dst", stack) end end -- Mesecons support if mc then nodedef["mesecons"] = mesecons_def if nodedef.states and nodedef.states["mesecons"] ~= false then nodedef.states["mesecons"] = true end end -- STATE MACHINE local original_on_receive_fields = nodedef.on_receive_fields nodedef.on_receive_fields = function (pos, formname, fields, sender) if sender and sender ~= "" and minetest.is_protected(pos, sender:get_player_name()) then return end if nodedef.states then if fields["cyclestate"] then switch_state(pos, nodedef.states) end end if original_on_receive_fields then return original_on_receive_fields(pos, formname, fields, sender) end end -- Finally, register the damn thing already minetest.register_node(nodename, nodedef) local active_name = nil -- Register an active variant if configured. if nodedef.ele_active_node then local active_nodedef = table.copy(nodedef) active_name = nodename.."_active" if nodedef.ele_active_node ~= true then active_name = nodedef.ele_active_node if i ~= 1 then active_name = active_name .. "_" .. i end end if nodedef.ele_active_nodedef then apply_patches(active_nodedef, nodedef.ele_active_nodedef) nodedef.ele_active_nodedef = nil active_nodedef.ele_active_nodedef = nil end -- Remove formspec functions from active nodedefs if active_nodedef.get_formspec then active_nodedef.get_formspec = nil end active_nodedef.groups["ele_active"] = 1 active_nodedef.groups["not_in_creative_inventory"] = 1 active_nodedef.drop = nodename minetest.register_node(active_name, active_nodedef) end -- tubelib support if tlsupp then local extras = {} if active_name then extras = {active_name} end tubelib.register_node(nodename, extras, tubelib_tube) end -- nodeio fluids if nodedef.groups and nodedef.groups['fluid_container'] then fluid_lib.register_node(nodename) if active_name then fluid_lib.register_node(active_name) end end end function ele.register_machine(nodename, nodedef) if not nodedef.groups then nodedef.groups = {} end -- Start cleaning up the nodedef local defaults = { ele_capacity = 1600, ele_inrush = 64, ele_usage = 64, ele_output = 64, ele_sides = nil, } -- Ensure everything that's required is present for k,v in pairs(defaults) do if not nodedef[k] then nodedef[k] = v end end if nodedef.paramtype2 ~= 0 or not nodedef.paramtype2 then nodedef.paramtype2 = "facedir" else nodedef.paramtype2 = nil end -- Ensure machine group is used properly if not nodedef.groups["ele_conductor"] and not nodedef.groups["ele_machine"] then nodedef.groups["ele_machine"] = 1 elseif nodedef.groups["ele_conductor"] and nodedef.groups["ele_machine"] then nodedef.groups["ele_machine"] = 0 end if not nodedef.ele_no_automatic_ports then -- Add ports to the device's faces if nodedef.tiles and #nodedef.tiles == 6 then for i = 1, 5 do nodedef.tiles[i] = nodedef.tiles[i] .. "^elepower_power_port.png" end end -- Add ports to the device's active faces if nodedef.ele_active_nodedef and nodedef.ele_active_nodedef.tiles and #nodedef.ele_active_nodedef.tiles == 6 then for i = 1, 5 do nodedef.ele_active_nodedef.tiles[i] = nodedef.ele_active_nodedef.tiles[i] .. "^elepower_power_port.png" end end end nodedef.ele_no_automatic_ports = nil -- Default metadata handlers for "src" and "dst" if not nodedef.allow_metadata_inventory_put then nodedef.allow_metadata_inventory_put = ele.default.allow_metadata_inventory_put nodedef.allow_metadata_inventory_move = ele.default.allow_metadata_inventory_move end if not nodedef.allow_metadata_inventory_take then nodedef.allow_metadata_inventory_take = ele.default.allow_metadata_inventory_take end -- Default metadata changed handlers for inventories -- Starts the timer on the node if not nodedef.on_metadata_inventory_move then nodedef.on_metadata_inventory_move = ele.default.metadata_inventory_changed end if not nodedef.on_metadata_inventory_put then nodedef.on_metadata_inventory_put = ele.default.metadata_inventory_changed end if not nodedef.on_metadata_inventory_take then nodedef.on_metadata_inventory_take = ele.default.metadata_inventory_changed end ele.register_base_device(nodename, nodedef) end