1-- doors/init.lua 2 3-- our API object 4doors = {} 5 6doors.registered_doors = {} 7doors.registered_trapdoors = {} 8 9-- Load support for MT game translation. 10local S = minetest.get_translator("doors") 11 12 13local function replace_old_owner_information(pos) 14 local meta = minetest.get_meta(pos) 15 local owner = meta:get_string("doors_owner") 16 if owner and owner ~= "" then 17 meta:set_string("owner", owner) 18 meta:set_string("doors_owner", "") 19 end 20end 21 22-- returns an object to a door object or nil 23function doors.get(pos) 24 local node_name = minetest.get_node(pos).name 25 if doors.registered_doors[node_name] then 26 -- A normal upright door 27 return { 28 pos = pos, 29 open = function(self, player) 30 if self:state() then 31 return false 32 end 33 return doors.door_toggle(self.pos, nil, player) 34 end, 35 close = function(self, player) 36 if not self:state() then 37 return false 38 end 39 return doors.door_toggle(self.pos, nil, player) 40 end, 41 toggle = function(self, player) 42 return doors.door_toggle(self.pos, nil, player) 43 end, 44 state = function(self) 45 local state = minetest.get_meta(self.pos):get_int("state") 46 return state %2 == 1 47 end 48 } 49 elseif doors.registered_trapdoors[node_name] then 50 -- A trapdoor 51 return { 52 pos = pos, 53 open = function(self, player) 54 if self:state() then 55 return false 56 end 57 return doors.trapdoor_toggle(self.pos, nil, player) 58 end, 59 close = function(self, player) 60 if not self:state() then 61 return false 62 end 63 return doors.trapdoor_toggle(self.pos, nil, player) 64 end, 65 toggle = function(self, player) 66 return doors.trapdoor_toggle(self.pos, nil, player) 67 end, 68 state = function(self) 69 return minetest.get_node(self.pos).name:sub(-5) == "_open" 70 end 71 } 72 else 73 return nil 74 end 75end 76 77-- this hidden node is placed on top of the bottom, and prevents 78-- nodes from being placed in the top half of the door. 79minetest.register_node("doors:hidden", { 80 description = S("Hidden Door Segment"), 81 inventory_image = "doors_hidden_segment.png^default_invisible_node_overlay.png", 82 wield_image = "doors_hidden_segment.png^default_invisible_node_overlay.png", 83 drawtype = "airlike", 84 paramtype = "light", 85 paramtype2 = "facedir", 86 sunlight_propagates = true, 87 -- has to be walkable for falling nodes to stop falling. 88 walkable = true, 89 pointable = false, 90 diggable = false, 91 buildable_to = false, 92 floodable = false, 93 drop = "", 94 groups = {not_in_creative_inventory = 1}, 95 on_blast = function() end, 96 -- 1px block inside door hinge near node top 97 collision_box = { 98 type = "fixed", 99 fixed = {-15/32, 13/32, -15/32, -13/32, 1/2, -13/32}, 100 }, 101}) 102 103-- table used to aid door opening/closing 104local transform = { 105 { 106 {v = "_a", param2 = 3}, 107 {v = "_a", param2 = 0}, 108 {v = "_a", param2 = 1}, 109 {v = "_a", param2 = 2}, 110 }, 111 { 112 {v = "_c", param2 = 1}, 113 {v = "_c", param2 = 2}, 114 {v = "_c", param2 = 3}, 115 {v = "_c", param2 = 0}, 116 }, 117 { 118 {v = "_b", param2 = 1}, 119 {v = "_b", param2 = 2}, 120 {v = "_b", param2 = 3}, 121 {v = "_b", param2 = 0}, 122 }, 123 { 124 {v = "_d", param2 = 3}, 125 {v = "_d", param2 = 0}, 126 {v = "_d", param2 = 1}, 127 {v = "_d", param2 = 2}, 128 }, 129} 130 131function doors.door_toggle(pos, node, clicker) 132 local meta = minetest.get_meta(pos) 133 node = node or minetest.get_node(pos) 134 local def = minetest.registered_nodes[node.name] 135 local name = def.door.name 136 137 local state = meta:get_string("state") 138 if state == "" then 139 -- fix up lvm-placed right-hinged doors, default closed 140 if node.name:sub(-2) == "_b" then 141 state = 2 142 else 143 state = 0 144 end 145 else 146 state = tonumber(state) 147 end 148 149 replace_old_owner_information(pos) 150 151 if clicker and not default.can_interact_with_node(clicker, pos) then 152 return false 153 end 154 155 -- until Lua-5.2 we have no bitwise operators :( 156 if state % 2 == 1 then 157 state = state - 1 158 else 159 state = state + 1 160 end 161 162 local dir = node.param2 163 164 -- It's possible param2 is messed up, so, validate before using 165 -- the input data. This indicates something may have rotated 166 -- the door, even though that is not supported. 167 if not transform[state + 1] or not transform[state + 1][dir + 1] then 168 return false 169 end 170 171 if state % 2 == 0 then 172 minetest.sound_play(def.door.sounds[1], 173 {pos = pos, gain = 0.3, max_hear_distance = 10}, true) 174 else 175 minetest.sound_play(def.door.sounds[2], 176 {pos = pos, gain = 0.3, max_hear_distance = 10}, true) 177 end 178 179 minetest.swap_node(pos, { 180 name = name .. transform[state + 1][dir+1].v, 181 param2 = transform[state + 1][dir+1].param2 182 }) 183 meta:set_int("state", state) 184 185 return true 186end 187 188 189local function on_place_node(place_to, newnode, 190 placer, oldnode, itemstack, pointed_thing) 191 -- Run script hook 192 for _, callback in ipairs(minetest.registered_on_placenodes) do 193 -- Deepcopy pos, node and pointed_thing because callback can modify them 194 local place_to_copy = {x = place_to.x, y = place_to.y, z = place_to.z} 195 local newnode_copy = 196 {name = newnode.name, param1 = newnode.param1, param2 = newnode.param2} 197 local oldnode_copy = 198 {name = oldnode.name, param1 = oldnode.param1, param2 = oldnode.param2} 199 local pointed_thing_copy = { 200 type = pointed_thing.type, 201 above = vector.new(pointed_thing.above), 202 under = vector.new(pointed_thing.under), 203 ref = pointed_thing.ref, 204 } 205 callback(place_to_copy, newnode_copy, placer, 206 oldnode_copy, itemstack, pointed_thing_copy) 207 end 208end 209 210local function can_dig_door(pos, digger) 211 replace_old_owner_information(pos) 212 return default.can_interact_with_node(digger, pos) 213end 214 215function doors.register(name, def) 216 if not name:find(":") then 217 name = "doors:" .. name 218 end 219 220 -- replace old doors of this type automatically 221 minetest.register_lbm({ 222 name = ":doors:replace_" .. name:gsub(":", "_"), 223 nodenames = {name.."_b_1", name.."_b_2"}, 224 action = function(pos, node) 225 local l = tonumber(node.name:sub(-1)) 226 local meta = minetest.get_meta(pos) 227 local h = meta:get_int("right") + 1 228 local p2 = node.param2 229 local replace = { 230 {{type = "a", state = 0}, {type = "a", state = 3}}, 231 {{type = "b", state = 1}, {type = "b", state = 2}} 232 } 233 local new = replace[l][h] 234 -- retain infotext and doors_owner fields 235 minetest.swap_node(pos, {name = name .. "_" .. new.type, param2 = p2}) 236 meta:set_int("state", new.state) 237 -- properly place doors:hidden at the right spot 238 local p3 = p2 239 if new.state >= 2 then 240 p3 = (p3 + 3) % 4 241 end 242 if new.state % 2 == 1 then 243 if new.state >= 2 then 244 p3 = (p3 + 1) % 4 245 else 246 p3 = (p3 + 3) % 4 247 end 248 end 249 -- wipe meta on top node as it's unused 250 minetest.set_node({x = pos.x, y = pos.y + 1, z = pos.z}, 251 {name = "doors:hidden", param2 = p3}) 252 end 253 }) 254 255 minetest.register_craftitem(":" .. name, { 256 description = def.description, 257 inventory_image = def.inventory_image, 258 groups = table.copy(def.groups), 259 260 on_place = function(itemstack, placer, pointed_thing) 261 local pos 262 263 if not pointed_thing.type == "node" then 264 return itemstack 265 end 266 267 local node = minetest.get_node(pointed_thing.under) 268 local pdef = minetest.registered_nodes[node.name] 269 if pdef and pdef.on_rightclick and 270 not (placer and placer:is_player() and 271 placer:get_player_control().sneak) then 272 return pdef.on_rightclick(pointed_thing.under, 273 node, placer, itemstack, pointed_thing) 274 end 275 276 if pdef and pdef.buildable_to then 277 pos = pointed_thing.under 278 else 279 pos = pointed_thing.above 280 node = minetest.get_node(pos) 281 pdef = minetest.registered_nodes[node.name] 282 if not pdef or not pdef.buildable_to then 283 return itemstack 284 end 285 end 286 287 local above = {x = pos.x, y = pos.y + 1, z = pos.z} 288 local top_node = minetest.get_node_or_nil(above) 289 local topdef = top_node and minetest.registered_nodes[top_node.name] 290 291 if not topdef or not topdef.buildable_to then 292 return itemstack 293 end 294 295 local pn = placer and placer:get_player_name() or "" 296 if minetest.is_protected(pos, pn) or minetest.is_protected(above, pn) then 297 return itemstack 298 end 299 300 local dir = placer and minetest.dir_to_facedir(placer:get_look_dir()) or 0 301 302 local ref = { 303 {x = -1, y = 0, z = 0}, 304 {x = 0, y = 0, z = 1}, 305 {x = 1, y = 0, z = 0}, 306 {x = 0, y = 0, z = -1}, 307 } 308 309 local aside = { 310 x = pos.x + ref[dir + 1].x, 311 y = pos.y + ref[dir + 1].y, 312 z = pos.z + ref[dir + 1].z, 313 } 314 315 local state = 0 316 if minetest.get_item_group(minetest.get_node(aside).name, "door") == 1 then 317 state = state + 2 318 minetest.set_node(pos, {name = name .. "_b", param2 = dir}) 319 minetest.set_node(above, {name = "doors:hidden", param2 = (dir + 3) % 4}) 320 else 321 minetest.set_node(pos, {name = name .. "_a", param2 = dir}) 322 minetest.set_node(above, {name = "doors:hidden", param2 = dir}) 323 end 324 325 local meta = minetest.get_meta(pos) 326 meta:set_int("state", state) 327 328 if def.protected then 329 meta:set_string("owner", pn) 330 meta:set_string("infotext", def.description .. "\n" .. S("Owned by @1", pn)) 331 end 332 333 if not minetest.is_creative_enabled(pn) then 334 itemstack:take_item() 335 end 336 337 minetest.sound_play(def.sounds.place, {pos = pos}, true) 338 339 on_place_node(pos, minetest.get_node(pos), 340 placer, node, itemstack, pointed_thing) 341 342 return itemstack 343 end 344 }) 345 def.inventory_image = nil 346 347 if def.recipe then 348 minetest.register_craft({ 349 output = name, 350 recipe = def.recipe, 351 }) 352 end 353 def.recipe = nil 354 355 if not def.sounds then 356 def.sounds = default.node_sound_wood_defaults() 357 end 358 359 if not def.sound_open then 360 def.sound_open = "doors_door_open" 361 end 362 363 if not def.sound_close then 364 def.sound_close = "doors_door_close" 365 end 366 367 def.groups.not_in_creative_inventory = 1 368 def.groups.door = 1 369 def.drop = name 370 def.door = { 371 name = name, 372 sounds = { def.sound_close, def.sound_open }, 373 } 374 if not def.on_rightclick then 375 def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) 376 doors.door_toggle(pos, node, clicker) 377 return itemstack 378 end 379 end 380 def.after_dig_node = function(pos, node, meta, digger) 381 minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) 382 minetest.check_for_falling({x = pos.x, y = pos.y + 1, z = pos.z}) 383 end 384 def.on_rotate = function(pos, node, user, mode, new_param2) 385 return false 386 end 387 388 if def.protected then 389 def.can_dig = can_dig_door 390 def.on_blast = function() end 391 def.on_key_use = function(pos, player) 392 local door = doors.get(pos) 393 door:toggle(player) 394 end 395 def.on_skeleton_key_use = function(pos, player, newsecret) 396 replace_old_owner_information(pos) 397 local meta = minetest.get_meta(pos) 398 local owner = meta:get_string("owner") 399 local pname = player:get_player_name() 400 401 -- verify placer is owner of lockable door 402 if owner ~= pname then 403 minetest.record_protection_violation(pos, pname) 404 minetest.chat_send_player(pname, S("You do not own this locked door.")) 405 return nil 406 end 407 408 local secret = meta:get_string("key_lock_secret") 409 if secret == "" then 410 secret = newsecret 411 meta:set_string("key_lock_secret", secret) 412 end 413 414 return secret, S("a locked door"), owner 415 end 416 def.node_dig_prediction = "" 417 else 418 def.on_blast = function(pos, intensity) 419 minetest.remove_node(pos) 420 -- hidden node doesn't get blasted away. 421 minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) 422 return {name} 423 end 424 end 425 426 def.on_destruct = function(pos) 427 minetest.remove_node({x = pos.x, y = pos.y + 1, z = pos.z}) 428 end 429 430 def.drawtype = "mesh" 431 def.paramtype = "light" 432 def.paramtype2 = "facedir" 433 def.sunlight_propagates = true 434 def.walkable = true 435 def.is_ground_content = false 436 def.buildable_to = false 437 def.selection_box = {type = "fixed", fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}} 438 def.collision_box = {type = "fixed", fixed = {-1/2,-1/2,-1/2,1/2,3/2,-6/16}} 439 def.use_texture_alpha = "clip" 440 441 def.mesh = "door_a.obj" 442 minetest.register_node(":" .. name .. "_a", def) 443 444 def.mesh = "door_b.obj" 445 minetest.register_node(":" .. name .. "_b", def) 446 447 def.mesh = "door_a2.obj" 448 minetest.register_node(":" .. name .. "_c", def) 449 450 def.mesh = "door_b2.obj" 451 minetest.register_node(":" .. name .. "_d", def) 452 453 doors.registered_doors[name .. "_a"] = true 454 doors.registered_doors[name .. "_b"] = true 455 doors.registered_doors[name .. "_c"] = true 456 doors.registered_doors[name .. "_d"] = true 457end 458 459doors.register("door_wood", { 460 tiles = {{ name = "doors_door_wood.png", backface_culling = true }}, 461 description = S("Wooden Door"), 462 inventory_image = "doors_item_wood.png", 463 groups = {node = 1, choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, 464 recipe = { 465 {"group:wood", "group:wood"}, 466 {"group:wood", "group:wood"}, 467 {"group:wood", "group:wood"}, 468 } 469}) 470 471doors.register("door_steel", { 472 tiles = {{name = "doors_door_steel.png", backface_culling = true}}, 473 description = S("Steel Door"), 474 inventory_image = "doors_item_steel.png", 475 protected = true, 476 groups = {node = 1, cracky = 1, level = 2}, 477 sounds = default.node_sound_metal_defaults(), 478 sound_open = "doors_steel_door_open", 479 sound_close = "doors_steel_door_close", 480 recipe = { 481 {"default:steel_ingot", "default:steel_ingot"}, 482 {"default:steel_ingot", "default:steel_ingot"}, 483 {"default:steel_ingot", "default:steel_ingot"}, 484 } 485}) 486 487doors.register("door_glass", { 488 tiles = {"doors_door_glass.png"}, 489 description = S("Glass Door"), 490 inventory_image = "doors_item_glass.png", 491 groups = {node = 1, cracky=3, oddly_breakable_by_hand=3}, 492 sounds = default.node_sound_glass_defaults(), 493 sound_open = "doors_glass_door_open", 494 sound_close = "doors_glass_door_close", 495 recipe = { 496 {"default:glass", "default:glass"}, 497 {"default:glass", "default:glass"}, 498 {"default:glass", "default:glass"}, 499 } 500}) 501 502doors.register("door_obsidian_glass", { 503 tiles = {"doors_door_obsidian_glass.png"}, 504 description = S("Obsidian Glass Door"), 505 inventory_image = "doors_item_obsidian_glass.png", 506 groups = {node = 1, cracky=3}, 507 sounds = default.node_sound_glass_defaults(), 508 sound_open = "doors_glass_door_open", 509 sound_close = "doors_glass_door_close", 510 recipe = { 511 {"default:obsidian_glass", "default:obsidian_glass"}, 512 {"default:obsidian_glass", "default:obsidian_glass"}, 513 {"default:obsidian_glass", "default:obsidian_glass"}, 514 }, 515}) 516 517-- Capture mods using the old API as best as possible. 518function doors.register_door(name, def) 519 if def.only_placer_can_open then 520 def.protected = true 521 end 522 def.only_placer_can_open = nil 523 524 local i = name:find(":") 525 local modname = name:sub(1, i - 1) 526 if not def.tiles then 527 if def.protected then 528 def.tiles = {{name = "doors_door_steel.png", backface_culling = true}} 529 else 530 def.tiles = {{name = "doors_door_wood.png", backface_culling = true}} 531 end 532 minetest.log("warning", modname .. " registered door \"" .. name .. "\" " .. 533 "using deprecated API method \"doors.register_door()\" but " .. 534 "did not provide the \"tiles\" parameter. A fallback tiledef " .. 535 "will be used instead.") 536 end 537 538 doors.register(name, def) 539end 540 541----trapdoor---- 542 543function doors.trapdoor_toggle(pos, node, clicker) 544 node = node or minetest.get_node(pos) 545 546 replace_old_owner_information(pos) 547 548 if clicker and not default.can_interact_with_node(clicker, pos) then 549 return false 550 end 551 552 local def = minetest.registered_nodes[node.name] 553 554 if string.sub(node.name, -5) == "_open" then 555 minetest.sound_play(def.sound_close, 556 {pos = pos, gain = 0.3, max_hear_distance = 10}, true) 557 minetest.swap_node(pos, {name = string.sub(node.name, 1, 558 string.len(node.name) - 5), param1 = node.param1, param2 = node.param2}) 559 else 560 minetest.sound_play(def.sound_open, 561 {pos = pos, gain = 0.3, max_hear_distance = 10}, true) 562 minetest.swap_node(pos, {name = node.name .. "_open", 563 param1 = node.param1, param2 = node.param2}) 564 end 565end 566 567function doors.register_trapdoor(name, def) 568 if not name:find(":") then 569 name = "doors:" .. name 570 end 571 572 local name_closed = name 573 local name_opened = name.."_open" 574 575 def.on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) 576 doors.trapdoor_toggle(pos, node, clicker) 577 return itemstack 578 end 579 580 -- Common trapdoor configuration 581 def.drawtype = "nodebox" 582 def.paramtype = "light" 583 def.paramtype2 = "facedir" 584 def.is_ground_content = false 585 def.use_texture_alpha = "clip" 586 587 if def.protected then 588 def.can_dig = can_dig_door 589 def.after_place_node = function(pos, placer, itemstack, pointed_thing) 590 local pn = placer:get_player_name() 591 local meta = minetest.get_meta(pos) 592 meta:set_string("owner", pn) 593 meta:set_string("infotext", def.description .. "\n" .. S("Owned by @1", pn)) 594 595 return minetest.is_creative_enabled(pn) 596 end 597 598 def.on_blast = function() end 599 def.on_key_use = function(pos, player) 600 local door = doors.get(pos) 601 door:toggle(player) 602 end 603 def.on_skeleton_key_use = function(pos, player, newsecret) 604 replace_old_owner_information(pos) 605 local meta = minetest.get_meta(pos) 606 local owner = meta:get_string("owner") 607 local pname = player:get_player_name() 608 609 -- verify placer is owner of lockable door 610 if owner ~= pname then 611 minetest.record_protection_violation(pos, pname) 612 minetest.chat_send_player(pname, S("You do not own this trapdoor.")) 613 return nil 614 end 615 616 local secret = meta:get_string("key_lock_secret") 617 if secret == "" then 618 secret = newsecret 619 meta:set_string("key_lock_secret", secret) 620 end 621 622 return secret, S("a locked trapdoor"), owner 623 end 624 def.node_dig_prediction = "" 625 else 626 def.on_blast = function(pos, intensity) 627 minetest.remove_node(pos) 628 return {name} 629 end 630 end 631 632 if not def.sounds then 633 def.sounds = default.node_sound_wood_defaults() 634 end 635 636 if not def.sound_open then 637 def.sound_open = "doors_door_open" 638 end 639 640 if not def.sound_close then 641 def.sound_close = "doors_door_close" 642 end 643 644 local def_opened = table.copy(def) 645 local def_closed = table.copy(def) 646 647 def_closed.node_box = { 648 type = "fixed", 649 fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} 650 } 651 def_closed.selection_box = { 652 type = "fixed", 653 fixed = {-0.5, -0.5, -0.5, 0.5, -6/16, 0.5} 654 } 655 def_closed.tiles = { 656 def.tile_front, 657 def.tile_front .. '^[transformFY', 658 def.tile_side, 659 def.tile_side, 660 def.tile_side, 661 def.tile_side 662 } 663 664 def_opened.node_box = { 665 type = "fixed", 666 fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} 667 } 668 def_opened.selection_box = { 669 type = "fixed", 670 fixed = {-0.5, -0.5, 6/16, 0.5, 0.5, 0.5} 671 } 672 def_opened.tiles = { 673 def.tile_side, 674 def.tile_side .. '^[transform2', 675 def.tile_side .. '^[transform3', 676 def.tile_side .. '^[transform1', 677 def.tile_front .. '^[transform46', 678 def.tile_front .. '^[transform6' 679 } 680 681 def_opened.drop = name_closed 682 def_opened.groups.not_in_creative_inventory = 1 683 684 minetest.register_node(name_opened, def_opened) 685 minetest.register_node(name_closed, def_closed) 686 687 doors.registered_trapdoors[name_opened] = true 688 doors.registered_trapdoors[name_closed] = true 689end 690 691doors.register_trapdoor("doors:trapdoor", { 692 description = S("Wooden Trapdoor"), 693 inventory_image = "doors_trapdoor.png", 694 wield_image = "doors_trapdoor.png", 695 tile_front = "doors_trapdoor.png", 696 tile_side = "doors_trapdoor_side.png", 697 groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2, door = 1}, 698}) 699 700doors.register_trapdoor("doors:trapdoor_steel", { 701 description = S("Steel Trapdoor"), 702 inventory_image = "doors_trapdoor_steel.png", 703 wield_image = "doors_trapdoor_steel.png", 704 tile_front = "doors_trapdoor_steel.png", 705 tile_side = "doors_trapdoor_steel_side.png", 706 protected = true, 707 sounds = default.node_sound_metal_defaults(), 708 sound_open = "doors_steel_door_open", 709 sound_close = "doors_steel_door_close", 710 groups = {cracky = 1, level = 2, door = 1}, 711}) 712 713minetest.register_craft({ 714 output = "doors:trapdoor 2", 715 recipe = { 716 {"group:wood", "group:wood", "group:wood"}, 717 {"group:wood", "group:wood", "group:wood"}, 718 {"", "", ""}, 719 } 720}) 721 722minetest.register_craft({ 723 output = "doors:trapdoor_steel", 724 recipe = { 725 {"default:steel_ingot", "default:steel_ingot"}, 726 {"default:steel_ingot", "default:steel_ingot"}, 727 } 728}) 729 730 731----fence gate---- 732local fence_collision_extra = minetest.settings:get_bool("enable_fence_tall") and 3/8 or 0 733 734function doors.register_fencegate(name, def) 735 local fence = { 736 description = def.description, 737 drawtype = "mesh", 738 tiles = {}, 739 paramtype = "light", 740 paramtype2 = "facedir", 741 sunlight_propagates = true, 742 is_ground_content = false, 743 drop = name .. "_closed", 744 connect_sides = {"left", "right"}, 745 groups = def.groups, 746 sounds = def.sounds, 747 on_rightclick = function(pos, node, clicker, itemstack, pointed_thing) 748 local node_def = minetest.registered_nodes[node.name] 749 minetest.swap_node(pos, {name = node_def.gate, param2 = node.param2}) 750 minetest.sound_play(node_def.sound, {pos = pos, gain = 0.3, 751 max_hear_distance = 8}, true) 752 return itemstack 753 end, 754 selection_box = { 755 type = "fixed", 756 fixed = {-1/2, -1/2, -1/4, 1/2, 1/2, 1/4} 757 }, 758 } 759 760 761 if type(def.texture) == "string" then 762 fence.tiles[1] = {name = def.texture, backface_culling = true} 763 elseif def.texture.backface_culling == nil then 764 fence.tiles[1] = table.copy(def.texture) 765 fence.tiles[1].backface_culling = true 766 else 767 fence.tiles[1] = def.texture 768 end 769 770 if not fence.sounds then 771 fence.sounds = default.node_sound_wood_defaults() 772 end 773 774 fence.groups.fence = 1 775 776 local fence_closed = table.copy(fence) 777 fence_closed.mesh = "doors_fencegate_closed.obj" 778 fence_closed.gate = name .. "_open" 779 fence_closed.sound = "doors_fencegate_open" 780 fence_closed.collision_box = { 781 type = "fixed", 782 fixed = {-1/2, -1/2, -1/8, 1/2, 1/2 + fence_collision_extra, 1/8} 783 } 784 785 local fence_open = table.copy(fence) 786 fence_open.mesh = "doors_fencegate_open.obj" 787 fence_open.gate = name .. "_closed" 788 fence_open.sound = "doors_fencegate_close" 789 fence_open.groups.not_in_creative_inventory = 1 790 fence_open.collision_box = { 791 type = "fixed", 792 fixed = {{-1/2, -1/2, -1/8, -3/8, 1/2 + fence_collision_extra, 1/8}, 793 {-1/2, -3/8, -1/2, -3/8, 3/8, 0 }} 794 } 795 796 minetest.register_node(":" .. name .. "_closed", fence_closed) 797 minetest.register_node(":" .. name .. "_open", fence_open) 798 799 minetest.register_craft({ 800 output = name .. "_closed", 801 recipe = { 802 {"group:stick", def.material, "group:stick"}, 803 {"group:stick", def.material, "group:stick"} 804 } 805 }) 806end 807 808doors.register_fencegate("doors:gate_wood", { 809 description = S("Apple Wood Fence Gate"), 810 texture = "default_wood.png", 811 material = "default:wood", 812 groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} 813}) 814 815doors.register_fencegate("doors:gate_acacia_wood", { 816 description = S("Acacia Wood Fence Gate"), 817 texture = "default_acacia_wood.png", 818 material = "default:acacia_wood", 819 groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} 820}) 821 822doors.register_fencegate("doors:gate_junglewood", { 823 description = S("Jungle Wood Fence Gate"), 824 texture = "default_junglewood.png", 825 material = "default:junglewood", 826 groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2} 827}) 828 829doors.register_fencegate("doors:gate_pine_wood", { 830 description = S("Pine Wood Fence Gate"), 831 texture = "default_pine_wood.png", 832 material = "default:pine_wood", 833 groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} 834}) 835 836doors.register_fencegate("doors:gate_aspen_wood", { 837 description = S("Aspen Wood Fence Gate"), 838 texture = "default_aspen_wood.png", 839 material = "default:aspen_wood", 840 groups = {choppy = 3, oddly_breakable_by_hand = 2, flammable = 3} 841}) 842 843 844----fuels---- 845 846minetest.register_craft({ 847 type = "fuel", 848 recipe = "doors:trapdoor", 849 burntime = 7, 850}) 851 852minetest.register_craft({ 853 type = "fuel", 854 recipe = "doors:door_wood", 855 burntime = 14, 856}) 857 858minetest.register_craft({ 859 type = "fuel", 860 recipe = "doors:gate_wood_closed", 861 burntime = 7, 862}) 863 864minetest.register_craft({ 865 type = "fuel", 866 recipe = "doors:gate_acacia_wood_closed", 867 burntime = 8, 868}) 869 870minetest.register_craft({ 871 type = "fuel", 872 recipe = "doors:gate_junglewood_closed", 873 burntime = 9, 874}) 875 876minetest.register_craft({ 877 type = "fuel", 878 recipe = "doors:gate_pine_wood_closed", 879 burntime = 6, 880}) 881 882minetest.register_craft({ 883 type = "fuel", 884 recipe = "doors:gate_aspen_wood_closed", 885 burntime = 5, 886}) 887