Chat commands

This commit is contained in:
Evert Prants 2019-01-12 22:12:06 +02:00
parent 2539ece481
commit 2853a8e3bc
Signed by: evert
GPG Key ID: 1688DA83D222D0B5
3 changed files with 425 additions and 15 deletions

150
chat.lua
View File

@ -10,17 +10,127 @@ minetest.register_privilege("towny_admin", {
give_to_singleplayer = false
})
-- API
-- Send message to all town members who are online
function towny.chat:announce_to_members(town,message)
local tdata = towny.towns[town]
if tdata then
for member in pairs(tdata.members) do
if minetest.get_player_by_name(member) then
minetest.chat_send_player(member,message)
end
end
end
end
-- Commands
local function invite_player(town,player,target)
local utown = towny:get_player_town(player)
if not utown or utown ~= town then
return false, "You are not in a town."
end
local target_town = towny:get_player_town(target)
if target_town then
return false, "This player is already in a town!"
end
if towny.chat.invites[town.."-"..target] then
return false, "This player has already been invited to join your town!"
end
local tdata = towny.towns[town]
minetest.chat_send_player(target, "You have been invited to join town '"..tdata.name.."' by "..player)
minetest.chat_send_player(target, "You can accept this invite by typing '/town invite accept' or deny '/town invite deny'")
towny.chat.invites[town.."-"..target] = { rejected = false, town = town, player = target, invited = player }
return true, "Player "..target.." has been invited to join your town."
end
local function join_town(town,player,from_invite)
local tdata = towny.towns[town]
if not tdata then return false, "No such town" end
if (not from_invite and not tdata.flags['joinable']) then return false, "You cannot join this town." end
towny.chat:announce_to_members(town, minetest.colorize("#02aacc", player.." has joined the town!"))
minetest.chat_send_player(player, "You have successfully joined the town '"..tdata.name.."'!")
tdata.members[player] = {}
return true
end
local function invite_respond(player,response)
local utown = towny:get_player_town(player)
if utown or utown ~= town then
return false, "You are already in a town."
end
for id,data in pairs(towny.chat.invites) do
if data.player == player then
if not data.rejected then
if response == true then
towny.chat.invites[id] = nil
return join_town(data.town,player,true)
else
towny.chat.invites[id] = { rejected = true }
return true, "You have rejected the join request."
end
end
end
end
return false, "You do not have any pending invites."
end
local function send_flags (player,flags,message)
local shiny = {}
for flag,value in pairs(flags) do
if type(value) == "table" then
if value.x and value.y and value.z then
value = minetest.pos_to_string(value)
else
value = dump(value)
end
elseif type(value) == "boolean" then
local str_value = "true"
if value == false then str_value = "false" end
value = str_value
end
shiny[#shiny+1] = flag..": "..value
end
return true, message ..": "..table.concat( shiny, ", " )
end
local function town_command (name, param)
if not minetest.get_player_by_name(name) then return false, "Can't run command on behalf of offline player." end
local pr1, pr2 = string.match(param, "^([%a%d_-]+) (.+)$")
local town = towny:get_player_town(name)
-- Pre town requirement
local print_town_info = nil
if (pr1 == "create" or pr1 == "new") and pr2 then
return towny:create_town(nil, name, pr2)
elseif (pr1 == "invite" and not minetest.get_player_by_name(pr2)) then
local tyes = pr2:lower()
return invite_respond(name, (tyes == "accept" or tyes == "yes" or tyes == "y"))
elseif pr1 == "join" and towny:get_town_by_name(pr2) and not town then
return join_town(pr2,name,false)
elseif pr1 == "show" or pr1 == "info" then
if towny:get_town_by_name(pr2) then
print_town_info = pr2
else
return false, "No such town."
end
elseif param == "" and town then
print_town_info = town
end
-- Print town information
if print_town_info then
return false, "Not yet implemented!"
end
if not town then
@ -39,6 +149,11 @@ local function town_command (name, param)
elseif param == "visualize" then
towny.regions:visualize_town(town)
return true
elseif param == "flags" then
local flags = towny:get_flags(town)
if flags then
return send_flags(player,flags,"Flags of your town")
end
elseif (param == "delete" or param == "abandon") or (pr1 == "delete" or pr1 == "abandon") then
if towny.chat['delete_verify_' .. name] and pr2 == "I WANT TO DELETE MY TOWN" then
towny.chat['delete_verify_' .. name] = nil
@ -49,12 +164,45 @@ local function town_command (name, param)
"WARNING! Deleting your town will render ALL of the buildings in it without protection!"))
return false, "Please run the command again with 'I WANT TO DELETE MY TOWN' in all caps written after it."
end
elseif pr1 == "kick" then
return towny:kick_member(town,name,pr2)
elseif pr1 == "set" then
local flag, value = string.match(pr2, "^([%a%d_-]+) (.+)$")
return towny:set_town_flags(nil,name,flag,value)
end
-- Plot management commands
if pr1 == "plot" then
local pl1, pl2 = string.match(pr2, "^([%a%d_-]+) (.+)$")
if pr2 == "claim" then
return towny:claim_plot(nil,name)
elseif pr2 == "abandon" then
return towny:abandon_plot(nil,name)
elseif pr2 == "delete" then
return towny:delete_plot(nil,name)
elseif pr2 == "flags" then
local flags = towny:get_plot_flags(town,nil,name)
if flags then
return send_flags(player,flags,"Flags of this plot")
else
return false, "There's no plot here."
end
elseif pl1 == "set" and pl2 then
local flag, value = string.match(pl2, "^([%a%d_-]+) (.+)$")
return towny:set_plot_flags(nil,name,flag,value)
elseif pl1 == "member" and pl2 then
local action, user = string.match(pl2, "^([%a%d_-]+) (.+)$")
if action == "add" then
return towny:plot_member(nil,name,user,1)
elseif action == "remove" or action == "del" or action == "kick" then
return towny:plot_member(nil,name,user,0)
elseif action == "set" then
local target, flag, value = string.match(user, "^([%a%d_-]+) ([%a%d_-]+) (.+)$")
return towny:set_plot_member_flags(nil,name,target,flag,value)
end
end
elseif pr1 == "invite" and minetest.get_player_by_name(pr2) then
return invite_player(town,name,pr2)
end
return false, "Invalid command usage."

View File

@ -3,11 +3,11 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
towny = {
claimbonus = minetest.settings:get('towny_claim_bonus') or 8,
claimbonus = tonumber(minetest.settings:get('towny_claim_bonus')) or 8,
regions = {
size = minetest.settings:get('towny_claim_size') or 16,
maxclaims = minetest.settings:get('towny_claim_max') or 128,
distance = minetest.settings:get('towny_distance') or 80,
size = tonumber(minetest.settings:get('towny_claim_size')) or 16,
maxclaims = tonumber(minetest.settings:get('towny_claim_max')) or 128,
distance = tonumber(minetest.settings:get('towny_distance')) or 80,
-- Regions loaded into memory cache, see "Town regions data structure"
memloaded = {},
@ -15,7 +15,11 @@ towny = {
-- See "Town data structure"
flatfile = {},
towns = {},
chat = {},
chat = {
chatmod = (minetest.settings:get('towny_chat') == "true") or true,
questionaire = (minetest.settings:get('towny_questionaire') == "true") or true,
invites = {},
},
-- Set to true if files need to be updated
dirty = false,

272
town.lua
View File

@ -17,6 +17,7 @@ function towny:get_player_town(name)
end
function towny:get_town_by_name(name)
if not name then return nil end
for town,data in pairs(towny.towns) do
if data.name:lower() == name:lower() then
return town
@ -165,7 +166,7 @@ function towny:abridge_town(pos,player)
return true
end
function towny:leave_town(player)
function towny:leave_town(player,kick)
local town = towny:get_player_town(player)
if not town then
return err_msg(player, "You're not currently in a town!")
@ -207,11 +208,39 @@ function towny:leave_town(player)
pdata.members = members
end
local msg = "You successfully left the town."
if kick then
msg = "You were kicked form town."
end
towny:mark_dirty(town, false)
minetest.chat_send_player(player, "You successfully left the town.")
minetest.chat_send_player(player, msg)
return true
end
function towny:kick_member(town,player,member)
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
local data = towny.towns[town]
if data.mayor ~= player and not towny_admin then
return err_msg(player, "You do not have permission to kick people from this town.")
end
if not data.members[member] then
return err_msg(player, "User "..member.." is not in this town.")
end
if member == data.mayor then
return err_msg(player, "You cannot kick the town mayor.")
end
if player == member then
return err_msg(player, "You cannot kick yourself from town.")
end
return towny:leave_town(member,true)
end
function towny:delete_town(pos,player)
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos then
@ -267,7 +296,7 @@ function towny:delete_plot(pos,player)
return err_msg(player, "You do not have permission to delete this plot.")
end
towny.regions:set_plot(c,t,nil)
towny.regions:set_plot(c[1],t,nil)
data.plots[p] = nil
towny:mark_dirty(t, true)
@ -320,12 +349,174 @@ function towny:create_plot(pos,player)
return true
end
local function flag_typeify(value)
function towny:claim_plot(pos,player)
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
end
local town = towny:get_player_town(player)
if not town then
return err_msg(player, "You're not currently in a town!")
end
local t,p,c = towny.regions:get_town_at(pos)
if not t or t ~= town then
return err_msg(player, "You are not in any town you can modify.")
end
local tdata = towny.towns[t]
if p ~= nil then
local plot_data = tdata.plots[p]
if plot_data.flags['claimable'] or player == tdata.mayor then
if plot_data.owner == player or plot_data.members[player] then
return err_msg(player, "You are already a member of this plot.")
end
-- TODO: enconomy
tdata.plots[p] = {
owner = player,
members = {[player] = {}},
flags = {},
}
towny:mark_dirty(t, false)
minetest.chat_send_player(player, "Successfully claimed the plot!")
towny.regions:visualize_radius(vector.subtract(c[1], {x=tr/2,y=tr/2,z=tr/2}))
return true
else
return err_msg(player, "This plot is not for sale.")
end
end
return towny:create_plot(pos,player)
end
function towny:abandon_plot(pos,player)
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
end
local town = towny:get_player_town(player)
if not town then
return err_msg(player, "You're not currently in a town!")
end
local t,p,c = towny.regions:get_town_at(pos)
if not t or t ~= town then
return err_msg(player, "You are not in any town you can modify.")
end
if p == nil then
return err_msg(player, "There is no plot here.")
end
local tdata = towny.towns[t]
local pdata = tdata.plots[p]
if not pdata.members[player] then
return err_msg(player, "You are not a member of this plot.")
end
-- Update plot members
local members = {}
if pdata.owner == player then
pdata.owner = nil
if pdata.flags["greeting"] ~= nil then
pdata.flags["greeting"] = nil
end
end
for mem,dat in pairs(pdata.members) do
if mem ~= player then
-- Transfer ownership to the first other member
if pdata.owner == nil then
pdata.owner = mem
end
members[mem] = dat
end
end
pdata.members = members
towny:mark_dirty(t, false)
minetest.chat_send_player(player, "Successfully abandoned the plot!")
return true
end
function towny:plot_member(pos,player,member,action)
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
end
local town = towny:get_player_town(player)
if not town then
return err_msg(player, "You're not currently in a town!")
end
local t,p,c = towny.regions:get_town_at(pos)
if not t or t ~= town then
return err_msg(player, "You are not in any town you can modify.")
end
if p == nil then
return err_msg(player, "There is no plot here.")
end
local tdata = towny.towns[t]
local pdata = tdata.plots[p]
if pdata.owner ~= player and player ~= tdata.mayor and not towny_admin then
return err_msg(player, "You do not have permission to modify this plot.")
end
if not tdata.members[member] then
return err_msg(player, "User '"..member.."' is not part of this town.")
end
-- Update plot members
local members = {}
local action_desc = "add yourself to"
if action == 0 then
action_desc = "remove yourself from"
end
if member == pdata.owner then
return err_msg(player, "You cannot "..action_desc.." from this plot.")
end
if action == 0 then
action_desc = "removed "..member.." from"
for mem,dat in pairs(pdata.members) do
if mem ~= member then
-- Transfer ownership to the first other member
members[mem] = dat
end
end
else
action_desc = "added "..member.." to"
members = pdata.members
members[member] = {}
end
pdata.members = members
towny:mark_dirty(t, false)
minetest.chat_send_player(player, "Successfully "..action_desc.." plot!")
return true
end
local function flag_typeify(value,pos)
if type(value) == "string" then
if value == "true" then
value = true
elseif value == "false" then
value = false
elseif value == "here" then
value = pos
elseif value == "none" or value == "null" or value == "nil" then
value = nil
elseif tonumber(value) ~= nil then
value = tonumber(value)
elseif minetest.string_to_pos(value) ~= nil then
@ -335,7 +526,10 @@ local function flag_typeify(value)
return value
end
-- Set flags
function towny:set_plot_flags(pos,player,flag,value)
if not flag then return false end
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
@ -351,7 +545,7 @@ function towny:set_plot_flags(pos,player,flag,value)
return err_msg(player, "You are not in any town you can modify.")
end
if p ~= nil then
if p == nil then
return err_msg(player, "There is no plot here! Please stand in the plot you wish to modify.")
end
@ -362,11 +556,50 @@ function towny:set_plot_flags(pos,player,flag,value)
end
minetest.chat_send_player(player, "Successfully set the plot flag '" .. flag .."' to '" .. value .. "'!")
plot_data.flags[flag] = flag_typeify(value,pos)
towny:mark_dirty(t, false)
end
function towny:set_plot_member_flags(pos,player,member,flag,value)
if not member or not flag then return false end
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
end
local town = towny:get_player_town(player)
if not town and not towny_admin then
return err_msg(player, "You're not currently in a town!")
end
local t,p,c = towny.regions:get_town_at(pos)
if not t or (t ~= town and not towny_admin) then
return err_msg(player, "You are not in any town you can modify.")
end
if p == nil then
return err_msg(player, "There is no plot here! Please stand in the plot you wish to modify.")
end
local data = towny.towns[t]
local plot_data = data.plots[p]
if data.mayor ~= player and plot_data.owner ~= player and not towny_admin then
return err_msg(player, "You do not have permission to modify this plot.")
end
if not plot_data.members[member] then
return err_msg(player, "There is no such member in this plot.")
end
if flag == "build" then flag = "plot_build" end
minetest.chat_send_player(player, "Successfully set the plot member "..member.."'s flag '" .. flag .."' to '" .. value .. "'!")
plot_data.members[member][flag] = flag_typeify(value,pos)
towny:mark_dirty(t, false)
plot_data.flags[flag] = flag_typeify(value)
end
function towny:set_town_flags(pos,player,flag,value)
if not flag then return false end
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos then
pos = minetest.get_player_by_name(player):get_pos()
@ -392,8 +625,33 @@ function towny:set_town_flags(pos,player,flag,value)
end
minetest.chat_send_player(player, "Successfully set the town flag '" .. flag .."' to '" .. value .. "'!")
data.flags[flag] = flag_typeify(value,pos)
towny:mark_dirty(t, false)
data.flags[flag] = flag_typeify(value)
end
-- Get flags
function towny:get_flags(town,plot)
local tdata = towny.towns[town]
if not tdata then return nil end
if not plot then return tdata.flags end
if not tdata.plots[plot] then return nil end
return tdata.plots[plot].flags
end
function towny:get_plot_flags(town,pos,player)
local towny_admin = minetest.check_player_privs(player, { towny_admin = true })
if not pos and player then
pos = minetest.get_player_by_name(player):get_pos()
end
local t,p,c = towny.regions:get_town_at(pos)
if not t or (t ~= town and not towny_admin) then
return err_msg(player, "You are not in any town you can access.")
end
if not t or not p then return nil end
return towny:get_flags(t,p)
end
function towny:get_claims_total(town)