123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473 |
- local S = minetest.get_translator("pipeworks")
- local assumed_eye_pos = vector.new(0, 1.5, 0)
- local function vector_copy(v)
- return { x = v.x, y = v.y, z = v.z }
- end
- local function delay(x)
- return (function() return x end)
- end
- local function set_wielder_formspec(data, meta)
- meta:set_string("formspec",
- "invsize[8,"..(6+data.wield_inv_height)..";]"..
- "item_image[0,0;1,1;"..data.name_base.."_off]"..
- "label[1,0;"..minetest.formspec_escape(data.description).."]"..
- "list[current_name;"..minetest.formspec_escape(data.wield_inv_name)..";"..((8-data.wield_inv_width)*0.5)..",1;"..data.wield_inv_width..","..data.wield_inv_height..";]"..
- "list[current_player;main;0,"..(2+data.wield_inv_height)..";8,4;]" ..
- "listring[]")
- meta:set_string("infotext", data.description)
- end
- local can_tool_dig_node = function(nodename, toolcaps, toolname)
- --pipeworks.logger("can_tool_dig_node() STUB nodename="..tostring(nodename).." toolname="..tostring(toolname).." toolcaps: "..dump(toolcaps))
- -- brief documentation of minetest.get_dig_params() as it's not yet documented in lua_api.txt:
- -- takes two arguments, a node's block groups and a tool's capabilities,
- -- both as they appear in their respective definitions.
- -- returns a table with the following fields:
- -- diggable: boolean, can this tool dig this node at all
- -- time: float, time needed to dig with this tool
- -- wear: int, number of wear points to inflict on the item
- local nodedef = minetest.registered_nodes[nodename]
- -- don't explode due to nil def in event of unknown node!
- if (nodedef == nil) then return false end
- local nodegroups = nodedef.groups
- local diggable = minetest.get_dig_params(nodegroups, toolcaps).diggable
- if not diggable then
- -- a pickaxe can't actually dig leaves based on it's groups alone,
- -- but a player holding one can - the game seems to fall back to the hand.
- -- fall back to checking the hand's properties if the tool isn't the correct one.
- local hand_caps = minetest.registered_items[""].tool_capabilities
- diggable = minetest.get_dig_params(nodegroups, hand_caps).diggable
- end
- return diggable
- end
- local function wielder_on(data, wielder_pos, wielder_node)
- data.fixup_node(wielder_pos, wielder_node)
- if wielder_node.name ~= data.name_base.."_off" then return end
- wielder_node.name = data.name_base.."_on"
- minetest.swap_node(wielder_pos, wielder_node)
- minetest.check_for_falling(wielder_pos)
- local wielder_meta = minetest.get_meta(wielder_pos)
- local inv = wielder_meta:get_inventory()
- local wield_inv_name = data.wield_inv_name
- local wieldindex
- for i, stack in ipairs(inv:get_list(wield_inv_name)) do
- if not stack:is_empty() then
- wieldindex = i
- break
- end
- end
- if not wieldindex then
- if not data.ghost_inv_name then return end
- wield_inv_name = data.ghost_inv_name
- inv:set_stack(wield_inv_name, 1, ItemStack(data.ghost_tool))
- wieldindex = 1
- end
- local dir = minetest.facedir_to_dir(wielder_node.param2)
- -- under/above is currently intentionally left switched
- -- even though this causes some problems with deployers and e.g. seeds
- -- as there are some issues related to nodebreakers otherwise breaking 2 nodes afar.
- -- solidity would have to be checked as well,
- -- but would open a whole can of worms related to difference in nodebreaker/deployer behavior
- -- and the problems of wielders acting on themselves if below is solid
- local under_pos = vector.subtract(wielder_pos, dir)
- local above_pos = vector.subtract(under_pos, dir)
- local pitch
- local yaw
- if dir.z < 0 then
- yaw = 0
- pitch = 0
- elseif dir.z > 0 then
- yaw = math.pi
- pitch = 0
- elseif dir.x < 0 then
- yaw = 3*math.pi/2
- pitch = 0
- elseif dir.x > 0 then
- yaw = math.pi/2
- pitch = 0
- elseif dir.y > 0 then
- yaw = 0
- pitch = -math.pi/2
- else
- yaw = 0
- pitch = math.pi/2
- end
- local virtplayer = pipeworks.create_fake_player({
- name = data.masquerade_as_owner and wielder_meta:get_string("owner")
- or ":pipeworks:" .. minetest.pos_to_string(wielder_pos),
- formspec = wielder_meta:get_string("formspec"),
- look_dir = vector.multiply(dir, -1),
- look_pitch = pitch,
- look_yaw = yaw,
- sneak = data.sneak,
- position = vector.subtract(wielder_pos, assumed_eye_pos),
- inventory = inv,
- wield_index = wieldindex,
- wield_list = wield_inv_name
- })
- local pointed_thing = { type="node", under=under_pos, above=above_pos }
- data.act(virtplayer, pointed_thing)
- if data.eject_drops then
- for i, stack in ipairs(inv:get_list("main")) do
- if not stack:is_empty() then
- pipeworks.tube_inject_item(wielder_pos, wielder_pos, dir, stack)
- inv:set_stack("main", i, ItemStack(""))
- end
- end
- end
- end
- local function wielder_off(data, pos, node)
- if node.name == data.name_base.."_on" then
- node.name = data.name_base.."_off"
- minetest.swap_node(pos, node)
- minetest.check_for_falling(pos)
- end
- end
- local function register_wielder(data)
- data.fixup_node = data.fixup_node or function (pos, node) end
- data.fixup_oldmetadata = data.fixup_oldmetadata or function (m) return m end
- for _, state in ipairs({ "off", "on" }) do
- local groups = { snappy=2, choppy=2, oddly_breakable_by_hand=2, mesecon=2, tubedevice=1, tubedevice_receiver=1 }
- if state == "on" then groups.not_in_creative_inventory = 1 end
- local tile_images = {}
- for _, face in ipairs({ "top", "bottom", "side2", "side1", "back", "front" }) do
- table.insert(tile_images, data.texture_base.."_"..face..(data.texture_stateful[face] and "_"..state or "")..".png")
- end
- minetest.register_node(data.name_base.."_"..state, {
- description = data.description,
- tiles = tile_images,
- mesecons = {
- effector = {
- rules = pipeworks.rules_all,
- action_on = function (pos, node)
- wielder_on(data, pos, node)
- end,
- action_off = function (pos, node)
- wielder_off(data, pos, node)
- end,
- },
- },
- tube = {
- can_insert = function(pos, node, stack, tubedir)
- if not data.tube_permit_anteroposterior_insert then
- local nodedir = minetest.facedir_to_dir(node.param2)
- if vector.equals(tubedir, nodedir) or vector.equals(tubedir, vector.multiply(nodedir, -1)) then
- return false
- end
- end
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- return inv:room_for_item(data.wield_inv_name, stack)
- end,
- insert_object = function(pos, node, stack, tubedir)
- if not data.tube_permit_anteroposterior_insert then
- local nodedir = minetest.facedir_to_dir(node.param2)
- if vector.equals(tubedir, nodedir) or vector.equals(tubedir, vector.multiply(nodedir, -1)) then
- return stack
- end
- end
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- return inv:add_item(data.wield_inv_name, stack)
- end,
- input_inventory = data.wield_inv_name,
- connect_sides = data.tube_connect_sides,
- can_remove = function(pos, node, stack, tubedir)
- return stack:get_count()
- end,
- },
- is_ground_content = true,
- paramtype2 = "facedir",
- tubelike = 1,
- groups = groups,
- sounds = default.node_sound_stone_defaults(),
- drop = data.name_base.."_off",
- on_construct = function(pos)
- local meta = minetest.get_meta(pos)
- set_wielder_formspec(data, meta)
- local inv = meta:get_inventory()
- inv:set_size(data.wield_inv_name, data.wield_inv_width*data.wield_inv_height)
- if data.ghost_inv_name then
- inv:set_size(data.ghost_inv_name, 1)
- end
- if data.eject_drops then
- inv:set_size("main", 100)
- end
- end,
- after_place_node = function (pos, placer)
- pipeworks.scan_for_tube_objects(pos)
- local placer_pos = placer:get_pos()
- if placer_pos and placer:is_player() then placer_pos = vector.add(placer_pos, assumed_eye_pos) end
- if placer_pos then
- local dir = vector.subtract(pos, placer_pos)
- local node = minetest.get_node(pos)
- node.param2 = minetest.dir_to_facedir(dir, true)
- minetest.set_node(pos, node)
- minetest.log("action", "real (6d) facedir: " .. node.param2)
- end
- minetest.get_meta(pos):set_string("owner", placer:get_player_name())
- end,
- can_dig = (data.can_dig_nonempty_wield_inv and delay(true) or function(pos, player)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- return inv:is_empty(data.wield_inv_name)
- end),
- after_dig_node = function(pos, oldnode, oldmetadata, digger)
- -- The legacy-node fixup is done here in a
- -- different form from the standard fixup,
- -- rather than relying on a standard fixup
- -- in an on_dig callback, because some
- -- non-standard diggers (such as technic's
- -- mining drill) don't respect on_dig.
- oldmetadata = data.fixup_oldmetadata(oldmetadata)
- for _, stack in ipairs(oldmetadata.inventory[data.wield_inv_name] or {}) do
- if not stack:is_empty() then
- minetest.add_item(pos, stack)
- end
- end
- pipeworks.scan_for_tube_objects(pos)
- end,
- on_rotate = pipeworks.on_rotate,
- on_punch = data.fixup_node,
- allow_metadata_inventory_put = function(pos, listname, index, stack, player)
- if not pipeworks.may_configure(pos, player) then return 0 end
- return stack:get_count()
- end,
- allow_metadata_inventory_take = function(pos, listname, index, stack, player)
- if not pipeworks.may_configure(pos, player) then return 0 end
- return stack:get_count()
- end,
- allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
- if not pipeworks.may_configure(pos, player) then return 0 end
- return count
- end
- })
- end
- end
- if pipeworks.enable_node_breaker then
- local data
- -- see after end of data table for other use of these variables
- local name_base = "pipeworks:nodebreaker"
- local wield_inv_name = "pick"
- data = {
- name_base = name_base,
- description = S("Node Breaker"),
- texture_base = "pipeworks_nodebreaker",
- texture_stateful = { top = true, bottom = true, side2 = true, side1 = true, front = true },
- tube_connect_sides = { top=1, bottom=1, left=1, right=1, back=1 },
- tube_permit_anteroposterior_insert = false,
- wield_inv_name = wield_inv_name,
- wield_inv_width = 1,
- wield_inv_height = 1,
- can_dig_nonempty_wield_inv = true,
- ghost_inv_name = "ghost_pick",
- ghost_tool = ":", -- hand by default
- fixup_node = function (pos, node)
- local meta = minetest.get_meta(pos)
- local inv = meta:get_inventory()
- -- Node breakers predating the visible pick slot
- -- may have been partially updated. This code
- -- fully updates them. Some have been observed
- -- to have no pick slot at all; first add one.
- if inv:get_size("pick") ~= 1 then
- inv:set_size("pick", 1)
- end
- -- Originally, they had a ghost pick in a "pick"
- -- inventory, no other inventory, and no form.
- -- The partial update of early with-form node
- -- breaker code gives them "ghost_pick" and "main"
- -- inventories, but leaves the old ghost pick in
- -- the "pick" inventory, and doesn't add a form.
- -- First perform that partial update.
- if inv:get_size("ghost_pick") ~= 1 then
- inv:set_size("ghost_pick", 1)
- inv:set_size("main", 100)
- end
- -- If the node breaker predates the visible pick
- -- slot, which we can detect by it not having a
- -- form, then the pick slot needs to be cleared
- -- of the old ghost pick.
- if (meta:get_string("formspec") or "") == "" then
- inv:set_stack("pick", 1, ItemStack(""))
- end
- -- Finally, unconditionally set the formspec
- -- and infotext. This not only makes the
- -- pick slot visible for node breakers where
- -- it wasn't before; it also updates the form
- -- for node breakers that had an older version
- -- of the form, and sets infotext where it was
- -- missing for early with-form node breakers.
- set_wielder_formspec(data, meta)
- end,
- fixup_oldmetadata = function (oldmetadata)
- -- Node breakers predating the visible pick slot,
- -- with node form, kept their ghost pick in an
- -- inventory named "pick", the same name as the
- -- later visible pick slot. The pick must be
- -- removed to avoid spilling it.
- if not oldmetadata.fields.formspec then
- return { inventory = { pick = {} }, fields = oldmetadata.fields }
- else
- return oldmetadata
- end
- end,
- masquerade_as_owner = true,
- sneak = false,
- act = function(virtplayer, pointed_thing)
- --local dname = "nodebreaker.act() "
- local wieldstack = virtplayer:get_wielded_item()
- local oldwieldstack = ItemStack(wieldstack)
- local on_use = (minetest.registered_items[wieldstack:get_name()] or {}).on_use
- if on_use then
- --pipeworks.logger(dname.."invoking on_use "..tostring(on_use))
- wieldstack = on_use(wieldstack, virtplayer, pointed_thing) or wieldstack
- virtplayer:set_wielded_item(wieldstack)
- else
- local under_node = minetest.get_node(pointed_thing.under)
- local def = minetest.registered_nodes[under_node.name]
- if not def then
- -- do not dig an unknown node
- return
- end
- -- check that the current tool is capable of destroying the
- -- target node.
- -- if we can't, don't dig, and leave the wield stack unchanged.
- -- note that wieldstack:get_tool_capabilities() returns hand
- -- properties if the item has none of it's own.
- if can_tool_dig_node(under_node.name,
- wieldstack:get_tool_capabilities(),
- wieldstack:get_name()) then
- def.on_dig(pointed_thing.under, under_node, virtplayer)
- local sound = def.sounds and def.sounds.dug
- if sound then
- minetest.sound_play(sound.name,
- {pos=pointed_thing.under, gain=sound.gain})
- end
- wieldstack = virtplayer:get_wielded_item()
- else
- --pipeworks.logger(dname.."couldn't dig node!")
- end
- end
- local wieldname = wieldstack:get_name()
- if wieldname == oldwieldstack:get_name() then
- -- don't mechanically wear out tool
- if wieldstack:get_count() == oldwieldstack:get_count() and
- wieldstack:get_metadata() == oldwieldstack:get_metadata() and
- ((minetest.registered_items[wieldstack:get_name()] or {}).wear_represents or "mechanical_wear") == "mechanical_wear" then
- virtplayer:set_wielded_item(oldwieldstack)
- end
- elseif wieldname ~= "" then
- -- tool got replaced by something else:
- -- treat it as a drop
- virtplayer:get_inventory():add_item("main", wieldstack)
- virtplayer:set_wielded_item(ItemStack(""))
- end
- end,
- eject_drops = true,
- }
- register_wielder(data)
- minetest.register_craft({
- output = "pipeworks:nodebreaker_off",
- recipe = {
- { "basic_materials:gear_steel", "basic_materials:gear_steel", "basic_materials:gear_steel" },
- { "default:stone", "mesecons:piston", "default:stone" },
- { "group:wood", "mesecons:mesecon", "group:wood" },
- }
- })
- -- aliases for when someone had technic installed, but then uninstalled it but not pipeworks
- minetest.register_alias("technic:nodebreaker_off", "pipeworks:nodebreaker_off")
- minetest.register_alias("technic:nodebreaker_on", "pipeworks:nodebreaker_on")
- minetest.register_alias("technic:node_breaker_off", "pipeworks:nodebreaker_off")
- minetest.register_alias("technic:node_breaker_on", "pipeworks:nodebreaker_on")
- -- turn legacy auto-tree-taps into node breakers
- dofile(pipeworks.modpath.."/legacy.lua")
- -- register LBM for transition to cheaper node breakers
- local lbm_id = "pipeworks:refund_node_breaker_pick"
- minetest.register_lbm({
- name = lbm_id,
- label = "Give back mese pick for pre-transition node breakers",
- run_at_every_load = false,
- nodenames = { name_base.."_on", name_base.."_off" },
- action = function(pos, node)
- pipeworks.logger(lbm_id.." entry, nodename="..node.name)
- local invref = minetest.get_meta(pos):get_inventory()
- invref:add_item(wield_inv_name, ItemStack("default:pick_mese"))
- end
- })
- end
- if pipeworks.enable_deployer then
- register_wielder({
- name_base = "pipeworks:deployer",
- description = S("Deployer"),
- texture_base = "pipeworks_deployer",
- texture_stateful = { front = true },
- tube_connect_sides = { back=1 },
- tube_permit_anteroposterior_insert = true,
- wield_inv_name = "main",
- wield_inv_width = 3,
- wield_inv_height = 3,
- can_dig_nonempty_wield_inv = false,
- masquerade_as_owner = true,
- sneak = false,
- act = function(virtplayer, pointed_thing)
- local wieldstack = virtplayer:get_wielded_item()
- virtplayer:set_wielded_item((minetest.registered_items[wieldstack:get_name()] or {on_place=minetest.item_place}).on_place(wieldstack, virtplayer, pointed_thing) or wieldstack)
- end,
- eject_drops = false,
- })
- minetest.register_craft({
- output = "pipeworks:deployer_off",
- recipe = {
- { "group:wood", "default:chest", "group:wood" },
- { "default:stone", "mesecons:piston", "default:stone" },
- { "default:stone", "mesecons:mesecon", "default:stone" },
- }
- })
- -- aliases for when someone had technic installed, but then uninstalled it but not pipeworks
- minetest.register_alias("technic:deployer_off", "pipeworks:deployer_off")
- minetest.register_alias("technic:deployer_on", "pipeworks:deployer_on")
- end
- if pipeworks.enable_dispenser then
- register_wielder({
- name_base = "pipeworks:dispenser",
- description = S("Dispenser"),
- texture_base = "pipeworks_dispenser",
- texture_stateful = { front = true },
- tube_connect_sides = { back=1 },
- tube_permit_anteroposterior_insert = true,
- wield_inv_name = "main",
- wield_inv_width = 3,
- wield_inv_height = 3,
- can_dig_nonempty_wield_inv = false,
- masquerade_as_owner = false,
- sneak = true,
- act = function(virtplayer, pointed_thing)
- local wieldstack = virtplayer:get_wielded_item()
- virtplayer:set_wielded_item((minetest.registered_items[wieldstack:get_name()] or
- {on_drop=minetest.item_drop}).on_drop(wieldstack, virtplayer, virtplayer:get_pos()) or
- wieldstack)
- end,
- eject_drops = false,
- })
- minetest.register_craft({
- output = "pipeworks:dispenser_off",
- recipe = {
- { "default:desert_sand", "default:chest", "default:desert_sand" },
- { "default:stone", "mesecons:piston", "default:stone" },
- { "default:stone", "mesecons:mesecon", "default:stone" },
- }
- })
- end
|