733 lines
25 KiB
Lua
733 lines
25 KiB
Lua
pocket_dimensions = {}
|
|
local S = minetest.get_translator(minetest.get_current_modname())
|
|
local MP = minetest.get_modpath(minetest.get_current_modname())
|
|
dofile(MP.."/voxelarea_iterator.lua")
|
|
dofile(MP.."/api.lua")
|
|
|
|
-- API
|
|
local get_pocket = pocket_dimensions.get_pocket
|
|
local get_all_pockets = pocket_dimensions.get_all_pockets
|
|
local get_deleted_pockets = pocket_dimensions.get_deleted_pockets
|
|
local rename_pocket = pocket_dimensions.rename_pocket
|
|
local register_pocket_type = pocket_dimensions.register_pocket_type
|
|
local create_pocket = pocket_dimensions.create_pocket
|
|
local delete_pocket = pocket_dimensions.delete_pocket
|
|
local undelete_pocket = pocket_dimensions.undelete_pocket
|
|
local set_protection = pocket_dimensions.set_protection
|
|
local pocket_containing_pos = pocket_dimensions.pocket_containing_pos
|
|
local set_destination = pocket_dimensions.set_destination
|
|
local get_personal_pocket = pocket_dimensions.get_personal_pocket
|
|
local set_personal_pocket = pocket_dimensions.set_personal_pocket
|
|
local set_owner = pocket_dimensions.set_owner
|
|
local teleport_player_to_pocket = pocket_dimensions.teleport_player_to_pocket
|
|
local return_player_to_origin = pocket_dimensions.return_player_to_origin
|
|
|
|
local pocket_size = pocket_dimensions.pocket_size
|
|
|
|
local personal_pockets_chat_command = minetest.settings:get_bool("pocket_dimensions_personal_pockets_chat_command", false)
|
|
local personal_pockets_key = minetest.settings:get_bool("pocket_dimensions_personal_pockets_key", false)
|
|
local personal_pockets_key_uses = tonumber(minetest.settings:get("pocket_dimensions_personal_pockets_key_uses")) or 0
|
|
local personal_pockets_spawn = minetest.settings:get_bool("pocket_dimensions_personal_pockets_spawn", false)
|
|
local personal_pockets_respawn = minetest.settings:get_bool("pocket_dimensions_personal_pockets_respawn", false) and not minetest.settings:get_bool("engine_spawn")
|
|
|
|
local personal_pockets_enabled = personal_pockets_chat_command or personal_pockets_key or personal_pockets_spawn or personal_pockets_respawn
|
|
|
|
local c_air = minetest.get_content_id("air")
|
|
|
|
local c_dirt
|
|
local c_dirt_with_grass
|
|
local c_stone
|
|
local c_water
|
|
local c_sand
|
|
|
|
local default_modpath = minetest.get_modpath("default")
|
|
if default_modpath then
|
|
c_dirt = minetest.get_content_id("default:dirt")
|
|
c_dirt_with_grass = minetest.get_content_id("default:dirt_with_grass")
|
|
c_stone = minetest.get_content_id("default:stone")
|
|
c_water = minetest.get_content_id("default:water_source")
|
|
c_sand = minetest.get_content_id("default:sand")
|
|
end
|
|
local mcl_core_modpath = minetest.get_modpath("mcl_core")
|
|
if mcl_core_modpath then
|
|
c_dirt = minetest.get_content_id("mcl_core:dirt")
|
|
c_dirt_with_grass = minetest.get_content_id("mcl_core:dirt_with_grass")
|
|
c_stone = minetest.get_content_id("mcl_core:stone")
|
|
c_water = minetest.get_content_id("mcl_core:water_source")
|
|
c_sand = minetest.get_content_id("mcl_core:sand")
|
|
end
|
|
|
|
|
|
-----------------------------------------------------------------
|
|
-- Border materials
|
|
|
|
local get_border_def = function(override)
|
|
local def = {
|
|
description = S("Boundary of a pocket dimension"),
|
|
groups = {not_in_creative_inventory = 1},
|
|
drawtype = "normal", -- See "Node drawtypes"
|
|
paramtype = "light", -- See "Nodes"
|
|
paramtype2 = "none", -- See "Nodes"
|
|
is_ground_content = false, -- If false, the cave generator and dungeon generator will not carve through this node.
|
|
walkable = true, -- If true, objects collide with node
|
|
pointable = true, -- If true, can be pointed at
|
|
diggable = false, -- If false, can never be dug
|
|
node_box = {type="regular"}, -- See "Node boxes"
|
|
sounds = {
|
|
footstep = {name = "pocket_dimensions_footstep", gain = 0.25},
|
|
},
|
|
can_dig = function(pos, player) return false end,
|
|
on_blast = function(pos, intensity) return false end,
|
|
on_punch = function(pos, node, clicker, pointed_thing)
|
|
if vector.distance(pos, clicker:get_pos()) > 2 then
|
|
return
|
|
end
|
|
return_player_to_origin(clicker:get_player_name())
|
|
end,
|
|
on_construct = function(pos)
|
|
-- if somehow a player gets ahold of one of these, ensure they can't place it anywhere.
|
|
minetest.set_node(pos, {name="air"})
|
|
end,
|
|
after_destruct = function(pos, oldnode)
|
|
-- likewise, don't let players remove these if they manage it somehow
|
|
minetest.set_node(pos, oldnode)
|
|
end,
|
|
}
|
|
for key, value in pairs(override) do
|
|
def[key] = value
|
|
end
|
|
return def
|
|
end
|
|
|
|
minetest.register_node("pocket_dimensions:border_glass", get_border_def({
|
|
light_source = 4,
|
|
sunlight_propagates = true, -- If true, sunlight will go infinitely through this node
|
|
use_texture_alpha = true,
|
|
tiles = {{name="pocket_dimensions_transparent.png",
|
|
tileable_vertical=true,
|
|
tileable_horizontal=true,
|
|
align_style="world",
|
|
scale=2,
|
|
}},
|
|
}))
|
|
|
|
local c_border_glass = minetest.get_content_id("pocket_dimensions:border_glass")
|
|
|
|
minetest.register_node("pocket_dimensions:border_gray", get_border_def({
|
|
tiles = {{name="pocket_dimensions_white.png", color="#888888"}}
|
|
}))
|
|
|
|
local c_border_gray = minetest.get_content_id("pocket_dimensions:border_gray")
|
|
|
|
---------------------------------------------------------------
|
|
-- Pocket mapgens
|
|
|
|
local scale_magnitude = 5
|
|
|
|
local perlin_params = {
|
|
offset = 0,
|
|
scale = scale_magnitude,
|
|
spread = {x = pocket_size, y = pocket_size, z = pocket_size},
|
|
seed = 577,
|
|
octaves = 5,
|
|
persist = 0.63,
|
|
lacunarity = 2.0,
|
|
}
|
|
|
|
local perlin_noise = PerlinNoise(perlin_params)
|
|
|
|
-- TODO don't know why minetest.get_perlin_map isn't working here, but don't really care
|
|
-- pocket dimensions are distributed randomly so doesn't really matter whether their terrain
|
|
-- is world-seeded. Nobody will ever notice.
|
|
local terrain_map = PerlinNoiseMap(
|
|
perlin_params,
|
|
{x=pocket_size, y=pocket_size, z=pocket_size}
|
|
)
|
|
|
|
-- Once the map block for the new pocket dimension is loaded, this initializes its node layout and finds a default spot for arrivals to teleport to
|
|
local grassy_mapgen = function(pocket_data)
|
|
local minp = pocket_data.minp
|
|
local maxp = vector.add(minp, pocket_size)
|
|
local vm = minetest.get_voxel_manip(minp, maxp)
|
|
local emin, emax = vm:get_emerged_area()
|
|
local data = vm:get_data()
|
|
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
|
local surface = minp.y + 40
|
|
local terrain_values = terrain_map:get_2d_map(minp)
|
|
|
|
-- Default is down on the floor of the border walls, in case default mod isn't installed and no landscape is created
|
|
local middlep = {x=minp.x + math.floor(pocket_size/2), y=2, z=minp.z + math.floor(pocket_size/2)}
|
|
|
|
local tree_spots = {}
|
|
for vi, x, y, z in area:iterp_xyz(minp, maxp) do
|
|
if x == minp.x or x == maxp.x or y == minp.y or y == maxp.y or z == minp.z or z == maxp.z then
|
|
data[vi] = c_border_glass
|
|
elseif default_modpath or mcl_core_modpath then
|
|
local terrain_level = math.floor(terrain_values[x-minp.x+1][z-minp.z+1] + surface)
|
|
local below_water = y < surface
|
|
if y == terrain_level then
|
|
if below_water then
|
|
data[vi] = c_sand
|
|
else
|
|
data[vi] = c_dirt_with_grass
|
|
if math.random() < 0.01 and x > minp.x + 3 and x < maxp.x - 3 and z > minp.z + 3 and z < maxp.z - 3 then
|
|
table.insert(tree_spots, {x=x,y=y+1,z=z})
|
|
end
|
|
end
|
|
if middlep.x == x and middlep.z == z then
|
|
middlep.y = math.max(y + 1, minp.y + pocket_size/2) -- surface of the ground or water in the center of the block
|
|
end
|
|
elseif y == terrain_level - 1 then
|
|
if below_water then
|
|
data[vi] = c_sand
|
|
else
|
|
data[vi] = c_dirt
|
|
end
|
|
elseif y <= terrain_level - 2 then
|
|
data[vi] = c_stone
|
|
elseif below_water then
|
|
data[vi] = c_water
|
|
else
|
|
data[vi] = c_air
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
|
|
for _, pos in pairs(tree_spots) do
|
|
if default_modpath then
|
|
default.grow_tree(pos, math.random() < 0.5)
|
|
elseif mcl_core_modpath then
|
|
mcl_core.generate_tree(pos, 1)
|
|
end
|
|
end
|
|
|
|
return middlep
|
|
end
|
|
|
|
register_pocket_type("grassy", grassy_mapgen)
|
|
|
|
local cave_mapgen = function(pocket_data)
|
|
local minp = pocket_data.minp
|
|
local maxp = vector.add(minp, pocket_size)
|
|
local vm = minetest.get_voxel_manip(minp, maxp)
|
|
local emin, emax = vm:get_emerged_area()
|
|
local data = vm:get_data()
|
|
local area = VoxelArea:new{MinEdge = emin, MaxEdge = emax}
|
|
local terrain_values = terrain_map:get_3d_map(minp)
|
|
|
|
local nearest_to_center = vector.add(minp, 2) -- start off down in the corner
|
|
local center = vector.add(minp, math.floor(pocket_size/2))
|
|
for vi, x, y, z in area:iterp_xyz(minp, maxp) do
|
|
if x == minp.x or x == maxp.x or y == minp.y or y == maxp.y or z == minp.z or z == maxp.z then
|
|
data[vi] = c_border_gray
|
|
elseif default_modpath or mcl_core_modpath then
|
|
local terrain_level = terrain_values[x-minp.x+1][y-minp.y+1][z-minp.z+1]
|
|
if terrain_level <= 2 then
|
|
data[vi] = c_stone
|
|
else
|
|
data[vi] = c_air
|
|
if vector.distance({x=x,y=y,z=z}, center) < vector.distance(nearest_to_center, center) then
|
|
nearest_to_center = {x=x,y=y,z=z}
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
vm:set_data(data)
|
|
vm:write_to_map()
|
|
|
|
-- drop the entry point downward until it hits non-air.
|
|
while minetest.get_node(nearest_to_center).name == "air" and nearest_to_center.y > minp.y do
|
|
nearest_to_center.y = nearest_to_center.y -1
|
|
end
|
|
nearest_to_center.y = nearest_to_center.y + 2
|
|
|
|
return nearest_to_center
|
|
end
|
|
|
|
register_pocket_type("cave", cave_mapgen)
|
|
|
|
|
|
-------------------------------------------------------------------------------
|
|
|
|
local portal_formspec_state = {}
|
|
|
|
local get_select_formspec = function(player_name)
|
|
local formspec = {
|
|
"formspec_version[2]"
|
|
.."size[8,2]"
|
|
.."button_exit[7.0,0.25;0.5,0.5;close;X]"
|
|
.."label[0.5,0.6;"..S("Link to pocket dimension:").."]dropdown[1,1;4,0.5;pocket_select;"
|
|
}
|
|
local names = {}
|
|
for _, def in pairs(get_all_pockets()) do
|
|
table.insert(names, minetest.formspec_escape(def.name))
|
|
end
|
|
table.sort(names)
|
|
portal_formspec_state[player_name].names = names
|
|
formspec[#formspec+1] = table.concat(names, ",") .. ";]"
|
|
return table.concat(formspec)
|
|
end
|
|
|
|
minetest.register_node("pocket_dimensions:portal", {
|
|
description = S("Pocket Dimension Access"),
|
|
groups = {oddly_breakable_by_hand = 1},
|
|
tiles = {"pocket_dimensions_portal.png"},
|
|
is_ground_content=false,
|
|
drawtype = "nodebox",
|
|
paramtype = "light",
|
|
paramtype2 = "facedir",
|
|
node_box = {
|
|
type = "fixed",
|
|
fixed = {
|
|
{-0.5, -0.375, -0.5, 0.5, -0.25, 0.5},
|
|
{-0.5, 0.25, -0.5, 0.5, 0.375, 0.5},
|
|
{-0.3125, 0.125, -0.3125, 0.3125, 0.5, 0.3125},
|
|
{-0.3125, -0.5, -0.3125, 0.3125, -0.125, 0.3125},
|
|
{-0.125, -0.125, -0.125, 0.125, -0.0625, 0.125},
|
|
{-0.125, 0.0625, -0.125, 0.125, 0.125, 0.125},
|
|
{-0.0625, -0.0625, -0.0625, 0.0625, 0.0625, 0.0625},
|
|
}
|
|
},
|
|
|
|
on_rightclick = function(pos, node, clicker, itemstack, pointed_thing)
|
|
local player_name = clicker:get_player_name()
|
|
local meta = minetest.get_meta(pos)
|
|
local pocket_dest = minetest.string_to_pos(meta:get_string("pocket_dest"))
|
|
if pocket_dest then
|
|
local pocket_data = pocket_containing_pos(pocket_dest)
|
|
if pocket_data then
|
|
teleport_player_to_pocket(player_name, pocket_data.name)
|
|
return
|
|
end
|
|
end
|
|
portal_formspec_state[player_name] = {pos = pos}
|
|
minetest.show_formspec(player_name, "pocket_dimensions:portal_select", get_select_formspec(player_name))
|
|
end,
|
|
})
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname ~= "pocket_dimensions:portal_select" then
|
|
return
|
|
end
|
|
|
|
if fields.close then
|
|
return
|
|
end
|
|
|
|
local player_name = player:get_player_name()
|
|
local state = portal_formspec_state[player_name]
|
|
if state == nil then
|
|
return
|
|
end
|
|
|
|
if fields.pocket_select then
|
|
for _, name in pairs(state.names) do
|
|
if fields.pocket_select == name then
|
|
local pocket_data = get_pocket(name) -- TODO: minetest.formspec_escape may screw up this lookup, do something different
|
|
if pocket_data then
|
|
local meta = minetest.get_meta(state.pos)
|
|
meta:set_string("pocket_dest", minetest.pos_to_string(pocket_data.minp))
|
|
meta:set_string("infotext", S("Portal to @1", name))
|
|
end
|
|
minetest.close_formspec(player_name, "pocket_dimensions:portal_select")
|
|
return
|
|
end
|
|
end
|
|
end
|
|
end)
|
|
|
|
-------------------------------------------------------------------------------
|
|
-- Admin commands
|
|
|
|
local formspec_state = {}
|
|
local get_admin_formspec = function(player_name)
|
|
formspec_state[player_name] = formspec_state[player_name] or {row_index=1}
|
|
local state = formspec_state[player_name]
|
|
|
|
local formspec = {
|
|
"formspec_version[2]"
|
|
.."size[8,10]"
|
|
.."button_exit[7.0,0.25;0.5,0.5;close;X]"
|
|
}
|
|
|
|
formspec[#formspec+1] = "tablecolumns[text,tooltip="..S("Name")
|
|
..";text,tooltip="..S("Owner")
|
|
..";text,tooltip="..S("Protected")
|
|
if personal_pockets_enabled then
|
|
formspec[#formspec+1] = ";text,tooltip="..S("Personal")
|
|
end
|
|
formspec[#formspec+1] = "]table[0.5,1.0;7,5.75;pocket_table;"
|
|
|
|
local table_to_use
|
|
local delete_label
|
|
local undelete_toggle
|
|
if state.undelete == "true" then
|
|
table_to_use = get_deleted_pockets()
|
|
delete_label = S("Undelete")
|
|
undelete_toggle = "true"
|
|
else
|
|
table_to_use = get_all_pockets()
|
|
delete_label = S("Delete")
|
|
undelete_toggle = "false"
|
|
end
|
|
|
|
local i = 0
|
|
for _, pocket_data in pairs(table_to_use) do
|
|
i = i + 1
|
|
if i == state.row_index then
|
|
state.selected_data = pocket_data
|
|
end
|
|
local owner = pocket_data.owner or "<none>"
|
|
formspec[#formspec+1] = minetest.formspec_escape(pocket_data.name)
|
|
..",".. minetest.formspec_escape(owner)
|
|
..","..tostring(pocket_data.protected or "false")
|
|
if personal_pockets_enabled then
|
|
formspec[#formspec+1] = ","..tostring(pocket_data.personal)
|
|
end
|
|
formspec[#formspec+1] = ","
|
|
end
|
|
formspec[#formspec] = ";"..state.row_index.."]" -- don't use +1, this overwrites the last ","
|
|
|
|
local selected_data = state.selected_data or {}
|
|
|
|
formspec[#formspec+1] = "container[0.5,7]"
|
|
.."field[0.0,0.0;6.5,0.5;pocket_name;;" .. minetest.formspec_escape(selected_data.name or "") .."]"
|
|
.."button[0,0.5;3,0.5;rename;"..S("Rename").."]"
|
|
.."button[3.5,0.5;2,0.5;create;"..S("Create").."]"
|
|
.."dropdown[5.5,0.5;1,0.5;create_type;grassy,cave;1]"
|
|
.."button[0,1;3,0.5;teleport;"..S("Teleport To").."]"
|
|
.."button[3.5,1;3,0.5;protect;"..S("Toggle Protect").."]"
|
|
.."button[0,1.5;3,0.5;delete;"..delete_label.."]"
|
|
.."field[0.0,2;3,0.5;owner;;".. minetest.formspec_escape(selected_data.owner or "").."]"
|
|
.."button[3.5,2;3,0.5;set_owner;"..S("Set Owner").."]"
|
|
.."checkbox[0,2.75;undelete_toggle;"..S("Show deleted")..";"..undelete_toggle.."]"
|
|
.."container_end[]"
|
|
return table.concat(formspec)
|
|
end
|
|
|
|
minetest.register_chatcommand("pocket_admin", {
|
|
params = "",
|
|
privs = {server=true},
|
|
description = S("Administrate pocket dimensions"),
|
|
func = function(player_name, param)
|
|
minetest.show_formspec(player_name, "pocket_dimensions:admin", get_admin_formspec(player_name))
|
|
end
|
|
})
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
if formname ~= "pocket_dimensions:admin" then
|
|
return
|
|
end
|
|
|
|
if fields.close then
|
|
return
|
|
end
|
|
|
|
local player_name = player:get_player_name()
|
|
if not minetest.check_player_privs(player_name, {server = true}) then
|
|
minetest.chat_send_player(player_name, S("This command is for server admins only."))
|
|
return
|
|
end
|
|
|
|
local refresh = false
|
|
local state = formspec_state[player_name]
|
|
local pocket_data = state.selected_data
|
|
if state == nil then
|
|
return
|
|
end
|
|
|
|
if fields.pocket_table then
|
|
local table_event = minetest.explode_table_event(fields.pocket_table)
|
|
if table_event.type == "CHG" then
|
|
state.row_index = table_event.row
|
|
refresh = true
|
|
end
|
|
end
|
|
|
|
if fields.rename and fields.pocket_name ~= pocket_data.name then
|
|
if not rename_pocket(pocket_data.name, fields.pocket_name)then
|
|
minetest.chat_send_player(player_name, S("A pocket dimension with that name already exists"))
|
|
else
|
|
refresh=true
|
|
end
|
|
end
|
|
|
|
if fields.undelete_toggle then
|
|
state.undelete = fields.undelete_toggle
|
|
refresh = true
|
|
end
|
|
|
|
if fields.create then
|
|
local success, message = create_pocket(fields.pocket_name, {type=fields.create_type})
|
|
if success then
|
|
refresh = true
|
|
end
|
|
minetest.chat_send_player(player_name, message)
|
|
end
|
|
|
|
if fields.delete then
|
|
if state.undelete == "true" then
|
|
local success, message = undelete_pocket(pocket_data)
|
|
minetest.chat_send_player(player_name, message)
|
|
else
|
|
local success, message = delete_pocket(pocket_data)
|
|
minetest.chat_send_player(player_name, message)
|
|
end
|
|
state.row_index = 1
|
|
refresh = true
|
|
end
|
|
|
|
if fields.protect then
|
|
set_protection(pocket_data, not pocket_data.protected)
|
|
refresh = true
|
|
end
|
|
|
|
if fields.teleport and pocket_data then
|
|
teleport_player_to_pocket(player_name, state.selected_data.name)
|
|
end
|
|
|
|
if fields.set_owner and pocket_data.owner ~= fields.owner then
|
|
if fields.owner == "" then
|
|
set_owner(pocket_data, nil)
|
|
else
|
|
set_owner(pocket_data, fields.owner)
|
|
end
|
|
refresh = true
|
|
end
|
|
|
|
if refresh then
|
|
minetest.show_formspec(player_name, "pocket_dimensions:admin", get_admin_formspec(player_name))
|
|
end
|
|
end)
|
|
|
|
--------------------------------------------------------------------------------------------------------
|
|
-- Personal pockets
|
|
|
|
if personal_pockets_enabled then
|
|
function teleport_to_pending(pocket_name, player_name, count)
|
|
local teleported = teleport_player_to_pocket(player_name, pocket_name)
|
|
if teleported then
|
|
return
|
|
end
|
|
if not teleported and count < 10 then
|
|
minetest.after(1, teleport_to_pending, pocket_name, player_name, count + 1)
|
|
return
|
|
end
|
|
minetest.chat_send_player(player_name, S("Teleport to personal pocket dimension @1 failed after @2 tries.", pocket_name, count))
|
|
end
|
|
|
|
local teleport_to_personal_pocket = function(player_name)
|
|
local pocket_data = get_personal_pocket(player_name)
|
|
if pocket_data then
|
|
teleport_player_to_pocket(player_name, pocket_data.name)
|
|
return
|
|
end
|
|
|
|
-- Find an unused default name
|
|
local new_pocket_name = player_name
|
|
if get_pocket(new_pocket_name) then
|
|
local count = 1
|
|
local new_pocket_name_prefix = new_pocket_name
|
|
new_pocket_name = new_pocket_name_prefix .. " " .. count
|
|
while get_pocket(new_pocket_name) do
|
|
count = count + 1
|
|
new_pocket_name = new_pocket_name_prefix .. " " .. count
|
|
end
|
|
end
|
|
|
|
local success, message = create_pocket(new_pocket_name, {type="grassy"})
|
|
if success then
|
|
pocket_data = get_pocket(new_pocket_name)
|
|
set_personal_pocket(pocket_data, player_name)
|
|
set_protection(pocket_data, true)
|
|
teleport_to_pending(new_pocket_name, player_name, 1)
|
|
end
|
|
minetest.chat_send_player(player_name, message)
|
|
end
|
|
|
|
if personal_pockets_chat_command then
|
|
minetest.register_chatcommand("pocket_personal", {
|
|
params = "",
|
|
-- privs = {}, -- TODO a new privilege here?
|
|
description = S("Teleport to your personal pocket dimension"),
|
|
func = function(player_name, param)
|
|
teleport_to_personal_pocket(player_name)
|
|
end,
|
|
})
|
|
end
|
|
|
|
if personal_pockets_key then
|
|
local trigger_stack_size = 99
|
|
local trigger_wear_amount = 0
|
|
local trigger_tool_capabilities = nil
|
|
local trigger_help_addendum = ""
|
|
|
|
if personal_pockets_key_uses > 0 then
|
|
trigger_stack_size = 1
|
|
trigger_wear_amount = math.ceil(65535 / personal_pockets_key_uses)
|
|
trigger_tool_capabilities = {
|
|
full_punch_interval=1.5,
|
|
max_drop_level=1,
|
|
groupcaps={},
|
|
damage_groups = {},
|
|
}
|
|
trigger_help_addendum = S(" This tool can be used @1 times before breaking.", personal_pockets_key_uses)
|
|
end
|
|
|
|
local trigger_def = {
|
|
description = S("Personal Pocket Dimensional Key"),
|
|
_doc_items_longdesc = S("A triggering device that allows teleportation to your personal pocket dimension."),
|
|
_doc_items_usagehelp = S("When triggered, this tool and its user will be teleported to the user's personal pocket dimension.") .. trigger_help_addendum,
|
|
inventory_image = "pocket_dimensions_key.png",
|
|
stack_max = trigger_stack_size,
|
|
tool_capabilites = trigger_tool_capabilities,
|
|
sound = {
|
|
breaks = "pocket_dimensions_key_break",
|
|
},
|
|
on_use = function(itemstack, user, pointed_thing)
|
|
local player_name = user:get_player_name()
|
|
teleport_to_personal_pocket(player_name)
|
|
if trigger_wear_amount > 0 and not minetest.is_creative_enabled(player_name) then
|
|
itemstack:add_wear(trigger_wear_amount)
|
|
end
|
|
return itemstack
|
|
end,
|
|
}
|
|
|
|
if trigger_tool_capabilities then
|
|
minetest.register_tool("pocket_dimensions:personal_key", trigger_def)
|
|
else
|
|
minetest.register_craftitem("pocket_dimensions:personal_key", trigger_def)
|
|
end
|
|
|
|
if default_modpath then
|
|
minetest.register_craft({
|
|
output = "pocket_dimensions:personal_key",
|
|
recipe = {
|
|
{"default:mese_crystal","default:skeleton_key"}
|
|
}})
|
|
end
|
|
end
|
|
|
|
if personal_pockets_spawn then
|
|
|
|
local return_methods = S("Make sure you take everything you want to before departing,\nthere is no conventional way to return here.")
|
|
local return_method_list = {}
|
|
if personal_pockets_respawn then
|
|
table.insert(return_method_list, S("Dying and respawning"))
|
|
end
|
|
if personal_pockets_key then
|
|
table.insert(return_method_list, S("Crafting and using a pocket dimension key"))
|
|
end
|
|
if personal_pockets_chat_command then
|
|
table.insert(return_method_list, S("Entering the \"/pocket_personal\" chat command"))
|
|
end
|
|
|
|
if #return_method_list > 0 then
|
|
return_methods = S("You can return to this pocket dimension by:")
|
|
.. "\n* " .. table.concat(return_method_list, "\n* ")
|
|
end
|
|
|
|
minetest.register_on_newplayer(function(player)
|
|
local player_name = player:get_player_name()
|
|
teleport_to_personal_pocket(player_name)
|
|
|
|
minetest.show_formspec(player_name, "pocket_dimensions:intro",
|
|
"formspec_version[2]"
|
|
.."size[8,3]"
|
|
.."button_exit[7.0,0.25;0.5,0.5;close;X]"
|
|
.."textarea[0.25,0.25;6.5,3;;;"
|
|
..S("You have spawned inside your own personal pocket dimension.\nTo leave, walk to within one meter of the pocket dimension's\nboundary and punch the barrier there.")
|
|
.."\n\n"
|
|
..return_methods
|
|
.."]")
|
|
|
|
return true
|
|
end)
|
|
end
|
|
|
|
if personal_pockets_respawn then
|
|
minetest.register_on_respawnplayer(function(player)
|
|
local player_name = player:get_player_name()
|
|
-- HACK: due to API limitations in the default game's "spawn" mod, this
|
|
-- code can't override its behaviour cleanly. See https://github.com/minetest/minetest_game/issues/2630
|
|
-- that's why this horrible minetest.after hack is here.
|
|
if default_modpath then
|
|
minetest.after(0, teleport_to_personal_pocket, player_name)
|
|
else
|
|
teleport_to_personal_pocket(player_name)
|
|
end
|
|
return true
|
|
end)
|
|
end
|
|
end
|
|
|
|
-------------------------------------------------------------------------------------------------------
|
|
-- Player commands
|
|
|
|
minetest.register_chatcommand("pocket_entry", {
|
|
params = "",
|
|
-- privs = {}, -- TODO a new privilege here?
|
|
description = S("Set the entry point of the pocket dimension you're in to where you're standing."),
|
|
func = function(player_name, param)
|
|
local pos = minetest.get_player_by_name(player_name):get_pos()
|
|
local pocket_data = pocket_containing_pos(pos)
|
|
if not pocket_data then
|
|
minetest.chat_send_player(player_name, S("You're not inside a pocket dimension right now."))
|
|
return
|
|
end
|
|
if player_name ~= pocket_data.owner and not minetest.check_player_privs(player_name, "server") then
|
|
minetest.chat_send_player(player_name, S("You don't have permission to change the entry point of pocket dimension @1.", pocket_data.name))
|
|
return
|
|
end
|
|
set_destination(pocket_data, pos)
|
|
minetest.chat_send_player(player_name, S("The entry point for pocket dimension @1 has been updated", pocket_data.name))
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand("pocket_rename", {
|
|
params = "pocketname",
|
|
-- privs = {}, -- TODO a new privilege here?
|
|
description = S("Renames the pocket dimension you're inside."),
|
|
func = function(player_name, param)
|
|
if param == nil or param == "" then
|
|
minetest.chat_send_player(player_name, S("Please provide a name as a parameter to this command."))
|
|
return
|
|
end
|
|
local pos = minetest.get_player_by_name(player_name):get_pos()
|
|
local pocket_data = pocket_containing_pos(pos)
|
|
if not pocket_data then
|
|
minetest.chat_send_player(player_name, S("You're not inside a pocket dimension right now."))
|
|
return
|
|
end
|
|
if player_name ~= pocket_data.owner and not minetest.check_player_privs(player_name, "server") then
|
|
minetest.chat_send_player(player_name, S("You don't have permission to change the name of pocket dimension @1.", pocket_data.name))
|
|
return
|
|
end
|
|
local oldname = pocket_data.name
|
|
if rename_pocket(oldname, param) then
|
|
minetest.chat_send_player(player_name, S("The name of pocket dimension @1 has been changed to \"@2\".", oldname, param))
|
|
else
|
|
minetest.chat_send_player(player_name, S("A pocket dimension with that name already exists"))
|
|
end
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand("pocket_name", {
|
|
params = "",
|
|
-- privs = {}, -- TODO a new privilege here?
|
|
description = S("Finds the name of the pocket dimension you're inside right now."),
|
|
func = function(player_name, param)
|
|
local pos = minetest.get_player_by_name(player_name):get_pos()
|
|
local pocket_data = pocket_containing_pos(pos)
|
|
if pocket_data then
|
|
minetest.chat_send_player(player_name, S("You're inside pocket dimension \"@1\"", pocket_data.name))
|
|
else
|
|
minetest.chat_send_player(player_name, S("You're not inside a pocket dimension right now."))
|
|
end
|
|
end,
|
|
}) |