124 lines
3.5 KiB
Lua
124 lines
3.5 KiB
Lua
-- LUALOCALS < ---------------------------------------------------------
|
|
local math, minetest, rawget, tonumber
|
|
= math, minetest, rawget, tonumber
|
|
local math_abs, math_cos, math_floor, math_pi, math_sin, math_sqrt
|
|
= math.abs, math.cos, math.floor, math.pi, math.sin, math.sqrt
|
|
-- LUALOCALS > ---------------------------------------------------------
|
|
|
|
local modname = minetest.get_current_modname()
|
|
|
|
local phi = (math_sqrt(5) + 1) / 2
|
|
local goldangle = math_pi * 2 / phi / phi
|
|
|
|
local scale = minetest.settings:get(modname .. "_scale") or 256
|
|
local areasize = minetest.setting_get_pos(modname .. "_area_size") or {x = 63, y = 127, z = 63}
|
|
areasize = vector.floor(vector.multiply({
|
|
x = math_abs(areasize.x),
|
|
y = math_abs(areasize.y),
|
|
z = math_abs(areasize.z)
|
|
}, 0.5))
|
|
local skipids = tonumber(minetest.settings:get(modname .. "_skip_ids"))
|
|
local maxdist = tonumber(minetest.settings:get(modname .. "_max_distance"))
|
|
or tonumber(minetest.settings:get("mapgen_limit"))
|
|
or 32768 * 7/8
|
|
|
|
local modstore = minetest.get_mod_storage()
|
|
local lastid = modstore:get_int("lastid") or 0
|
|
if skipids and lastid < skipids then lastid = math_floor(skipids) end
|
|
|
|
local areas = rawget(_G, "areas")
|
|
local beds = rawget(_G, "beds")
|
|
local sethome = rawget(_G, "sethome")
|
|
|
|
local function playerid(player)
|
|
local meta = player:get_meta()
|
|
local id = meta:get_int(modname .. "_id")
|
|
if id == 0 then
|
|
lastid = lastid + 1
|
|
modstore:set_int("lastid", lastid)
|
|
id = lastid
|
|
meta:set_int(modname .. "_id", id)
|
|
end
|
|
return id
|
|
end
|
|
|
|
local function distreflect(r)
|
|
if r > maxdist then return distreflect(maxdist * 2 - r) end
|
|
if r < 0 then return distreflect(-r) end
|
|
return r
|
|
end
|
|
|
|
local function findhome(player, pos)
|
|
if not pos then
|
|
local id = playerid(player)
|
|
local theta = id * goldangle
|
|
local r = distreflect((id - 1) * scale)
|
|
pos = vector.round({
|
|
x = r * math_cos(theta),
|
|
y = 0,
|
|
z = r * math_sin(theta)
|
|
})
|
|
end
|
|
while true do
|
|
local ll = minetest.get_node_light(pos, 0.5)
|
|
if not ll then
|
|
minetest.after(1, function()
|
|
return findhome(player, pos)
|
|
end)
|
|
return player:set_pos(pos)
|
|
end
|
|
if ll > 0 then
|
|
player:get_meta():set_string(modname .. "_home", minetest.pos_to_string(pos))
|
|
local pname = player:get_player_name()
|
|
if areas and areasize.x > 0 and areasize.y > 0 and areasize.z > 0 then
|
|
areas:add(
|
|
pname,
|
|
pname .. "'s Home",
|
|
vector.subtract(pos, areasize),
|
|
vector.add(pos, areasize)
|
|
)
|
|
areas:save()
|
|
end
|
|
if sethome then
|
|
sethome.set(pname, pos)
|
|
end
|
|
return player:set_pos(pos)
|
|
end
|
|
pos.y = pos.y + 1
|
|
end
|
|
end
|
|
minetest.register_on_newplayer(function(player)
|
|
return findhome(player)
|
|
end)
|
|
|
|
minetest.register_on_respawnplayer(function(player)
|
|
if beds then
|
|
local pname = player:get_player_name()
|
|
if beds.spawn[pname] then return end
|
|
end
|
|
return minetest.after(0, function()
|
|
local pos = player:get_meta():get_string(modname .. "_home")
|
|
if pos and pos ~= "" then
|
|
return player:set_pos(minetest.string_to_pos(pos))
|
|
end
|
|
end)
|
|
end)
|
|
|
|
if not sethome then
|
|
minetest.register_privilege("home", {
|
|
description = "Can use /home",
|
|
give_to_singleplayer = false
|
|
})
|
|
minetest.register_chatcommand("home", {
|
|
description = "Teleport you to your home",
|
|
privs = {home = true},
|
|
func = function(pname)
|
|
local player = minetest.get_player_by_name(pname)
|
|
if not player then return false, "player not found" end
|
|
local pos = player:get_meta():get_string(modname .. "_home")
|
|
if not pos then return false, "No home set!" end
|
|
player:set_pos(minetest.string_to_pos(pos))
|
|
end
|
|
})
|
|
end
|