local utils = ... local S = utils.S if utils.digilines_supported or utils.mesecon_supported then local fan_interval = 0.2 local fan_force = 15.0 local function direction_vector (node) local axis = math.floor (node.param2 / 4) local rotate = node.param2 % 4 local vec = { x = 0, y = 0, z = 0 } if rotate == 0 then vec = { x = 0, y = 0, z = -1 } elseif rotate == 1 then vec = { x = -1, y = 0, z = 0 } elseif rotate == 2 then vec = { x = 0, y = 0, z = 1 } elseif rotate == 3 then vec = { x = 1, y = 0, z = 0 } end if axis == 1 then vec = vector.rotate (vec, { x = math.pi / -2, y = 0, z = 0 }) elseif axis == 2 then vec = vector.rotate (vec, { x = math.pi / 2, y = 0, z = 0 }) elseif axis == 3 then vec = vector.rotate (vec, { x = 0, y = 0, z = math.pi / 2 }) elseif axis == 4 then vec = vector.rotate (vec, { x = 0, y = 0, z = math.pi / -2 }) elseif axis == 5 then vec = vector.rotate (vec, { x = math.pi, y = 0, z = 0 }) end return vec end local function blow (pos) local node = minetest.get_node (pos) local dir = direction_vector (node) local reach = 5 for r = 1, reach, 1 do local tpos = vector.add (pos, vector.multiply (dir, r)) local tnode = minetest.get_node_or_nil (tpos) if tnode and tnode.name ~= "air" then local def = utils.find_item_def (tnode.name) if def and def.walkable then return end end local object = minetest.get_objects_inside_radius (tpos, 1.5) local vel = vector.multiply (dir, (dir.y > 0 and fan_force / 2) or fan_force) for i = 1, #object do if object[i].add_velocity then local opos = object[i]:get_pos () if opos.x >= (tpos.x - 0.5) and opos.x <= (tpos.x + 0.5) and opos.z >= (tpos.z - 0.5) and opos.z <= (tpos.z + 0.5) and opos.y >= (tpos.y - 0.5) and opos.y <= (tpos.y + 0.5) then if object[i].get_luaentity and object[i]:get_luaentity () and object[i]:get_luaentity ().name and object[i]:get_luaentity ().name == "__builtin:item" then object[i]:add_velocity (vector.multiply (vel, 5)) else object[i]:add_velocity (vel) end end end end end end local function fan_off (pos) local node = minetest.get_node (pos) if node then if node.name == "lwcomponents:fan_on" then node.name = "lwcomponents:fan" minetest.get_node_timer (pos):stop () minetest.swap_node (pos, node) elseif node.name == "lwcomponents:fan_locked_on" then node.name = "lwcomponents:fan_locked" minetest.get_node_timer (pos):stop () minetest.swap_node (pos, node) end end end local function fan_on (pos) local node = minetest.get_node (pos) if node then if node.name == "lwcomponents:fan" then node.name = "lwcomponents:fan_on" minetest.swap_node (pos, node) minetest.get_node_timer (pos):start (fan_interval) elseif node.name == "lwcomponents:fan_locked" then node.name = "lwcomponents:fan_locked_on" minetest.swap_node (pos, node) minetest.get_node_timer (pos):start (fan_interval) end end end local function on_place (itemstack, placer, pointed_thing) local param2 = 0 if placer and placer:is_player () then param2 = minetest.dir_to_facedir (placer:get_look_dir (), true) elseif pointed_thing and pointed_thing.type == "node" then param2 = minetest.dir_to_facedir (vector.subtract (pointed_thing.under, pointed_thing.above), true) end return minetest.item_place (itemstack, placer, pointed_thing, param2) end local function after_place_node (pos, placer, itemstack, pointed_thing) local meta = minetest.get_meta (pos) local spec = "size[7.5,3]".. "field[1,1;6,2;channel;Channel;${channel}]".. "button_exit[2.5,2;3,1;submit;Set]" meta:set_string ("formspec", spec) -- If return true no item is taken from itemstack return false end local function after_place_node_locked (pos, placer, itemstack, pointed_thing) after_place_node (pos, placer, itemstack, pointed_thing) if placer and placer:is_player () then local meta = minetest.get_meta (pos) meta:set_string ("owner", placer:get_player_name ()) meta:set_string ("infotext", "Fan (owned by "..placer:get_player_name ()..")") end -- If return true no item is taken from itemstack return false end local function on_receive_fields (pos, formname, fields, sender) if not utils.can_interact_with_node (pos, sender) then return end local meta = minetest.get_meta(pos) if fields.submit then meta:set_string ("channel", fields.channel) end end local function on_blast (pos, intensity) local meta = minetest.get_meta (pos) if meta then if intensity >= 1.0 then minetest.remove_node (pos) else -- intensity < 1.0 local node = minetest.get_node_or_nil (pos) if node then local items = minetest.get_node_drops (node, nil) if items and #items > 0 then local stack = ItemStack (items[1]) if stack then utils.item_drop (stack, nil, pos) minetest.remove_node (pos) end end end end end end local function can_dig (pos, player) if not utils.can_interact_with_node (pos, player) then return false end return true end local function on_rightclick (pos, node, clicker, itemstack, pointed_thing) if not utils.can_interact_with_node (pos, clicker) then if clicker and clicker:is_player () then local owner = "" local meta = minetest.get_meta (pos) if meta then owner = meta:get_string ("owner") end local spec = "formspec_version[3]".. "size[8.0,4.0,false]".. "label[1.0,1.0;Owned by "..minetest.formspec_escape (owner).."]".. "button_exit[3.0,2.0;2.0,1.0;close;Close]" minetest.show_formspec (clicker:get_player_name (), "lwcomponents:component_privately_owned", spec) end end return itemstack end local function on_timer (pos, elapsed) blow (pos) return true end local function digilines_support () if utils.digilines_supported then return { wire = { rules = utils.digilines_default_rules, }, effector = { action = function (pos, node, channel, msg) local meta = minetest.get_meta(pos) if meta then local this_channel = meta:get_string ("channel") if this_channel ~= "" and this_channel == channel then if type (msg) == "string" then local m = { } for w in string.gmatch(msg, "[^%s]+") do m[#m + 1] = w end if m[1] == "start" then fan_on (pos) elseif m[1] == "stop" then fan_off (pos) end end end end end, } } end return nil end local function mesecon_support () if utils.mesecon_supported then return { effector = { rules = utils.mesecon_default_rules, action_on = function (pos, node) -- do something to turn the effector on fan_on (pos) end, action_off = function (pos, node) -- do something to turn the effector off fan_off (pos) end, } } end return nil end minetest.register_node("lwcomponents:fan", { description = S("Fan"), tiles = { "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan_face.png"}, is_ground_content = false, groups = { cracky = 3, wires_connect = 1 }, sounds = default.node_sound_stone_defaults (), paramtype = "none", param1 = 0, paramtype2 = "facedir", param2 = 0, floodable = false, drop = "lwcomponents:fan", _digistuff_channelcopier_fieldname = "channel", mesecons = mesecon_support (), digiline = digilines_support (), on_place = on_place, on_receive_fields = on_receive_fields, can_dig = can_dig, after_place_node = after_place_node, on_blast = on_blast, on_rightclick = on_rightclick, }) minetest.register_node("lwcomponents:fan_locked", { description = S("Fan (locked)"), tiles = { "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan_face.png"}, is_ground_content = false, groups = { cracky = 3, wires_connect = 1 }, sounds = default.node_sound_stone_defaults (), paramtype = "none", param1 = 0, paramtype2 = "facedir", param2 = 0, floodable = false, drop = "lwcomponents:fan_locked", _digistuff_channelcopier_fieldname = "channel", mesecons = mesecon_support (), digiline = digilines_support (), on_place = on_place, on_receive_fields = on_receive_fields, can_dig = can_dig, after_place_node = after_place_node_locked, on_blast = on_blast, on_rightclick = on_rightclick, }) minetest.register_node("lwcomponents:fan_on", { description = S("Fan"), tiles = { "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan_face_on.png"}, is_ground_content = false, groups = { cracky = 3, not_in_creative_inventory = 1, wires_connect = 1 }, sounds = default.node_sound_stone_defaults (), paramtype = "none", param1 = 0, paramtype2 = "facedir", param2 = 0, floodable = false, drop = "lwcomponents:fan", _digistuff_channelcopier_fieldname = "channel", mesecons = mesecon_support (), digiline = digilines_support (), on_place = on_place, on_receive_fields = on_receive_fields, can_dig = can_dig, after_place_node = after_place_node, on_blast = on_blast, on_timer = on_timer, on_rightclick = on_rightclick, }) minetest.register_node("lwcomponents:fan_locked_on", { description = S("Fan (locked)"), tiles = { "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan.png", "lwfan_face_on.png"}, is_ground_content = false, groups = { cracky = 3, not_in_creative_inventory = 1, wires_connect = 1 }, sounds = default.node_sound_stone_defaults (), paramtype = "none", param1 = 0, paramtype2 = "facedir", param2 = 0, floodable = false, drop = "lwcomponents:fan_locked", _digistuff_channelcopier_fieldname = "channel", mesecons = mesecon_support (), digiline = digilines_support (), on_place = on_place, on_receive_fields = on_receive_fields, can_dig = can_dig, after_place_node = after_place_node_locked, on_blast = on_blast, on_timer = on_timer, on_rightclick = on_rightclick, }) end -- utils.digilines_supported or utils.mesecon_supported