123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570 |
- -- returns an object to a door object or nil
- function doors.get(pos)
- local node_name = minetest.get_node(pos).name
- if doors.registered_doors[node_name] then
- -- A normal upright door
- return {
- pos = pos,
- open = function(self, player)
- if self:state() then
- return false
- end
- return doors.door_toggle(self.pos, nil, player)
- end,
- close = function(self, player)
- if not self:state() then
- return false
- end
- return doors.door_toggle(self.pos, nil, player)
- end,
- toggle = function(self, player)
- return doors.door_toggle(self.pos, nil, player)
- end,
- state = function(self)
- local state = minetest.get_meta(self.pos):get_int('state')
- return state %2 == 1
- end
- }
- elseif doors.registered_trapdoors[node_name] then
- -- A trapdoor
- return {
- pos = pos,
- open = function(self, player)
- if self:state() then
- return false
- end
- return doors.trapdoor_toggle(self.pos, nil, player)
- end,
- close = function(self, player)
- if not self:state() then
- return false
- end
- return doors.trapdoor_toggle(self.pos, nil, player)
- end,
- toggle = function(self, player)
- return doors.trapdoor_toggle(self.pos, nil, player)
- end,
- state = function(self)
- return minetest.get_node(self.pos).name:sub(-5) == '_open'
- end
- }
- else
- return nil
- end
- end
- -- this hidden node is placed on top of the bottom, and prevents
- -- nodes from being placed in the top half of the door.
- minetest.register_node('doors:hidden', {
- drawtype = 'airlike',
- paramtype = 'light',
- paramtype2 = 'facedir',
- sunlight_propagates = true,
- -- has to be walkable for falling nodes to stop falling.
- --walkable = true,
- pointable = false,
- diggable = false,
- buildable_to = false,
- floodable = false,
- drop = '',
- groups = {not_in_creative_inventory = 1},
- collision_box = {
- type = "fixed",
- fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32},
- },
- })
- -- table used to aid door opening/closing
- local transform = {
- {
- {v = '_a', param2 = 3},
- {v = '_a', param2 = 0},
- {v = '_a', param2 = 1},
- {v = '_a', param2 = 2},
- },
- {
- {v = '_c', param2 = 1},
- {v = '_c', param2 = 2},
- {v = '_c', param2 = 3},
- {v = '_c', param2 = 0},
- },
- {
- {v = '_b', param2 = 1},
- {v = '_b', param2 = 2},
- {v = '_b', param2 = 3},
- {v = '_b', param2 = 0},
- },
- {
- {v = '_d', param2 = 3},
- {v = '_d', param2 = 0},
- {v = '_d', param2 = 1},
- {v = '_d', param2 = 2},
- },
- }
- function doors.door_toggle(pos, node, clicker, close)
- local meta = minetest.get_meta(pos)
- node = node or minetest.get_node(pos)
- local def = minetest.registered_nodes[node.name]
- local name = def.door.name
- local player_name = clicker:get_player_name()
- local lock_status = meta:get_int('lock_s')
- if not close then
- local wield = clicker:get_wielded_item()
- local wield_name = wield:get_name()
- if not minetest.is_protected(pos, player_name) and minetest.check_player_privs(player_name, { creative = true }) then
- else
- local map_id = lobby.game[player_name]
- local sabotage_level = lobby.sabotage_level[map_id] or 5
- local level = meta:get_int('level') or 0
- if level < sabotage_level then
- if lock_status == 1 and (minetest.is_protected(pos, player_name) or not minetest.check_player_privs(player_name, { creative = true })) then
- return
- elseif lock_status == 2 then
- local key = meta:get_string('key')
- if wield_name ~= key then
- local def = minetest.registered_items[key]
- local key_name = def.description
- minetest.chat_send_player(player_name, 'This door can be opened/closed with a '..key_name..'.')
- return
- else
- minetest.after(3, function()
- doors.door_toggle(pos, nil, clicker, true)
- end)
- end
- elseif lock_status >= 3 then
- minetest.chat_send_player(player_name, 'The lock looks cheap, you might be able to pick it.')
- return
- end
- else
- minetest.chat_send_player(player_name, 'This door can\'t be used right now.')
- return
- end
- end
- end
- local state = meta:get_string('state')
- if state == '' then
- -- fix up lvm-placed right-hinged doors, default closed
- if node.name:sub(-2) == '_b' then
- state = 2
- else
- state = 0
- end
- else
- state = tonumber(state)
- end
- -- until Lua-5.2 we have no bitwise operators :(
- if state % 2 == 1 then
- state = state - 1
- else
- state = state + 1
- end
- local dir = node.param2
- -- It's possible param2 is messed up, so, validate before using
- -- the input data. This indicates something may have rotated
- -- the door, even though that is not supported.
- if not transform[state + 1] or not transform[state + 1][dir + 1] then
- return false
- end
- if state % 2 == 0 then
- minetest.sound_play(def.door.sounds[1],
- {pos = pos, gain = 0.3, max_hear_distance = 10}, true)
- else
- minetest.sound_play(def.door.sounds[2],
- {pos = pos, gain = 0.3, max_hear_distance = 10}, true)
- end
- minetest.swap_node(pos, {
- name = 'doors:'..name .. transform[state + 1][dir+1].v,
- param2 = transform[state + 1][dir+1].param2
- })
- meta:set_int('state', state)
- return true
- end
- local function on_place_node(place_to, newnode,
- placer, oldnode, itemstack, pointed_thing)
- -- Run script hook
- for _, callback in ipairs(minetest.registered_on_placenodes) do
- -- Deepcopy pos, node and pointed_thing because callback can modify them
- local place_to_copy = {x = place_to.x, y = place_to.y, z = place_to.z}
- local newnode_copy =
- {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2}
- local oldnode_copy =
- {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2}
- local pointed_thing_copy = {
- type = pointed_thing.type,
- above = vector.new(pointed_thing.above),
- under = vector.new(pointed_thing.under),
- ref = pointed_thing.ref,
- }
- callback(place_to_copy, newnode_copy, placer,
- oldnode_copy, itemstack, pointed_thing_copy)
- end
- end
- function doors.register(name, def)
- minetest.register_craftitem('doors:' .. name, {
- description = def.description,
- inventory_image = 'doors_'..name..'_inv.png',
- groups = {breakable=1},
- on_place = function(itemstack, placer, pointed_thing)
- local pos
- if not pointed_thing.type == 'node' then
- return itemstack
- end
- local node = minetest.get_node(pointed_thing.under)
- local pdef = minetest.registered_nodes[node.name]
- if pdef and pdef.on_rightclick and
- not (placer and placer:is_player() and
- placer:get_player_control().sneak) then
- return pdef.on_rightclick(pointed_thing.under,
- node, placer, itemstack, pointed_thing)
- end
- if pdef and pdef.buildable_to then
- pos = pointed_thing.under
- else
- pos = pointed_thing.above
- node = minetest.get_node(pos)
- pdef = minetest.registered_nodes[node.name]
- if not pdef or not pdef.buildable_to then
- return itemstack
- end
- end
- local above = {x = pos.x, y = pos.y + 1, z = pos.z}
- local top_node = minetest.get_node_or_nil(above)
- local topdef = top_node and minetest.registered_nodes[top_node.name]
- if not topdef or not topdef.buildable_to then
- return itemstack
- end
- local pn = placer and placer:get_player_name() or ''
- if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then
- return itemstack
- end
- local dir = placer and minetest.dir_to_facedir(placer:get_look_dir()) or 0
- local ref = {
- {x = -1, y = 0, z = 0},
- {x = 0, y = 0, z = 1},
- {x = 1, y = 0, z = 0},
- {x = 0, y = 0, z = -1},
- }
- local aside = {
- x = pos.x + ref[dir + 1].x,
- y = pos.y + ref[dir + 1].y,
- z = pos.z + ref[dir + 1].z,
- }
- local state = 0
- if minetest.get_item_group(minetest.get_node(aside).name, 'door') == 1 then
- state = state + 2
- minetest.set_node(pos, {name = 'doors:'..name .. '_b', param2 = dir})
- minetest.set_node(above, {name = 'doors:hidden', param2 = (dir + 3) % 4})
- else
- minetest.set_node(pos, {name = 'doors:'..name .. '_a', param2 = dir})
- minetest.set_node(above, {name = 'doors:hidden', param2 = dir})
- end
- local meta = minetest.get_meta(pos)
- meta:set_int('state', state)
- if not minetest.is_creative_enabled(pn) then
- itemstack:take_item()
- end
- on_place_node(pos, minetest.get_node(pos),
- placer, node, itemstack, pointed_thing)
- return itemstack
- end
- })
- def.inventory_image = nil
- def.tiles = {{name = 'doors_'..name..'.png', backface_culling=true}}
- def.groups = {breakable=1, door=1, not_in_creative_inventory=1}
- --if not def.sounds then
- -- def.sounds = default.node_sound_wood_defaults()
- --end
- if not def.sound_open then
- def.sound_open = 'doors_door_open'
- end
- if not def.sound_close then
- def.sound_close = 'doors_door_close'
- end
- def.drop = 'doors:'..name
- def.door = {
- name = name,
- sounds = { def.sound_close, def.sound_open },
- }
- if not def.on_rightclick then
- def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
- doors.door_toggle(pos, node, clicker)
- return itemstack
- end
- end
- def.after_dig_node = function(pos, node, meta, digger)
- minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
- end
- def.on_rotate = function(pos, node, user, mode, new_param2)
- return false
- end
- def.on_destruct = function(pos)
- minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z})
- end
- def.drawtype = 'mesh'
- def.paramtype = 'light'
- def.paramtype2 = 'facedir'
- def.sunlight_propagates = true
- def.walkable = true
- def.is_ground_content = false
- def.buildable_to = false
- def.use_texture_alpha = 'clip'
- def.selection_box = {type = 'fixed', fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}}
- def.collision_box = {type = 'fixed', fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}}
- def.mesh = 'door_a.obj'
- minetest.register_node('doors:' .. name .. '_a', def)
- def.mesh = 'door_b.obj'
- minetest.register_node('doors:' .. name .. '_b', def)
- def.mesh = 'door_a2.obj'
- minetest.register_node('doors:' .. name .. '_c', def)
- def.mesh = 'door_b2.obj'
- minetest.register_node('doors:' .. name .. '_d', def)
- doors.registered_doors['doors:'..name .. '_a'] = true
- doors.registered_doors['doors:'..name .. '_b'] = true
- doors.registered_doors['doors:'..name .. '_c'] = true
- doors.registered_doors['doors:'..name .. '_d'] = true
- end
- ----trapdoor----
- function doors.trapdoor_toggle(pos, node, clicker, close)
- node = node or minetest.get_node(pos)
- local meta = minetest.get_meta(pos)
- local def = minetest.registered_nodes[node.name]
- local player_name = clicker:get_player_name()
- local lock_status = meta:get_int('lock_s')
- if not close then
- local wield = clicker:get_wielded_item()
- local wield_name = wield:get_name()
- if not minetest.is_protected(pos, player_name) and minetest.check_player_privs(player_name, { creative = true }) then
- else
- local map_id = lobby.game[player_name]
- local sabotage_level = lobby.sabotage_level[map_id] or 5
- local level = meta:get_int('level') or 0
- if level < sabotage_level then
- if lock_status == 1 and (minetest.is_protected(pos, player_name) or not minetest.check_player_privs(player_name, { creative = true })) then
- return
- elseif lock_status == 2 then
- local key = meta:get_string('key')
- if wield_name ~= key then
- local def = minetest.registered_items[key]
- local key_name = def.description
- minetest.chat_send_player(player_name, 'This door can be opened/closed with a '..key_name..'.')
- return
- else
- minetest.after(3, function()
- doors.trapdoor_toggle(pos, nil, clicker, true)
- end)
- end
- elseif lock_status >= 3 then
- minetest.chat_send_player(player_name, 'The lock looks cheap, you might be able to pick it.')
- return
- end
- else
- minetest.chat_send_player(player_name, 'This door can\'t be used right now.')
- return
- end
- end
- end
- if string.sub(node.name, -5) == '_open' then
- minetest.sound_play(def.sound_close,
- {pos = pos, gain = 0.3, max_hear_distance = 10}, true)
- minetest.swap_node(pos, {name = string.sub(node.name, 1,
- string.len(node.name) - 5), param1 = node.param1, param2 = node.param2})
- else
- minetest.sound_play(def.sound_open,
- {pos = pos, gain = 0.3, max_hear_distance = 10}, true)
- minetest.swap_node(pos, {name = node.name .. '_open',
- param1 = node.param1, param2 = node.param2})
- end
- end
- function doors.register_trapdoor(name, def)
- local name_closed = name
- local name_opened = name..'_open'
- def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
- doors.trapdoor_toggle(pos, node, clicker)
- return itemstack
- end
- -- Common trapdoor configuration
- def.inventory_image = 'doors_'..name..'.png'
- def.drawtype = 'nodebox'
- def.paramtype = 'light'
- def.paramtype2 = 'facedir'
- def.is_ground_content = false
- def.use_texture_alpha = 'clip'
- def.groups = {breakable=1, door=2}
- --if not def.sounds then
- -- def.sounds = default.node_sound_wood_defaults()
- --end
- if not def.sound_open then
- def.sound_open = 'doors_door_open'
- end
- if not def.sound_close then
- def.sound_close = 'doors_door_close'
- end
- local def_opened = table.copy(def)
- local def_closed = table.copy(def)
- def_closed.node_box = {
- type = 'fixed',
- fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
- }
- def_closed.selection_box = {
- type = 'fixed',
- fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
- }
- def_closed.tiles = {
- 'doors_'..name..'.png',
- 'doors_'..name..'.png^[transformFY',
- 'doors_'..name..'_side.png',
- 'doors_'..name..'_side.png',
- 'doors_'..name..'_side.png',
- 'doors_'..name..'_side.png'
- }
- def_opened.groups.not_in_creative_inventory=1
- def_opened.node_box = {
- type = 'fixed',
- fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5}
- }
- def_opened.selection_box = {
- type = 'fixed',
- fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5}
- }
- def_opened.tiles = {
- def.tile_side,
- 'doors_'..name..'_side.png^[transform2',
- 'doors_'..name..'_side.png^[transform3',
- 'doors_'..name..'_side.png^[transform1',
- 'doors_'..name..'.png^[transform46',
- 'doors_'..name..'.png^[transform6'
- }
- def_opened.drop = name_closed
- minetest.register_node('doors:'..name_opened, def_opened)
- minetest.register_node('doors:'..name_closed, def_closed)
- doors.registered_trapdoors['doors:'..name_opened] = true
- doors.registered_trapdoors['doors:'..name_closed] = true
- end
- function doors.lock(pos, name)
- local meta = minetest.get_meta(pos)
- local status = meta:get_int('lock_s')
- local key_i = meta:get_int('key_i')
- local level = meta:get_int('level')
- local infotext = meta:get_string('infotext')
- minetest.show_formspec(name, 'doors:configuration', doors.lock_formspec(status, key_i, level, infotext))
- end
- local keys = {
- 'doors:key_skeleton', 'doors:key_modern', 'doors:keycard_red', 'doors:keycard_green', 'doors:keycard_blue'
- }
- function doors.lock_formspec(status, key_i, level, infotext)
- local formspec =
- 'formspec_version[3]'..
- 'size[8,8]'..
- 'textarea[.5,.5;7,4.25;;;Set the lock status here, different numbers mean different things, the following breakdown should be helpful.\n'..
- '\n0: Standard door, anybody can open it.\n'..
- '1: Locked door, only people within the area protection can open. Not pickable.\n'..
- '2: Locked door, uses Key to open.\n'..
- '3-13: locked door, can be picked, higher values are harder to pick. Limited time is offered to pick a door. '..
- 'Formula is (20-lock Status)+Luck.\n'..
- '\nYou can ignore the level input if you aren\'t adding a node you can sabotage.]'..
- 'field[1,5;6,.5;infotext;Infotext;'..infotext..']'..
- 'field[1,6;2,.5;status;Lock Status;'..status..']'..
- 'dropdown[4,6;3,.5;key;'..table.concat(keys, ',')..';'..key_i..']'..
- 'field[1,7;2,.5;level;Level;'..level..']'..
- 'button_exit[5,7;2,.5;save;Submit]'
- return formspec
- end
- minetest.register_on_player_receive_fields(function(player, formname, fields)
- local name = player:get_player_name()
- if formname == 'doors:configuration' then
- if fields.save then
- local state = tonumber(fields.status) or 0
- if state >= 0 and state <= 13 then
- local pos = tasks.player_config[name]
- local meta = minetest.get_meta(pos)
- local info = fields.infotext
- local lower = string.lower(info)
- meta:set_int('lock_s', state)
- meta:set_int('level', math.min(fields.level, 4))
- if state == 0 then
- meta:set_string('infotext', info)
- elseif state == 2 then
- if string.find(lower, 'lock') then
- meta:set_string('infotext', info)
- else
- meta:set_string('infotext', info..' (locked)')
- end
- for i, index in ipairs(keys) do
- if index == fields.key then
- meta:set_string('key', fields.key)
- meta:set_int('key_i', i)
- end
- end
- else
- if string.find(lower, 'lock') then
- meta:set_string('infotext', info)
- else
- meta:set_string('infotext', info..' (locked)')
- end
- end
- else
- minetest.chat_send_player(name, 'Faulty input, try again.')
- end
- end
- end
- end)
|