4 Copyright (C) 2012 PilzAdam
5 modified by BlockMen (added sounds, glassdoors[glass, obsidian glass], trapdoor)
6 Copyright (C) 2015 - Auke Kok <sofar@foo-projects.org>
15 _doors.registered_doors = {}
16 _doors.registered_trapdoors = {}
18 -- returns an object to a door object or nil
19 function doors.get(pos)
20 if _doors.registered_doors[minetest.get_node(pos).name] then
21 -- A normal upright door
24 open = function(self, player)
28 return _doors.door_toggle(self.pos, player)
30 close = function(self, player)
31 if not self:state() then
34 return _doors.door_toggle(self.pos, player)
36 toggle = function(self, player)
37 return _doors.door_toggle(self.pos, player)
39 state = function(self)
40 local state = minetest.get_meta(self.pos):get_int("state")
44 elseif _doors.registered_trapdoors[minetest.get_node(pos).name] then
48 open = function(self, player)
52 return _doors.trapdoor_toggle(self.pos, player)
54 close = function(self, player)
55 if not self:state() then
58 return _doors.trapdoor_toggle(self.pos, player)
60 toggle = function(self, player)
61 return _doors.trapdoor_toggle(self.pos, player)
63 state = function(self)
64 local name = minetest.get_node(pos).name
65 return name:sub(-5) == "_open"
73 -- this hidden node is placed on top of the bottom, and prevents
74 -- nodes from being placed in the top half of the door.
75 minetest.register_node("doors:hidden", {
76 description = "Hidden Door Segment",
79 sunlight_propagates = true,
86 groups = { not_in_creative_inventory = 1 },
87 on_blast = function() end
90 -- table used to aid door opening/closing
93 { v = "_a", param2 = 3 },
94 { v = "_a", param2 = 0 },
95 { v = "_a", param2 = 1 },
96 { v = "_a", param2 = 2 },
99 { v = "_b", param2 = 1 },
100 { v = "_b", param2 = 2 },
101 { v = "_b", param2 = 3 },
102 { v = "_b", param2 = 0 },
105 { v = "_b", param2 = 1 },
106 { v = "_b", param2 = 2 },
107 { v = "_b", param2 = 3 },
108 { v = "_b", param2 = 0 },
111 { v = "_a", param2 = 3 },
112 { v = "_a", param2 = 0 },
113 { v = "_a", param2 = 1 },
114 { v = "_a", param2 = 2 },
118 function _doors.door_toggle(pos, clicker)
119 local meta = minetest.get_meta(pos)
120 local state = meta:get_int("state")
121 local def = minetest.registered_nodes[minetest.get_node(pos).name]
122 local name = def.door.basename
125 local owner = meta:get_string("doors_owner")
127 if clicker:get_player_name() ~= owner then
134 -- until Lua-5.2 we have no bitwise operators :(
135 if state % 2 == 1 then
141 local dir = minetest.get_node(pos).param2
142 if state % 2 == 0 then
143 minetest.sound_play(def.door.sounds[1], {pos = pos, gain = 0.3, max_hear_distance = 10})
145 minetest.sound_play(def.door.sounds[2], {pos = pos, gain = 0.3, max_hear_distance = 10})
148 minetest.swap_node(pos, {
149 name = "doors:" .. name .. transform[state + 1][dir+1].v,
150 param2 = transform[state + 1][dir+1].param2
152 meta:set_int("state", state)
157 function doors.register(name, def)
158 -- replace old doors of this type automatically
159 minetest.register_abm({
160 nodenames = {"doors:"..name.."_b_1", "doors:"..name.."_b_2"},
163 action = function(pos, node, active_object_count, active_object_count_wider)
164 local l = tonumber(node.name:sub(-1))
165 local meta = minetest.get_meta(pos)
166 local h = meta:get_int("right") + 1
167 local p2 = node.param2
169 { { type = "a", state = 0 }, { type = "a", state = 3 } },
170 { { type = "b", state = 1 }, { type = "b", state = 2 } }
172 local new = replace[l][h]
173 -- retain infotext and doors_owner fields
174 minetest.swap_node(pos, { name = "doors:" .. name .. "_" .. new.type, param2 = p2})
175 meta:set_int("state", new.state)
176 -- wipe meta on top node as it's unused
177 minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, { name = "doors:hidden" })
181 minetest.register_craftitem(":doors:" .. name, {
182 description = def.description,
183 inventory_image = def.inventory_image,
185 on_place = function(itemstack, placer, pointed_thing)
186 local pos = pointed_thing.above
187 local node = minetest.get_node(pos)
189 if not minetest.registered_nodes[node.name].buildable_to then
193 local above = { x = pos.x, y = pos.y + 1, z = pos.z }
194 if not minetest.registered_nodes[minetest.get_node(above).name].buildable_to then
198 local dir = minetest.dir_to_facedir(placer:get_look_dir())
201 { x = -1, y = 0, z = 0 },
202 { x = 0, y = 0, z = 1 },
203 { x = 1, y = 0, z = 0 },
204 { x = 0, y = 0, z = -1 },
208 x = pos.x + ref[dir + 1].x,
209 y = pos.y + ref[dir + 1].y,
210 z = pos.z + ref[dir + 1].z,
214 if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then
216 minetest.set_node(pos, {name = "doors:" .. name .. "_b", param2 = dir})
218 minetest.set_node(pos, {name = "doors:" .. name .. "_a", param2 = dir})
220 minetest.set_node(above, { name = "doors:hidden" })
222 local meta = minetest.get_meta(pos)
223 meta:set_int("state", state)
225 if def.protected then
226 local pn = placer:get_player_name()
227 meta:set_string("doors_owner", pn)
228 meta:set_string("infotext", "Owned by " .. pn)
231 if not minetest.setting_getbool("creative_mode") then
232 itemstack:take_item()
239 local can_dig = function(pos, digger)
240 if not def.protected then
243 local meta = minetest.get_meta(pos)
244 return meta:get_string("doors_owner") == digger:get_player_name()
247 if not def.sounds then
248 def.sounds = default.node_sound_wood_defaults()
251 if not def.sound_open then
252 def.sound_open = "doors_door_open"
255 if not def.sound_close then
256 def.sound_close = "doors_door_close"
259 def.groups.not_in_creative_inventory = 1
261 def.drop = "doors:" .. name
264 sounds = { def.sound_close, def.sound_open },
267 def.on_rightclick = function(pos, node, clicker)
268 _doors.door_toggle(pos, clicker)
270 def.after_dig_node = function(pos, node, meta, digger)
271 minetest.remove_node({ x = pos.x, y = pos.y + 1, z = pos.z})
273 def.can_dig = function(pos, player)
274 return can_dig(pos, player)
276 def.on_rotate = function(pos, node, user, mode, new_param2)
280 if def.protected then
281 def.on_blast = function() end
283 def.on_blast = function(pos, intensity)
284 minetest.remove_node(pos)
285 -- hidden node doesn't get blasted away.
286 minetest.remove_node({ x = pos.x, y = pos.y + 1, z = pos.z})
287 return { "doors:" .. name }
291 minetest.register_node(":doors:" .. name .. "_a", {
292 description = def.description,
298 paramtype2 = "facedir",
299 sunlight_propagates = true,
300 use_texture_alpha = true,
302 is_ground_content = false,
303 buildable_to = false,
308 on_rightclick = def.on_rightclick,
309 after_dig_node = def.after_dig_node,
310 can_dig = def.can_dig,
311 on_rotate = def.on_rotate,
312 on_blast = def.on_blast,
315 fixed = { -1/2,-1/2,-1/2,1/2,3/2,-6/16}
319 fixed = { -1/2,-1/2,-1/2,1/2,3/2,-6/16}
323 minetest.register_node(":doors:" .. name .. "_b", {
324 description = def.description,
330 paramtype2 = "facedir",
331 sunlight_propagates = true,
332 use_texture_alpha = true,
334 is_ground_content = false,
335 buildable_to = false,
340 on_rightclick = def.on_rightclick,
341 after_dig_node = def.after_dig_node,
342 can_dig = def.can_dig,
343 on_rotate = def.on_rotate,
344 on_blast = def.on_blast,
347 fixed = { -1/2,-1/2,-1/2,1/2,3/2,-6/16}
351 fixed = { -1/2,-1/2,-1/2,1/2,3/2,-6/16}
355 minetest.register_craft({
356 output = "doors:" .. name,
358 {def.material,def.material};
359 {def.material,def.material};
360 {def.material,def.material};
364 _doors.registered_doors["doors:" .. name .. "_a"] = true
365 _doors.registered_doors["doors:" .. name .. "_b"] = true
368 doors.register("door_wood", {
369 tiles = {{ name = "doors_door_wood.png", backface_culling = true }},
370 description = "Wooden Door",
371 inventory_image = "doors_item_wood.png",
372 groups = { snappy = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 2 },
373 material = "group:wood",
376 doors.register("door_steel", {
377 tiles = {{ name = "doors_door_steel.png", backface_culling = true }},
378 description = "Steel Door",
379 inventory_image = "doors_item_steel.png",
381 groups = { snappy = 1, bendy = 2, cracky = 1, melty = 2, level = 2 },
382 material = "default:steel_ingot",
385 doors.register("door_glass", {
386 tiles = { "doors_door_glass.png"},
387 description = "Glass Door",
388 inventory_image = "doors_item_glass.png",
389 groups = { snappy=1, cracky=1, oddly_breakable_by_hand=3 },
390 material = "default:glass",
391 sounds = default.node_sound_glass_defaults(),
394 doors.register("door_obsidian_glass", {
395 tiles = { "doors_door_obsidian_glass.png" },
396 description = "Glass Door",
397 inventory_image = "doors_item_obsidian_glass.png",
398 groups = { snappy=1, cracky=1, oddly_breakable_by_hand=3 },
399 material = "default:obsidian_glass",
400 sounds = default.node_sound_glass_defaults(),
405 function _doors.trapdoor_toggle(pos, clicker)
407 local meta = minetest.get_meta(pos)
408 local owner = meta:get_string("doors_owner")
410 if clicker:get_player_name() ~= owner then
416 local node = minetest.get_node(pos)
417 local def = minetest.registered_nodes[node.name]
419 if string.sub(node.name, -5) == "_open" then
420 minetest.sound_play(def.sound_close, {pos = pos, gain = 0.3, max_hear_distance = 10})
421 minetest.swap_node(pos, {name = string.sub(node.name, 1, string.len(node.name) - 5), param1 = node.param1, param2 = node.param2})
423 minetest.sound_play(def.sound_open, {pos = pos, gain = 0.3, max_hear_distance = 10})
424 minetest.swap_node(pos, {name = node.name .. "_open", param1 = node.param1, param2 = node.param2})
428 function doors.register_trapdoor(name, def)
429 local name_closed = name
430 local name_opened = name.."_open"
432 local function check_player_priv(pos, player)
433 if not def.protected then
436 local meta = minetest.get_meta(pos)
437 local pn = player:get_player_name()
438 return meta:get_string("doors_owner") == pn
441 def.on_rightclick = function(pos, node, clicker)
442 _doors.trapdoor_toggle(pos, clicker)
445 -- Common trapdoor configuration
446 def.drawtype = "nodebox"
447 def.paramtype = "light"
448 def.paramtype2 = "facedir"
449 def.is_ground_content = false
450 def.can_dig = check_player_priv
452 if def.protected then
453 def.after_place_node = function(pos, placer, itemstack, pointed_thing)
454 local pn = placer:get_player_name()
455 local meta = minetest.get_meta(pos)
456 meta:set_string("doors_owner", pn)
457 meta:set_string("infotext", "Owned by "..pn)
459 return minetest.setting_getbool("creative_mode")
462 def.on_blast = function() end
464 def.on_blast = function(pos, intensity)
465 minetest.remove_node(pos)
466 minetest.remove_node({ x = pos.x, y = pos.y + 1, z = pos.z})
471 if not def.sounds then
472 def.sounds = default.node_sound_wood_defaults()
475 if not def.sound_open then
476 def.sound_open = "doors_door_open"
479 if not def.sound_close then
480 def.sound_close = "doors_door_close"
483 local def_opened = table.copy(def)
484 local def_closed = table.copy(def)
486 def_closed.node_box = {
488 fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
490 def_closed.selection_box = {
492 fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5}
494 def_closed.tiles = { def.tile_front, def.tile_front, def.tile_side, def.tile_side,
495 def.tile_side, def.tile_side }
497 def_opened.node_box = {
499 fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5}
501 def_opened.selection_box = {
503 fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5}
505 def_opened.tiles = { def.tile_side, def.tile_side,
506 def.tile_side .. '^[transform3',
507 def.tile_side .. '^[transform1',
508 def.tile_front, def.tile_front }
510 def_opened.drop = name_closed
511 def_opened.groups.not_in_creative_inventory = 1
513 minetest.register_node(name_opened, def_opened)
514 minetest.register_node(name_closed, def_closed)
516 _doors.registered_trapdoors[name_opened] = true
517 _doors.registered_trapdoors[name_closed] = true
520 doors.register_trapdoor("doors:trapdoor", {
521 description = "Trapdoor",
522 inventory_image = "doors_trapdoor.png",
523 wield_image = "doors_trapdoor.png",
524 tile_front = "doors_trapdoor.png",
525 tile_side = "doors_trapdoor_side.png",
526 groups = {snappy=1, choppy=2, oddly_breakable_by_hand=2, flammable=2, door=1},
529 doors.register_trapdoor("doors:trapdoor_steel", {
530 description = "Steel Trapdoor",
531 inventory_image = "doors_trapdoor_steel.png",
532 wield_image = "doors_trapdoor_steel.png",
533 tile_front = "doors_trapdoor_steel.png",
534 tile_side = "doors_trapdoor_steel_side.png",
536 groups = {snappy=1, bendy=2, cracky=1, melty=2, level=2, door=1},
539 minetest.register_craft({
540 output = 'doors:trapdoor 2',
542 {'group:wood', 'group:wood', 'group:wood'},
543 {'group:wood', 'group:wood', 'group:wood'},
548 minetest.register_craft({
549 output = 'doors:trapdoor_steel',
551 {'default:steel_ingot', 'default:steel_ingot'},
552 {'default:steel_ingot', 'default:steel_ingot'},