minetest.log('action','Loading Land Rush Land Claim')

landrush = {}

local requireClaim = false 		-- Change this to true if you want to require people to claim an area before building or digging
local onlineProtection = true	-- false turns protection off when the claim owner is online

local offenseDamage = 4			-- how much damage is dealt to the player when they dig in protected areas

local autoBan = false		-- users who attempt to dig and build in claimed areas can be auto banned
local banLevel = 40			-- the offense level they must exceed to get banned, 40 is roughly 5 nodes dug in the same area
local banWarning = 25		-- the offense level they start getting ban warnings
local offenseReset = 1440	-- after this number of minutes all offenses will be forgiven
local adminUser = nil		-- this user will be messaged if chat plus is installed when a player is autobanned

chunkSize = 16		-- don't change this value after you start using landrush
claims = {}
local offense = {}

gstepCount = 0
playerHudItems = {}

local path = minetest.get_modpath("landrush")

-- These are items that can be dug in unclaimed areas when requireClaim is true
local global_dig_list = {["default:ladder"]=true,["default:leaves"]=true,["default:tree"]=true,["default:grass"]=true,["default:grass_1"]=true,["default:grass_2"]=true,["default:grass_3"]=true,["default:grass_4"]=true}

local filename = minetest.get_worldpath().."/landrush-claims"

minetest.register_privilege("landrush", "Allows player to dig and build anywhere, and use the landrush chat commands.")

function landrush.load_claims()
	local file = io.open(filename, "r")
	if file then
		for line in file:lines() do
			if line ~= "" then
				local area = line:split(" ")
				local shared = {}
				if area[3] and area[3] ~= "*" then
					for k,v in ipairs(area[3]:split(",")) do
						shared[v] = v
					end
				end
				local claimtype
				if area[4] then
					claimtype = area[4]
				else
					claimtype = "landrush:landclaim"
				end
				claims[area[1]] = {owner=area[2], shared=shared, claimtype=claimtype}
			end
		end
		file:close()
	end
end

function landrush.save_claims()
	local file = io.open(filename, "w")
	for key,value in pairs(claims) do
		local sharedata = ""
		for k,v in pairs(value.shared) do
			sharedata = sharedata..v..","
		end
		local sharestring
		if sharedata == "" then
			sharestring = "*"
		else
			sharestring = sharedata:sub(1,-2)
		end
		file:write(key.." "..value.owner.." "..sharestring.." "..value.claimtype.."\n")
	end
	file:close()
end

function landrush.get_chunk(pos)
	local x = math.floor(pos.x/chunkSize)
	-- 3 levels of vertical protection
	local y = 0

	if ( pos.y < -200 ) then
		y = -32000
	elseif ( pos.y < -60 ) then
		y = -200
	elseif ( pos.y < 140 ) then
		y = -30
	else
		y = 90
	end


	local z = math.floor(pos.z/chunkSize)
	return x..","..y..","..z
end

function landrush.get_chunk_center(pos)
	local x = math.floor(pos.x/chunkSize)*chunkSize+7.5
	local y = 0

	if ( pos.y < -60 ) then
		y = -200
	elseif ( pos.y < 120 ) then
		y = -30
	else
		y = 120
	end

	local z = math.floor(pos.z/chunkSize)*chunkSize+7.5
	return {x=x,y=y,z=z}
end

function landrush.get_owner(pos)
	local chunk = landrush.get_chunk(pos)
	if claims[chunk] then
		return claims[chunk].owner
	end
end

function landrush.can_interact(name, pos)

	if ( minetest.check_player_privs(name, {landrush=true}) ) then
		return true
	end

	local chunk = landrush.get_chunk(pos)
	-- return claims[chunk] == nil or claims[chunk].owner == name or claims[chunk].shared[name]
	if ( claims[chunk] == nil ) then
		if ( requireClaim == true ) then
			return false
		else
			return true
		end
	end

	-- if it's the owner or it's shared
	if ( claims[chunk].shared[name] or claims[chunk].owner == name or claims[chunk].shared['*all'] ) then
		return true
	end

	-- see if the owner is offline, and area is not shared then it's off limits
	if ( minetest.env:get_player_by_name(claims[chunk].owner) == nil ) then
		if ( claims[chunk].shared[name] ) then
			return true
		else
			return nil
		end
	else
		if ( claims[chunk].owner ~= name and onlineProtection == false ) then
			minetest.chat_send_player( claims[chunk].owner, "You are being griefed by "..name.." at "..minetest.pos_to_string(pos) )

			for u,u in pairs(claims[chunk].shared) do
				minetest.chat_send_player( u, name.." is griefing your shared claim at "..minetest.pos_to_string(pos) )
			end

			minetest.chat_send_player( name, "You are griefing "..claims[chunk].owner )
			return true
		end
	end
	return claims[chunk].owner == name or claims[chunk].shared[name]
end

landrush.default_place = minetest.item_place
landrush.default_dig = minetest.node_dig

-- Redefined Lua:
function minetest.node_dig(pos, node, digger)
	local player = digger:get_player_name()
	if landrush.can_interact(player, pos) or player == "" then
		landrush.default_dig(pos, node, digger)
	else
		local owner = landrush.get_owner(pos)
		if ( owner ~= nil ) then
			minetest.chat_send_player(player, "Area owned by "..owner.." stop trying to dig here!")
			digger:set_hp( digger:get_hp() - offenseDamage )
			--[[ **********************************************
					START THE AUTOBAN SECTION!!
				***********************************************]]
			if ( autoBan == true ) then
				if ( offense[player] == nil ) then
					offense[player] = {count=0,lastpos=nil,lasttime=os.time(),bancount=0}
				end

				local timediff = (os.time() - offense[player].lasttime)/60
				local distance = landrush.get_distance(offense[player].lastpos,pos)

				-- reset offenses after a given time period
				if timediff > offenseReset then
					offense[player].count=0
				end

				-- offense amount starts at 10 and is decreased based on the length of time between offenses
				-- and the distance from the last offense. This weighted system tries to make it fair for people who aren't
				-- intentionally griefing
				offenseAmount = ( 10 - ( timediff / 10 ) ) - ( ( distance / chunkSize ) * 0.5 )

				offense[player].count=offense[player].count + offenseAmount
				minetest.log("action",player.." greifing attempt")

				if ( offense[player].count > banLevel ) then
					offense[player].bancount = offense[player].bancount + 1

					local banlength = offense[player].bancount * 10

					if ( offense[player].bancount < 4 ) then
						minetest.chat_send_player(player, "You have been banned for "..tostring(banlength).." minutes!")
					else
						minetest.chat_send_player(player, "You have been banned!")
					end

					minetest.log("action",player.." has been banned for griefing attempts")
					minetest.chat_send_all(player.." has been banned for griefing attempts")

					if ( chatplus and adminUser ~= nil) then
						table.insert(chatplus.players[adminUser].messages,"mail from <LandRush>: "..player.." banned for "..tostring(banlength).." minutes for attempted griefing")
					end
					minetest.ban_player(player)

					offense[player].count = 0
					offense[player].lastpos = nil

					if ( offense[player].bancount < 4 ) then
						minetest.after( (banlength * 60), minetest.unban_player_or_ip,player )
					end

					return
				end

				if ( offense[player].count > banWarning ) then
					minetest.chat_send_player(player, "Stop trying to dig in claimed areas or you will be banned!")
					minetest.chat_send_player(player, "Use /showarea and /landowner to see the protected area and who owns it.")
					minetest.sound_play("landrush_ban_warning", {to_player=player,gain = 10.0})
				end

				offense[player].lasttime = os.time()
				offense[player].lastpos = pos

			end
			--[[ **********************************************
					END THE AUTOBAN SECTION!!
				***********************************************]]
		else
			-- allow them to dig the global dig list
			if ( global_dig_list[node['name']] ~= true ) then
				minetest.chat_send_player(player,"Area unclaimed, claim this area to build")
			else
				landrush.default_dig(pos, node, digger)
			end
		end
	end
end

function minetest.item_place(itemstack, placer, pointed_thing)
	owner = landrush.get_owner(pointed_thing.above)
	player = placer:get_player_name()
		if landrush.can_interact(player, pointed_thing.above) or itemstack:get_name() == "" then
			return landrush.default_place(itemstack, placer, pointed_thing)
		else
			if ( owner ~= nil ) then
				minetest.chat_send_player(player, "Area owned by "..owner)
				return itemstack
			else
				minetest.chat_send_player(player,"Area unclaimed, claim this area to build")
				return itemstack
			end
		end
end

landrush.load_claims()
-- Load now

	minetest.register_node("landrush:landclaim", {
		description = "Land Rush Land Claim",
		tiles = {"landrush_landclaim.png"},
		groups = {oddly_breakable_by_hand=2},
		on_place = function(itemstack, placer, pointed_thing)
			owner = landrush.get_owner(pointed_thing.above)
			player = placer:get_player_name()
			if owner then
				minetest.chat_send_player(player, "This area is already owned by "..owner)
			else
				minetest.env:remove_node(pointed_thing.above)
				chunk = landrush.get_chunk(pointed_thing.above)
				claims[chunk] = {owner=placer:get_player_name(),shared={},claimtype="landclaim"}
				landrush.save_claims()
				minetest.chat_send_player(claims[chunk].owner, "You now own this area.")
				itemstack:take_item()
				return itemstack
			end
		end,
	})

minetest.register_craft({
			output = 'landrush:landclaim',
			recipe = {
				{'default:stone','default:steel_ingot','default:stone'},
				{'default:steel_ingot','default:mese_crystal','default:steel_ingot'},
				{'default:stone','default:steel_ingot','default:stone'}
			}
		})
minetest.register_alias("landclaim", "landrush:landclaim")
minetest.register_alias("landrush:landclaim_b","landrush:landclaim")

doors:register_door("landrush:shared_door", {
	description = "Shared Door",
	inventory_image = "shared_door_inv.png",
	groups = {snappy=1,bendy=2,cracky=1,melty=2,level=2,door=1},
	tiles_bottom = {"shared_door_b.png", "door_blue.png"},
	tiles_top = {"shared_door_a.png", "door_blue.png"},
})

minetest.register_craft({
	output = 'landrush:shared_door',
	recipe = {
		{'default:steel_ingot','default:steel_ingot',''},
		{'default:steel_ingot','landrush:landclaim',''},
		{'default:steel_ingot','default:steel_ingot',''}
	}
})

function landrush.on_rightclick(pos, dir, check_name, replace, replace_dir, params)
		pos.y = pos.y+dir
		if not minetest.get_node(pos).name == check_name then
			return
		end
		local p2 = minetest.get_node(pos).param2
		p2 = params[p2+1]

		local meta = minetest.get_meta(pos):to_table()
		minetest.set_node(pos, {name=replace_dir, param2=p2})
		minetest.get_meta(pos):from_table(meta)

		pos.y = pos.y-dir
		meta = minetest.get_meta(pos):to_table()
		minetest.set_node(pos, {name=replace, param2=p2})
		minetest.get_meta(pos):from_table(meta)
	end

minetest.registered_nodes['landrush:shared_door_b_1'].on_rightclick = function(pos, node, clicker)
if ( landrush.can_interact(clicker:get_player_name(),pos) ) then
	landrush.on_rightclick(pos, 1, "landrush:shared_door_t_1", "landrush:shared_door_b_2", "landrush:shared_door_t_2", {1,2,3,0})
end
end

minetest.registered_nodes['landrush:shared_door_t_1'].on_rightclick = function(pos, node, clicker)
if ( landrush.can_interact(clicker:get_player_name(),pos) ) then
	landrush.on_rightclick(pos, -1, "landrush:shared_door_b_1", "landrush:shared_door_t_2", "landrush:shared_door_b_2", {1,2,3,0})
end
end

-- Fix for duplicating Bug!
-- Bug was caused, because the reverse order of the on_rightclick was not taken into account

minetest.registered_nodes['landrush:shared_door_b_2'].on_rightclick = function(pos, node, clicker)
if ( landrush.can_interact(clicker:get_player_name(),pos) ) then
	landrush.on_rightclick(pos, 1, "landrush:shared_door_t_2", "landrush:shared_door_b_1", "landrush:shared_door_t_1", {3,0,1,2})
end
end

minetest.registered_nodes['landrush:shared_door_t_2'].on_rightclick = function(pos, node, clicker)
if ( landrush.can_interact(clicker:get_player_name(),pos) ) then
	landrush.on_rightclick(pos, -1, "landrush:shared_door_b_2", "landrush:shared_door_t_1", "landrush:shared_door_b_1", {3,0,1,2})
end
end

-- End of fix

--landrush.register_claimnode("landclaim", "landrush_landclaim.png")
--landrush.register_claimnode("landclaim_b", "landrush_landclaim.png")

minetest.register_entity("landrush:showarea",{
	on_activate = function(self, staticdata, dtime_s)
		minetest.after(16,function()
			self.object:remove()
		end)
	end,
	initial_properties = {
		hp_max = 1,
		physical = true,
		weight = 0,
		collisionbox = {-8,-8,-8,8,8,8},
		visual = "mesh",
		visual_size = {x=16.1, y=16.1},
		mesh = "landrush_showarea.x",
		textures = {nil, nil, "landrush_showarea.png", "landrush_showarea.png", "landrush_showarea.png", "landrush_showarea.png"}, -- number of required textures depends on visual
		colors = {}, -- number of required colors depends on visual
		spritediv = {x=1, y=1},
		initial_sprite_basepos = {x=0, y=0},
		is_visible = true,
		makes_footstep_sound = false,
		automatic_rotate = false,
	}
})

minetest.register_globalstep(function(dtime)
	gstepCount = gstepCount + dtime
	if ( gstepCount > 2 ) then
		gstepCount=0
		local oplayers = minetest.get_connected_players()
		for _,player in ipairs(oplayers) do
			local name = player:get_player_name()
			local sameowner = false
			owner = landrush.get_owner(player:getpos())

			if ( playerHudItems[name] ~= nil ) then
				if ( playerHudItems[name].lastowner == owner ) then
					-- same owner as last time don't update the hud
					sameowner = true
				end
			end

			if ( playerHudItems[name] ~= nil and sameowner == false ) then
					player:hud_remove(playerHudItems[name].hud)
					playerHudItems[name] = nil
			end

			if ( owner ~= nil and sameowner == false ) then
				--minetest.log('action','Redraw hud for '..name)
				playerHudItems[name] = {hud = player:hud_add({
						hud_elem_type = "text",
						name = "LandOwner",
						number = 0xFFFFFF,
						position = {x=.2, y=.98},
						text="Land Owner: "..owner,
						scale = {x=200,y=25},
						alignment = {x=0, y=0},
				}), lastowner=owner}
			end
		end
	end
end)

function landrush.get_distance(pos1,pos2)

	if ( pos1 ~= nil and pos2 ~= nil ) then
		return math.abs(math.floor(math.sqrt( (pos1.x - pos2.x)^2 + (pos1.z - pos2.z)^2 )))
	else
		return 0
	end

end

if ( minetest.get_modpath("money2") ) then
	minetest.log('action','Loading Landrush Land Sale')
	dofile(path.."/landsale.lua")
end

minetest.after(0, function ()

dofile(path.."/default.lua")
dofile(path.."/bucket.lua")
dofile(path.."/doors.lua")
dofile(path.."/fire.lua")
dofile(path.."/chatcommands.lua")

end )