From 34fa2fc7faa0da7b24c0a4762ba9eb51162909ad Mon Sep 17 00:00:00 2001 From: Evert Prants Date: Sun, 13 Jan 2019 01:27:26 +0200 Subject: [PATCH] more commands --- chat.lua | 23 +++++++-- flatfile.lua | 4 +- init.lua | 71 +++++++++++++------------- town.lua | 139 +++++++++++++++++++++++++++++++++++++++++---------- 4 files changed, 167 insertions(+), 70 deletions(-) diff --git a/chat.lua b/chat.lua index d8d5d37..5fac2f2 100644 --- a/chat.lua +++ b/chat.lua @@ -115,7 +115,7 @@ local function town_command (name, param) local town = towny:get_player_town(name) -- Pre town requirement - local print_town_info = nil + local town_info = nil if (pr1 == "create" or pr1 == "new") and pr2 then return towny:create_town(nil, name, pr2) @@ -125,16 +125,16 @@ local function town_command (name, param) 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 + town_info = pr2 else return false, "No such town." end elseif param == "" and town then - print_town_info = town + town_info = town end -- Print town information - if print_town_info then + if town_info then return false, "Not yet implemented!" end @@ -169,11 +169,26 @@ 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 param == "greeting" then + local tdata = towny.towns[town] + if not tdata.flags["greeting"] then return false, "This town has no greeting message." end + + return true, + minetest.colorize("#078e36", ("[%s] "):format(towny:get_full_name(town))) .. + minetest.colorize("#02aacc", tdata.flags["greeting"]) 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) + elseif pr1 == "member" then + local action, user = string.match(pr2, "^([%a%d_-]+) (.+)$") + if action == "kick" then + return towny:kick_member(town,name,pr2) + elseif action == "set" then + local target, flag, value = string.match(user, "^([%a%d_-]+) ([%a%d_-]+) (.+)$") + return towny:set_town_member_flags(nil,name,target,flag,value) + end end -- Plot management commands diff --git a/flatfile.lua b/flatfile.lua index 4a27e68..cf1905c 100644 --- a/flatfile.lua +++ b/flatfile.lua @@ -8,8 +8,8 @@ function towny.flatfile:write_meta(town,dir,data) local filepath = town.."."..extension minetest.mkdir(directory) - if data.dirty then data.dirty = nil end - if data.level then data.level = nil end + data.dirty = nil + data.level = nil local serialized if serialize then diff --git a/init.lua b/init.lua index 8789c8e..f8e42e4 100644 --- a/init.lua +++ b/init.lua @@ -68,6 +68,40 @@ towny = { claimblocks = 448, } }, + flags = { + town = { + ['town_build'] = {"boolean", "lets everyone build in unplotted town claims"}, + ['plot_build'] = {"boolean", "lets everyone build in unowned town plots"}, + ['plot_member_build'] = {"boolean", "if false, plot members don't have build rights to plots by default"}, + ['teleport'] = {"vector", "town teleport point"}, + ['pvp'] = {"boolean", "players can fight in the town if true, ignores server pvp settings"}, + ['plot_pvp'] = {"boolean", "default plot pvp setting. defaults to false"}, + ['joinable'] = {"boolean", "if true, anyone can join this town. defaults to false"}, + ['greeting'] = {"string", "town's greeting message"}, + ['tax'] = {"number", "how much each member has to pay each day to stay in town"}, + ['bank'] = {"number", "town's treasury", false}, + ['claim_blocks'] = {"number", "town's bonus claim blocks", false}, + ['origin'] = {"vector", "town's center position, set at town creation", false}, + }, + town_member = { + ['town_build'] = {"boolean", "member can build in unplotted town claims"}, + ['claim_create'] = {"boolean", "member can claim land for the town"}, + ['claim_delete'] = {"boolean", "member can abandon claim blocks"}, + ['plot_create'] = {"boolean", "member can create plots"}, + ['plot_delete'] = {"boolean", "member can delete plots"}, + }, + plot = { + ['teleport'] = {"vector", "plot's teleport point"}, + ['pvp'] = {"boolean", "players can fight here if true, ignores server pvp settings"}, + ['cost'] = {"number", "plot cost (only with economy)"}, + ['claimable'] = {"boolean", "is this plot available for claiming. if cost is more than 0, require payment"}, + ['greeting'] = {"string", "plot's greeting message (defaults to \"{owner}'s Plot\"/\"Unclaimed Plot\")"}, + }, + plot_member = { + ['plot_build'] = {"boolean", "member can build on plot. defaults to 'plot_member_build' town flag"}, + ['build'] = "plot_build", + }, + }, -- Set to true if files need to be updated dirty = false, @@ -103,43 +137,6 @@ towny = { } ]] --- Town-specific flags ---[[ - 'town_build' boolean lets everyone build in unplotted town claims - 'plot_build' boolean lets everyone build in unowned town plots - 'plot_member_build' boolean if false, plot members don't have build rights to plots by default - 'teleport' position town teleport point - 'pvp' boolean players can fight in the town if true, ignores server pvp settings - 'plot_pvp' boolean default plot pvp setting. defaults to false - 'joinable' boolean if true, anyone can join this town. defaults to false - 'greeting' string town's greeting message - 'tax' float how much each member has to pay each day to stay in town (only with economy) - 'bank' float town's wealth (only with economy) (unchangeable by owner) - 'claim_blocks' int town's bonus claim blocks (unchangeable by owner) - 'origin' position town's center position, set at town creation (unchangeable by owner) -]] - --- Members with flags ---[[ - 'plot_build' boolean if 'plot_member_build' town flag is false, - this one must be true for a plot member to be able to build on a plot. - If set to true in town flags, this member can build in all plots. - 'town_build' boolean if true, this member can build in town claims. - 'claim_create' boolean if true, this member can claim land for the town - 'claim_delete' boolean if true, this member can abandon claim blocks - 'plot_create' boolean if true, this member can create plots - 'plot_delete' boolean if true, this member can delete plots -]] - --- Plot-specific flags ---[[ - 'teleport' position plot's teleport point - 'pvp' boolean players can fight here if true, ignores server pvp settings - 'cost' float plot cost (only with economy) - 'claimable' boolean is this plot available for claiming. if cost is more than 0, require payment - 'greeting' string plot's greeting message (defaults to "{owner}'s Plot"/"Unclaimed Plot") -]] - dofile(modpath.."/flatfile.lua") dofile(modpath.."/visualize.lua") dofile(modpath.."/regions.lua") diff --git a/town.lua b/town.lua index 4ba6273..b01b332 100644 --- a/town.lua +++ b/town.lua @@ -12,6 +12,45 @@ local function count(T) return count 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" and pos 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 + value = minetest.string_to_pos(value) + end + end + return value +end + +local function flag_validity(flag,scope,value,pos) + value = flag_typeify(value,pos) + if value == nil then return true end + local spd = towny.flags[scope] + if type(spd[flag]) == "string" then + flag = spd[flag] + end + + if not spd[flag] then return false end + if spd[flag][3] == false then return false end + + if spd[flag][1] == "vector" and (not value.x or not value.y or not value.z) then + return false + elseif spd[flag][1] ~= "vary" and type(value) ~= spd[flag][1] then + return false + end + + return true, flag, value +end + function towny:get_player_town(name) for town,data in pairs(towny.towns) do if data.mayor == name then @@ -515,25 +554,6 @@ function towny:plot_member(pos,player,member,action) 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 - value = minetest.string_to_pos(value) - end - end - return value -end - -- Set flags function towny:set_plot_flags(pos,player,flag,value) @@ -563,9 +583,13 @@ function towny:set_plot_flags(pos,player,flag,value) return err_msg(player, "You do not have permission to modify this plot.") end - minetest.chat_send_player(player, ("Successfully set the plot flag '%s' to '%s'!") - :format(flag, value)) - plot_data.flags[flag] = flag_typeify(value,pos) + local fs,flag,res = flag_validity(flag, 'plot', value, pos) + if not fs then + return err_msg(player, "Invalid flag or flag value.") + end + + minetest.chat_send_player(player, ("Successfully set the plot flag '%s' to '%s'!"):format(flag, value)) + plot_data.flags[flag] = res towny:mark_dirty(t, false) end @@ -600,11 +624,14 @@ function towny:set_plot_member_flags(pos,player,member,flag,value) return err_msg(player, "There is no such member in this plot.") end - if flag == "build" then flag = "plot_build" end + local fs,flag,res = flag_validity(flag, 'plot_member', value, pos) + if not fs then + return err_msg(player, "Invalid flag or flag value.") + end minetest.chat_send_player(player, ("Successfully set the plot member %s's flag '%s' to '%s'!") :format(member, flag, value)) - plot_data.members[member][flag] = flag_typeify(value,pos) + plot_data.members[member][flag] = res towny:mark_dirty(t, false) end @@ -630,12 +657,50 @@ function towny:set_town_flags(pos,player,flag,value) return err_msg(player, "You do not have permission to modify this town.") end - if (flag == 'bank' or flag == 'claim_blocks' or flag == 'origin') and not towny_admin then - return err_msg(player, "You cannot change this flag.") + local fs,flag,res = flag_validity(flag, 'town', value, pos) + if not fs then + return err_msg(player, "Invalid flag or invalid or unchangeable flag value.") end minetest.chat_send_player(player, ("Successfully set the town flag '%s' to '%s'!"):format(flag,value)) - data.flags[flag] = flag_typeify(value,pos) + data.flags[flag] = res + towny:mark_dirty(t, false) +end + +function towny:set_town_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 + + local data = towny.towns[t] + if data.mayor ~= player and not towny_admin then + return err_msg(player, "You do not have permission to modify this town.") + end + + if not data.members[member] then + return err_msg(player, "There is no such member in this town.") + end + + local fs,flag,res = flag_validity(flag, 'town_member', value, pos) + if not fs then + return err_msg(player, "Invalid flag or flag value.") + end + + minetest.chat_send_player(player, ("Successfully set the town member %s's flag '%s' to '%s'!") + :format(member, flag, value)) + data.members[member][flag] = res towny:mark_dirty(t, false) end @@ -695,6 +760,13 @@ function towny:get_member_count(town) return count(tdata.members) end +function towny:get_full_name(town) + local tdata = towny.towns[town] + if not tdata then return nil end + if not tdata.level then return tdata.name end + return ("%s (%s)"):format(tdata.name, tdata.level.name_tag) +end + function towny:get_town_level(town, update) local tdata = towny.towns[town] if not tdata then return nil end @@ -708,3 +780,16 @@ function towny:get_town_level(town, update) tdata.level = lvl return lvl end + +minetest.register_on_joinplayer(function (player) + local town = towny:get_player_town(player:get_player_name()) + if not town then return end + + local tdata = towny.towns[town] + if not tdata then return nil end + if not tdata.flags["greeting"] then return nil end + + minetest.chat_send_player(player:get_player_name(), + minetest.colorize("#078e36", ("[%s] "):format(towny:get_full_name(town))) .. + minetest.colorize("#02aacc", tdata.flags["greeting"])) +end)