1-- 2-- Sounds 3-- 4 5function default.node_sound_defaults(table) 6 table = table or {} 7 table.footstep = table.footstep or 8 {name = "", gain = 1.0} 9 table.dug = table.dug or 10 {name = "default_dug_node", gain = 0.25} 11 table.place = table.place or 12 {name = "default_place_node_hard", gain = 1.0} 13 return table 14end 15 16function default.node_sound_stone_defaults(table) 17 table = table or {} 18 table.footstep = table.footstep or 19 {name = "default_hard_footstep", gain = 0.3} 20 table.dug = table.dug or 21 {name = "default_hard_footstep", gain = 1.0} 22 default.node_sound_defaults(table) 23 return table 24end 25 26function default.node_sound_dirt_defaults(table) 27 table = table or {} 28 table.footstep = table.footstep or 29 {name = "default_dirt_footstep", gain = 0.4} 30 table.dug = table.dug or 31 {name = "default_dirt_footstep", gain = 1.0} 32 table.place = table.place or 33 {name = "default_place_node", gain = 1.0} 34 default.node_sound_defaults(table) 35 return table 36end 37 38function default.node_sound_sand_defaults(table) 39 table = table or {} 40 table.footstep = table.footstep or 41 {name = "default_sand_footstep", gain = 0.05} 42 table.dug = table.dug or 43 {name = "default_sand_footstep", gain = 0.15} 44 table.place = table.place or 45 {name = "default_place_node", gain = 1.0} 46 default.node_sound_defaults(table) 47 return table 48end 49 50function default.node_sound_gravel_defaults(table) 51 table = table or {} 52 table.footstep = table.footstep or 53 {name = "default_gravel_footstep", gain = 0.1} 54 table.dig = table.dig or 55 {name = "default_gravel_dig", gain = 0.35} 56 table.dug = table.dug or 57 {name = "default_gravel_dug", gain = 1.0} 58 table.place = table.place or 59 {name = "default_place_node", gain = 1.0} 60 default.node_sound_defaults(table) 61 return table 62end 63 64function default.node_sound_wood_defaults(table) 65 table = table or {} 66 table.footstep = table.footstep or 67 {name = "default_wood_footstep", gain = 0.3} 68 table.dug = table.dug or 69 {name = "default_wood_footstep", gain = 1.0} 70 default.node_sound_defaults(table) 71 return table 72end 73 74function default.node_sound_leaves_defaults(table) 75 table = table or {} 76 table.footstep = table.footstep or 77 {name = "default_grass_footstep", gain = 0.45} 78 table.dug = table.dug or 79 {name = "default_grass_footstep", gain = 0.7} 80 table.place = table.place or 81 {name = "default_place_node", gain = 1.0} 82 default.node_sound_defaults(table) 83 return table 84end 85 86function default.node_sound_glass_defaults(table) 87 table = table or {} 88 table.footstep = table.footstep or 89 {name = "default_glass_footstep", gain = 0.3} 90 table.dig = table.dig or 91 {name = "default_glass_footstep", gain = 0.5} 92 table.dug = table.dug or 93 {name = "default_break_glass", gain = 1.0} 94 default.node_sound_defaults(table) 95 return table 96end 97 98function default.node_sound_ice_defaults(table) 99 table = table or {} 100 table.footstep = table.footstep or 101 {name = "default_ice_footstep", gain = 0.3} 102 table.dig = table.dig or 103 {name = "default_ice_dig", gain = 0.5} 104 table.dug = table.dug or 105 {name = "default_ice_dug", gain = 0.5} 106 default.node_sound_defaults(table) 107 return table 108end 109 110function default.node_sound_metal_defaults(table) 111 table = table or {} 112 table.footstep = table.footstep or 113 {name = "default_metal_footstep", gain = 0.4} 114 table.dig = table.dig or 115 {name = "default_dig_metal", gain = 0.5} 116 table.dug = table.dug or 117 {name = "default_dug_metal", gain = 0.5} 118 table.place = table.place or 119 {name = "default_place_node_metal", gain = 0.5} 120 default.node_sound_defaults(table) 121 return table 122end 123 124function default.node_sound_water_defaults(table) 125 table = table or {} 126 table.footstep = table.footstep or 127 {name = "default_water_footstep", gain = 0.2} 128 default.node_sound_defaults(table) 129 return table 130end 131 132function default.node_sound_snow_defaults(table) 133 table = table or {} 134 table.footstep = table.footstep or 135 {name = "default_snow_footstep", gain = 0.2} 136 table.dig = table.dig or 137 {name = "default_snow_footstep", gain = 0.3} 138 table.dug = table.dug or 139 {name = "default_snow_footstep", gain = 0.3} 140 table.place = table.place or 141 {name = "default_place_node", gain = 1.0} 142 default.node_sound_defaults(table) 143 return table 144end 145 146 147-- 148-- Lavacooling 149-- 150 151default.cool_lava = function(pos, node) 152 if node.name == "default:lava_source" then 153 minetest.set_node(pos, {name = "default:obsidian"}) 154 else -- Lava flowing 155 minetest.set_node(pos, {name = "default:stone"}) 156 end 157 minetest.sound_play("default_cool_lava", 158 {pos = pos, max_hear_distance = 16, gain = 0.25}, true) 159end 160 161if minetest.settings:get_bool("enable_lavacooling") ~= false then 162 minetest.register_abm({ 163 label = "Lava cooling", 164 nodenames = {"default:lava_source", "default:lava_flowing"}, 165 neighbors = {"group:cools_lava", "group:water"}, 166 interval = 2, 167 chance = 2, 168 catch_up = false, 169 action = function(...) 170 default.cool_lava(...) 171 end, 172 }) 173end 174 175 176-- 177-- Optimized helper to put all items in an inventory into a drops list 178-- 179 180function default.get_inventory_drops(pos, inventory, drops) 181 local inv = minetest.get_meta(pos):get_inventory() 182 local n = #drops 183 for i = 1, inv:get_size(inventory) do 184 local stack = inv:get_stack(inventory, i) 185 if stack:get_count() > 0 then 186 drops[n+1] = stack:to_table() 187 n = n + 1 188 end 189 end 190end 191 192 193-- 194-- Papyrus and cactus growing 195-- 196 197-- Wrapping the functions in ABM action is necessary to make overriding them possible 198 199function default.grow_cactus(pos, node) 200 if node.param2 >= 4 then 201 return 202 end 203 pos.y = pos.y - 1 204 if minetest.get_item_group(minetest.get_node(pos).name, "sand") == 0 then 205 return 206 end 207 pos.y = pos.y + 1 208 local height = 0 209 while node.name == "default:cactus" and height < 4 do 210 height = height + 1 211 pos.y = pos.y + 1 212 node = minetest.get_node(pos) 213 end 214 if height == 4 or node.name ~= "air" then 215 return 216 end 217 if minetest.get_node_light(pos) < 13 then 218 return 219 end 220 minetest.set_node(pos, {name = "default:cactus"}) 221 return true 222end 223 224function default.grow_papyrus(pos, node) 225 pos.y = pos.y - 1 226 local name = minetest.get_node(pos).name 227 if name ~= "default:dirt" and 228 name ~= "default:dirt_with_grass" and 229 name ~= "default:dirt_with_dry_grass" and 230 name ~= "default:dirt_with_rainforest_litter" and 231 name ~= "default:dry_dirt" and 232 name ~= "default:dry_dirt_with_dry_grass" then 233 return 234 end 235 if not minetest.find_node_near(pos, 3, {"group:water"}) then 236 return 237 end 238 pos.y = pos.y + 1 239 local height = 0 240 while node.name == "default:papyrus" and height < 4 do 241 height = height + 1 242 pos.y = pos.y + 1 243 node = minetest.get_node(pos) 244 end 245 if height == 4 or node.name ~= "air" then 246 return 247 end 248 if minetest.get_node_light(pos) < 13 then 249 return 250 end 251 minetest.set_node(pos, {name = "default:papyrus"}) 252 return true 253end 254 255minetest.register_abm({ 256 label = "Grow cactus", 257 nodenames = {"default:cactus"}, 258 neighbors = {"group:sand"}, 259 interval = 12, 260 chance = 83, 261 action = function(...) 262 default.grow_cactus(...) 263 end 264}) 265 266minetest.register_abm({ 267 label = "Grow papyrus", 268 nodenames = {"default:papyrus"}, 269 -- Grows on the dirt and surface dirt nodes of the biomes papyrus appears in, 270 -- including the old savanna nodes. 271 -- 'default:dirt_with_grass' is here only because it was allowed before. 272 neighbors = { 273 "default:dirt", 274 "default:dirt_with_grass", 275 "default:dirt_with_dry_grass", 276 "default:dirt_with_rainforest_litter", 277 "default:dry_dirt", 278 "default:dry_dirt_with_dry_grass", 279 }, 280 interval = 14, 281 chance = 71, 282 action = function(...) 283 default.grow_papyrus(...) 284 end 285}) 286 287 288-- 289-- Dig upwards 290-- 291 292function default.dig_up(pos, node, digger) 293 if digger == nil then return end 294 local np = {x = pos.x, y = pos.y + 1, z = pos.z} 295 local nn = minetest.get_node(np) 296 if nn.name == node.name then 297 minetest.node_dig(np, nn, digger) 298 end 299end 300 301 302-- 303-- Fence registration helper 304-- 305local fence_collision_extra = minetest.settings:get_bool("enable_fence_tall") and 3/8 or 0 306 307function default.register_fence(name, def) 308 minetest.register_craft({ 309 output = name .. " 4", 310 recipe = { 311 { def.material, 'group:stick', def.material }, 312 { def.material, 'group:stick', def.material }, 313 } 314 }) 315 316 local fence_texture = "default_fence_overlay.png^" .. def.texture .. 317 "^default_fence_overlay.png^[makealpha:255,126,126" 318 -- Allow almost everything to be overridden 319 local default_fields = { 320 paramtype = "light", 321 drawtype = "nodebox", 322 node_box = { 323 type = "connected", 324 fixed = {-1/8, -1/2, -1/8, 1/8, 1/2, 1/8}, 325 -- connect_top = 326 -- connect_bottom = 327 connect_front = {{-1/16, 3/16, -1/2, 1/16, 5/16, -1/8 }, 328 {-1/16, -5/16, -1/2, 1/16, -3/16, -1/8 }}, 329 connect_left = {{-1/2, 3/16, -1/16, -1/8, 5/16, 1/16}, 330 {-1/2, -5/16, -1/16, -1/8, -3/16, 1/16}}, 331 connect_back = {{-1/16, 3/16, 1/8, 1/16, 5/16, 1/2 }, 332 {-1/16, -5/16, 1/8, 1/16, -3/16, 1/2 }}, 333 connect_right = {{ 1/8, 3/16, -1/16, 1/2, 5/16, 1/16}, 334 { 1/8, -5/16, -1/16, 1/2, -3/16, 1/16}} 335 }, 336 collision_box = { 337 type = "connected", 338 fixed = {-1/8, -1/2, -1/8, 1/8, 1/2 + fence_collision_extra, 1/8}, 339 -- connect_top = 340 -- connect_bottom = 341 connect_front = {-1/8, -1/2, -1/2, 1/8, 1/2 + fence_collision_extra, -1/8}, 342 connect_left = {-1/2, -1/2, -1/8, -1/8, 1/2 + fence_collision_extra, 1/8}, 343 connect_back = {-1/8, -1/2, 1/8, 1/8, 1/2 + fence_collision_extra, 1/2}, 344 connect_right = { 1/8, -1/2, -1/8, 1/2, 1/2 + fence_collision_extra, 1/8} 345 }, 346 connects_to = {"group:fence", "group:wood", "group:tree", "group:wall"}, 347 inventory_image = fence_texture, 348 wield_image = fence_texture, 349 tiles = {def.texture}, 350 sunlight_propagates = true, 351 is_ground_content = false, 352 groups = {}, 353 } 354 for k, v in pairs(default_fields) do 355 if def[k] == nil then 356 def[k] = v 357 end 358 end 359 360 -- Always add to the fence group, even if no group provided 361 def.groups.fence = 1 362 363 def.texture = nil 364 def.material = nil 365 366 minetest.register_node(name, def) 367end 368 369 370-- 371-- Fence rail registration helper 372-- 373 374function default.register_fence_rail(name, def) 375 minetest.register_craft({ 376 output = name .. " 16", 377 recipe = { 378 { def.material, def.material }, 379 { "", ""}, 380 { def.material, def.material }, 381 } 382 }) 383 384 local fence_rail_texture = "default_fence_rail_overlay.png^" .. def.texture .. 385 "^default_fence_rail_overlay.png^[makealpha:255,126,126" 386 -- Allow almost everything to be overridden 387 local default_fields = { 388 paramtype = "light", 389 drawtype = "nodebox", 390 node_box = { 391 type = "connected", 392 fixed = {{-1/16, 3/16, -1/16, 1/16, 5/16, 1/16}, 393 {-1/16, -3/16, -1/16, 1/16, -5/16, 1/16}}, 394 -- connect_top = 395 -- connect_bottom = 396 connect_front = {{-1/16, 3/16, -1/2, 1/16, 5/16, -1/16}, 397 {-1/16, -5/16, -1/2, 1/16, -3/16, -1/16}}, 398 connect_left = {{-1/2, 3/16, -1/16, -1/16, 5/16, 1/16}, 399 {-1/2, -5/16, -1/16, -1/16, -3/16, 1/16}}, 400 connect_back = {{-1/16, 3/16, 1/16, 1/16, 5/16, 1/2 }, 401 {-1/16, -5/16, 1/16, 1/16, -3/16, 1/2 }}, 402 connect_right = {{ 1/16, 3/16, -1/16, 1/2, 5/16, 1/16}, 403 { 1/16, -5/16, -1/16, 1/2, -3/16, 1/16}} 404 }, 405 collision_box = { 406 type = "connected", 407 fixed = {-1/8, -1/2, -1/8, 1/8, 1/2 + fence_collision_extra, 1/8}, 408 -- connect_top = 409 -- connect_bottom = 410 connect_front = {-1/8, -1/2, -1/2, 1/8, 1/2 + fence_collision_extra, -1/8}, 411 connect_left = {-1/2, -1/2, -1/8, -1/8, 1/2 + fence_collision_extra, 1/8}, 412 connect_back = {-1/8, -1/2, 1/8, 1/8, 1/2 + fence_collision_extra, 1/2}, 413 connect_right = { 1/8, -1/2, -1/8, 1/2, 1/2 + fence_collision_extra, 1/8} 414 }, 415 connects_to = {"group:fence", "group:wall"}, 416 inventory_image = fence_rail_texture, 417 wield_image = fence_rail_texture, 418 tiles = {def.texture}, 419 sunlight_propagates = true, 420 is_ground_content = false, 421 groups = {}, 422 } 423 for k, v in pairs(default_fields) do 424 if def[k] == nil then 425 def[k] = v 426 end 427 end 428 429 -- Always add to the fence group, even if no group provided 430 def.groups.fence = 1 431 432 def.texture = nil 433 def.material = nil 434 435 minetest.register_node(name, def) 436end 437 438-- 439-- Mese post registration helper 440-- 441 442function default.register_mesepost(name, def) 443 minetest.register_craft({ 444 output = name .. " 4", 445 recipe = { 446 {'', 'default:glass', ''}, 447 {'default:mese_crystal', 'default:mese_crystal', 'default:mese_crystal'}, 448 {'', def.material, ''}, 449 } 450 }) 451 452 local post_texture = def.texture .. "^default_mese_post_light_side.png^[makealpha:0,0,0" 453 local post_texture_dark = def.texture .. "^default_mese_post_light_side_dark.png^[makealpha:0,0,0" 454 -- Allow almost everything to be overridden 455 local default_fields = { 456 wield_image = post_texture, 457 drawtype = "nodebox", 458 node_box = { 459 type = "fixed", 460 fixed = { 461 {-2 / 16, -8 / 16, -2 / 16, 2 / 16, 8 / 16, 2 / 16}, 462 }, 463 }, 464 paramtype = "light", 465 tiles = {def.texture, def.texture, post_texture_dark, post_texture_dark, post_texture, post_texture}, 466 use_texture_alpha = "opaque", 467 light_source = default.LIGHT_MAX, 468 sunlight_propagates = true, 469 is_ground_content = false, 470 groups = {choppy = 2, oddly_breakable_by_hand = 2, flammable = 2}, 471 sounds = default.node_sound_wood_defaults(), 472 } 473 for k, v in pairs(default_fields) do 474 if def[k] == nil then 475 def[k] = v 476 end 477 end 478 479 def.texture = nil 480 def.material = nil 481 482 minetest.register_node(name, def) 483end 484 485-- 486-- Leafdecay 487-- 488 489-- Prevent decay of placed leaves 490 491default.after_place_leaves = function(pos, placer, itemstack, pointed_thing) 492 if placer and placer:is_player() then 493 local node = minetest.get_node(pos) 494 node.param2 = 1 495 minetest.set_node(pos, node) 496 end 497end 498 499-- Leafdecay 500local function leafdecay_after_destruct(pos, oldnode, def) 501 for _, v in pairs(minetest.find_nodes_in_area(vector.subtract(pos, def.radius), 502 vector.add(pos, def.radius), def.leaves)) do 503 local node = minetest.get_node(v) 504 local timer = minetest.get_node_timer(v) 505 if node.param2 ~= 1 and not timer:is_started() then 506 timer:start(math.random(20, 120) / 10) 507 end 508 end 509end 510 511local movement_gravity = tonumber( 512 minetest.settings:get("movement_gravity")) or 9.81 513 514local function leafdecay_on_timer(pos, def) 515 if minetest.find_node_near(pos, def.radius, def.trunks) then 516 return false 517 end 518 519 local node = minetest.get_node(pos) 520 local drops = minetest.get_node_drops(node.name) 521 for _, item in ipairs(drops) do 522 local is_leaf 523 for _, v in pairs(def.leaves) do 524 if v == item then 525 is_leaf = true 526 end 527 end 528 if minetest.get_item_group(item, "leafdecay_drop") ~= 0 or 529 not is_leaf then 530 minetest.add_item({ 531 x = pos.x - 0.5 + math.random(), 532 y = pos.y - 0.5 + math.random(), 533 z = pos.z - 0.5 + math.random(), 534 }, item) 535 end 536 end 537 538 minetest.remove_node(pos) 539 minetest.check_for_falling(pos) 540 541 -- spawn a few particles for the removed node 542 minetest.add_particlespawner({ 543 amount = 8, 544 time = 0.001, 545 minpos = vector.subtract(pos, {x=0.5, y=0.5, z=0.5}), 546 maxpos = vector.add(pos, {x=0.5, y=0.5, z=0.5}), 547 minvel = vector.new(-0.5, -1, -0.5), 548 maxvel = vector.new(0.5, 0, 0.5), 549 minacc = vector.new(0, -movement_gravity, 0), 550 maxacc = vector.new(0, -movement_gravity, 0), 551 minsize = 0, 552 maxsize = 0, 553 node = node, 554 }) 555end 556 557function default.register_leafdecay(def) 558 assert(def.leaves) 559 assert(def.trunks) 560 assert(def.radius) 561 for _, v in pairs(def.trunks) do 562 minetest.override_item(v, { 563 after_destruct = function(pos, oldnode) 564 leafdecay_after_destruct(pos, oldnode, def) 565 end, 566 }) 567 end 568 for _, v in pairs(def.leaves) do 569 minetest.override_item(v, { 570 on_timer = function(pos) 571 leafdecay_on_timer(pos, def) 572 end, 573 }) 574 end 575end 576 577 578-- 579-- Convert default:dirt to something that fits the environment 580-- 581 582minetest.register_abm({ 583 label = "Grass spread", 584 nodenames = {"default:dirt"}, 585 neighbors = { 586 "air", 587 "group:grass", 588 "group:dry_grass", 589 "default:snow", 590 }, 591 interval = 6, 592 chance = 50, 593 catch_up = false, 594 action = function(pos, node) 595 -- Check for darkness: night, shadow or under a light-blocking node 596 -- Returns if ignore above 597 local above = {x = pos.x, y = pos.y + 1, z = pos.z} 598 if (minetest.get_node_light(above) or 0) < 13 then 599 return 600 end 601 602 -- Look for spreading dirt-type neighbours 603 local p2 = minetest.find_node_near(pos, 1, "group:spreading_dirt_type") 604 if p2 then 605 local n3 = minetest.get_node(p2) 606 minetest.set_node(pos, {name = n3.name}) 607 return 608 end 609 610 -- Else, any seeding nodes on top? 611 local name = minetest.get_node(above).name 612 -- Snow check is cheapest, so comes first 613 if name == "default:snow" then 614 minetest.set_node(pos, {name = "default:dirt_with_snow"}) 615 elseif minetest.get_item_group(name, "grass") ~= 0 then 616 minetest.set_node(pos, {name = "default:dirt_with_grass"}) 617 elseif minetest.get_item_group(name, "dry_grass") ~= 0 then 618 minetest.set_node(pos, {name = "default:dirt_with_dry_grass"}) 619 end 620 end 621}) 622 623 624-- 625-- Grass and dry grass removed in darkness 626-- 627 628minetest.register_abm({ 629 label = "Grass covered", 630 nodenames = {"group:spreading_dirt_type", "default:dry_dirt_with_dry_grass"}, 631 interval = 8, 632 chance = 50, 633 catch_up = false, 634 action = function(pos, node) 635 local above = {x = pos.x, y = pos.y + 1, z = pos.z} 636 local name = minetest.get_node(above).name 637 local nodedef = minetest.registered_nodes[name] 638 if name ~= "ignore" and nodedef and not ((nodedef.sunlight_propagates or 639 nodedef.paramtype == "light") and 640 nodedef.liquidtype == "none") then 641 if node.name == "default:dry_dirt_with_dry_grass" then 642 minetest.set_node(pos, {name = "default:dry_dirt"}) 643 else 644 minetest.set_node(pos, {name = "default:dirt"}) 645 end 646 end 647 end 648}) 649 650 651-- 652-- Moss growth on cobble near water 653-- 654 655local moss_correspondences = { 656 ["default:cobble"] = "default:mossycobble", 657 ["stairs:slab_cobble"] = "stairs:slab_mossycobble", 658 ["stairs:stair_cobble"] = "stairs:stair_mossycobble", 659 ["stairs:stair_inner_cobble"] = "stairs:stair_inner_mossycobble", 660 ["stairs:stair_outer_cobble"] = "stairs:stair_outer_mossycobble", 661 ["walls:cobble"] = "walls:mossycobble", 662} 663minetest.register_abm({ 664 label = "Moss growth", 665 nodenames = {"default:cobble", "stairs:slab_cobble", "stairs:stair_cobble", 666 "stairs:stair_inner_cobble", "stairs:stair_outer_cobble", 667 "walls:cobble"}, 668 neighbors = {"group:water"}, 669 interval = 16, 670 chance = 200, 671 catch_up = false, 672 action = function(pos, node) 673 node.name = moss_correspondences[node.name] 674 if node.name then 675 minetest.set_node(pos, node) 676 end 677 end 678}) 679 680-- 681-- Register a craft to copy the metadata of items 682-- 683 684function default.register_craft_metadata_copy(ingredient, result) 685 minetest.register_craft({ 686 type = "shapeless", 687 output = result, 688 recipe = {ingredient, result} 689 }) 690 691 minetest.register_on_craft(function(itemstack, player, old_craft_grid, craft_inv) 692 if itemstack:get_name() ~= result then 693 return 694 end 695 696 local original 697 local index 698 for i = 1, #old_craft_grid do 699 if old_craft_grid[i]:get_name() == result then 700 original = old_craft_grid[i] 701 index = i 702 end 703 end 704 if not original then 705 return 706 end 707 local copymeta = original:get_meta():to_table() 708 itemstack:get_meta():from_table(copymeta) 709 -- put the book with metadata back in the craft grid 710 craft_inv:set_stack("craft", index, original) 711 end) 712end 713 714 715-- 716-- NOTICE: This method is not an official part of the API yet. 717-- This method may change in future. 718-- 719 720function default.can_interact_with_node(player, pos) 721 if player and player:is_player() then 722 if minetest.check_player_privs(player, "protection_bypass") then 723 return true 724 end 725 else 726 return false 727 end 728 729 local meta = minetest.get_meta(pos) 730 local owner = meta:get_string("owner") 731 732 if not owner or owner == "" or owner == player:get_player_name() then 733 return true 734 end 735 736 -- Is player wielding the right key? 737 local item = player:get_wielded_item() 738 if minetest.get_item_group(item:get_name(), "key") == 1 then 739 local key_meta = item:get_meta() 740 741 if key_meta:get_string("secret") == "" then 742 local key_oldmeta = item:get_metadata() 743 if key_oldmeta == "" or not minetest.parse_json(key_oldmeta) then 744 return false 745 end 746 747 key_meta:set_string("secret", minetest.parse_json(key_oldmeta).secret) 748 item:set_metadata("") 749 end 750 751 return meta:get_string("key_lock_secret") == key_meta:get_string("secret") 752 end 753 754 return false 755end 756