forked from nalc/h2omes
Crabman77
63ac6dfa0f
Add hell home to support hell mod, and better support to nether/hell coordinates. Forbids teleportion between 2 worlds. add variable cooldown in minestest.conf
511 lines
17 KiB
Lua
511 lines
17 KiB
Lua
local S = minetest.get_translator(minetest.get_current_modname())
|
|
|
|
|
|
h2omes = {}
|
|
h2omes.homes = {} -- table players home
|
|
h2omes.path = minetest.get_worldpath() .. "/h2omes/"
|
|
minetest.mkdir(h2omes.path)
|
|
|
|
h2omes.time_home = tonumber(minetest.settings:get("h2omes.time_home")) or 2 * 60
|
|
h2omes.time_spawn = tonumber(minetest.settings:get("h2omes.time_spawn")) or 5 * 60
|
|
h2omes.time_from_player = tonumber(minetest.settings:get("h2omes.time_from_player")) or 5 * 60
|
|
h2omes.time_to_player = tonumber(minetest.settings:get("h2omes.time_to_player")) or 5 * 60
|
|
|
|
|
|
|
|
local tmp_players = {}
|
|
local from_players = {}
|
|
|
|
h2omes.have_hell = false -- hell mod
|
|
if (minetest.get_modpath("hell") ~= nil) then
|
|
h2omes.have_hell = true
|
|
h2omes.hell_ceiling = hell.DEPTH
|
|
h2omes.hell_floor = hell.DEPTH - 510
|
|
end
|
|
|
|
h2omes.have_nether = false -- nether mod
|
|
if (minetest.get_modpath("nether") ~= nil) then
|
|
h2omes.have_nether = true
|
|
h2omes.nether_ceiling = nether.DEPTH_CEILING
|
|
h2omes.nether_floor = nether.DEPTH_FLOOR
|
|
end
|
|
|
|
function h2omes.check(name)
|
|
if h2omes.homes[name] == nil then
|
|
h2omes.homes[name] = {["home"] = {}, ["pit"] = {}}
|
|
end
|
|
end
|
|
|
|
|
|
--function save_homes
|
|
function h2omes.save_homes(name)
|
|
local file = h2omes.path..name
|
|
local input, err = io.open(file, "w")
|
|
if input then
|
|
input:write(minetest.serialize(h2omes.homes[name]))
|
|
input:close()
|
|
else
|
|
minetest.log("error", "open(" .. file .. ", 'w') failed: " .. err)
|
|
end
|
|
end
|
|
|
|
|
|
--function load_homes
|
|
function h2omes.load_homes(name)
|
|
h2omes.check(name)
|
|
local file = h2omes.path..name
|
|
local input, err = io.open(file, "r")
|
|
if input then
|
|
local data = minetest.deserialize(input:read())
|
|
io.close(input)
|
|
if data and type(data) == "table" then
|
|
if data.home then
|
|
if data.home.real then
|
|
h2omes.homes[name].home.real = data.home.real
|
|
end
|
|
if data.home.nether then
|
|
h2omes.homes[name].home.nether = data.home.nether
|
|
end
|
|
if data.home.hell then
|
|
h2omes.homes[name].home.hell = data.home.hell
|
|
end
|
|
end
|
|
if data.pit then
|
|
if data.pit.real then
|
|
h2omes.homes[name].pit.real = data.pit.real
|
|
end
|
|
if data.pit.nether then
|
|
h2omes.homes[name].pit.nether = data.pit.nether
|
|
end
|
|
if data.pit.hell then
|
|
h2omes.homes[name].pit.hell = data.pit.hell
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
|
|
local function is_inside(pos, pos_min, pos_max)
|
|
if pos < pos_min and pos > pos_max then
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
-- disallowed tp real-->nether or nether-->real
|
|
function h2omes.can_teleport(from_pos, to_pos)
|
|
if not h2omes.have_nether and not h2omes.have_hell then -- not nether/hell mod
|
|
return true
|
|
end
|
|
|
|
if h2omes.have_nether then
|
|
if is_inside(from_pos.y, h2omes.nether_ceiling, h2omes.nether_floor) and not is_inside(to_pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
return false
|
|
elseif is_inside(to_pos.y, h2omes.nether_ceiling, h2omes.nether_floor) and not is_inside(from_pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
return false
|
|
end
|
|
end
|
|
|
|
if h2omes.have_hell then
|
|
if is_inside(from_pos.y, h2omes.hell_ceiling, h2omes.hell_floor) and not is_inside(to_pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
return false
|
|
elseif is_inside(to_pos.y, h2omes.hell_ceiling, h2omes.hell_floor) and not is_inside(from_pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
return false
|
|
end
|
|
end
|
|
return true
|
|
end
|
|
|
|
|
|
--function set_homes
|
|
function h2omes.set_home(name, home_type)
|
|
h2omes.check(name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return false end
|
|
|
|
local pos = player:get_pos()
|
|
if not pos then return false end
|
|
|
|
if h2omes.have_nether and is_inside(pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
h2omes.homes[name][home_type].nether = pos
|
|
elseif h2omes.have_hell and is_inside(pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
h2omes.homes[name][home_type].hell = pos
|
|
else
|
|
h2omes.homes[name][home_type].real = pos
|
|
end
|
|
|
|
if home_type == "home" then
|
|
minetest.chat_send_player(name, S("Home set!"))
|
|
else
|
|
minetest.chat_send_player(name, S("Pit set!"))
|
|
end
|
|
minetest.sound_play("dingdong", {to_player = name, gain = 1.0})
|
|
h2omes.save_homes(name)
|
|
return true
|
|
end
|
|
|
|
|
|
--function get_homes
|
|
function h2omes.get_home(name, home_type)
|
|
h2omes.check(name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return nil end
|
|
local pos = player:get_pos()
|
|
if not pos then return nil end
|
|
local status = "real"
|
|
|
|
if h2omes.have_nether and is_inside(pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
status = "nether"
|
|
elseif h2omes.have_hell and is_inside(pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
status = "hell"
|
|
end
|
|
|
|
if h2omes.homes[name][home_type][status] then
|
|
return h2omes.homes[name][home_type][status]
|
|
end
|
|
return nil
|
|
end
|
|
|
|
--function getspawn
|
|
function h2omes.getspawn(name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return nil end
|
|
local pos = player:get_pos()
|
|
if not pos then return nil end
|
|
local spawn_pos
|
|
if h2omes.have_nether and is_inside(pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
spawn_pos = minetest.string_to_pos(minetest.settings:get("nether_static_spawnpoint") or "")
|
|
if spawn_pos and not is_inside(spawn_pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
minetest.log("error","[h2omes] nether_static_spawnpoint is not in nether, fix in minetest.conf.")
|
|
return nil
|
|
end
|
|
elseif h2omes.have_hell and is_inside(pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
spawn_pos = minetest.string_to_pos(minetest.settings:get("hell_static_spawnpoint") or "")
|
|
if spawn_pos and not is_inside(spawn_pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
minetest.log("error","[h2omes] hell_static_spawnpoint is not in hell, fix in minetest.conf.")
|
|
return nil
|
|
end
|
|
else
|
|
spawn_pos = minetest.string_to_pos(minetest.settings:get("static_spawnpoint") or "")
|
|
end
|
|
return spawn_pos
|
|
end
|
|
|
|
|
|
--function to_spawn
|
|
function h2omes.to_spawn(name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return false end
|
|
local spawn_pos = h2omes.getspawn(name)
|
|
if spawn_pos then
|
|
minetest.chat_send_player(name, S("Teleporting to spawn..."))
|
|
player:set_pos(spawn_pos)
|
|
minetest.sound_play("teleport", {to_player = name, gain = 1.0})
|
|
minetest.log("action", "Player ".. name .." respawned. Next allowed respawn in ".. h2omes.time_spawn .." seconds.")
|
|
return true
|
|
else
|
|
minetest.chat_send_player(name, S("ERROR: No spawn point is set on this server!"))
|
|
return false
|
|
end
|
|
end
|
|
|
|
|
|
--function to_homes
|
|
function h2omes.to_home(name, home_type)
|
|
h2omes.check(name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return false end
|
|
local pos = player:get_pos()
|
|
if not pos then return false end
|
|
local status = "real"
|
|
|
|
if h2omes.have_nether and is_inside(pos.y, h2omes.nether_ceiling, h2omes.nether_floor) then
|
|
status = "nether"
|
|
elseif h2omes.have_hell and is_inside(pos.y, h2omes.hell_ceiling, h2omes.hell_floor) then
|
|
status = "hell"
|
|
end
|
|
if h2omes.homes[name][home_type][status] then
|
|
player:set_pos(h2omes.homes[name][home_type][status])
|
|
minetest.chat_send_player(name, S("Teleported to @1!", home_type))
|
|
minetest.sound_play("teleport", {to_player=name, gain = 1.0})
|
|
return true
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
--function to_player
|
|
function h2omes.to_player(name, to_pos, to_name)
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return false end
|
|
local from_pos = player:get_pos()
|
|
if to_pos then
|
|
if h2omes.can_teleport(from_pos, to_pos) then
|
|
minetest.chat_send_player(name, S("Teleporting to player @1", to_name))
|
|
player:set_pos(to_pos)
|
|
minetest.sound_play("teleport", {to_player=name, gain = 1.0})
|
|
return true
|
|
else
|
|
minetest.chat_send_player(name, S("Sorry, teleport between 2 worlds is not allowed!"))
|
|
return false
|
|
end
|
|
else
|
|
minetest.chat_send_player(name, S("ERROR: No position to player!"))
|
|
return false
|
|
end
|
|
end
|
|
|
|
|
|
function h2omes.update_pos(name, pos, from_name)
|
|
from_players[name] = {name = from_name, pos = pos}
|
|
minetest.chat_send_player(name, S("@1 sent you their position to teleport.", from_name))
|
|
minetest.sound_play("dingdong", {to_player = name, gain = 0.8})
|
|
return true
|
|
end
|
|
|
|
|
|
function h2omes.send_pos_to_player(name, pos, to_name)
|
|
local player = minetest.get_player_by_name(to_name)
|
|
if not player or not pos then return false end
|
|
if action_timers.wrapper(name, "send_pos_to_player", "from_player_" .. to_name, h2omes.time_from_player, h2omes.update_pos, {to_name, pos, name}) then
|
|
minetest.chat_send_player(name, S("Your position has been sent to @1.", to_name))
|
|
return true
|
|
else
|
|
minetest.chat_send_player(name, "Error: "..to_name.." already received a request. please try again later.")
|
|
end
|
|
return false
|
|
end
|
|
|
|
|
|
function h2omes.show_formspec_home(name)
|
|
if tmp_players[name] == nil then
|
|
tmp_players[name] = {}
|
|
end
|
|
local player = minetest.get_player_by_name(name)
|
|
if not player then return false end
|
|
local formspec = {"size[8,9]label[3,0;".. S("Home Settings") .."]"}
|
|
local pos = player:get_pos()
|
|
--spawn
|
|
table.insert(formspec, "label[3.35,0.8;".. S("TO SPAWN") .."]")
|
|
local spawn_pos = h2omes.getspawn(name)
|
|
if spawn_pos then
|
|
table.insert(formspec, string.format("label[2.9,1.3;x:%s, y:%s, z:%s]", math.floor(spawn_pos.x), math.floor(spawn_pos.y), math.floor(spawn_pos.z) ))
|
|
table.insert(formspec, "button_exit[6,1.1;2,1;to_spawn;".. S("To Spawn") .."]")
|
|
else
|
|
table.insert(formspec, "label[2.9,1.3;".. S("No spawn set") .."]")
|
|
end
|
|
|
|
--home
|
|
table.insert(formspec, "label[3.5,2.1;".. S("TO HOME") .."]")
|
|
table.insert(formspec, "button[0,2.4;2,1;set_home;".. S("Set Home") .."]")
|
|
local home_pos = h2omes.get_home(name, "home")
|
|
if home_pos then
|
|
table.insert(formspec, string.format("label[2.9,2.5;x:%s, y:%s, z:%s]", math.floor(home_pos.x), math.floor(home_pos.y), math.floor(home_pos.z) ))
|
|
table.insert(formspec, "button_exit[6,2.4;2,1;to_home;".. S("To Home") .."]")
|
|
else
|
|
table.insert(formspec, "label[2.9,2.5;".. S("Home no set") .."]")
|
|
end
|
|
|
|
--pit
|
|
table.insert(formspec, "label[3.55,3.4;".. S("TO PIT") .."]")
|
|
table.insert(formspec, "button[0,3.7;2,1;set_pit;".. S("Set Pit") .."]")
|
|
local pit_pos = h2omes.get_home(name, "pit")
|
|
if pit_pos then
|
|
table.insert(formspec, string.format("label[2.9,3.8;x:%s, y:%s, z:%s]", math.floor(pit_pos.x), math.floor(pit_pos.y), math.floor(pit_pos.z) ))
|
|
table.insert(formspec, "button_exit[6,3.7;2,1;to_pit;".. S("To Pit") .."]")
|
|
else
|
|
table.insert(formspec, "label[2.9,3.8;".. S("Pit no set") .."]")
|
|
end
|
|
|
|
--to player
|
|
table.insert(formspec, "label[3.35,4.7;".. S("TO PLAYER") .."]")
|
|
local to_player = from_players[name]
|
|
if to_player and to_player.name and to_player.pos then
|
|
table.insert(formspec, "label[0,5.1;".. S("To @1", to_player.name) .."]")
|
|
table.insert(formspec,string.format("label[2.9,5.1;x:%s, y:%s, z:%s]", math.floor(to_player.pos.x),math.floor(to_player.pos.y),math.floor(to_player.pos.z)))
|
|
table.insert(formspec, "button_exit[6,5;2,1;to_player;".. S("To Player") .."]")
|
|
else
|
|
table.insert(formspec, "label[2.7,5.1;".. S("No request from player") .."]")
|
|
end
|
|
|
|
table.insert(formspec, "label[2,6;".. S("SEND MY POS TO PLAYER") .."]")
|
|
if not tmp_players[name] or not tmp_players[name].players_list or #tmp_players[name].players_list < 1 or tmp_players[name].refresh then
|
|
tmp_players[name].refresh = nil
|
|
tmp_players[name].players_list = {}
|
|
tmp_players[name].selected_id = 0
|
|
for _,player in pairs(minetest.get_connected_players()) do
|
|
local player_name = player:get_player_name()
|
|
if player_name and player_name ~= "" and player_name ~= name then
|
|
table.insert(tmp_players[name].players_list, player_name)
|
|
end
|
|
end
|
|
tmp_players[name]["select_player"] = nil
|
|
end
|
|
if #tmp_players[name].players_list == 0 then
|
|
table.insert(formspec, "label[2.5,6.4;".. S("No player, try later") .."]")
|
|
else
|
|
table.insert(formspec,"button[3,6.4;2,1;refresh;".. S("Refresh") .."]")
|
|
table.insert(formspec, "dropdown[0,6.5;3,1;select_player;"..table.concat(tmp_players[name].players_list, ",")..";"..tmp_players[name].selected_id.."]")
|
|
end
|
|
if tmp_players[name].selected_id and tmp_players[name].selected_id > 0 then
|
|
table.insert(formspec, "button_exit[6,6.4;2,1;send_to;".. S("Send To") .."]")
|
|
end
|
|
|
|
table.insert(formspec, "button_exit[3.25,8.3;2,1;close;".. S("Close") .."]")
|
|
minetest.show_formspec(name, "h2omes:formspec", table.concat(formspec))
|
|
end
|
|
|
|
|
|
minetest.register_on_player_receive_fields(function(player, formname, fields)
|
|
local name = player:get_player_name()
|
|
if not name or name == "" then return end
|
|
if formname == "h2omes:formspec" then
|
|
if fields["set_home"] then
|
|
--h2omes.set_home(name, "home")
|
|
action_timers.wrapper(name, "sethome", "sethome_" .. name, h2omes.time_home, h2omes.set_home, {name, "home"})
|
|
elseif fields["set_pit"] then
|
|
--h2omes.set_home(name, "pit")
|
|
action_timers.wrapper(name, "setpit", "sethome_" .. name, h2omes.time_home, h2omes.set_home, {name, "pit"})
|
|
elseif fields["to_home"] then
|
|
--h2omes.to_home(name, "home")
|
|
action_timers.wrapper(name, "home", "tohome_" .. name, h2omes.time_home, h2omes.to_home, {name, "home"})
|
|
elseif fields["to_pit"] then
|
|
--h2omes.to_home(name, "pit")
|
|
action_timers.wrapper(name, "pit", "tohome_" .. name, h2omes.time_home, h2omes.to_home, {name, "pit"})
|
|
elseif fields["to_spawn"] then
|
|
action_timers.wrapper(name, "spawn", "tospawn_" .. name, h2omes.time_spawn, h2omes.to_spawn, {name})
|
|
elseif fields["to_player"] then
|
|
if not from_players[name] then return end
|
|
local to_name = from_players[name].name
|
|
local pos = from_players[name].pos
|
|
from_players[name] = nil
|
|
if not to_name or not pos then return end
|
|
h2omes.to_player(name, pos, to_name)
|
|
elseif fields["send_to"] then
|
|
local to_name = tmp_players[name]["select_player"]
|
|
if not to_name then return end
|
|
local pos = player:get_pos()
|
|
action_timers.wrapper(name, "send_pos_to_player", "to_player_" .. name, h2omes.time_to_player, h2omes.send_pos_to_player, {name, pos, to_name})
|
|
tmp_players[name] = nil
|
|
elseif fields["refresh"] then
|
|
tmp_players[name].refresh = true
|
|
elseif fields["select_player"] then
|
|
for i, n in pairs(tmp_players[name].players_list) do
|
|
if n == fields["select_player"] then
|
|
tmp_players[name]["select_player"] = fields["select_player"]
|
|
tmp_players[name].selected_id = i
|
|
break
|
|
end
|
|
end
|
|
end
|
|
if not fields["quit"] then
|
|
h2omes.show_formspec_home(name)
|
|
end
|
|
end
|
|
end)
|
|
|
|
|
|
minetest.register_on_joinplayer(function(player)
|
|
local name = player:get_player_name()
|
|
if not name or name == "" then return end
|
|
h2omes.load_homes(name)
|
|
end)
|
|
|
|
|
|
minetest.register_on_leaveplayer(function(player)
|
|
local name = player:get_player_name()
|
|
if not name or name == "" then return end
|
|
h2omes.homes[name] = nil
|
|
tmp_players[name] = nil
|
|
from_players[name] = nil
|
|
end)
|
|
|
|
|
|
minetest.register_privilege("home", S("Can use /sethome, /home, /setpit and /pit"))
|
|
|
|
minetest.register_chatcommand("spawn", {
|
|
description = S("Teleport a player to the defined spawnpoint"),
|
|
func = function(name)
|
|
local spawn_pos = h2omes.getspawn(name)
|
|
if spawn_pos then
|
|
action_timers.wrapper(name, "spawn", "tospawn_" .. name, h2omes.time_spawn, h2omes.to_spawn, {name})
|
|
else
|
|
minetest.chat_send_player(name, S("ERROR: No spawn point is set on this server!"))
|
|
return false
|
|
end
|
|
end
|
|
})
|
|
|
|
minetest.register_chatcommand("home", {
|
|
description = S("Teleport you to your home point"),
|
|
privs = {home = true},
|
|
func = function (name, params)
|
|
if not h2omes.get_home(name, "home") then
|
|
minetest.chat_send_player(name, S("Set a home using /sethome"))
|
|
return false
|
|
end
|
|
--h2omes.to_home(name, "home")
|
|
return action_timers.wrapper(name, "home", "tohome_" .. name, h2omes.time_home, h2omes.to_home, {name, "home"})
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_chatcommand("sethome", {
|
|
description = S("Set your home point"),
|
|
privs = {home = true},
|
|
func = function (name, params)
|
|
--h2omes.set_home(name, "home")
|
|
return action_timers.wrapper(name, "sethome", "sethome_" .. name, h2omes.time_home, h2omes.set_home, {name, "home"})
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_chatcommand("pit", {
|
|
description = S("Teleport you to your pit point"),
|
|
privs = {home = true},
|
|
func = function (name, params)
|
|
if not h2omes.get_home(name, "pit") then
|
|
minetest.chat_send_player(name, S("Set a pit using /setpit"))
|
|
return false
|
|
end
|
|
--h2omes.to_home(name, "pit")
|
|
return action_timers.wrapper(name, "pit", "tohome_" .. name, h2omes.time_home, h2omes.to_home, {name, "pit"})
|
|
end,
|
|
})
|
|
|
|
|
|
minetest.register_chatcommand("setpit", {
|
|
description = S("Set your pit point"),
|
|
privs = {home = true},
|
|
func = function (name, params)
|
|
--h2omes.set_home(name, "pit")
|
|
return action_timers.wrapper(name, "setpit", "sethome_" .. name, h2omes.time_home, h2omes.set_home, {name, "pit"})
|
|
end,
|
|
})
|
|
|
|
minetest.register_chatcommand("homegui", {
|
|
description = S("Show home menu"),
|
|
privs = {home = true},
|
|
func = function (name, params)
|
|
h2omes.show_formspec_home(name)
|
|
end,
|
|
})
|
|
|
|
if (minetest.get_modpath("unified_inventory")) then
|
|
unified_inventory.register_button("home_formspec", {
|
|
type = "image",
|
|
image = "h2omes_home.png",
|
|
tooltip = S("My Home"),
|
|
show_with = "home",
|
|
action = function(player)
|
|
local name = player:get_player_name()
|
|
if not name then return end
|
|
h2omes.show_formspec_home(name)
|
|
end,
|
|
})
|
|
end
|
|
|
|
minetest.log("action","[h2omes] Loaded.")
|