Added logging, isolated act_on_behalf, fixed auto kick proximity

Specifically, if a player's spawn is close to a spawn they are banned from,
and they are close to their spawn, we avoid kicking them in loop.
master
Tai Kedzierski 2019-01-30 10:22:15 +00:00
parent 82f252a713
commit 976853c6cb
3 changed files with 60 additions and 28 deletions

View File

@ -1,6 +1,6 @@
# `[rspawn]` Randomized Spawning for Minetest # `[rspawn]` Randomized Spawning for Minetest
Causes players to receive a spawn point anywhere on the map. Players will likely spawn veeery far from eachother into prisitine areas. Causes players to receive a spawn point anywhere on the map. Players will likely spawn very far from eachother into prisitine areas.
## Features ## Features
@ -10,7 +10,8 @@ Causes players to receive a spawn point anywhere on the map. Players will likely
* If `beds` spawning is active, then beds can be used to set players' re-spawn point (they still go to their main spawnpoint on invoking `/spawn`). * If `beds` spawning is active, then beds can be used to set players' re-spawn point (they still go to their main spawnpoint on invoking `/spawn`).
* Commands * Commands
* Players can return to their spawn point with the `/spawn` command if they have `spawn` privilege. * Players can return to their spawn point with the `/spawn` command if they have `spawn` privilege.
* Players can invite other players to join their spawn - see "Spawn invites" below * Players can invite other players to join their spawn - see "Spawn guests" below
* Players can allow any other player to visit their spawn - see "Town hosting" below
* Players can request a new spawn point by typing `/newspawn` if they have the `newspawn` privilege. * Players can request a new spawn point by typing `/newspawn` if they have the `newspawn` privilege.
* Players can set their spawn point by typing `/setspawn` if they have the `setspawn` privelege. * Players can set their spawn point by typing `/setspawn` if they have the `setspawn` privelege.
* Moderator players can assign a new random spawn for another player using `/playerspawn` if they have the `spawnadmin` privilege. * Moderator players can assign a new random spawn for another player using `/playerspawn` if they have the `spawnadmin` privilege.
@ -31,6 +32,8 @@ The player issuing the invite (host) must typically pay a levvy when adding anot
* `/spawn guests` - see who you have added to your spawn * `/spawn guests` - see who you have added to your spawn
* `/spawn hosts` - see whose spawns you may visit * `/spawn hosts` - see whose spawns you may visit
Guests can help the spawn owner manage bans on their town.
### Town hosting ### Town hosting
You can host a town from your spawn if you wish. Hosting a town means that any player who connects to the server will be able to visit your spawn. You can still `/spawn kick <playername>` individually in this mode. If you switch off town hosting, only allowed guests in your normal guestlist can visit. You can host a town from your spawn if you wish. Hosting a town means that any player who connects to the server will be able to visit your spawn. You can still `/spawn kick <playername>` individually in this mode. If you switch off town hosting, only allowed guests in your normal guestlist can visit.
@ -41,6 +44,10 @@ There is no levvy on hosting a town.
* `/spawn town { ban | unban } <playername> [<town>]` - ban or unban a player from a town * `/spawn town { ban | unban } <playername> [<town>]` - ban or unban a player from a town
* Town owners can use this, as well as unexiled guests of the town owner * Town owners can use this, as well as unexiled guests of the town owner
Explicit guests can ban/unban other players from a town.
Town owner can forcibly ban a player by first adding the player to their guest list, and then exiling them. Guests cannot override this.
## Settings ## Settings
Note that the spawn generation is performed in the background on a timer, allowing storing a collection of random spawn points to be generated ahead of time. Note that the spawn generation is performed in the background on a timer, allowing storing a collection of random spawn points to be generated ahead of time.
@ -94,7 +101,7 @@ Resolutions in order of best to worst:
* Stop minetest, delete the `force_loaded.txt` file, and start it again * Stop minetest, delete the `force_loaded.txt` file, and start it again
* (bad - some things in the mods using the forceload mechanism may break) * (bad - some things in the mods using the forceload mechanism may break)
## Singple Player Mode ## Single Player Mode
This mod is mainly intended for use on servers with multiple players. This mod is mainly intended for use on servers with multiple players.

View File

@ -1,4 +1,10 @@
function rspawn:d(stuff)
-- Quick debugging
minetest.debug(dump(stuff))
end
function rspawn:debug(message, data) function rspawn:debug(message, data)
-- Debugging from setting
if not rspawn.debug_on then if not rspawn.debug_on then
return return
end end
@ -8,7 +14,7 @@ function rspawn:debug(message, data)
if data ~= nil then if data ~= nil then
debug_data = " :: "..dump(data) debug_data = " :: "..dump(data)
end end
local debug_string = "rspawn : "..message..debug_data local debug_string = "[rspawn] DEBUG : "..message..debug_data
minetest.debug(debug_string) minetest.debug(debug_string)
end end

View File

@ -32,7 +32,7 @@ local function find_levvy(player)
local i local i
if not player then if not player then
minetest.log("action", "Tried to access undefined player") minetest.log("error", "[rspawn] Levvy : Tried to access undefined player")
return false return false
end end
@ -41,7 +41,7 @@ local function find_levvy(player)
local total_count = 0 local total_count = 0
if not player_inv then if not player_inv then
minetest.log("action", "Could not access inventory for "..pname) minetest.log("error", "[rspawn] Levvy : Could not access inventory for "..pname)
return false return false
end end
@ -67,7 +67,7 @@ end
function rspawn:consume_levvy(player) function rspawn:consume_levvy(player)
if not player then if not player then
minetest.log("action", "Tried to access undefined player") minetest.log("error", "[rspawn] Levvy : Tried to access undefined player")
return false return false
end end
@ -103,10 +103,6 @@ function rspawn:consume_levvy(player)
return false return false
end end
local function d(stuff)
minetest.debug(dump(stuff))
end
-- Visitation rights check -- Visitation rights check
local function canvisit(hostname, guestname) local function canvisit(hostname, guestname)
@ -136,12 +132,14 @@ function rspawn.guestlists:addplayer(hostname, guestname)
if guestlist[guestname] ~= nil then if guestlist[guestname] ~= nil then
if guestlist[guestname] == GUEST_BAN then if guestlist[guestname] == GUEST_BAN then
minetest.chat_send_player(guestname, hostname.." let you back into their spawn.") minetest.chat_send_player(guestname, hostname.." let you back into their spawn.")
minetest.log("action", "[rspawn] "..hostname.." lifted exile on "..guestname)
end end
guestlist[guestname] = GUEST_ALLOW guestlist[guestname] = GUEST_ALLOW
elseif rspawn:consume_levvy(minetest.get_player_by_name(hostname) ) then -- Automatically notifies host if they don't have enough elseif rspawn:consume_levvy(minetest.get_player_by_name(hostname) ) then -- Automatically notifies host if they don't have enough
guestlist[guestname] = GUEST_ALLOW guestlist[guestname] = GUEST_ALLOW
minetest.chat_send_player(guestname, hostname.." added you to their spawn! You can now visit them with /spawn visit "..hostname) minetest.chat_send_player(guestname, hostname.." added you to their spawn! You can now visit them with /spawn visit "..hostname)
minetest.log("action", "[rspawn] "..hostname.." added "..guestname.." to their spawn")
else else
return return
end end
@ -149,7 +147,6 @@ function rspawn.guestlists:addplayer(hostname, guestname)
minetest.chat_send_player(hostname, guestname.." is allowed to visit your spawn.") minetest.chat_send_player(hostname, guestname.." is allowed to visit your spawn.")
rspawn.playerspawns["guest lists"][hostname] = guestlist rspawn.playerspawns["guest lists"][hostname] = guestlist
rspawn:spawnsave() rspawn:spawnsave()
minetest.log("action", "rspawn - "..hostname.." adds "..guestname.." to their spawn")
end end
function rspawn.guestlists:exileplayer(hostname, guestname) function rspawn.guestlists:exileplayer(hostname, guestname)
@ -174,15 +171,10 @@ function rspawn.guestlists:exileplayer(hostname, guestname)
return true return true
end end
function rspawn.guestlists:kickplayer(callername, guestname) function rspawn.guestlists:kickplayer(hostname, guestname)
if rspawn.guestlists:exileplayer(hostname, guestname) then
-- Caller is an explicit non-exiled guest minetest.chat_send_player(hostname, "Evicted "..guestname.." from your spawn")
if hostname then minetest.log("action", "rspawn - "..hostname.." evicts "..guestname)
else
if rspawn.guestlists:exileplayer(callername, guestname) then
minetest.chat_send_player(callername, "Evicted "..guestname.." from "..callername.."'s spawn")
minetest.log("action", "rspawn - "..callername.." evicts "..guestname)
end
end end
end end
@ -195,8 +187,16 @@ function rspawn.guestlists:listguests(hostname)
guests = ", You are an active town host." guests = ", You are an active town host."
end end
-- Explicit guests
for guestname,status in pairs(guestlist) do for guestname,status in pairs(guestlist) do
if status == GUEST_ALLOW then status = "" else status = " (exiled)" end if status == GUEST_ALLOW then status = "" else status = " (exiled guest)" end
guests = guests..", "..guestname..status
end
-- Town bans - always list so this can be maanged even when town is closed
for guestname,status in pairs(global_hosts[hostname] or {}) do
if status == GUEST_ALLOW then status = "" else status = " (banned from town)" end
guests = guests..", "..guestname..status guests = guests..", "..guestname..status
end end
@ -249,17 +249,27 @@ function rspawn.guestlists:visitplayer(hostname, guestname)
end end
if guest and canvisit(hostname, guestname) then if guest and canvisit(hostname, guestname) then
minetest.log("action", "[rspawn] "..guestname.." visits "..hostname.." (/spawn visit)")
guest:setpos(hostpos) guest:setpos(hostpos)
else else
minetest.chat_send_player(guestname, "Could not visit "..hostname) minetest.chat_send_player(guestname, "Could not visit "..hostname)
end end
end end
local function act_on_behalf(hostname, callername)
return hostname == callername or -- caller is the town owner, always allow
( -- caller can act on behalf of town owner
rspawn.playerspawns["guest lists"][hostname] and
rspawn.playerspawns["guest lists"][hostname][callername] == GUEST_ALLOW
)
end
local function townban(callername, guestname, hostname) local function townban(callername, guestname, hostname)
if not (callername and guestname) then return end if not (callername and guestname) then return end
hostname = hostname or callername hostname = hostname or callername
if hostname == callername or (rspawn.playerspawns["guest lists"][hostname] and rspawn.playerspawns["guest lists"][hostname][callername] == GUEST_ALLOW) then
if act_on_behalf(hostname, callername) then
if not rspawn.playerspawns["town lists"][hostname] then if not rspawn.playerspawns["town lists"][hostname] then
minetest.chat_send_player(callername, "No such town "..hostname) minetest.chat_send_player(callername, "No such town "..hostname)
return return
@ -268,7 +278,7 @@ local function townban(callername, guestname, hostname)
rspawn.playerspawns["town lists"][hostname][guestname] = GUEST_BAN rspawn.playerspawns["town lists"][hostname][guestname] = GUEST_BAN
minetest.chat_send_player(callername, "Evicted "..guestname.." from "..hostname.."'s spawn") minetest.chat_send_player(callername, "Evicted "..guestname.." from "..hostname.."'s spawn")
minetest.log("action", "rspawn - "..callername.." evicts "..guestname.." on behalf of "..hostname) minetest.log("action", "[rspawn] - "..callername.." evicts "..guestname.." on behalf of "..hostname)
else else
minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname) minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname)
end end
@ -279,7 +289,7 @@ local function townunban(callername, guestname, hostname)
if not (callername and guestname) then return end if not (callername and guestname) then return end
hostname = hostname or callername hostname = hostname or callername
if hostname == callername or (rspawn.playerspawns["guest lists"][hostname] and rspawn.playerspawns["guest lists"][hostname][callername] == GUEST_ALLOW) then if act_on_behalf(hostname, callername) then
if not rspawn.playerspawns["town lists"][hostname] then if not rspawn.playerspawns["town lists"][hostname] then
minetest.chat_send_player(callername, "No such town "..hostname) minetest.chat_send_player(callername, "No such town "..hostname)
return return
@ -288,7 +298,7 @@ local function townunban(callername, guestname, hostname)
rspawn.playerspawns["town lists"][hostname][guestname] = nil rspawn.playerspawns["town lists"][hostname][guestname] = nil
minetest.chat_send_player(callername, "Evicted "..guestname.." from "..hostname.."'s spawn") minetest.chat_send_player(callername, "Evicted "..guestname.." from "..hostname.."'s spawn")
minetest.log("action", "rspawn - "..callername.." evicts "..guestname.." on behalf of "..hostname) minetest.log("action", "[rspawn] - "..callername.." lifts eviction on "..guestname.." on behalf of "..hostname)
else else
minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname) minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname)
end end
@ -309,10 +319,12 @@ function rspawn.guestlists:townset(hostname, params)
if mode == "open" then if mode == "open" then
town_banlist["town status"] = "on" town_banlist["town status"] = "on"
minetest.chat_send_all(hostname.." is opens access to all!") minetest.chat_send_all(hostname.." is opens access to all!")
minetest.log("action", "[rspawn] town: "..hostname.." sets their spawn to open")
elseif mode == "close" then elseif mode == "close" then
town_banlist["town status"] = "off" town_banlist["town status"] = "off"
minetest.chat_send_all(hostname.." closes town access - only guests may directly visit.") minetest.chat_send_all(hostname.." closes town access - only guests may directly visit.")
minetest.log("action", "[rspawn] town: "..hostname.." sets their spawn to closed")
elseif mode == "status" then elseif mode == "status" then
minetest.chat_send_player(hostname, "Town mode is: "..town_banlist["town status"]) minetest.chat_send_player(hostname, "Town mode is: "..town_banlist["town status"])
@ -355,14 +367,21 @@ minetest.register_globalstep(function(dtime)
for hostname,host_guestlist in pairs(rspawn.playerspawns[player_list_name] or {}) do for hostname,host_guestlist in pairs(rspawn.playerspawns[player_list_name] or {}) do
if host_guestlist[guestname] == GUEST_BAN then if host_guestlist[guestname] == GUEST_BAN then
-- Check distance of guest from banned pos
local vdist = vector.distance(guestpos, rspawn.playerspawns[hostname]) local vdist = vector.distance(guestpos, rspawn.playerspawns[hostname])
if vdist < exile_distance then -- Check distance of guest from their own pos
-- If their spawn is very close to one they are banned from,
-- and they are close to their own, kick should not occur
local sdist = vector.distance(guestpos, rspawn.playerspawns[guestname])
if vdist < exile_distance and sdist > exile_distance then
guest:setpos(rspawn.playerspawns[guestname]) guest:setpos(rspawn.playerspawns[guestname])
minetest.chat_send_player(guestname, "You got too close to "..hostname.."'s turf.") minetest.chat_send_player(guestname, "You got too close to "..hostname.."'s turf.")
minetest.log("action", "[rspawn] Auto-kicked "..guestname.." for being too close to "..hostname.."'s spawn")
return return
elseif vdist < exile_distance*1.5 then elseif vdist < exile_distance*1.5 and sdist > exile_distance then
minetest.chat_send_player(guestname, "You are getting too close to "..hostname.."'s turf.") minetest.chat_send_player(guestname, "You are getting too close to "..hostname.."'s turf.")
return return
end end