Add player invites
* Allow players to invite others to use their spawn (permanently) * change pregeneration to be actioned relative to frequency
This commit is contained in:
parent
e3c57fc241
commit
b298d680cf
24
init.lua
24
init.lua
@ -12,7 +12,7 @@ local function notnil_or(d, v)
|
||||
end
|
||||
|
||||
-- Water level, plus one to ensure we are above the sea.
|
||||
local water_level = tonumber(minetest.settings:get("water_level", "1") )+1
|
||||
local water_level = tonumber(minetest.settings:get("water_level", "0") )
|
||||
local radial_step = 16
|
||||
|
||||
-- Setting with no namespace for interoperability
|
||||
@ -34,6 +34,7 @@ rspawn.gen_frequency = tonumber(minetest.settings:get("rspawn.gen_frequency") or
|
||||
rspawn.spawn_block = minetest.settings:get("rspawn.spawn_block")
|
||||
|
||||
dofile(mpath.."/src/data.lua")
|
||||
dofile(mpath.."/src/invites.lua")
|
||||
dofile(mpath.."/src/commands.lua")
|
||||
dofile(mpath.."/src/forceload.lua")
|
||||
dofile(mpath.."/src/debugging.lua")
|
||||
@ -87,6 +88,7 @@ function rspawn:newspawn(pos, radius)
|
||||
if under.walkable
|
||||
and not over.walkable
|
||||
and not minetest.is_protected(anode, rspawn.adminname)
|
||||
and not (under.groups and under.groups.leaves ) -- no spawning on treetops!
|
||||
and daylight_above(7, anode) then
|
||||
validnodes[#validnodes+1] = anode
|
||||
end
|
||||
@ -109,8 +111,7 @@ function rspawn:genpos()
|
||||
if rspawn.spawnanywhere then
|
||||
pos = {
|
||||
x = math.random(-30000,30000),
|
||||
--y = math.random(water_level, water_level+20),
|
||||
y = water_level, -- always at waterlevel
|
||||
y = water_level, -- always start at waterlevel
|
||||
z = math.random(-30000,30000),
|
||||
}
|
||||
end
|
||||
@ -118,7 +119,7 @@ function rspawn:genpos()
|
||||
return pos
|
||||
end
|
||||
|
||||
local function confirm_new_spawn(name, newpos)
|
||||
function rspawn:set_player_spawn(name, newpos)
|
||||
local spos = minetest.pos_to_string(newpos)
|
||||
|
||||
rspawn.debug("Saving spawn for "..name, spos)
|
||||
@ -140,21 +141,18 @@ function rspawn:set_newplayer_spawn(player)
|
||||
local newpos = rspawn:get_next_spawn()
|
||||
|
||||
if newpos then
|
||||
confirm_new_spawn(playername, newpos)
|
||||
rspawn:set_player_spawn(playername, newpos)
|
||||
|
||||
else
|
||||
if rspawn.adminname ~= "singleplayer" or playername ~= rspawn.adminname then
|
||||
minetest.chat_send_player(playername, "Please wait until a spawn point is available ...")
|
||||
minetest.after(15, function()
|
||||
rspawn:set_newplayer_spawn(player)
|
||||
end)
|
||||
elseif rspawn.kick_on_fail then
|
||||
-- We did not get a new position
|
||||
|
||||
if rspawn.kick_on_fail then
|
||||
minetest.kick_player(playername, "No personalized spawn points available - please try again later.")
|
||||
|
||||
else
|
||||
minetest.chat_send_player(playername, "Could not get custom spawn! Retrying in "..rspawn.gen_frequency.." seconds")
|
||||
|
||||
minetest.after(gen_frequency, function()
|
||||
minetest.after(rspawn.gen_frequency+2, function()
|
||||
rspawn:set_newplayer_spawn(player)
|
||||
end)
|
||||
end
|
||||
@ -168,7 +166,7 @@ function rspawn:renew_player_spawn(playername)
|
||||
local newpos = rspawn:get_next_spawn()
|
||||
|
||||
if newpos then
|
||||
confirm_new_spawn(playername, newpos)
|
||||
rspawn:set_player_spawn(playername, newpos)
|
||||
|
||||
else
|
||||
minetest.chat_send_player(playername, "Could not get custom spawn!")
|
||||
|
@ -19,7 +19,7 @@ local function splitstring(sdata, sep)
|
||||
|
||||
if idx then
|
||||
tdata[#tdata+1] = sdata:sub(1,idx-1)
|
||||
sdata = sdata:sub(idx+1, idx:len() )
|
||||
sdata = sdata:sub(idx+1, sdata:len() )
|
||||
|
||||
else -- last element
|
||||
tdata[#tdata+1] = sdata
|
||||
@ -33,8 +33,8 @@ end
|
||||
-- Commands
|
||||
|
||||
minetest.register_chatcommand("spawn", {
|
||||
description = "Teleport to spawn position.",
|
||||
params = "[ invite <player> | accept | decline ]",
|
||||
description = "Teleport to spawn position, or manage invitations. See you current invitation with '/spawn invite'",
|
||||
params = "[ invite [<player>] | accept | decline ]",
|
||||
privs = "spawn",
|
||||
func = function(name, args)
|
||||
local target = rspawn.playerspawns[name]
|
||||
@ -43,23 +43,35 @@ minetest.register_chatcommand("spawn", {
|
||||
if #args == 0 then
|
||||
if target then
|
||||
minetest.get_player_by_name(name):setpos(target)
|
||||
return
|
||||
|
||||
else
|
||||
minetest.chat_send_player(name, "You have no spawn position!")
|
||||
return
|
||||
end
|
||||
|
||||
elseif args[1] == "accept" then
|
||||
accept_invitation(name) -- TODO, only one at a time, must be accepted or declined
|
||||
rspawn.invites:accept(name)
|
||||
-- TODO, only one at a time, must be accepted or declined, and DO move player - not to be used lightly
|
||||
return
|
||||
|
||||
elseif args[1] == "decline" then
|
||||
decline_invitation(name) -- TODO, free up invitation slot
|
||||
rspawn.invites:decline(name) -- TODO, free up invitation slot
|
||||
return
|
||||
|
||||
elseif#args == 2 and args[1] == "invite" then
|
||||
invite_player_fromto(name, args[2]) -- TODO, and DO move player - not to be used lightly
|
||||
|
||||
else
|
||||
minetest.chat_send_player(name, "Please check '/help spawn'")
|
||||
elseif args[1] == "invite" then
|
||||
if #args == 2 then
|
||||
rspawn.invites:invite_player_fromto(name, args[2]) -- TODO
|
||||
return
|
||||
|
||||
elseif #args == 1 then
|
||||
rspawn.invites:show_invite_for(name) -- TODO
|
||||
return
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
minetest.chat_send_player(name, "Please check '/help spawn'")
|
||||
end
|
||||
})
|
||||
|
||||
|
@ -1,3 +1,6 @@
|
||||
local forceloading_happening = false
|
||||
|
||||
|
||||
local function forceload_operate(pos1, pos2, handler)
|
||||
local i,j,k
|
||||
|
||||
@ -11,13 +14,22 @@ local function forceload_operate(pos1, pos2, handler)
|
||||
end
|
||||
|
||||
function rspawn:forceload_blocks_in(pos1, pos2)
|
||||
if forceloading_happening then
|
||||
rspawn:debug("Forceload operation already underway - abort")
|
||||
return false
|
||||
end
|
||||
|
||||
rspawn:debug("Forceloading blocks -----------¬", {pos1=minetest.pos_to_string(pos1),pos2=minetest.pos_to_string(pos2)})
|
||||
forceloading_happening = true
|
||||
minetest.emerge_area(pos1, pos2)
|
||||
forceload_operate(pos1, pos2, minetest.forceload_block)
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
function rspawn:forceload_free_blocks_in(pos1, pos2)
|
||||
rspawn:debug("Freeing forceloaded blocks ____/", {pos1=minetest.pos_to_string(pos1),pos2=minetest.pos_to_string(pos2)})
|
||||
forceload_operate(pos1, pos2, minetest.forceload_free_block)
|
||||
forceloading_happening = false
|
||||
end
|
||||
|
||||
|
176
src/invites.lua
Normal file
176
src/invites.lua
Normal file
@ -0,0 +1,176 @@
|
||||
rspawn.invites = {}
|
||||
|
||||
-- invitations[guest] = host
|
||||
rspawn.invitations = {}
|
||||
|
||||
local invite_charge = {}
|
||||
|
||||
levvy_name = minetest.settings:get("rspawn.levvy_name") or "default:cobble"
|
||||
levvy_qtty = minetest.settings:get("rspawn.levvy_qtty") or 99
|
||||
levvy_nicename = "cobblestone"
|
||||
|
||||
if minetest.registered_nodes[levvy_name] then
|
||||
levvy_nicename = minetest.registered_nodes[levvy_name].description
|
||||
else
|
||||
minetest.debug("No such node "..levvy_name.." -- reverting to defaults.")
|
||||
levvy_name = "default:cobble"
|
||||
levvy_qtty = 99
|
||||
end
|
||||
|
||||
local function get_players(p1name, p2name)
|
||||
-- Check both players are online.
|
||||
-- It is easier to implement agains online players than to manage offline interactions
|
||||
local err, p1, p2
|
||||
local errmsg_generic = " is not online."
|
||||
|
||||
if not p1name then
|
||||
minetest.log("error", "Missing p1name")
|
||||
return nil,nil,"Internal error."
|
||||
|
||||
elseif not p2name then
|
||||
minetest.log("error", "Missing p2name")
|
||||
return nil,nil,"Internal error."
|
||||
end
|
||||
|
||||
p1 = minetest.get_player_by_name(p1name)
|
||||
p2 = minetest.get_player_by_name(p2name)
|
||||
|
||||
if not p1 then err = p1name..errmsg_generic end
|
||||
if not p2 then err = p2name..errmsg_generic end
|
||||
|
||||
return p1,p2,err
|
||||
end
|
||||
|
||||
function rspawn.invites:invite_player_fromto(hostname, guestname)
|
||||
local host,guest = get_players(hostname, guestname)
|
||||
|
||||
if err then
|
||||
minetest.chat_send_player(hostname, err)
|
||||
return
|
||||
end
|
||||
|
||||
if not rspawn.invitations[guestname] then
|
||||
rspawn.invitations[guestname] = hostname
|
||||
else
|
||||
minetest.chat_send_player(hostname, guestname.." already has a pending invitation, and cannot be invited.")
|
||||
return
|
||||
end
|
||||
|
||||
local hostspawn_s = minetest.pos_to_string(rspawn.playerspawns[hostname])
|
||||
|
||||
minetest.chat_send_player(guestname, hostname.." invited you to join their spawn point.\nIf you accept, your spawn point will be set to "..hostspawn_s.." and you will be taken there immediately.\n This cannot be undone.\n\nRun '/spawn accept' to accept, '/spawn decline' to decline and clear the invite.")
|
||||
|
||||
minetest.chat_send_player(hostname,
|
||||
"You have invited "..guestname.." to join your spawn.\nIf they accept, you will be charged \n\n "..levvy_qtty.." "..levvy_nicename.." \n\nwhich will be taken from your inventory."
|
||||
)
|
||||
end
|
||||
|
||||
local function find_levvy(player)
|
||||
-- return itemstack index, and stack itself, with qtty removed
|
||||
-- or none if not found/not enough found
|
||||
local i
|
||||
local pname = player:get_player_name()
|
||||
local player_inv = minetest.get_inventory({type='player', name = pname})
|
||||
local total_count = 0
|
||||
|
||||
for i = 1,32 do
|
||||
local itemstack = player_inv:get_stack('main', i)
|
||||
local itemname = itemstack:get_name()
|
||||
if itemname == levvy_name then
|
||||
if itemstack:get_count() >= levvy_qtty then
|
||||
return true
|
||||
else
|
||||
total_count = total_count + itemstack:get_count()
|
||||
|
||||
if total_count >= (levvy_qtty) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
minetest.chat_send_player(pname, "You do not have enough "..levvy_nicename.." to pay the spawn levvy for your invitaiton.")
|
||||
return false
|
||||
end
|
||||
|
||||
local function consume_levvy(player)
|
||||
local i
|
||||
local pname = player:get_player_name()
|
||||
local player_inv = minetest.get_inventory({type='player', name = pname})
|
||||
local total_count = 0
|
||||
|
||||
-- TODO combine find_levvy and consume_levvy so that we're
|
||||
-- not scouring the inventory twice...
|
||||
if find_levvy(player) then
|
||||
for i = 1,32 do
|
||||
local itemstack = player_inv:get_stack('main', i)
|
||||
local itemname = itemstack:get_name()
|
||||
if itemname == levvy_name then
|
||||
if itemstack:get_count() >= levvy_qtty then
|
||||
itemstack:take_item(levvy_qtty)
|
||||
player_inv:set_stack('main', i, itemstack)
|
||||
return true
|
||||
else
|
||||
total_count = total_count + itemstack:get_count()
|
||||
itemstack:clear()
|
||||
player_inv:set_stack('main', i, itemstack)
|
||||
|
||||
if total_count >= (levvy_qtty) then
|
||||
return true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
function rspawn.invites:accept(guestname)
|
||||
local hostname = rspawn.invitations[guestname]
|
||||
|
||||
if not hostname then
|
||||
minetest.chat_send_player(guestname, "No invitation to accept.")
|
||||
return
|
||||
end
|
||||
|
||||
local host,guest = get_players(hostname, guestname)
|
||||
|
||||
if err then
|
||||
minetest.chat_send_player(guestname, err)
|
||||
return
|
||||
end
|
||||
|
||||
if consume_levvy(minetest.get_player_by_name(hostname) ) then -- Systematically notifies host if they don't have enough
|
||||
local hostspawn = rspawn.playerspawns[hostname]
|
||||
rspawn:set_player_spawn(guestname, hostspawn) -- sets new spawn position, saves, teleports player
|
||||
|
||||
else -- Host was notified, now notify guest
|
||||
minetest.chat_send_player(guestname, hostname.." was unable to pay the levvy. Invitation could not be accepted.")
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function rspawn.invites:decline(guestname)
|
||||
local hostname = rspawn.invitations[guestname]
|
||||
|
||||
if hostname then
|
||||
rspawn.invitations[guestname] = nil
|
||||
-- Player not online, message simply ignored.
|
||||
minetest.chat_send_player(guestname, "Declined invitation to join "..hostname.."'s spawn for now.")
|
||||
minetest.chat_send_player(hostname, guestname.." declined to join your spawn point for now.")
|
||||
else
|
||||
minetest.chat_send_player(guestname, "No invitation to decline.")
|
||||
end
|
||||
end
|
||||
|
||||
function rspawn.invites:show_invite_for(guestname)
|
||||
local hostname = rspawn.invitations[guestname]
|
||||
|
||||
if hostname then
|
||||
minetest.chat_send_player(guestname, "You have been invited to join "..hostname.." at "..minetest.pos_to_string(rspawn.playerspawns[hostname]))
|
||||
else
|
||||
minetest.chat_send_player(guestname, "No pending invitation.")
|
||||
end
|
||||
end
|
@ -26,21 +26,23 @@ local function push_new_spawn()
|
||||
local random_pos = rspawn:genpos()
|
||||
local pos1,pos2 = rspawn:get_positions_for(random_pos, rspawn.search_radius)
|
||||
|
||||
rspawn:forceload_blocks_in(pos1, pos2)
|
||||
if rspawn:forceload_blocks_in(pos1, pos2) then
|
||||
minetest.after(rspawn.gen_frequency*0.8, function()
|
||||
-- Let the forceload do its thing, then act
|
||||
|
||||
minetest.after(10, function()
|
||||
-- Let the forceload do its thing, then act
|
||||
local newpos = rspawn:newspawn(random_pos, rspawn.search_radius)
|
||||
if newpos then
|
||||
rspawn:debug("Generated "..minetest.pos_to_string(newpos))
|
||||
set_pgen(len_pgen()+1, newpos )
|
||||
else
|
||||
rspawn:debug("Failed to generate new spawn point to push")
|
||||
end
|
||||
|
||||
local newpos = rspawn:newspawn(random_pos, rspawn.search_radius)
|
||||
if newpos then
|
||||
rspawn:debug("Generated "..minetest.pos_to_string(newpos))
|
||||
set_pgen(len_pgen()+1, newpos )
|
||||
else
|
||||
rspawn:debug("Failed to generate new spawn point to push")
|
||||
end
|
||||
|
||||
rspawn:forceload_free_blocks_in(pos1, pos2)
|
||||
end)
|
||||
rspawn:forceload_free_blocks_in(pos1, pos2)
|
||||
end)
|
||||
else
|
||||
rspawn:debug("Failed to push new spawn point - preexisting operation took precedence.")
|
||||
end
|
||||
end
|
||||
|
||||
minetest.register_globalstep(function(dtime)
|
||||
@ -63,8 +65,6 @@ function rspawn:get_next_spawn()
|
||||
nspawn = get_pgen(len_pgen() )
|
||||
rspawn:debug("Returning pregenerated spawn",nspawn)
|
||||
set_pgen(len_pgen(), nil)
|
||||
else
|
||||
push_new_spawn()
|
||||
end
|
||||
|
||||
return nspawn
|
||||
|
Loading…
x
Reference in New Issue
Block a user