b9de6b6ef6
Fix power distribution so its spread evenly across all machines Fix glitch when removing machines from network other machines can stop working
531 lines
15 KiB
Lua
531 lines
15 KiB
Lua
|
|
-- 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"] = nil
|
|
nodedef.groups["tube"] = nil
|
|
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
|
|
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
|