-- spawnpoint/init.lua spawnpoint = {} local storage local path = minetest.get_worldpath().."/spawnpoint.conf" local data = Settings(path) if minetest.get_mod_storage then storage = minetest.get_mod_storage() end -- [function] Log function spawnpoint.log(content, log_type) if not content then return false end if log_type == nil then log_type = "action" end minetest.log(log_type, "[SpawnPoint] "..content) end ---------------------- ----- GLOBALSTEP ----- ---------------------- local moved = {} local huds = {} local pos = {} minetest.register_globalstep(function(dtime) for _, player in pairs(minetest.get_connected_players()) do local name = player:get_player_name() if pos[name] and spawnpoint.do_not_move then if not moved[name] and not vector.equals(pos[name], player:getpos()) then moved[name] = true player:hud_remove(huds[name]) minetest.chat_send_player(name, "Teleportation interrupted! (Player moved)") end end end end) ---------------------- -- HELPER FUNCTIONS -- ---------------------- -- [local function] Count table contents local function count(t) local count = 0 for _, i in pairs(t) do count = count + 1 end return count end -- [local function] Check if table is empty local function is_empty(t) if t.fields then return count(t.fields) == 0 else return count(t) == 0 end end -- [function] Load function spawnpoint.load() if data and not is_empty(data:to_table()) then spawnpoint.time = tonumber(data:get("time")) spawnpoint.do_not_move = data:get_bool("do_not_move") local pos = data:get("pos") if pos then spawnpoint.pos = minetest.string_to_pos(pos) end local privilegespawnpoint = data:get("privilegespawnpoint") if privilegespawnpoint then spawnpoint.privilegespawnpoint = minetest.deserialize(privilegespawnpoint) end if storage then os.remove(path) end elseif storage and not is_empty(storage:to_table()) then local pos = storage:get_string("pos") if pos then spawnpoint.pos = minetest.string_to_pos(pos) end local privilegespawnpoint = storage:get_string("privilegespawnpoint") if privilegespawnpoint then spawnpoint.privilegespawnpoint = minetest.deserialize(privilegespawnpoint) end local do_not_move = storage:get_string("do_not_move") if do_not_move == "true" or do_not_move == true then spawnpoint.do_not_move = true else spawnpoint.do_not_move = false end spawnpoint.time = storage:get_float("time") else local f = io.open(path, "r") if f then local res = f:read("*all"):split("\n", true) spawnpoint.time = tonumber(res[1]) if res[2] == "true" or res[2] == true then spawnpoint.do_not_move = true else spawnpoint.do_not_move = false end if res[3] then spawnpoint.pos = minetest.string_to_pos(res[3]) end if res[4] then spawnpoint.privilegespawnpoint = minetest.deserialize(res[4]) end f:close() -- Clear file os.remove(path) end end end -- [function] Save function spawnpoint.save() if storage then storage:set_float("time", spawnpoint.time or 0) storage:set_string("do_not_move", tostring(spawnpoint.do_not_move)) if spawnpoint.pos then storage:set_string("pos", minetest.pos_to_string(spawnpoint.pos)) end if spawnpoint.privilegespawnpoint then storage:set_string("privilegespawnpoint", minetest.serialize(spawnpoint.privilegespawnpoint)) end return true elseif data then data:set("time", tostring(spawnpoint.time)) data:set_bool("do_not_move", spawnpoint.do_not_move) if spawnpoint.pos then data:set("pos", minetest.pos_to_string(spawnpoint.pos)) end if spawnpoint.privilegespawnpoint then data:set("privilegespawnpoint", minetest.serialize(spawnpoint.privilegespawnpoint)) end data:write() return true end end -- [function] Set function spawnpoint.set(pos,privilege) if type(pos) == "string" then pos = minetest.string_to_pos(pos) end if type(pos) == "table" then if privilege then spawnpoint.privilegespawnpoint = {} spawnpoint.privilegespawnpoint.pos = pos spawnpoint.privilegespawnpoint.privilege = privilege spawnpoint.log("Set a second spawnpoint to "..minetest.pos_to_string(pos).." associated to privilege "..privilege) else spawnpoint.pos = pos spawnpoint.log("Set spawnpoint to "..minetest.pos_to_string(pos)) end spawnpoint.save() end end -- [function] Bring function spawnpoint.bring(player,forcePrivilegeSpawnpoint) -- forcePrivilegeSpawnpoint used in area mod forcePrivilegeSpawnpoint = forcePrivilegeSpawnpoint or false if type(player) == "string" then player = minetest.get_player_by_name(player) end if player then local is_bring_to_privilegespawnpoint = false local is_privilegespawnpoint = spawnpoint.privilegespawnpoint and spawnpoint.privilegespawnpoint.privilege if is_privilegespawnpoint then local is_priv = minetest.check_player_privs(player, {[spawnpoint.privilegespawnpoint.privilege] = true }) if forcePrivilegeSpawnpoint or is_priv then is_priv = minetest.check_player_privs(player, {server = true }) if not is_priv then is_bring_to_privilegespawnpoint = true end end end if is_bring_to_privilegespawnpoint then local pos = spawnpoint.privilegespawnpoint.pos if pos then player:setpos({x=pos.x, y=pos.y+0.5, z=pos.z}) end else local pos = spawnpoint.pos if pos then player:setpos({x=pos.x, y=pos.y+0.5, z=pos.z}) end end end end -- [function] Begin Countdown function spawnpoint.begin(player, time) if not time then time = spawnpoint.time end if type(player) == string then player = minetest.get_player_by_name(player) end local name = player:get_player_name() if player and time and time ~= 0 then local move = "Do not move!" if spawnpoint.do_not_move ~= true then move = "" end local seconds = "s" if time < 2 then seconds = "" end -- Send to chat minetest.chat_send_player(name, "Teleportation will be complete in "..time.. " second"..seconds..". "..move) -- Add initial HUD huds[name] = player:hud_add({ hud_elem_type = "text", text = "Teleportation Progress: "..time.." seconds remaining!", position = {x = 0.5, y = 0.5}, number = 0xFFFFFF, }) local hud = huds[name] pos[name] = player:getpos() moved[name] = false -- Register update callbacks for i = 1, time do if i == time then minetest.after(i, function() if not moved[name] then player:hud_remove(hud) spawnpoint.bring(player) -- Send to chat minetest.chat_send_player(name, "Teleportation successful!") -- Prevent further callbacks from globalstep moved[name] = true end end) else minetest.after(i, function() if not moved[name] then player:hud_change(hud, "text", "Teleportation Progress: "..time - i.." seconds remaining!") end end) end end elseif player then minetest.chat_send_player(name, "Teleporting to spawn") spawnpoint.bring(player) end end ------------------- ---- CALLBACKS ---- ------------------- spawnpoint.load() -- [register] On Shutdown minetest.register_on_shutdown(spawnpoint.save) -- [register] On Respawn Player minetest.register_on_respawnplayer(function(player) spawnpoint.bring(player) end) -- [register] On New Player minetest.register_on_newplayer(function(player) spawnpoint.bring(player) end) -- [register priv] Spawn minetest.register_privilege("spawn", "Ability to teleport to spawn at will with /spawn") -- [register cmd] Set spawn minetest.register_chatcommand("setspawn", { description = "Set spawn", privs = {server=true}, func = function(name, param) local pos = minetest.get_player_by_name(name):getpos() local privilege = nil if param then local ppos = minetest.string_to_pos(param) if type(ppos) == "table" then pos = ppos elseif minetest.registered_privileges[param] then -- define a /setspawn cmd only with player pos (cant put pos in parameter) privilege = param end end pos = vector.round(pos) spawnpoint.set(pos,privilege) if privilege then return true, "Set a second spawnpoint to "..minetest.pos_to_string(pos).." associated to privilege "..privilege else return true, "Set default spawnpoint to "..minetest.pos_to_string(pos) end end, }) -- [register cmd] Teleport to spawn minetest.register_chatcommand("spawn", { description = "Teleport to spawn", privs = {spawn=true}, func = function(name, param) local player = minetest.get_player_by_name(name) if param ~= "" then local pplayer = minetest.get_player_by_name(param) if pplayer and minetest.check_player_privs(player, {bring=true}) then player = pplayer else return false, "Cannot teleport another player to spawn without bring privilege" end end if not spawnpoint.pos then return false, "No spawnpoint set!" end spawnpoint.begin(player) end, }) -- [register cmd] Manage spawnpoint minetest.register_chatcommand("spawnpoint", { description = "Get/Set SpawnPoint information", func = function(name, param) local is_privilegespawnpoint = spawnpoint.privilegespawnpoint ~= nil if is_privilegespawnpoint then local player = minetest.get_player_by_name(name) local is_priv = minetest.check_player_privs(player, {[spawnpoint.privilegespawnpoint.privilege] = true }) if (is_privilegespawnpoint and is_priv) then if not param or param == "" then local pos = "Not set!" if spawnpoint.privilegespawnpoint.pos then pos = minetest.pos_to_string(spawnpoint.pos) end return true, "SpawnPoint Position: "..pos end end elseif not param or param == "" then local pos = "Not set!" if spawnpoint.pos then pos = minetest.pos_to_string(spawnpoint.pos) end return true, "SpawnPoint Position: "..pos elseif minetest.check_player_privs(minetest.get_player_by_name(name), {server=true}) then local p = param:split(" ") local is_privilegespawnpoint = minetest.registered_privileges[p[3]] ~= nil and spawnpoint.privilegespawnpoint ~= nil if p[1] == "time" then local num = tonumber(p[2]) if not num then if is_privilegespawnpoint then return true, "SpawnPoint "..p[3].." ->time: "..dump(spawnpoint.privilegespawnpoint.time) else return true, "SpawnPoint->time: "..dump(spawnpoint.time) end else if is_privilegespawnpoint then spawnpoint.privilegespawnpoint.time = num spawnpoint.save() spawnpoint.log("Set time to "..dump(num).." for "..p[3].."spawn point") return true, "Set time to "..dump(num).." for "..p[3].."spawn point" else spawnpoint.time = num spawnpoint.save() spawnpoint.log("Set time to "..dump(num)) return true, "Set time to "..dump(num) end end elseif p[1] == "do_not_move" then local move = minetest.is_yes(p[2]) if move == nil or not p[2] then if is_privilegespawnpoint then return true, "SpawnPoint "..p[3].." ->do_not_move: "..dump(spawnpoint.privilegespawnpoint.do_not_move) else return true, "SpawnPoint->do_not_move: "..dump(spawnpoint.do_not_move) end else if is_privilegespawnpoint then spawnpoint.privilegespawnpoint.do_not_move = move spawnpoint.save() spawnpoint.log("Set do_not_move to "..dump(move).." for "..p[3].."spawn point") return true, "Set do_not_move to "..dump(move).." for "..p[3].."spawn point" else spawnpoint.do_not_move = move spawnpoint.save() spawnpoint.log("Set do_not_move to "..dump(move)) return true, "Set do_not_move to "..dump(move) end end end end end, })