From 976853c6cbe1f6692d30217a26e5491abe21202e Mon Sep 17 00:00:00 2001 From: Tai Kedzierski Date: Wed, 30 Jan 2019 10:22:15 +0000 Subject: [PATCH] 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. --- README.md | 13 ++++++--- lua/debugging.lua | 8 +++++- lua/guestlists.lua | 67 +++++++++++++++++++++++++++++----------------- 3 files changed, 60 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 07f5c6b..58e27ab 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # `[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 @@ -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`). * Commands * 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 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. @@ -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 hosts` - see whose spawns you may visit +Guests can help the spawn owner manage bans on their town. + ### 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 ` 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 } []` - ban or unban a player from a town * 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 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 * (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. diff --git a/lua/debugging.lua b/lua/debugging.lua index 4da10d3..7765506 100644 --- a/lua/debugging.lua +++ b/lua/debugging.lua @@ -1,4 +1,10 @@ +function rspawn:d(stuff) + -- Quick debugging + minetest.debug(dump(stuff)) +end + function rspawn:debug(message, data) + -- Debugging from setting if not rspawn.debug_on then return end @@ -8,7 +14,7 @@ function rspawn:debug(message, data) if data ~= nil then debug_data = " :: "..dump(data) end - local debug_string = "rspawn : "..message..debug_data + local debug_string = "[rspawn] DEBUG : "..message..debug_data minetest.debug(debug_string) end diff --git a/lua/guestlists.lua b/lua/guestlists.lua index 849195e..f126bfd 100644 --- a/lua/guestlists.lua +++ b/lua/guestlists.lua @@ -32,7 +32,7 @@ local function find_levvy(player) local i if not player then - minetest.log("action", "Tried to access undefined player") + minetest.log("error", "[rspawn] Levvy : Tried to access undefined player") return false end @@ -41,7 +41,7 @@ local function find_levvy(player) local total_count = 0 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 end @@ -67,7 +67,7 @@ end function rspawn:consume_levvy(player) if not player then - minetest.log("action", "Tried to access undefined player") + minetest.log("error", "[rspawn] Levvy : Tried to access undefined player") return false end @@ -103,10 +103,6 @@ function rspawn:consume_levvy(player) return false end -local function d(stuff) - minetest.debug(dump(stuff)) -end - -- Visitation rights check local function canvisit(hostname, guestname) @@ -136,12 +132,14 @@ function rspawn.guestlists:addplayer(hostname, guestname) if guestlist[guestname] ~= nil then if guestlist[guestname] == GUEST_BAN then minetest.chat_send_player(guestname, hostname.." let you back into their spawn.") + minetest.log("action", "[rspawn] "..hostname.." lifted exile on "..guestname) end guestlist[guestname] = GUEST_ALLOW elseif rspawn:consume_levvy(minetest.get_player_by_name(hostname) ) then -- Automatically notifies host if they don't have enough 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.log("action", "[rspawn] "..hostname.." added "..guestname.." to their spawn") else return end @@ -149,7 +147,6 @@ function rspawn.guestlists:addplayer(hostname, guestname) minetest.chat_send_player(hostname, guestname.." is allowed to visit your spawn.") rspawn.playerspawns["guest lists"][hostname] = guestlist rspawn:spawnsave() - minetest.log("action", "rspawn - "..hostname.." adds "..guestname.." to their spawn") end function rspawn.guestlists:exileplayer(hostname, guestname) @@ -174,15 +171,10 @@ function rspawn.guestlists:exileplayer(hostname, guestname) return true end -function rspawn.guestlists:kickplayer(callername, guestname) - - -- Caller is an explicit non-exiled guest - if hostname then - 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 +function rspawn.guestlists:kickplayer(hostname, guestname) + if rspawn.guestlists:exileplayer(hostname, guestname) then + minetest.chat_send_player(hostname, "Evicted "..guestname.." from your spawn") + minetest.log("action", "rspawn - "..hostname.." evicts "..guestname) end end @@ -195,8 +187,16 @@ function rspawn.guestlists:listguests(hostname) guests = ", You are an active town host." end + -- Explicit guests 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 end @@ -249,17 +249,27 @@ function rspawn.guestlists:visitplayer(hostname, guestname) end if guest and canvisit(hostname, guestname) then + minetest.log("action", "[rspawn] "..guestname.." visits "..hostname.." (/spawn visit)") guest:setpos(hostpos) else minetest.chat_send_player(guestname, "Could not visit "..hostname) 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) if not (callername and guestname) then return end 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 minetest.chat_send_player(callername, "No such town "..hostname) return @@ -268,7 +278,7 @@ local function townban(callername, guestname, hostname) rspawn.playerspawns["town lists"][hostname][guestname] = GUEST_BAN 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 minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname) end @@ -279,7 +289,7 @@ local function townunban(callername, guestname, hostname) if not (callername and guestname) then return end 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 minetest.chat_send_player(callername, "No such town "..hostname) return @@ -288,7 +298,7 @@ local function townunban(callername, guestname, hostname) rspawn.playerspawns["town lists"][hostname][guestname] = nil 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 minetest.chat_send_player(callername, "You are not permitted to act on behalf of "..hostname) end @@ -309,10 +319,12 @@ function rspawn.guestlists:townset(hostname, params) if mode == "open" then town_banlist["town status"] = "on" 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 town_banlist["town status"] = "off" 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 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 if host_guestlist[guestname] == GUEST_BAN then + -- Check distance of guest from banned pos 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]) 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 - 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.") return end