Decouple ctf_flag

master
rubenwardy 2015-07-12 16:37:45 +01:00
parent 821edc9637
commit a1b24f73e1
7 changed files with 158 additions and 164 deletions

View File

@ -1,133 +1,33 @@
ctf.area = {}
-- add a flag to a team
function ctf.area.add_flag(team,pos)
if not team or team == "" then
return
end
if not ctf.team(team).flags then
ctf.team(team).flags = {}
end
pos.team = team
table.insert(ctf.team(team).flags,pos)
ctf.save()
end
-- get a flag from a team
function ctf.area.get_flag(pos)
if not pos then
return
end
local result = nil
for _, team in pairs(ctf.teams) do
for i = 1, #team.flags do
if (
team.flags[i].x == pos.x and
team.flags[i].y == pos.y and
team.flags[i].z == pos.z
) then
if result then
minetest.chat_send_all("[CTF ERROR] Multiple teams have same flag. Please report this to the server operator / admin")
print("CTF ERROR DATA")
print("Multiple teams have same flag.")
print("This is a sign of ctf.txt corruption.")
print("----------------")
print(dump(result))
print(dump(team.flags[i]))
print("----------------")
else
result = team.flags[i]
end
function ctf.area.get_territory_owner(pos)
local largest = nil
local largest_weight = 0
for i = 1, #ctf.registered_on_territory_query do
local team, weight = ctf.registered_on_territory_query[i](pos)
if team and weight then
if weight == -1 then
return team
end
if weight > largest_weight then
largest = team
largest_weight = weight
end
end
end
return result
end
-- delete a flag from a team
function ctf.area.delete_flag(team, pos)
if not team or team == "" then
return
end
for i = 1, #ctf.team(team).flags do
if (
ctf.team(team).flags[i].x == pos.x and
ctf.team(team).flags[i].y == pos.y and
ctf.team(team).flags[i].z == pos.z
) then
table.remove(ctf.team(team).flags,i)
return
end
end
end
-- Gets the nearest flag in a 25 metre radius block
function ctf.area.nearest_flag(pos)
if not pos then
ctf.error("No position provided to nearest_flag()")
return nil
end
local nodes = minetest.find_nodes_in_area(
{
x = pos.x - ctf.setting("flag.protect_distance"),
y = pos.y - ctf.setting("flag.protect_distance"),
z = pos.z - ctf.setting("flag.protect_distance")
},
{
x = pos.x + ctf.setting("flag.protect_distance"),
y = pos.y + ctf.setting("flag.protect_distance"),
z = pos.z + ctf.setting("flag.protect_distance")
},
{"group:is_flag"}
)
if nodes then
local closest = nil
local _dis = 1000
for a = 1, #nodes do
local this_dis = vector.distance(pos, nodes[a])
if this_dis < _dis then
closest = nodes[a]
_dis = this_dis
end
end
return closest
end
return nil
end
-- gets the name of the owner of that location
function ctf.area.get_area(pos)
local closest = ctf.area.nearest_flag(pos)
if not closest then
return nil
end
local flag = ctf.area.get_flag(closest)
if flag then
return flag.team
end
return nil
return largest
end
-- updates the spawn position for a team
function ctf.area.get_spawn(team)
ctf.area.asset_flags(team)
ctf_flag.asset_flags(team)
if not ctf.team(team) then
return nil
end
if ctf.team(team).spawn and minetest.env:get_node(ctf.team(team).spawn).name == "ctf:flag" then
local flag = ctf.area.get_flag(ctf.team(team).spawn)
local flag = ctf_flag.get(ctf.team(team).spawn)
if not flag then
return nil
@ -148,24 +48,6 @@ function ctf.area.get_spawn(team)
end
end
function ctf.area.asset_flags(team)
--[[
if not team or not ctf.team(team) then
return false
end
ctf.log("utils", "Checking the flags of "..team)
local tmp = ctf.team(team).flags
local get_res = minetest.env:get_node(tmp[i])
for i=1,#tmp do
if tmp[i] and (not get_res or not get_res.name == "ctf:flag") then
ctf.log("utils", "Replacing flag...")
-- TODO: ctf.area.asset_flags
end
end]]--
end
minetest.register_on_respawnplayer(function(player)
if player and ctf.player(player:get_player_name()) then
local team = ctf.player(player:get_player_name()).team

View File

@ -15,6 +15,17 @@ ctf.registered_on_new_team = {}
function ctf.register_on_new_team(func)
table.insert(ctf.registered_on_new_team, func)
end
ctf.registered_on_territory_query = {}
function ctf.register_on_territory_query(func)
table.insert(ctf.registered_on_territory_query, func)
end
function vector.distanceSQ(p1, p2)
local x = p1.x - p2.x
local y = p1.y - p2.y
local z = p1.z - p2.z
return x*x + y*y + z*z
end

View File

@ -7,7 +7,7 @@ ctf_flag = {
on_rightclick_top = function(pos, node, clicker)
pos.y=pos.y-1
local flag = ctf.area.get_flag(pos)
local flag = ctf_flag.get(pos)
if not flag then
return
end
@ -26,7 +26,7 @@ ctf_flag = {
ctf.gui.flag_board(clicker:get_player_name(),pos)
end,
on_rightclick = function(pos, node, clicker)
local flag = ctf.area.get_flag(pos)
local flag = ctf_flag.get(pos)
if not flag then
return
end
@ -49,7 +49,7 @@ ctf_flag = {
return
end
local flag = ctf.area.get_flag(pos)
local flag = ctf_flag.get(pos)
if not flag then
return
end
@ -111,11 +111,11 @@ ctf_flag = {
end
ctf.team(team).spawn = nil
if ctf.setting("flag.allow_multiple") == true then
ctf.area.delete_flag(team,pos)
ctf.area.add_flag(ctf.player(player).team,pos)
ctf_flag.delete(team,pos)
ctf_flag.add(ctf.player(player).team,pos)
else
minetest.env:set_node(pos,{name="air"})
ctf.area.delete_flag(team,pos)
ctf_flag.delete(team,pos)
end
end
ctf.save()
@ -148,11 +148,11 @@ ctf_flag = {
fteam.spawn = nil
local fpos = {x=ctf.claimed[i].x,y=ctf.claimed[i].y,z=ctf.claimed[i].z}
if ctf.setting("flag.allow_multiple") == true then
ctf.area.delete_flag(fteam.data.name,fpos)
ctf.area.add_flag(ctf.claimed[i].claimed.team,fpos)
ctf_flag.delete(fteam.data.name,fpos)
ctf_flag.add(ctf.claimed[i].claimed.team,fpos)
else
minetest.env:set_node(fpos,{name="air"})
ctf.area.delete_flag(fteam.data.name,fpos)
ctf_flag.delete(fteam.data.name,fpos)
end
ctf.collect_claimed()
end
@ -178,7 +178,7 @@ ctf_flag = {
meta:set_string("infotext", team.."'s flag")
-- add flag
ctf.area.add_flag(team,pos)
ctf_flag.add(team, pos)
if ctf.teams[team].spawn and minetest.env:get_node(ctf.teams[team].spawn).name == "ctf_flag:flag" then
if not ctf.setting("flag.allow_multiple") then
@ -199,23 +199,23 @@ ctf_flag = {
ctf.save()
local pos2 = {
x=pos.x,
y=pos.y+1,
z=pos.z
}
x = pos.x,
y = pos.y+1,
z = pos.z
}
if not ctf.team(team).data.color then
ctf.team(team).data.color = "red"
ctf.save()
end
minetest.env:set_node(pos2,{name="ctf_flag:flag_top_"..ctf.team(team).data.color})
minetest.env:set_node(pos2, {name="ctf_flag:flag_top_"..ctf.team(team).data.color})
local meta2 = minetest.env:get_meta(pos2)
meta2:set_string("infotext", team.."'s flag")
else
minetest.chat_send_player(placer:get_player_name(),"You are not part of a team!")
minetest.chat_send_player(placer:get_player_name(), "You are not part of a team!")
minetest.env:set_node(pos,{name="air"})
end
end

View File

@ -70,7 +70,7 @@ end)
-- Flag interface
function ctf.gui.flag_board(name,pos)
ctf.log("gui", name .. " views flag board")
local flag = ctf.area.get_flag(pos)
local flag = ctf_flag.get(pos)
if not flag then
return
end
@ -123,7 +123,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
end
if fields.save and fields.flag_name then
local flag = ctf.area.get_flag(ctf.gui.flag_data[name].pos)
local flag = ctf_flag.get(ctf.gui.flag_data[name].pos)
if not flag then
return false
end
@ -156,7 +156,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
elseif fields.delete then
local pos = ctf.gui.flag_data[name].pos
local flag = ctf.area.get_flag(ctf.gui.flag_data[name].pos)
local flag = ctf_flag.get(ctf.gui.flag_data[name].pos)
if not flag then
return
@ -171,7 +171,7 @@ minetest.register_on_player_receive_fields(function(player, formname, fields)
return false
end
ctf.area.delete_flag(team,pos)
ctf_flag.delete(team,pos)
minetest.env:set_node(pos,{name="air"})
pos.y=pos.y+1

View File

@ -9,10 +9,113 @@ init()
ctf.register_on_new_team(function(team)
team.flags = {}
end)
ctf.register_on_territory_query(function(pos)
local closest = nil
local closest_team = nil
local closest_distSQ = 1000000
local pd = ctf.setting("flag.protect_distance")
local pdSQ = pd * pd
for tname, team in pairs(ctf.teams) do
for i = 1, #team.flags do
local distSQ = vector.distanceSQ(pos, team.flags[i])
if distSQ < pdSQ and distSQ < closest_distSQ then
closest = team.flags[i]
closest_team = tname
closest_distSQ = distSQ
end
end
end
return closest_team, closest_distSQ
end)
ctf_flag = {}
dofile(minetest.get_modpath("ctf_flag") .. "/gui.lua")
dofile(minetest.get_modpath("ctf_flag") .. "/flag_func.lua")
-- add a flag to a team
function ctf_flag.add(team, pos)
if not team or team == "" then
return
end
if not ctf.team(team).flags then
ctf.team(team).flags = {}
end
pos.team = team
table.insert(ctf.team(team).flags,pos)
ctf.save()
end
-- get a flag from a team
function ctf_flag.get(pos)
if not pos then
return
end
local result = nil
for _, team in pairs(ctf.teams) do
for i = 1, #team.flags do
if (
team.flags[i].x == pos.x and
team.flags[i].y == pos.y and
team.flags[i].z == pos.z
) then
if result then
minetest.chat_send_all("[CTF ERROR] Multiple teams have same flag. Please report this to the server operator / admin")
print("CTF ERROR DATA")
print("Multiple teams have same flag.")
print("This is a sign of ctf.txt corruption.")
print("----------------")
print(dump(result))
print(dump(team.flags[i]))
print("----------------")
else
result = team.flags[i]
end
end
end
end
return result
end
-- delete a flag from a team
function ctf_flag.delete(team, pos)
if not team or team == "" then
return
end
for i = 1, #ctf.team(team).flags do
if (
ctf.team(team).flags[i].x == pos.x and
ctf.team(team).flags[i].y == pos.y and
ctf.team(team).flags[i].z == pos.z
) then
table.remove(ctf.team(team).flags,i)
return
end
end
end
function ctf_flag.asset_flags(team)
--[[
if not team or not ctf.team(team) then
return false
end
ctf.log("utils", "Checking the flags of "..team)
local tmp = ctf.team(team).flags
local get_res = minetest.env:get_node(tmp[i])
for i=1,#tmp do
if tmp[i] and (not get_res or not get_res.name == "ctf:flag") then
ctf.log("utils", "Replacing flag...")
-- TODO: ctf_flag.asset_flags
end
end]]--
end
-- The flag
minetest.register_node("ctf_flag:flag", {
description = "Flag",
@ -108,7 +211,7 @@ minetest.register_abm({
return
end
local flag_team_data = ctf.area.get_flag(pos)
local flag_team_data = ctf_flag.get(pos)
if not flag_team_data or not ctf.team(flag_team_data.team)then
ctf.log("flag", "Flag does not exist! Deleting nodes. "..dump(pos))
minetest.env:set_node(pos,{name="air"})

View File

@ -2,18 +2,16 @@
local old_is_protected = minetest.is_protected
function minetest.is_protected(pos, name)
local team = ctf.area.get_area(pos)
local team = ctf.area.get_territory_owner(pos)
if not team then
if not team or not ctf.team(team) then
return old_is_protected(pos, name)
end
if ctf.players and ctf.player(name) and ctf.player(name).team then
if ctf.player(name).team == team then
return old_is_protected(pos, name)
end
if ctf.player(name).team == team then
return old_is_protected(pos, name)
else
minetest.chat_send_player(name, "You cannot dig on team "..team.."'s land")
return true
end
minetest.chat_send_player(name, "You cannot dig on team "..team.."'s land")
return true
end

View File

@ -60,7 +60,7 @@ if ctf.setting("turrets") then
return
end
local app = ctf.area.get_area(pos)
local app = ctf.area.get_territory_owner(pos)
if app and app~=team then
team = app
meta:set_string("team",team)