taller claim blocks

parent 2853a8e3
......@@ -32,6 +32,10 @@ local function invite_player(town,player,target)
return false, "You are not in a town."
end
if not minetest.get_player_by_name(target) then
return false, "You can only invite online players to your town."
end
local target_town = towny:get_player_town(target)
if target_town then
return false, "This player is already in a town!"
......@@ -43,11 +47,12 @@ local function invite_player(town,player,target)
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 have been invited to join town '%s' by %s")
:format(tdata.name, 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."
return true, ("Player %s has been invited to join your town."):format(target)
end
local function join_town(town,player,from_invite)
......@@ -55,8 +60,9 @@ local function join_town(town,player,from_invite)
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.."'!")
minetest.chat_send_player(player, ("You have successfully joined the town '%s'!"):format(tdata.name))
tdata.members[player] = {}
towny:mark_dirty(town,false)
return true
end
......@@ -114,8 +120,7 @@ local function town_command (name, param)
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"))
return invite_respond(name, (tyes:lower() == "accept" or minetest.is_yes(tyes)))
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
......
......@@ -9,6 +9,7 @@ function towny.flatfile:write_meta(town,dir,data)
minetest.mkdir(directory)
if data.dirty then data.dirty = nil end
if data.level then data.level = nil end
local serialized
if serialize then
......@@ -47,18 +48,17 @@ function towny.flatfile:load_meta(filepath)
end
function towny.flatfile:save_town_meta(town)
if not towny.towns[town] then return end
local tmeta = towny.towns[town]
if tmeta.dirty then
if tmeta and tmeta.dirty then
towny:get_town_level(town, true)
minetest.after(0.1, function ()
towny.flatfile:write_meta(town,"meta",tmeta)
tmeta.dirty = false
end)
end
if not towny.regions.memloaded[town] then return end
local rmeta = towny.regions.memloaded[town]
if rmeta.dirty then
if rmeta and rmeta.dirty then
minetest.after(0.2, function ()
towny.flatfile:write_meta(town,"region",rmeta)
rmeta.dirty = false
......@@ -80,6 +80,7 @@ function towny.flatfile:load_all_towns()
local towndata = towny.flatfile:load_meta(metadir.."/"..file)
if not towndata then return end
towny.towns[town] = towndata
towny:get_town_level(town, true)
end)
end
end
......
......@@ -3,9 +3,9 @@
local modpath = minetest.get_modpath(minetest.get_current_modname())
towny = {
claimbonus = tonumber(minetest.settings:get('towny_claim_bonus')) or 8,
regions = {
size = tonumber(minetest.settings:get('towny_claim_size')) or 16,
height = tonumber(minetest.settings:get('towny_claim_height')) or 64,
maxclaims = tonumber(minetest.settings:get('towny_claim_max')) or 128,
distance = tonumber(minetest.settings:get('towny_distance')) or 80,
......@@ -20,6 +20,54 @@ towny = {
questionaire = (minetest.settings:get('towny_questionaire') == "true") or true,
invites = {},
},
levels = {
{
members = 0,
name_tag = 'Ruins',
mayor_tag = 'Spirit',
claimblocks = 1,
}, {
members = 1,
name_tag = 'Settlement',
mayor_tag = 'Hermit',
claimblocks = 16,
}, {
members = 2,
name_tag = 'Hamlet',
mayor_tag = 'Chief',
claimblocks = 32,
}, {
members = 6,
name_tag = 'Village',
mayor_tag = 'Baron Von',
claimblocks = 96,
}, {
members = 10,
name_tag = 'Town',
mayor_tag = 'Viscount',
claimblocks = 160,
}, {
members = 14,
name_tag = 'Large Town',
mayor_tag = 'Count Von',
claimblocks = 224,
}, {
members = 20,
name_tag = 'City',
mayor_tag = 'Earl',
claimblocks = 320,
}, {
members = 24,
name_tag = 'Large City',
mayor_tag = 'Duke',
claimblocks = 384,
}, {
members = 28,
name_tag = 'Metropolis',
mayor_tag = 'Lord',
claimblocks = 448,
}
},
-- Set to true if files need to be updated
dirty = false,
......@@ -65,9 +113,9 @@ towny = {
'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
'plot_tax' float how much each plot costs each day (only with economy)
'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 available claim blocks (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)
]]
......
local tr = towny.regions.size
local th = towny.regions.height
local main_is_protected = minetest.is_protected
-- Calculate a region from the center point and radius
local function region_from_diameter(center, diameter)
local r = {x = diameter / 2, y = diameter / 2, z = diameter / 2}
return vector.subtract(center, r), vector.add(center, r)
end
-- Test to see if a position is in a region
local function pos_in_region(pos, p1, p2)
return (pos.x <= p1.x and pos.y <= p1.y and pos.z <= p1.z) and
......@@ -51,7 +46,6 @@ function towny.regions:build_perms(town, name, plotid)
-- Plot build rights
if plotid and towndata.plots[plotid] then
print(plotid, dump(towndata.plots[plotid]))
-- This flag dictates that this member can build in all town plots, no matter if they own it or not
if towndata.members[name]['plot_build'] == true then return true end
......@@ -84,7 +78,7 @@ local function single_range(p)
local p1,p2
if p.x then
p1 = p
p2 = vector.subtract(p, {x=towny.regions.size,y=towny.regions.size,z=towny.regions.size})
p2 = vector.subtract(p, {x=tr,y=th,z=tr})
elseif #p == 2 then
p1 = p[1]
p2 = p[2]
......@@ -126,7 +120,8 @@ function towny.regions:get_closest_town(pos,name)
if count and vector.distance(pos, regions.origin) <= towny.regions.size * towny.regions.maxclaims then
for _,tc in pairs(regions.blocks) do
local p1,p2 = single_range(tc)
local dist = vector.distance(pos, p1)
local center = vector.subtract(p1, {x=tr/2,y=th/2,z=tr/2})
local dist = vector.distance(pos, center)
if dist < last_distance or last_distance == 0 then
last_distance = dist
in_town = town
......@@ -150,7 +145,7 @@ end
function towny.regions:align_new_claim_block(pos,name)
local closest_town,closest_block,distance = towny.regions:get_closest_town(pos,name)
if not closest_town then return nil end
if distance > (tr * 2) then return nil end -- Too far
if distance > (tr + th) then return nil end -- Too far
local new_pos
local p1,p2 = closest_block[1],closest_block[2]
......@@ -165,9 +160,9 @@ function towny.regions:align_new_claim_block(pos,name)
-- Y
elseif (pos.x <= p1.x and pos.x >= p2.x) and (pos.z <= p1.z and pos.z >= p2.z) then
if pos.y > p1.y then
new_pos = vector.add(p1, {x=0,y=tr,z=0})
new_pos = vector.add(p1, {x=0,y=th,z=0})
else
new_pos = vector.add(p1, {x=0,y=-tr,z=0})
new_pos = vector.add(p1, {x=0,y=-th,z=0})
end
-- Z
elseif (pos.x <= p1.x and pos.x >= p2.x) and (p1.y >= pos.y and p2.y <= pos.y) then
......@@ -186,7 +181,7 @@ function towny.regions:remove_claim(p1,town)
local blocks = {}
if not towny.regions.memloaded[town] then return false, "This town does not exist anymore." end
for _,pos in pairs(towny.regions.memloaded[town].blocks) do
if pos['plot'] and towny.towns[town].plots[pos['plot']] then
if region_equal(p1, pos) and pos['plot'] and towny.towns[town].plots[pos['plot']] then
return false, "This town claim defines a plot. Please remove the plot before removing the claim!"
elseif region_equal(p1, pos) and pos['origin'] == true then
return false, "This town claim is the origin of this town!"
......@@ -214,7 +209,7 @@ function towny.regions:visualize_town(town)
if not towny.regions.memloaded[town] then return end
for _,pos in pairs(towny.regions.memloaded[town].blocks) do
towny.regions:visualize_radius(vector.subtract(pos,
{x=towny.regions.size/2,y=towny.regions.size/2,z=towny.regions.size/2}))
{x=tr/2,y=th/2,z=tr/2}))
end
end
......
......@@ -5,11 +5,11 @@
# Towny claim diameter
towny_claim_size (Claim size) int 16
# Towny max claim blocks
towny_claim_max (Max town claims) int 128
# Towny claim height
towny_claim_size (Claim height) int 64
# Towny max claim blocks
towny_claim_bonus (Claim blocks added per new member) int 8
towny_claim_max (Max town claims) int 128
# Minimum distance between towns (in claim blocks)
towny_distance (Max town claims) int 80
......@@ -37,4 +37,4 @@ towny_tax (Enable taxation) bool false
# Units depend on economy mod used in server
towny_create_cost (Town creation cost) int 10000
towny_claim_cost (Town claim block cost) int 1000
towny_upkeep_cost (Town upkeep cost, multiplied by member count) int 10
towny_upkeep_cost (Town daily upkeep cost, multiplied by member count) int 10
textures/towny_visualize.png

225 Bytes | W: | H:

textures/towny_visualize.png

198 Bytes | W: | H:

textures/towny_visualize.png
textures/towny_visualize.png
textures/towny_visualize.png
textures/towny_visualize.png
  • 2-up
  • Swipe
  • Onion skin
local tr = towny.regions.size
local th = towny.regions.height
local function err_msg(player, msg)
minetest.chat_send_player(player, minetest.colorize("#ff1111", msg))
return false
end
local function count(T)
local count = 0
for _ in pairs(T) do count = count + 1 end
return count
end
function towny:get_player_town(name)
for town,data in pairs(towny.towns) do
if data.mayor == name then
......@@ -56,14 +63,14 @@ function towny:create_town(pos, player, name)
-- TODO: Economy
-- New town information
local p1 = vector.add(pos, {x=tr / 2,y=tr - 1,z=tr / 2})
local p1 = vector.add(pos, {x=tr / 2,y=th - 1,z=tr / 2})
local p2 = vector.subtract(pos, {x=tr / 2,y=1,z=tr / 2})
local id = minetest.sha1(minetest.hash_node_position(pos))
local data = {
name = name,
mayor = player,
members = {
[player] = {["town_build"] = true, ["plot_build"] = true}
[player] = {}
},
plots = {},
flags = {
......@@ -85,7 +92,9 @@ function towny:create_town(pos, player, name)
towny:mark_dirty(id, true)
minetest.chat_send_player(player, "Your town has successfully been founded!")
minetest.chat_send_all(player .. " has started a new town called '" .. name .. "'!")
minetest.chat_send_all(("%s has started a new town called '%s'!"):format(player,name))
minetest.set_node(p1,{name="default:wood"})
towny.regions:visualize_area(p1,p2)
......@@ -107,7 +116,7 @@ function towny:extend_town(pos,player)
return err_msg(player, "You do not have permission to spend claim blocks in your town.")
end
if data.flags["claim_blocks"] < 1 then
if towny:get_claims_available(town) < 1 then
return err_msg(player, "You do not have enough remaining claim blocks!")
end
......@@ -125,11 +134,10 @@ function towny:extend_town(pos,player)
end
table.insert(towny.regions.memloaded[town].blocks, p1)
data.flags["claim_blocks"] = data.flags["claim_blocks"] - 1
minetest.chat_send_player(player, "Successfully claimed this block!")
minetest.chat_send_player(player, ("Successfully claimed this block! You have %d claim blocks left!"):format(towny:get_claims_available(town)))
towny:mark_dirty(town, true)
towny.regions:visualize_radius(vector.subtract(p1, {x=tr/2,y=tr/2,z=tr/2}))
towny.regions:visualize_radius(vector.subtract(p1, {x=tr/2,y=th/2,z=tr/2}))
return true
end
......@@ -159,8 +167,8 @@ function towny:abridge_town(pos,player)
return err_msg(player, "Failed to abandon claim block: " .. message)
end
data.flags["claim_blocks"] = data.flags["claim_blocks"] + 1
minetest.chat_send_player(player, "Successfully abandoned this claim block!")
minetest.chat_send_player(player, ("Successfully abandoned this claim block! You now have %d claim blocks available!")
:format(towny:get_claims_available(town)))
towny:mark_dirty(t, true)
return true
......@@ -270,7 +278,7 @@ function towny:delete_town(pos,player)
towny.flatfile:delete_all_meta(t)
minetest.chat_send_player(player, "Successfully deleted the town!")
minetest.chat_send_all("The town '" .. name .. "' has fell into ruin.")
minetest.chat_send_all(("The town '%s' has fell into ruin."):format(name))
return true
end
......@@ -345,7 +353,7 @@ function towny:create_plot(pos,player)
towny:mark_dirty(t, true)
minetest.chat_send_player(player, "Successfully created a plot!")
towny.regions:visualize_radius(vector.subtract(c[1], {x=tr/2,y=tr/2,z=tr/2}))
towny.regions:visualize_radius(vector.subtract(c[1], {x=tr/2,y=th/2,z=tr/2}))
return true
end
......@@ -382,7 +390,7 @@ function towny:claim_plot(pos,player)
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}))
towny.regions:visualize_radius(vector.subtract(c[1], {x=tr/2,y=th/2,z=tr/2}))
return true
else
......@@ -472,7 +480,7 @@ function towny:plot_member(pos,player,member,action)
end
if not tdata.members[member] then
return err_msg(player, "User '"..member.."' is not part of this town.")
return err_msg(player, ("User '%s' is not part of this town."):format(member))
end
-- Update plot members
......@@ -483,11 +491,11 @@ function towny:plot_member(pos,player,member,action)
end
if member == pdata.owner then
return err_msg(player, "You cannot "..action_desc.." from this plot.")
return err_msg(player, ("You cannot %s from this plot."):format(action_desc))
end
if action == 0 then
action_desc = "removed "..member.." from"
action_desc = ("removed %s from"):format(member)
for mem,dat in pairs(pdata.members) do
if mem ~= member then
-- Transfer ownership to the first other member
......@@ -495,14 +503,14 @@ function towny:plot_member(pos,player,member,action)
end
end
else
action_desc = "added "..member.." to"
action_desc = ("added %s to"):format(member)
members = pdata.members
members[member] = {}
end
pdata.members = members
towny:mark_dirty(t, false)
minetest.chat_send_player(player, "Successfully "..action_desc.." plot!")
minetest.chat_send_player(player, ("Successfully %s plot!"):format(action_desc))
return true
end
......@@ -555,7 +563,8 @@ 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 '" .. flag .."' to '" .. value .. "'!")
minetest.chat_send_player(player, ("Successfully set the plot flag '%s' to '%s'!")
:format(flag, value))
plot_data.flags[flag] = flag_typeify(value,pos)
towny:mark_dirty(t, false)
end
......@@ -593,7 +602,8 @@ function towny:set_plot_member_flags(pos,player,member,flag,value)
if flag == "build" then flag = "plot_build" end
minetest.chat_send_player(player, "Successfully set the plot member "..member.."'s flag '" .. flag .."' to '" .. value .. "'!")
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)
towny:mark_dirty(t, false)
end
......@@ -624,12 +634,12 @@ function towny:set_town_flags(pos,player,flag,value)
return err_msg(player, "You cannot change this flag.")
end
minetest.chat_send_player(player, "Successfully set the town flag '" .. flag .."' to '" .. value .. "'!")
minetest.chat_send_player(player, ("Successfully set the town flag '%s' to '%s'!"):format(flag,value))
data.flags[flag] = flag_typeify(value,pos)
towny:mark_dirty(t, false)
end
-- Get flags
-- Getters
function towny:get_flags(town,plot)
local tdata = towny.towns[town]
......@@ -654,7 +664,47 @@ function towny:get_plot_flags(town,pos,player)
return towny:get_flags(t,p)
end
function towny:get_claims_total(town)
-- Get used claim blocks
function towny:get_claims_used(town)
if not towny.regions.memloaded[town] then return 0 end
return #towny.regions.memloaded[town].blocks
end
-- Get maximum available claim blocks, including bonuses
function towny:get_claims_max(town)
local tdata = towny.towns[town]
if not tdata then return 0 end
if not tdata.level then towny:get_town_level(town, true) end
local bonus = 0
if tdata.flags['claim_blocks'] and tdata.flags['claim_blocks'] > 0 then
bonus = tdata.flags['claim_blocks']
end
return tdata.level.claimblocks + bonus, tdata.level.claimblocks, bonus
end
-- Get available claim blocks
function towny:get_claims_available(town)
local used = towny:get_claims_used(town)
local max = towny:get_claims_max(town)
return max - used
end
function towny:get_member_count(town)
local tdata = towny.towns[town]
if not tdata then return nil end
return count(tdata.members)
end
function towny:get_town_level(town, update)
local tdata = towny.towns[town]
if not tdata then return nil end
if tdata.level and not update then return tdata.level end
local lvl
for _,describe in pairs(towny.levels) do
if count(tdata.members) >= describe.members then
lvl = describe
end
end
tdata.level = lvl
return lvl
end
-- Visualize an area
local r1 = towny.regions.size + 1
local r2 = towny.regions.height + 1
local c_obj_props = {
hp = 1,
glow = 1,
physical = false,
pointable = true,
visual = "cube",
visual_size = {x = r1, y = r1},
visual_size = {x = r1, y = r2},
textures = {"towny_visualize.png","towny_visualize.png","towny_visualize.png",
"towny_visualize.png","towny_visualize.png","towny_visualize.png"},
static_save = false,
......@@ -33,7 +34,6 @@ function towny.regions:visualize_radius(pos)
end
function towny.regions:visualize_area(p1,p2)
local r = towny.regions.size / 2
local center = {x=p2.x + r,y=p2.y + r,z=p2.z + r}
local center = {x=p2.x + r1/2,y=p2.y + r2/2,z=p2.z + r1/2}
local e = minetest.add_entity(center, "towny:region_visual")
end
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment