Update protector and title logo fo 416
BIN
menu/icon.png
Before Width: | Height: | Size: 6.4 KiB After Width: | Height: | Size: 6.8 KiB |
|
@ -0,0 +1,14 @@
|
|||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
|
@ -0,0 +1,10 @@
|
|||
Bedrock mod.
|
||||
|
||||
Version 1.0.0
|
||||
|
||||
This mod adds an indestructible bedrock layer at the bottom of the world.
|
||||
|
||||
|
||||
This mod recognizes the following minetest.conf setting:
|
||||
|
||||
* `bedrock2_y`: Sets the Y coordinate on which the bedrock layer will be created (default: -30912).
|
|
@ -0,0 +1 @@
|
|||
mesecons_mvps?
|
|
@ -0,0 +1 @@
|
|||
Adds an indestructable bedrock layer at the bottom of the world.
|
|
@ -0,0 +1,47 @@
|
|||
local bedrock = {}
|
||||
|
||||
bedrock.layer = -6001 -- determined as appropriate by experiment
|
||||
bedrock.node = {name = "bedrock2:bedrock"}
|
||||
|
||||
local depth = tonumber(minetest.setting_get("bedrock2_y"))
|
||||
if depth ~= nil then
|
||||
bedrock.layer = depth
|
||||
end
|
||||
|
||||
minetest.register_on_generated(function(minp, maxp)
|
||||
if maxp.y >= bedrock.layer and minp.y <= bedrock.layer then
|
||||
local vm, emin, emax = minetest.get_mapgen_object("voxelmanip")
|
||||
local data = vm:get_data()
|
||||
local area = VoxelArea:new({MinEdge=emin, MaxEdge=emax})
|
||||
local c_bedrock = minetest.get_content_id("bedrock2:bedrock")
|
||||
|
||||
for x = minp.x, maxp.x do
|
||||
for z = minp.z, maxp.z do
|
||||
local p_pos = area:index(x, bedrock.layer, z)
|
||||
data[p_pos] = c_bedrock
|
||||
end
|
||||
end
|
||||
|
||||
vm:set_data(data)
|
||||
vm:calc_lighting()
|
||||
vm:update_liquids()
|
||||
vm:write_to_map()
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_node("bedrock2:bedrock", {
|
||||
description = "Bedrock",
|
||||
tiles = {"bedrock2_bedrock.png"},
|
||||
groups = {immortal=1, not_in_creative_inventory=1},
|
||||
sounds = { footstep = { name = "bedrock2_step", gain = 1 } },
|
||||
is_ground_content = false,
|
||||
on_blast = function() end,
|
||||
on_destruct = function () end,
|
||||
can_dig = function() return false end,
|
||||
diggable = false,
|
||||
drop = "",
|
||||
})
|
||||
|
||||
if minetest.get_modpath("mesecons_mvps") ~= nil then
|
||||
mesecon:register_mvps_stopper("bedrock2:bedrock")
|
||||
end
|
After Width: | Height: | Size: 327 B |
Before Width: | Height: | Size: 1.0 KiB After Width: | Height: | Size: 1.0 KiB |
|
@ -3,53 +3,118 @@ Protector Redo mod [protect]
|
|||
Protector redo for minetest is a mod that protects a players builds by placing
|
||||
a block that stops other players from digging or placing blocks in that area.
|
||||
|
||||
based on glomie's mod, remade by Zeg9 and reworked by TenPlus1.
|
||||
based on glomie's mod, remade by Zeg9 and rewritten by TenPlus1.
|
||||
|
||||
https://forum.minetest.net/viewtopic.php?f=11&t=9376
|
||||
|
||||
Released under WTFPL
|
||||
Change log:
|
||||
|
||||
0.1 - Initial release
|
||||
0.2 - Texture update
|
||||
0.3 - Added Protection Logo to blend in with player builds
|
||||
0.4 - Code tweak for 0.4.10+
|
||||
0.5 - Added protector.radius variable in init.lua (default: 5)
|
||||
0.6 - Added Protected Doors (wood and steel) and Protected Chest
|
||||
0.7 - Protected Chests now have "To Chest" and "To Inventory" buttons to copy
|
||||
- 0.1 - Initial release
|
||||
- 0.2 - Texture update
|
||||
- 0.3 - Added Protection Logo to blend in with player builds
|
||||
- 0.4 - Code tweak for 0.4.10+
|
||||
- 0.5 - Added protector.radius variable in init.lua (default: 5)
|
||||
- 0.6 - Added Protected Doors (wood and steel) and Protected Chest
|
||||
- 0.7 - Protected Chests now have "To Chest" and "To Inventory" buttons to copy
|
||||
contents across, also chests can be named
|
||||
0.8 - Updated to work with Minetest 0.4.12, simplified textures
|
||||
0.9 - Tweaked code
|
||||
1.0 - Only owner can remove protector
|
||||
1.1 - Set 'protector_pvp = true' in minetest.conf to disable pvp in protected
|
||||
- 0.8 - Updated to work with Minetest 0.4.12, simplified textures
|
||||
- 0.9 - Tweaked code
|
||||
- 1.0 - Only owner can remove protector
|
||||
- 1.1 - Set 'protector_pvp = true' in minetest.conf to disable pvp in protected
|
||||
areas except your own, also setting protector_pvp_spawn higher than 0 will
|
||||
disable pvp around spawn area with the radius you entered
|
||||
1.2 - Shift and click support added with Minetest 0.4.13 to quickly copy stacks
|
||||
- 1.2 - Shift and click support added with Minetest 0.4.13 to quickly copy stacks
|
||||
to and from protected chest
|
||||
1.3 - Moved protector on_place into node itself, protector zone display changed
|
||||
- 1.3 - Moved protector on_place into node itself, protector zone display changed
|
||||
from 10 to 5 seconds, general code tidy
|
||||
1.4 - Changed protector recipes to give single item instead of 4, added + button
|
||||
- 1.4 - Changed protector recipes to give single item instead of 4, added + button
|
||||
to interface, tweaked and tidied code, added admin command /delprot to remove
|
||||
protectors in bulk from banned/old players
|
||||
1.5 - Added much requested protected trapdoor
|
||||
1.6 - Added protector_drop (true or false) and protector_hurt (hurt by this num)
|
||||
- 1.5 - Added much requested protected trapdoor
|
||||
- 1.6 - Added protector_drop (true or false) and protector_hurt (hurt by this num)
|
||||
variables to minetest.conf settings to stop players breaking protected
|
||||
areas by dropping tools and hurting player.
|
||||
1.7 - Included an edited version of WTFPL doors mod since protected doors didn't
|
||||
- 1.7 - Included an edited version of WTFPL doors mod since protected doors didn't
|
||||
work with the doors mod in the latest daily build... Now it's fine :)
|
||||
added support for "protection_bypass" privelage.
|
||||
- 1.8 - Added 'protector_flip' setting to stop players using lag to grief into
|
||||
another players house, it flips them around to stop them digging.
|
||||
- 1.9 - Renamed 'protector_pvp_spawn' setting to 'protector_spawn' which protects
|
||||
an area around static spawnpoint and disables pvp if active.
|
||||
(note: previous name can still be used)
|
||||
- 2.0 - Added protector placement tool (thanks to Shara) so that players can easily
|
||||
stand on a protector, face in a direction and it places a new one at a set
|
||||
distance to cover protection radius. Added /protector_show command (thanks agaran)
|
||||
Protectors and chest cannot be moved by mesecon pistons or machines.
|
||||
- 2.1 - Added 'protector_night_pvp' setting so night-time becomes a free for all and
|
||||
players can hurt one another even inside protected areas (not spawn protected)
|
||||
- 2.2 - Updated protector tool so that player only needs to stand nearby (2 block radius)
|
||||
It can also place vertically (up and down) as well. New protector recipe added.
|
||||
- 2.3 - Localise many of the protector functions and tidy code.
|
||||
- 2.4 - Update to newer functions, Minetest 0.4.16 needed to run now.
|
||||
- 2.5 - Added HUD text to show when player is inside a protected area (updates every 5 seconds)
|
||||
|
||||
Lucky Blocks: 10
|
||||
|
||||
|
||||
Usage: (requires server privelage)
|
||||
|
||||
list names to remove
|
||||
|
||||
/delprot
|
||||
/protector_remove
|
||||
|
||||
remove specific user names
|
||||
|
||||
/delprot name1 name2
|
||||
/protector_remove name1 name2
|
||||
|
||||
remove all names from list
|
||||
|
||||
/delprot -
|
||||
/protector_remove -
|
||||
|
||||
Whenever a player is near any protectors with name1 or name2 then it will be
|
||||
replaced by an air block.
|
||||
|
||||
|
||||
show owner name to replace
|
||||
|
||||
/protector_replace
|
||||
|
||||
replace owner with new name
|
||||
|
||||
/protector_replace owner new_owner
|
||||
|
||||
reset name list
|
||||
|
||||
/protector_replace -
|
||||
|
||||
|
||||
show protected areas of your nearby protectors (max of 5)
|
||||
/protector_show
|
||||
|
||||
|
||||
The following lines can be added to your minetest.conf file to configure specific features of the mod:
|
||||
|
||||
protector_radius = 5
|
||||
- Sets the area around each protection node so that other players cannot dig, place or enter through protected doors or chests.
|
||||
|
||||
protector_pvp = true
|
||||
- true or false this setting disabled pvp inside of protected areas for all players apart from those listed on the protector node.
|
||||
|
||||
protector_night_pvp = false
|
||||
- when true this setting enables pvp at night time only, even inside protected areas, requires protector_pvp to be active to work.
|
||||
|
||||
protector_spawn = 10
|
||||
- Sets an area 10 nodes around static spawnpoint that is protected.
|
||||
|
||||
protector_hurt = 2
|
||||
- When set to above 0, players digging in protected areas will be hurt by 2 health points (or whichever number it's set to)
|
||||
|
||||
protector_flip = true
|
||||
- When true players who dig inside a protected area will flipped around to stop them using lag to grief into someone else's build
|
||||
|
||||
|
||||
Protector Tool
|
||||
|
||||
Can be crafted with a protector surrounded by steel ingots and is used to place new protectors at a set distance of protector.radius in all directions including up and down simply by looking in a direction.
|
||||
|
||||
Use by standing near an existing protector, looking in a direction and using as a tool, hold sneak/shift to place new protector containing member list from inside nearest one.
|
||||
|
|
|
@ -1,9 +1,12 @@
|
|||
|
||||
local S = protector.intllib
|
||||
|
||||
protector.removal_names = ""
|
||||
protector.replace_names = ""
|
||||
|
||||
minetest.register_chatcommand("delprot", {
|
||||
params = "",
|
||||
description = "Remove Protectors near players with names provided (separate names with spaces)",
|
||||
minetest.register_chatcommand("protector_remove", {
|
||||
params = "<names list>",
|
||||
description = S("Remove Protectors around players (separate names with spaces)"),
|
||||
privs = {server = true},
|
||||
func = function(name, param)
|
||||
|
||||
|
@ -17,8 +20,9 @@ minetest.register_chatcommand("delprot", {
|
|||
end
|
||||
|
||||
if param == "-" then
|
||||
|
||||
minetest.chat_send_player(name,
|
||||
"Name List Reset")
|
||||
S("Name List Reset"))
|
||||
|
||||
protector.removal_names = ""
|
||||
|
||||
|
@ -30,6 +34,42 @@ minetest.register_chatcommand("delprot", {
|
|||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_chatcommand("protector_replace", {
|
||||
params = "<owner name> <name to replace with>",
|
||||
description = S("Replace Protector Owner with name provided"),
|
||||
privs = {server = true},
|
||||
func = function(name, param)
|
||||
|
||||
-- reset list to empty
|
||||
if param == "-" then
|
||||
|
||||
minetest.chat_send_player(name, S("Name List Reset"))
|
||||
|
||||
protector.replace_names = ""
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- show name info
|
||||
if param == ""
|
||||
and protector.replace_names ~= "" then
|
||||
|
||||
local names = protector.replace_names:split(" ")
|
||||
|
||||
minetest.chat_send_player(name,
|
||||
"Replacing Protector name '" .. (names[1] or "")
|
||||
.. "' with '" .. (names[2] or "").. "'")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
protector.replace_names = param
|
||||
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
minetest.register_abm({
|
||||
nodenames = {"protector:protect", "protector:protect2"},
|
||||
interval = 8,
|
||||
|
@ -37,14 +77,17 @@ minetest.register_abm({
|
|||
catch_up = false,
|
||||
action = function(pos, node)
|
||||
|
||||
if protector.removal_names == "" then
|
||||
if protector.removal_names == ""
|
||||
and protector.replace_names == "" then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
local meta = minetest.get_meta(pos) ; if not meta then return end
|
||||
local owner = meta:get_string("owner")
|
||||
--local members = meta:get_string("members")
|
||||
|
||||
if protector.removal_names ~= "" then
|
||||
|
||||
local names = protector.removal_names:split(" ")
|
||||
|
||||
for _, n in pairs(names) do
|
||||
|
@ -52,8 +95,52 @@ minetest.register_abm({
|
|||
if n == owner then
|
||||
minetest.set_node(pos, {name = "air"})
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
if protector.replace_names ~= "" then
|
||||
|
||||
local names = protector.replace_names:split(" ")
|
||||
|
||||
if names[1] and names[2] and owner == names[1] then
|
||||
|
||||
meta:set_string("owner", names[2])
|
||||
meta:set_string("infotext", "Protection (owned by " .. names[2] .. ")")
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
})
|
||||
|
||||
|
||||
-- show protection areas of nearby protectors owned by you (thanks agaran)
|
||||
minetest.register_chatcommand("protector_show", {
|
||||
params = "",
|
||||
description = "Show protected areas of your nearby protectors",
|
||||
privs = {},
|
||||
func = function(name, param)
|
||||
|
||||
local player = minetest.get_player_by_name(name)
|
||||
local pos = player:get_pos()
|
||||
local r = protector.radius -- max protector range.
|
||||
|
||||
-- find the protector nodes
|
||||
local pos = minetest.find_nodes_in_area(
|
||||
{x = pos.x - r, y = pos.y - r, z = pos.z - r},
|
||||
{x = pos.x + r, y = pos.y + r, z = pos.z + r},
|
||||
{"protector:protect", "protector:protect2"})
|
||||
|
||||
local meta, owner
|
||||
|
||||
-- show a maximum of 5 protected areas only
|
||||
for n = 1, math.min(#pos, 5) do
|
||||
|
||||
meta = minetest.get_meta(pos[n])
|
||||
owner = meta:get_string("owner") or ""
|
||||
|
||||
if owner == name then
|
||||
minetest.add_entity(pos[n], "protector:display")
|
||||
end
|
||||
end
|
||||
end
|
||||
})
|
|
@ -1,3 +1,4 @@
|
|||
default
|
||||
doors?
|
||||
mobs?
|
||||
intllib?
|
||||
lucky_block?
|
||||
mesecons_mvps?
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Lets players craft special blocks to protect their builds or disable PVP in areas.
|
|
@ -1,7 +1,9 @@
|
|||
|
||||
-- Since the doors mod has changed in the latest daily builds I have taken the
|
||||
-- WTFPL licenced code from the old doors mod and included an edited version
|
||||
-- of it within this mod for local use.
|
||||
-- within this mod for local use.
|
||||
|
||||
local S = protector.intllib
|
||||
|
||||
-- Registers a door
|
||||
function register_door(name, def)
|
||||
|
@ -295,7 +297,7 @@ end
|
|||
local name = "protector:door_wood"
|
||||
|
||||
register_door(name, {
|
||||
description = "Protected Wooden Door",
|
||||
description = S("Protected Wooden Door"),
|
||||
inventory_image = "doors_wood.png^protector_logo.png",
|
||||
groups = {
|
||||
snappy = 1, choppy = 2, oddly_breakable_by_hand = 2,
|
||||
|
@ -328,7 +330,7 @@ minetest.register_craft({
|
|||
local name = "protector:door_steel"
|
||||
|
||||
register_door(name, {
|
||||
description = "Protected Steel Door",
|
||||
description = S("Protected Steel Door"),
|
||||
inventory_image = "doors_steel.png^protector_logo.png",
|
||||
groups = {
|
||||
snappy = 1, bendy = 2, cracky = 1,
|
||||
|
@ -419,7 +421,7 @@ end
|
|||
-- Protected Wooden Trapdoor
|
||||
|
||||
register_trapdoor("protector:trapdoor", {
|
||||
description = "Protected Trapdoor",
|
||||
description = S("Protected Trapdoor"),
|
||||
inventory_image = "doors_trapdoor.png^protector_logo.png",
|
||||
wield_image = "doors_trapdoor.png^protector_logo.png",
|
||||
tile_front = "doors_trapdoor.png^protector_logo.png",
|
||||
|
@ -450,7 +452,7 @@ minetest.register_craft({
|
|||
-- Protected Steel Trapdoor
|
||||
|
||||
register_trapdoor("protector:trapdoor_steel", {
|
||||
description = "Protected Steel Trapdoor",
|
||||
description = S("Protected Steel Trapdoor"),
|
||||
inventory_image = "doors_trapdoor_steel.png^protector_logo.png",
|
||||
wield_image = "doors_trapdoor_steel.png^protector_logo.png",
|
||||
tile_front = "doors_trapdoor_steel.png^protector_logo.png",
|
||||
|
@ -480,7 +482,7 @@ minetest.register_craft({
|
|||
-- Protected Chest
|
||||
|
||||
minetest.register_node("protector:chest", {
|
||||
description = "Protected Chest",
|
||||
description = S("Protected Chest"),
|
||||
tiles = {
|
||||
"default_chest_top.png", "default_chest_top.png",
|
||||
"default_chest_side.png", "default_chest_side.png",
|
||||
|
@ -497,7 +499,7 @@ minetest.register_node("protector:chest", {
|
|||
local meta = minetest.get_meta(pos)
|
||||
local inv = meta:get_inventory()
|
||||
|
||||
meta:set_string("infotext", "Protected Chest")
|
||||
meta:set_string("infotext", S("Protected Chest"))
|
||||
meta:set_string("name", "")
|
||||
inv:set_size("main", 8 * 4)
|
||||
end,
|
||||
|
@ -517,16 +519,47 @@ minetest.register_node("protector:chest", {
|
|||
|
||||
on_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", player:get_player_name()
|
||||
.. " moves stuff to protected chest at "
|
||||
.. minetest.pos_to_string(pos))
|
||||
minetest.log("action", S("@1 moves stuff to protected chest at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
|
||||
minetest.log("action", player:get_player_name()
|
||||
.. " takes stuff from protected chest at "
|
||||
.. minetest.pos_to_string(pos))
|
||||
minetest.log("action", S("@1 takes stuff from protected chest at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
on_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
minetest.log("action", S("@1 moves stuff inside protected chest at @2",
|
||||
player:get_player_name(), minetest.pos_to_string(pos)))
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_put = function(pos, listname, index, stack, player)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_take = function(pos, listname, index, stack, player)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return stack:get_count()
|
||||
end,
|
||||
|
||||
allow_metadata_inventory_move = function(pos, from_list, from_index, to_list, to_index, count, player)
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return 0
|
||||
end
|
||||
|
||||
return count
|
||||
end,
|
||||
|
||||
on_rightclick = function(pos, node, clicker)
|
||||
|
@ -547,10 +580,10 @@ minetest.register_node("protector:chest", {
|
|||
.. default.gui_bg_img
|
||||
.. default.gui_slots
|
||||
.. "list[nodemeta:".. spos .. ";main;0,0.3;8,4;]"
|
||||
.. "button[0,4.5;2,0.25;toup;To Chest]"
|
||||
.. "button[0,4.5;2,0.25;toup;" .. S("To Chest") .. "]"
|
||||
.. "field[2.3,4.8;4,0.25;chestname;;"
|
||||
.. meta:get_string("name") .. "]"
|
||||
.. "button[6,4.5;2,0.25;todn;To Inventory]"
|
||||
.. "button[6,4.5;2,0.25;todn;" .. S("To Inventory") .. "]"
|
||||
.. "list[current_player;main;0,5;8,1;]"
|
||||
.. "list[current_player;main;0,6.08;8,3;8]"
|
||||
.. "listring[nodemeta:" .. spos .. ";main]"
|
||||
|
@ -569,24 +602,30 @@ minetest.register_node("protector:chest", {
|
|||
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
|
||||
if string.sub(formname, 0, string.len("protector:chest_")) == "protector:chest_" then
|
||||
if string.sub(formname, 0, string.len("protector:chest_")) ~= "protector:chest_" then
|
||||
return
|
||||
end
|
||||
|
||||
local pos_s = string.sub(formname,string.len("protector:chest_") + 1)
|
||||
local pos = minetest.string_to_pos(pos_s)
|
||||
local meta = minetest.get_meta(pos)
|
||||
local chest_inv = meta:get_inventory()
|
||||
|
||||
if minetest.is_protected(pos, player:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
local meta = minetest.get_meta(pos) ; if not meta then return end
|
||||
local chest_inv = meta:get_inventory() ; if not chest_inv then return end
|
||||
local player_inv = player:get_inventory()
|
||||
local leftover
|
||||
|
||||
if fields.toup then
|
||||
|
||||
-- copy contents of players inventory to chest
|
||||
for i, v in pairs (player_inv:get_list("main") or {}) do
|
||||
for i, v in ipairs(player_inv:get_list("main") or {}) do
|
||||
|
||||
if chest_inv
|
||||
and chest_inv:room_for_item('main', v) then
|
||||
if chest_inv:room_for_item("main", v) then
|
||||
|
||||
leftover = chest_inv:add_item('main', v)
|
||||
leftover = chest_inv:add_item("main", v)
|
||||
|
||||
player_inv:remove_item("main", v)
|
||||
|
||||
|
@ -600,17 +639,17 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
elseif fields.todn then
|
||||
|
||||
-- copy contents of chest to players inventory
|
||||
for i, v in pairs (chest_inv:get_list('main') or {}) do
|
||||
for i, v in ipairs(chest_inv:get_list("main") or {}) do
|
||||
|
||||
if player_inv:room_for_item("main", v) then
|
||||
|
||||
leftover = player_inv:add_item("main", v)
|
||||
|
||||
chest_inv:remove_item('main', v)
|
||||
chest_inv:remove_item("main", v)
|
||||
|
||||
if leftover
|
||||
and not leftover:is_empty() then
|
||||
chest_inv:add_item('main', v)
|
||||
chest_inv:add_item("main", v)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
@ -622,14 +661,12 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|||
|
||||
meta:set_string("name", fields.chestname)
|
||||
meta:set_string("infotext",
|
||||
"Protected Chest (" .. fields.chestname .. ")")
|
||||
S("Protected Chest (@1)", fields.chestname))
|
||||
else
|
||||
meta:set_string("infotext", "Protected Chest")
|
||||
meta:set_string("infotext", S("Protected Chest"))
|
||||
end
|
||||
|
||||
end
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
-- Protected Chest recipes
|
||||
|
|
|
@ -0,0 +1,60 @@
|
|||
|
||||
local radius = (tonumber(minetest.setting_get("protector_radius")) or 5)
|
||||
local hud = {}
|
||||
local hud_timer = 0
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
|
||||
hud_timer = hud_timer + dtime
|
||||
if hud_timer < 5 then
|
||||
return
|
||||
end
|
||||
hud_timer = 0
|
||||
|
||||
for _, player in pairs(minetest.get_connected_players()) do
|
||||
|
||||
local name = player:get_player_name()
|
||||
local pos = vector.round(player:getpos())
|
||||
local hud_text = "You can build here"
|
||||
|
||||
local protectors = minetest.find_nodes_in_area(
|
||||
{x=pos.x -radius , y=pos.y -radius , z=pos.z -radius},
|
||||
{x=pos.x +radius , y=pos.y +radius , z=pos.z +radius},
|
||||
{"protector:protect","protector:protect2"})
|
||||
|
||||
if #protectors > 0 then
|
||||
local npos = protectors[1]
|
||||
local meta = minetest.get_meta(npos)
|
||||
local nodeowner = meta:get_string("owner")
|
||||
|
||||
hud_text = "Owned by: " .. nodeowner
|
||||
end
|
||||
|
||||
if not hud[name] then
|
||||
|
||||
hud[name] = {}
|
||||
|
||||
hud[name].id = player:hud_add({
|
||||
hud_elem_type = "text",
|
||||
name = "Protector Area",
|
||||
number = 0xFFFF22,
|
||||
position = {x=0, y=0.95},
|
||||
offset = {x=8, y=-8},
|
||||
text = hud_text,
|
||||
scale = {x=200, y=60},
|
||||
alignment = {x=1, y=-1},
|
||||
})
|
||||
|
||||
return
|
||||
|
||||
else
|
||||
|
||||
player:hud_change(hud[name].id, "text", hud_text)
|
||||
end
|
||||
end
|
||||
end)
|
||||
|
||||
minetest.register_on_leaveplayer(function(player)
|
||||
hud[player:get_player_name()] = nil
|
||||
end)
|
||||
|
|
@ -1,24 +1,59 @@
|
|||
minetest.register_privilege("delprotect","Ignore player protection")
|
||||
|
||||
-- get minetest.conf settings
|
||||
protector = {}
|
||||
protector.mod = "redo"
|
||||
protector.radius = (tonumber(minetest.setting_get("protector_radius")) or 3)
|
||||
protector.drop = minetest.setting_getbool("protector_drop") or false
|
||||
protector.hurt = (tonumber(minetest.setting_get("protector_hurt")) or 0)
|
||||
protector.radius = tonumber(minetest.settings:get("protector_radius")) or 3
|
||||
protector.flip = minetest.settings:get_bool("protector_flip") or false
|
||||
protector.hurt = tonumber(minetest.settings:get("protector_hurt")) or 0
|
||||
protector.spawn = tonumber(minetest.settings:get("protector_spawn")
|
||||
or minetest.settings:get("protector_pvp_spawn")) or 0
|
||||
|
||||
protector.get_member_list = function(meta)
|
||||
|
||||
-- get static spawn position
|
||||
local statspawn = minetest.string_to_pos(minetest.settings:get("static_spawnpoint"))
|
||||
or {x = 0, y = 2, z = 0}
|
||||
|
||||
|
||||
-- Intllib
|
||||
local S
|
||||
if minetest.get_modpath("intllib") then
|
||||
S = intllib.Getter()
|
||||
else
|
||||
S = function(s, a, ...) a = {a, ...}
|
||||
return s:gsub("@(%d+)", function(n)
|
||||
return a[tonumber(n)]
|
||||
end)
|
||||
end
|
||||
|
||||
end
|
||||
protector.intllib = S
|
||||
|
||||
|
||||
-- return list of members as a table
|
||||
local get_member_list = function(meta)
|
||||
|
||||
return meta:get_string("members"):split(" ")
|
||||
end
|
||||
|
||||
protector.set_member_list = function(meta, list)
|
||||
|
||||
-- write member list table in protector meta as string
|
||||
local set_member_list = function(meta, list)
|
||||
|
||||
meta:set_string("members", table.concat(list, " "))
|
||||
end
|
||||
|
||||
protector.is_member = function (meta, name)
|
||||
|
||||
for _, n in pairs(protector.get_member_list(meta)) do
|
||||
-- check for owner name
|
||||
local is_owner = function(meta, name)
|
||||
|
||||
return name == meta:get_string("owner")
|
||||
end
|
||||
|
||||
|
||||
-- check for member name
|
||||
local is_member = function (meta, name)
|
||||
|
||||
for _, n in pairs(get_member_list(meta)) do
|
||||
|
||||
if n == name then
|
||||
return true
|
||||
|
@ -28,22 +63,28 @@ protector.is_member = function (meta, name)
|
|||
return false
|
||||
end
|
||||
|
||||
protector.add_member = function(meta, name)
|
||||
|
||||
if protector.is_member(meta, name) then
|
||||
-- add player name to table as member
|
||||
local add_member = function(meta, name)
|
||||
|
||||
-- does name already exist?
|
||||
if is_owner(meta, name)
|
||||
or is_member(meta, name) then
|
||||
return
|
||||
end
|
||||
|
||||
local list = protector.get_member_list(meta)
|
||||
local list = get_member_list(meta)
|
||||
|
||||
table.insert(list, name)
|
||||
|
||||
protector.set_member_list(meta, list)
|
||||
set_member_list(meta, list)
|
||||
end
|
||||
|
||||
protector.del_member = function(meta, name)
|
||||
|
||||
local list = protector.get_member_list(meta)
|
||||
-- remove player name from table
|
||||
local del_member = function(meta, name)
|
||||
|
||||
local list = get_member_list(meta)
|
||||
|
||||
for i, n in pairs(list) do
|
||||
|
||||
|
@ -53,39 +94,39 @@ protector.del_member = function(meta, name)
|
|||
end
|
||||
end
|
||||
|
||||
protector.set_member_list(meta, list)
|
||||
set_member_list(meta, list)
|
||||
end
|
||||
|
||||
-- Protector Interface
|
||||
|
||||
protector.generate_formspec = function(meta)
|
||||
-- protector interface
|
||||
local protector_formspec = function(meta)
|
||||
|
||||
local formspec = "size[8,7]"
|
||||
.. default.gui_bg
|
||||
.. default.gui_bg_img
|
||||
.. default.gui_slots
|
||||
.. "label[2.5,0;-- Protector interface --]"
|
||||
.. "label[0,1;PUNCH node to show protected area or USE for area check]"
|
||||
.. "label[0,2;Members: (type player name then press Enter to add)]"
|
||||
.. "button_exit[2.5,6.2;3,0.5;close_me;Close]"
|
||||
.. "label[2.5,0;" .. S("-- Protector interface --") .. "]"
|
||||
.. "label[0,1;" .. S("PUNCH node to show protected area") .. "]"
|
||||
.. "label[0,2;" .. S("Members:") .. "]"
|
||||
.. "button_exit[2.5,6.2;3,0.5;close_me;" .. S("Close") .. "]"
|
||||
|
||||
local members = protector.get_member_list(meta)
|
||||
local npp = 12 -- max users added onto protector list
|
||||
local members = get_member_list(meta)
|
||||
local npp = 12 -- max users added to protector list
|
||||
local i = 0
|
||||
|
||||
for _, member in pairs(members) do
|
||||
for n = 1, #members do
|
||||
|
||||
if i < npp then
|
||||
|
||||
-- show username
|
||||
formspec = formspec .. "button[" .. (i % 4 * 2)
|
||||
.. "," .. math.floor(i / 4 + 3)
|
||||
.. ";1.5,.5;protector_member;" .. member .. "]"
|
||||
.. ";1.5,.5;protector_member;" .. members[n] .. "]"
|
||||
|
||||
-- username remove button
|
||||
.. "button[" .. (i % 4 * 2 + 1.25) .. ","
|
||||
.. math.floor(i / 4 + 3)
|
||||
.. ";.75,.5;protector_del_member_" .. member .. ";X]"
|
||||
.. ";.75,.5;protector_del_member_" .. members[n] .. ";X]"
|
||||
end
|
||||
|
||||
i = i + 1
|
||||
|
@ -107,6 +148,28 @@ protector.generate_formspec = function(meta)
|
|||
return formspec
|
||||
end
|
||||
|
||||
|
||||
-- check if pos is inside a protected spawn area
|
||||
local inside_spawn = function(pos, radius)
|
||||
|
||||
if protector.spawn <= 0 then
|
||||
return false
|
||||
end
|
||||
|
||||
if pos.x < statspawn.x + radius
|
||||
and pos.x > statspawn.x - radius
|
||||
and pos.y < statspawn.y + radius
|
||||
and pos.y > statspawn.y - radius
|
||||
and pos.z < statspawn.z + radius
|
||||
and pos.z > statspawn.z - radius then
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
-- Infolevel:
|
||||
-- 0 for no info
|
||||
-- 1 for "This area is owned by <owner> !" if you can't dig
|
||||
|
@ -115,76 +178,67 @@ end
|
|||
|
||||
protector.can_dig = function(r, pos, digger, onlyowner, infolevel)
|
||||
|
||||
if not digger
|
||||
or not pos then
|
||||
if not digger or not pos then
|
||||
return false
|
||||
end
|
||||
|
||||
-- Delprotect privileged users can override protections
|
||||
|
||||
if minetest.check_player_privs(digger, {delprotect = true})
|
||||
and infolevel == 1 then
|
||||
-- protector_bypass privileged users can override protection
|
||||
if infolevel == 1
|
||||
and minetest.check_player_privs(digger, {protection_bypass = true}) then
|
||||
return true
|
||||
end
|
||||
|
||||
-- infolevel 3 is only used to bypass priv check, change to 1 now
|
||||
if infolevel == 3 then infolevel = 1 end
|
||||
|
||||
-- Find the protector nodes
|
||||
-- is spawn area protected ?
|
||||
if inside_spawn(pos, protector.spawn) then
|
||||
|
||||
local positions = minetest.find_nodes_in_area(
|
||||
minetest.chat_send_player(digger,
|
||||
S("Spawn @1 has been protected up to a @2 block radius.",
|
||||
minetest.pos_to_string(statspawn), protector.spawn))
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
-- find the protector nodes
|
||||
local pos = minetest.find_nodes_in_area(
|
||||
{x = pos.x - r, y = pos.y - r, z = pos.z - r},
|
||||
{x = pos.x + r, y = pos.y + r, z = pos.z + r},
|
||||
{"protector:protect", "protector:protect2"})
|
||||
|
||||
local meta, owner, members
|
||||
|
||||
for _, pos in pairs(positions) do
|
||||
for n = 1, #pos do
|
||||
|
||||
meta = minetest.get_meta(pos)
|
||||
owner = meta:get_string("owner")
|
||||
members = meta:get_string("members")
|
||||
meta = minetest.get_meta(pos[n])
|
||||
owner = meta:get_string("owner") or ""
|
||||
members = meta:get_string("members") or ""
|
||||
|
||||
if owner ~= digger then
|
||||
-- node change and digger isn't owner
|
||||
if infolevel == 1 and owner ~= digger then
|
||||
|
||||
if onlyowner
|
||||
or not protector.is_member(meta, digger) then
|
||||
|
||||
if infolevel == 1 then
|
||||
-- and you aren't on the member list
|
||||
if onlyowner or not is_member(meta, digger) then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"This area is owned by " .. owner .. " !")
|
||||
|
||||
elseif infolevel == 2 then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"This area is owned by " .. owner .. ".")
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"Protection located at: " .. minetest.pos_to_string(pos))
|
||||
|
||||
if members ~= "" then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"Members: " .. members .. ".")
|
||||
end
|
||||
end
|
||||
S("This area is owned by @1!", owner))
|
||||
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- when using protector as tool, show protector information
|
||||
if infolevel == 2 then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"This area is owned by " .. owner .. ".")
|
||||
minetest.chat_send_player(digger, S("This area is owned by @1.", owner))
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"Protection located at: " .. minetest.pos_to_string(pos))
|
||||
S("Protection located at: @1", minetest.pos_to_string(pos[n])))
|
||||
|
||||
if members ~= "" then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"Members: " .. members .. ".")
|
||||
minetest.chat_send_player(digger, S("Members: @1.", members))
|
||||
end
|
||||
|
||||
return false
|
||||
|
@ -192,98 +246,121 @@ protector.can_dig = function(r, pos, digger, onlyowner, infolevel)
|
|||
|
||||
end
|
||||
|
||||
-- show when you can build on unprotected area
|
||||
if infolevel == 2 then
|
||||
|
||||
if #positions < 1 then
|
||||
if #pos < 1 then
|
||||
|
||||
minetest.chat_send_player(digger,
|
||||
"This area is not protected.")
|
||||
minetest.chat_send_player(digger, S("This area is not protected."))
|
||||
end
|
||||
|
||||
minetest.chat_send_player(digger, "You can build here.")
|
||||
minetest.chat_send_player(digger, S("You can build here."))
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
-- Can node be added or removed, if so return node else true (for protected)
|
||||
|
||||
protector.old_is_protected = minetest.is_protected
|
||||
local old_is_protected = minetest.is_protected
|
||||
|
||||
-- check for protected area, return true if protected and digger isn't on list
|
||||
function minetest.is_protected(pos, digger)
|
||||
|
||||
digger = digger or "" -- nil check
|
||||
|
||||
-- is area protected against digger?
|
||||
if not protector.can_dig(protector.radius, pos, digger, false, 1) then
|
||||
|
||||
local player = minetest.get_player_by_name(digger)
|
||||
|
||||
if player and player:is_player() then
|
||||
|
||||
-- hurt player if protection violated
|
||||
if protector.hurt > 0
|
||||
and player then
|
||||
if protector.hurt > 0 and player:get_hp() > 0 then
|
||||
player:set_hp(player:get_hp() - protector.hurt)
|
||||
end
|
||||
|
||||
-- drop tool/item if protection violated
|
||||
if protector.drop == true
|
||||
and player then
|
||||
|
||||
local holding = player:get_wielded_item()
|
||||
|
||||
if holding:to_string() ~= "" then
|
||||
|
||||
-- take stack
|
||||
local sta = holding:take_item(holding:get_count())
|
||||
player:set_wielded_item(holding)
|
||||
|
||||
-- incase of lag, reset stack
|
||||
minetest.after(0.1, function()
|
||||
player:set_wielded_item(holding)
|
||||
|
||||
-- drop stack
|
||||
local obj = minetest.add_item(player:getpos(), sta)
|
||||
obj:setvelocity({x = 0, y = 5, z = 0})
|
||||
end)
|
||||
-- flip player when protection violated
|
||||
if protector.flip then
|
||||
-- yaw + 180°
|
||||
local yaw = player:get_look_horizontal() + math.pi
|
||||
--local yaw = player:get_look_yaw() + math.pi
|
||||
|
||||
if yaw > 2 * math.pi then
|
||||
yaw = yaw - 2 * math.pi
|
||||
end
|
||||
|
||||
--player:set_look_horizontal(yaw)
|
||||
player:set_look_yaw(yaw)
|
||||
|
||||
-- invert pitch
|
||||
player:set_look_vertical(-player:get_look_vertical())
|
||||
--player:set_look_pitch(-player:get_look_pitch())
|
||||
|
||||
-- if digging below player, move up to avoid falling through hole
|
||||
local pla_pos = player:get_pos()
|
||||
|
||||
if pos.y < pla_pos.y then
|
||||
|
||||
player:setpos({
|
||||
x = pla_pos.x,
|
||||
y = pla_pos.y + 0.8,
|
||||
z = pla_pos.z
|
||||
})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
return protector.old_is_protected(pos, digger)
|
||||
|
||||
-- otherwise can dig or place
|
||||
return old_is_protected(pos, digger)
|
||||
end
|
||||
|
||||
-- Make sure protection block doesn't overlap another protector's area
|
||||
|
||||
function protector.check_overlap(itemstack, placer, pointed_thing)
|
||||
-- make sure protection block doesn't overlap another protector's area
|
||||
local check_overlap = function(itemstack, placer, pointed_thing)
|
||||
|
||||
if pointed_thing.type ~= "node" then
|
||||
return itemstack
|
||||
end
|
||||
|
||||
if not protector.can_dig(protector.radius * 2, pointed_thing.above,
|
||||
placer:get_player_name(), true, 3) then
|
||||
local pos = pointed_thing.above
|
||||
local name = placer:get_player_name()
|
||||
|
||||
minetest.chat_send_player(placer:get_player_name(),
|
||||
"Overlaps into above players protected area")
|
||||
-- make sure protector doesn't overlap onto protected spawn area
|
||||
if inside_spawn(pos, protector.spawn + protector.radius) then
|
||||
|
||||
return
|
||||
minetest.chat_send_player(name,
|
||||
S("Spawn @1 has been protected up to a @2 block radius.",
|
||||
minetest.pos_to_string(statspawn), protector.spawn))
|
||||
|
||||
return itemstack
|
||||
end
|
||||
|
||||
-- make sure protector doesn't overlap any other player's area
|
||||
if not protector.can_dig(protector.radius * 2, pos, name, true, 3) then
|
||||
|
||||
minetest.chat_send_player(name,
|
||||
S("Overlaps into above players protected area"))
|
||||
|
||||
return itemstack
|
||||
end
|
||||
|
||||
return minetest.item_place(itemstack, placer, pointed_thing)
|
||||
|
||||
end
|
||||
|
||||
--= Protection Block
|
||||
|
||||
-- protection node
|
||||
minetest.register_node("protector:protect", {
|
||||
description = "Protection Block",
|
||||
description = S("Protection Block") .. " (" .. S("USE for area check") .. ")",
|
||||
drawtype = "nodebox",
|
||||
tiles = {
|
||||
"moreblocks_circle_stone_bricks.png",
|
||||
"moreblocks_circle_stone_bricks.png",
|
||||
"moreblocks_circle_stone_bricks.png^protector_logo.png"
|
||||
"es_circle_stone_bricks.png",
|
||||
"es_circle_stone_bricks.png",
|
||||
"es_circle_stone_bricks.png^protector_logo.png"
|
||||
},
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
groups = {dig_immediate = 2, unbreakable = 1},
|
||||
|
@ -298,14 +375,14 @@ minetest.register_node("protector:protect", {
|
|||
}
|
||||
},
|
||||
|
||||
on_place = protector.check_overlap,
|
||||
on_place = check_overlap,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
meta:set_string("owner", placer:get_player_name() or "")
|
||||
meta:set_string("infotext", "Protection (owned by " .. meta:get_string("owner") .. ")")
|
||||
meta:set_string("infotext", S("Protection (owned by @1)", meta:get_string("owner")))
|
||||
meta:set_string("members", "")
|
||||
end,
|
||||
|
||||
|
@ -324,14 +401,16 @@ minetest.register_node("protector:protect", {
|
|||
|
||||
if meta
|
||||
and protector.can_dig(1, pos, clicker:get_player_name(), true, 1) then
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
"protector:node_" .. minetest.pos_to_string(pos), protector.generate_formspec(meta))
|
||||
"protector:node_" .. minetest.pos_to_string(pos),
|
||||
protector_formspec(meta))
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher)
|
||||
|
||||
if not protector.can_dig(1, pos, puncher:get_player_name(), true, 1) then
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -340,7 +419,7 @@ minetest.register_node("protector:protect", {
|
|||
|
||||
can_dig = function(pos, player)
|
||||
|
||||
return protector.can_dig(1, pos, player:get_player_name(), true, 1)
|
||||
return player and protector.can_dig(1, pos, player:get_player_name(), true, 1)
|
||||
end,
|
||||
|
||||
on_blast = function() end,
|
||||
|
@ -355,16 +434,16 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
--= Protection Logo
|
||||
|
||||
-- protection logo
|
||||
minetest.register_node("protector:protect2", {
|
||||
description = "Protection Logo",
|
||||
description = S("Protection Logo") .. " (" .. S("USE for area check") .. ")",
|
||||
tiles = {"protector_logo.png"},
|
||||
wield_image = "protector_logo.png",
|
||||
inventory_image = "protector_logo.png",
|
||||
sounds = default.node_sound_stone_defaults(),
|
||||
groups = {dig_immediate = 2, unbreakable = 1},
|
||||
paramtype = 'light',
|
||||
paramtype = "light",
|
||||
paramtype2 = "wallmounted",
|
||||
legacy_wallmounted = true,
|
||||
light_source = 4,
|
||||
|
@ -379,14 +458,14 @@ minetest.register_node("protector:protect2", {
|
|||
},
|
||||
selection_box = {type = "wallmounted"},
|
||||
|
||||
on_place = protector.check_overlap,
|
||||
on_place = check_overlap,
|
||||
|
||||
after_place_node = function(pos, placer)
|
||||
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
meta:set_string("owner", placer:get_player_name() or "")
|
||||
meta:set_string("infotext", "Protection (owned by " .. meta:get_string("owner") .. ")")
|
||||
meta:set_string("infotext", S("Protection (owned by @1)", meta:get_string("owner")))
|
||||
meta:set_string("members", "")
|
||||
end,
|
||||
|
||||
|
@ -406,13 +485,13 @@ minetest.register_node("protector:protect2", {
|
|||
if protector.can_dig(1, pos, clicker:get_player_name(), true, 1) then
|
||||
|
||||
minetest.show_formspec(clicker:get_player_name(),
|
||||
"protector:node_" .. minetest.pos_to_string(pos), protector.generate_formspec(meta))
|
||||
"protector:node_" .. minetest.pos_to_string(pos), protector_formspec(meta))
|
||||
end
|
||||
end,
|
||||
|
||||
on_punch = function(pos, node, puncher)
|
||||
|
||||
if not protector.can_dig(1, pos, puncher:get_player_name(), true, 1) then
|
||||
if minetest.is_protected(pos, puncher:get_player_name()) then
|
||||
return
|
||||
end
|
||||
|
||||
|
@ -421,7 +500,7 @@ minetest.register_node("protector:protect2", {
|
|||
|
||||
can_dig = function(pos, player)
|
||||
|
||||
return protector.can_dig(1, pos, player:get_player_name(), true, 1)
|
||||
return player and protector.can_dig(1, pos, player:get_player_name(), true, 1)
|
||||
end,
|
||||
|
||||
on_blast = function() end,
|
||||
|
@ -436,44 +515,65 @@ minetest.register_craft({
|
|||
}
|
||||
})
|
||||
|
||||
-- If name entered or button press
|
||||
|
||||
--[[
|
||||
-- recipes to switch between protectors
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "protector:protect",
|
||||
recipe = {"protector:protect2"}
|
||||
})
|
||||
|
||||
minetest.register_craft({
|
||||
type = "shapeless",
|
||||
output = "protector:protect2",
|
||||
recipe = {"protector:protect"}
|
||||
})
|
||||
]]
|
||||
|
||||
-- check formspec buttons or when name entered
|
||||
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
||||
|
||||
-- protector formspec found
|
||||
if string.sub(formname, 0, string.len("protector:node_")) == "protector:node_" then
|
||||
|
||||
local pos_s = string.sub(formname, string.len("protector:node_") + 1)
|
||||
local pos = minetest.string_to_pos(pos_s)
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
-- only owner can add names
|
||||
if not protector.can_dig(1, pos, player:get_player_name(), true, 1) then
|
||||
return
|
||||
end
|
||||
|
||||
-- add member [+]
|
||||
if fields.protector_add_member then
|
||||
|
||||
for _, i in pairs(fields.protector_add_member:split(" ")) do
|
||||
protector.add_member(meta, i)
|
||||
add_member(meta, i)
|
||||
end
|
||||
end
|
||||
|
||||
-- remove member [x]
|
||||
for field, value in pairs(fields) do
|
||||
|
||||
if string.sub(field, 0, string.len("protector_del_member_")) == "protector_del_member_" then
|
||||
protector.del_member(meta, string.sub(field,string.len("protector_del_member_") + 1))
|
||||
if string.sub(field, 0,
|
||||
string.len("protector_del_member_")) == "protector_del_member_" then
|
||||
|
||||
del_member(meta,
|
||||
string.sub(field,string.len("protector_del_member_") + 1))
|
||||
end
|
||||
end
|
||||
|
||||
-- reset formspec until close button pressed
|
||||
if not fields.close_me then
|
||||
minetest.show_formspec(player:get_player_name(), formname, protector.generate_formspec(meta))
|
||||
minetest.show_formspec(player:get_player_name(), formname, protector_formspec(meta))
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
end)
|
||||
|
||||
-- Display entity shown when protector node is punched
|
||||
|
||||
-- display entity shown when protector node is punched
|
||||
minetest.register_entity("protector:display", {
|
||||
physical = false,
|
||||
collisionbox = {0, 0, 0, 0, 0, 0},
|
||||
|
@ -483,24 +583,18 @@ minetest.register_entity("protector:display", {
|
|||
textures = {"protector:display_node"},
|
||||
timer = 0,
|
||||
|
||||
on_activate = function(self, staticdata)
|
||||
|
||||
-- Xanadu server only
|
||||
if mobs and mobs.entity and mobs.entity == false then
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
|
||||
on_step = function(self, dtime)
|
||||
|
||||
self.timer = self.timer + dtime
|
||||
|
||||
-- remove after 5 seconds
|
||||
if self.timer > 5 then
|
||||
self.object:remove()
|
||||
end
|
||||
end,
|
||||
})
|
||||
|
||||
|
||||
-- Display-zone node, Do NOT place the display as a node,
|
||||
-- it is made to be used as an entity (see above)
|
||||
|
||||
|
@ -534,8 +628,23 @@ minetest.register_node("protector:display_node", {
|
|||
drop = "",
|
||||
})
|
||||
|
||||
dofile(minetest.get_modpath("protector") .. "/doors_chest.lua")
|
||||
dofile(minetest.get_modpath("protector") .. "/pvp.lua")
|
||||
dofile(minetest.get_modpath("protector") .. "/admin.lua")
|
||||
|
||||
print ("[MOD] Protector Redo loaded")
|
||||
local path = minetest.get_modpath("protector")
|
||||
|
||||
dofile(path .. "/doors_chest.lua")
|
||||
dofile(path .. "/pvp.lua")
|
||||
dofile(path .. "/admin.lua")
|
||||
dofile(path .. "/tool.lua")
|
||||
dofile(path .. "/hud.lua")
|
||||
dofile(path .. "/lucky_block.lua")
|
||||
|
||||
|
||||
-- stop mesecon pistons from pushing protectors
|
||||
if minetest.get_modpath("mesecons_mvps") then
|
||||
mesecon.register_mvps_stopper("protector:protect")
|
||||
mesecon.register_mvps_stopper("protector:protect2")
|
||||
mesecon.register_mvps_stopper("protector:chest")
|
||||
end
|
||||
|
||||
|
||||
print (S("[MOD] Protector Redo loaded"))
|
||||
|
|
|
@ -1,34 +1,21 @@
|
|||
The MIT License (MIT)
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
Version 2, December 2004
|
||||
Copyright (c) 2016 TenPlus1
|
||||
|
||||
Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
|
||||
Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
of this software and associated documentation files (the "Software"), to deal
|
||||
in the Software without restriction, including without limitation the rights
|
||||
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
copies of the Software, and to permit persons to whom the Software is
|
||||
furnished to do so, subject to the following conditions:
|
||||
|
||||
Everyone is permitted to copy and distribute verbatim or modified
|
||||
copies of this license document, and changing it is allowed as long
|
||||
as the name is changed.
|
||||
The above copyright notice and this permission notice shall be included in
|
||||
all copies or substantial portions of the Software.
|
||||
|
||||
DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
|
||||
TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
|
||||
|
||||
0. You just DO WHAT THE FUCK YOU WANT TO.
|
||||
|
||||
|
||||
License of textures
|
||||
--------------------------------------
|
||||
following Textures created by Fernando Zapata (CC BY-SA 3.0):
|
||||
door_wood.png
|
||||
door_wood_a.png
|
||||
door_wood_a_r.png
|
||||
door_wood_b.png
|
||||
door_wood_b_r.png
|
||||
|
||||
following Textures created by BlockMen (WTFPL):
|
||||
door_trapdoor.png
|
||||
|
||||
following textures created by sofar (CC-BY-SA-3.0)
|
||||
doors_trapdoor_steel.png
|
||||
doors_trapdoor_steel_side.png
|
||||
door_trapdoor_side.png
|
||||
|
||||
All other door textures (created by PilzAdam): WTFPL
|
||||
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||
THE SOFTWARE.
|
||||
|
|
|
@ -0,0 +1,44 @@
|
|||
# German Translation for protector mod
|
||||
# Deutsche Übersetzung der protector Mod
|
||||
# last update: 2016/June/5
|
||||
# Author: Xanthin
|
||||
|
||||
#admin.lua
|
||||
Remove Protectors near players with names provided (separate names with spaces) = Entferne Stoerschuetzer von bestimmten Namen in der Naehe von Spielern (trenne Namen durch Leerzeichen)
|
||||
Protector Names to remove: @1 = Stoerschutznamen zum Entfernen: @1
|
||||
Name List Reset = Namensliste zurueckgesetzt
|
||||
|
||||
#doors_chest.lua
|
||||
Protected Wooden Door = Geschützte Holztür
|
||||
Protected Steel Door = Geschützte Stahltür
|
||||
Protected Trapdoor = Geschützte Falltür
|
||||
Protected Steel Trapdoor = Geschützte Stahlfalltür
|
||||
Protected Chest = Geschützte Truhe
|
||||
@1 moves stuff to protected chest at @2 = @1 verlagert Dinge in geschützte Truhe bei @2
|
||||
@1 takes stuff from protected chest at @2 = @1 nimmt Dinge aus geschützter Truhe bei @2
|
||||
To Chest = Zur Truhe
|
||||
To Inventory = Zum Inventar
|
||||
Protected Chest (@1) = Geschützte Truhe (@1)
|
||||
|
||||
#init.lua
|
||||
-- Protector interface -- = -- Störschutz-Interface --
|
||||
PUNCH node to show protected area = SCHLAGE Node, um geschützten Bereich anzuzeigen oder
|
||||
USE for area check = BENUTZE für Bereichsprüfung
|
||||
Members: = Mitglieder:
|
||||
Close = Schließen
|
||||
This area is owned by @1! = Dieses Gebiet gehoert @1!
|
||||
This area is owned by @1. = Dieses Gebiet gehoert @1.
|
||||
Protection located at: @1 = Stoerschutz befindet sich bei: @1
|
||||
Members: @1. = Mitglieder: @1.
|
||||
This area is not protected. = Dieses Gebiet ist nicht geschuetzt.
|
||||
You can build here. = Du kannst hier bauen.
|
||||
Overlaps into above players protected area = Ueberlappt in geschuetzen Bereich eines Spielers
|
||||
Protection Block = Störschutzblock
|
||||
Protection (owned by @1) = Störschutz (gehört @1)
|
||||
Protection Logo = Störschutzlogo
|
||||
[MOD] Protector Redo loaded = [MOD] Protector Redo geladen
|
||||
|
||||
#pvp.lua
|
||||
[Protector] on_punchplayer called with nil objects = on_punchplayer wurde durch "nil objects" aufgerufen
|
||||
[Protector] pvp_protect not active, update your version of Minetest = pvp_protect ist nicht aktiv, aktualisiere deine Minetestversion
|
||||
[Protector] pvp_protect is disabled = pvp_protect ist ausgeschaltet
|
|
@ -0,0 +1,42 @@
|
|||
# Template for translations of protector mod
|
||||
# last update: 2016/June/5
|
||||
|
||||
#admin.lua
|
||||
Remove Protectors near players with names provided (separate names with spaces) =
|
||||
Protector Names to remove: @1 =
|
||||
Name List Reset =
|
||||
|
||||
#doors_chest.lua
|
||||
Protected Wooden Door =
|
||||
Protected Steel Door =
|
||||
Protected Trapdoor =
|
||||
Protected Steel Trapdoor =
|
||||
Protected Chest =
|
||||
@1 moves stuff to protected chest at @2 =
|
||||
@1 takes stuff from protected chest at @2 =
|
||||
To Chest =
|
||||
To Inventory =
|
||||
Protected Chest (@1) =
|
||||
|
||||
#init.lua
|
||||
-- Protector interface -- =
|
||||
PUNCH node to show protected area =
|
||||
USE for area check =
|
||||
Members: =
|
||||
Close =
|
||||
This area is owned by @1! =
|
||||
This area is owned by @1. =
|
||||
Protection located at: @1 =
|
||||
Members: @1. =
|
||||
This area is not protected. =
|
||||
You can build here. =
|
||||
Overlaps into above players protected area =
|
||||
Protection Block =
|
||||
Protection (owned by @1) =
|
||||
Protection Logo =
|
||||
[MOD] Protector Redo loaded =
|
||||
|
||||
#pvp.lua
|
||||
[Protector] on_punchplayer called with nil objects =
|
||||
[Protector] pvp_protect not active, update your version of Minetest =
|
||||
[Protector] pvp_protect is disabled =
|
|
@ -0,0 +1,42 @@
|
|||
# Turkish translation by mahmutelmas06
|
||||
# last update: 2016/June/5
|
||||
|
||||
#admin.lua
|
||||
Remove Protectors near players with names provided (separate names with spaces) = Ismi verilen oyuncuların yanındaki korumaları kaldır. ( İsimleri boşlukla ayır)
|
||||
Protector Names to remove: @1 = Silinecek korumaların isimleri: @1
|
||||
Name List Reset = İsim listesini sıfırla
|
||||
|
||||
#doors_chest.lua
|
||||
Protected Wooden Door = Korumalı ahşap kapı
|
||||
Protected Steel Door = Korumalı çelik kapı
|
||||
Protected Trapdoor = Korumalı tuzak kapısı
|
||||
Protected Steel Trapdoor = Korumalı çelik tuzak kapısı
|
||||
Protected Chest = Korumalı sandık
|
||||
@1 moves stuff to protected chest at @2 = @1 korumalı sandığa birşeyler koydu @2
|
||||
@1 takes stuff from protected chest at @2 = @1 korumalı sandıktan birşeyler aldı @2
|
||||
To Chest = Sandığa
|
||||
To Inventory = Envantere
|
||||
Protected Chest (@1) = Korumalı sandık (@1)
|
||||
|
||||
#init.lua
|
||||
-- Protector interface -- =
|
||||
PUNCH node to show protected area = Korunan alanı göstermek için yumruk
|
||||
USE for area check = Bölge kontrolü için kullan
|
||||
Members: = Üyeler
|
||||
Close = Kapat
|
||||
This area is owned by @1! = Burasının sahibi @1!
|
||||
This area is owned by @1. = Burasının sahibi @1.
|
||||
Protection located at: @1 = Korumanın bulunduğu yer @1
|
||||
Members: @1. = Üyeler @1.
|
||||
This area is not protected. = Bu alan korumalı değildir.
|
||||
You can build here. = Buraya inşaa edebilirsiniz.
|
||||
Overlaps into above players protected area =
|
||||
Protection Block = Koruma kutusu
|
||||
Protection (owned by @1) = Koruma (@1 sahibidir)
|
||||
Protection Logo = Koruma arması
|
||||
[MOD] Protector Redo loaded = [MOD] Protector Redo yüklendi
|
||||
|
||||
#pvp.lua
|
||||
[Protector] on_punchplayer called with nil objects = [Protector] on_punchplayer boş objelerle çağrıldı
|
||||
[Protector] pvp_protect not active, update your version of Minetest = [Protector] pvp_protect aktif değil, Minetest sürümünüzü güncelleyin.
|
||||
[Protector] pvp_protect is disabled = [Protector] pvp_protect kapatıldı.
|
|
@ -0,0 +1,18 @@
|
|||
|
||||
-- add lucky blocks
|
||||
|
||||
if minetest.get_modpath("lucky_block") then
|
||||
|
||||
lucky_block:add_blocks({
|
||||
{"dro", {"protector:protect"}, 3},
|
||||
{"dro", {"protector:protect2"}, 3},
|
||||
{"dro", {"protector:door_wood"}, 1},
|
||||
{"dro", {"protector:door_steel"}, 1},
|
||||
{"exp", 5, true},
|
||||
{"dro", {"protector:trapdoor"}, 1},
|
||||
{"dro", {"protector:trapdoor_steel"}, 1},
|
||||
{"dro", {"protector:tool"}, 1},
|
||||
{"dro", {"protector:chest"}, 1},
|
||||
{"exp"},
|
||||
})
|
||||
end
|
|
@ -0,0 +1 @@
|
|||
name = protector
|
|
@ -1,22 +1,27 @@
|
|||
|
||||
local S = protector.intllib
|
||||
|
||||
-- get static spawn position
|
||||
local statspawn = (minetest.setting_get_pos("static_spawnpoint") or {x = 0, y = 2, z = 0})
|
||||
local statspawn = minetest.string_to_pos(minetest.settings:get("static_spawnpoint"))
|
||||
or {x = 0, y = 2, z = 0}
|
||||
|
||||
-- is pvp protection enabled and spawn protected
|
||||
protector.pvp = minetest.setting_getbool("protector_pvp")
|
||||
protector.spawn = (tonumber(minetest.setting_get("protector_pvp_spawn")) or 0)
|
||||
-- is pvp protection enabled
|
||||
protector.pvp = minetest.settings:get_bool("protector_pvp")
|
||||
|
||||
-- Disable PVP in your own protected areas
|
||||
if minetest.setting_getbool("enable_pvp") and protector.pvp then
|
||||
-- is night-only pvp enabled
|
||||
protector.night_pvp = minetest.settings:get_bool("protector_night_pvp")
|
||||
|
||||
-- disables PVP in your own protected areas
|
||||
if minetest.settings:get_bool("enable_pvp") and protector.pvp then
|
||||
|
||||
if minetest.register_on_punchplayer then
|
||||
|
||||
minetest.register_on_punchplayer(
|
||||
function(player, hitter, time_from_last_punch, tool_capabilities, dir, damage)
|
||||
minetest.register_on_punchplayer(function(player, hitter,
|
||||
time_from_last_punch, tool_capabilities, dir, damage)
|
||||
|
||||
if not player
|
||||
or not hitter then
|
||||
print("[Protector] on_punchplayer called with nil objects")
|
||||
print(S("[Protector] on_punchplayer called with nil objects"))
|
||||
end
|
||||
|
||||
if not hitter:is_player() then
|
||||
|
@ -24,7 +29,7 @@ if minetest.setting_getbool("enable_pvp") and protector.pvp then
|
|||
end
|
||||
|
||||
-- no pvp at spawn area
|
||||
local pos = player:getpos()
|
||||
local pos = player:get_pos()
|
||||
|
||||
if pos.x < statspawn.x + protector.spawn
|
||||
and pos.x > statspawn.x - protector.spawn
|
||||
|
@ -35,17 +40,31 @@ if minetest.setting_getbool("enable_pvp") and protector.pvp then
|
|||
return true
|
||||
end
|
||||
|
||||
if minetest.is_protected(pos, hitter:get_player_name()) then
|
||||
return true
|
||||
-- do we enable pvp at night time only ?
|
||||
if protector.night_pvp then
|
||||
|
||||
-- get time of day
|
||||
local tod = minetest.get_timeofday() or 0
|
||||
|
||||
if tod > 0.2 and tod < 0.8 then
|
||||
--
|
||||
else
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
-- is player being punched inside a protected area ?
|
||||
if minetest.is_protected(pos, hitter:get_player_name()) then
|
||||
return true
|
||||
end
|
||||
|
||||
return false
|
||||
|
||||
end)
|
||||
else
|
||||
print("[Protector] pvp_protect not active, update your version of Minetest")
|
||||
print(S("[Protector] pvp_protect not active, update your version of Minetest"))
|
||||
|
||||
end
|
||||
else
|
||||
print("[Protector] pvp_protect is disabled")
|
||||
print(S("[Protector] pvp_protect is disabled"))
|
||||
end
|
||||
|
|
After Width: | Height: | Size: 12 KiB |
After Width: | Height: | Size: 421 B |
After Width: | Height: | Size: 375 B |
After Width: | Height: | Size: 418 B |
Before Width: | Height: | Size: 672 B |
Before Width: | Height: | Size: 862 B |
|
@ -0,0 +1,15 @@
|
|||
|
||||
following Textures created by Fernando Zapata (CC BY-SA 3.0):
|
||||
door_wood.png
|
||||
door_wood_a.png
|
||||
door_wood_a_r.png
|
||||
door_wood_b.png
|
||||
door_wood_b_r.png
|
||||
|
||||
following Textures created by BlockMen (WTFPL):
|
||||
door_trapdoor.png
|
||||
|
||||
following textures created by sofar (CC-BY-SA-3.0)
|
||||
doors_trapdoor_steel.png
|
||||
doors_trapdoor_steel_side.png
|
||||
door_trapdoor_side.png
|
Before Width: | Height: | Size: 1.6 KiB |
|
@ -0,0 +1,124 @@
|
|||
|
||||
-- protector placement tool (thanks to Shara for code and idea)
|
||||
|
||||
minetest.register_craftitem("protector:tool", {
|
||||
description = "Protector Placer Tool (stand near protector, face direction and use)",
|
||||
inventory_image = "protector_display.png^protector_logo.png",
|
||||
stack_max = 1,
|
||||
|
||||
on_use = function(itemstack, user, pointed_thing)
|
||||
|
||||
local name = user:get_player_name()
|
||||
|
||||
-- check for protector near player (2 block radius)
|
||||
local pos = user:get_pos()
|
||||
local pp = minetest.find_nodes_in_area(
|
||||
vector.subtract(pos, 2), vector.add(pos, 2),
|
||||
{"protector:protect", "protector:protect2"})
|
||||
|
||||
if #pp == 0 then return end -- none found
|
||||
|
||||
pos = pp[1] -- take position of first protector found
|
||||
|
||||
-- get members on protector
|
||||
local meta = minetest.get_meta(pos)
|
||||
local members = meta:get_string("members") or ""
|
||||
|
||||
-- get direction player is facing
|
||||
local dir = minetest.dir_to_facedir( user:get_look_dir() )
|
||||
local vec = {x = 0, y = 0, z = 0}
|
||||
local gap = (protector.radius * 2) + 1
|
||||
local pit = user:get_look_pitch()
|
||||
|
||||
-- set placement coords
|
||||
if pit > 1.2 then
|
||||
vec.y = gap -- up
|
||||
elseif pit < -1.2 then
|
||||
vec.y = -gap -- down
|
||||
elseif dir == 0 then
|
||||
vec.z = gap -- north
|
||||
elseif dir == 1 then
|
||||
vec.x = gap -- east
|
||||
elseif dir == 2 then
|
||||
vec.z = -gap -- south
|
||||
elseif dir == 3 then
|
||||
vec.x = -gap -- west
|
||||
end
|
||||
|
||||
-- new position
|
||||
pos.x = pos.x + vec.x
|
||||
pos.y = pos.y + vec.y
|
||||
pos.z = pos.z + vec.z
|
||||
|
||||
-- does placing a protector overlap existing area
|
||||
if not protector.can_dig(protector.radius * 2, pos,
|
||||
user:get_player_name(), true, 3) then
|
||||
|
||||
minetest.chat_send_player(name,
|
||||
"Overlaps into above players protected area")
|
||||
|
||||
return
|
||||
end
|
||||
|
||||
-- does a protector already exist ?
|
||||
if #minetest.find_nodes_in_area(
|
||||
vector.subtract(pos, 1), vector.add(pos, 1),
|
||||
{"protector:protect", "protector:protect2"}) > 0 then
|
||||
|
||||
minetest.chat_send_player(name, "Protector already in place!")
|
||||
return
|
||||
end
|
||||
|
||||
-- do we have protectors to use ?
|
||||
local nod
|
||||
local inv = user:get_inventory()
|
||||
|
||||
if not inv:contains_item("main", "protector:protect")
|
||||
and not inv:contains_item("main", "protector:protect2") then
|
||||
minetest.chat_send_player(name, "No protectors available to place!")
|
||||
return
|
||||
end
|
||||
|
||||
-- take protector (block first then logo)
|
||||
if inv:contains_item("main", "protector:protect") then
|
||||
|
||||
inv:remove_item("main", "protector:protect")
|
||||
nod = "protector:protect"
|
||||
|
||||
elseif inv:contains_item("main", "protector:protect2") then
|
||||
|
||||
inv:remove_item("main", "protector:protect2")
|
||||
nod = "protector:protect2"
|
||||
end
|
||||
|
||||
-- place protector
|
||||
minetest.set_node(pos, {name = nod, param2 = 1})
|
||||
|
||||
-- set protector metadata
|
||||
local meta = minetest.get_meta(pos)
|
||||
|
||||
meta:set_string("owner", name)
|
||||
meta:set_string("infotext", "Protection (owned by " .. name .. ")")
|
||||
|
||||
-- copy members across if holding sneak when using tool
|
||||
if user:get_player_control().sneak then
|
||||
meta:set_string("members", members)
|
||||
else
|
||||
meta:set_string("members", "")
|
||||
end
|
||||
|
||||
minetest.chat_send_player(name,
|
||||
"Protector placed at " .. minetest.pos_to_string(pos))
|
||||
|
||||
end,
|
||||
})
|
||||
|
||||
-- tool recipe
|
||||
minetest.register_craft({
|
||||
output = "protector:tool",
|
||||
recipe = {
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "protector:protect", "default:steel_ingot"},
|
||||
{"default:steel_ingot", "default:steel_ingot", "default:steel_ingot"},
|
||||
}
|
||||
})
|