summaryrefslogtreecommitdiff
path: root/protection.lua
blob: c5b8f9fbc332b2408b3b4bc4258ccb835a4a9cc3 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
landrush.offense = {}

function landrush.can_interact(pos, name)

	if ( pos.y < -200 ) then
		return true
	end

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

	local chunk = landrush.get_chunk(pos)

	if ( landrush.claims[chunk] ~= nil ) then
		if ( landrush.claims[chunk].shared['*all'] ) then
			return true
		end
	end
	
	
	-- return landrush.claims[chunk] == nil or landrush.claims[chunk].owner == name or landrush.claims[chunk].shared[name]
	if ( landrush.claims[chunk] == nil ) then
		if ( landrush.config:get_bool("requireClaim") == true ) then
			return false
		else
			return true
		end
	end

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

			for u,u in pairs(landrush.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 "..landrush.claims[chunk].owner )
			return true
		end
	end
	return landrush.claims[chunk].owner == name or landrush.claims[chunk].shared[name]
end

function landrush.do_autoban(pos,name) 
	-- moved this to it's own function so landrush.protection_violation is a little cleaner, and this could be overwritten as well
	
	if ( landrush.offense[name] == nil ) then
			landrush.offense[name] = {count=0,lastpos=nil,lasttime=os.time(),bancount=0}
		end

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

		-- reset offenses after a given time period
		if timediff > tonumber(landrush.config:get("offenseReset")) then
			landrush.offense[name].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 / landrush.config:get("chunkSize") ) * 0.5 )

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

		if ( landrush.offense[name].count > tonumber(landrush.config:get("banLevel")) ) then
			landrush.offense[name].bancount = landrush.offense[name].bancount + 1

			local banlength = landrush.offense[name].bancount * 10

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

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

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

			landrush.offense[name].count = 0
			landrush.offense[name].lastpos = nil

			if ( landrush.offense[name].bancount < 4 ) then
				minetest.after( (banlength * 60), minetest.unban_name_or_ip,name )
			end

			return
		end

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

		landrush.offense[name].lasttime = os.time()
		landrush.offense[name].lastpos = pos
end

function landrush.protection_violation(pos,name)
	-- this function can be overwritten to apply whatever discipline the server admin wants
	-- this is the default discipline
	
	local player = minetest.get_player_by_name(name)
	
	if ( player == nil ) then
	  return
	end
	
	local owner = landrush.get_owner(pos)
	
	if ( landrush.config:get_bool("requireClaim") == true ) then
		if ( owner == nil ) then
			minetest.chat_send_player(name,"This area is unowned, but you must claim it to build or mine")
			return true
		end	
	end
	
	minetest.chat_send_player(name, "Area owned by "..tostring(owner).." stop trying to dig here!")
	player:set_hp( player:get_hp() - landrush.config:get("offenseDamage") )
	
	if ( landrush.config:get_bool("autoBan") == true ) then
		landrush.do_autoban(pos,name)
	end

end

landrush.default_is_protected = minetest.is_protected

function minetest.is_protected (pos, name)
	if ( landrush.can_interact(pos, name) ) then
		return landrush.default_is_protected(pos,name)
	else
		return true
	end
end

minetest.register_on_protection_violation( landrush.protection_violation )


-- I'm keeping this just for the TNT workaround
landrush.default_place = minetest.item_place

function minetest.item_place(itemstack, placer, pointed_thing)
	owner = landrush.get_owner(pointed_thing.above)
	name = placer:get_player_name()
		if landrush.can_interact(pointed_thing.above,name) or itemstack:get_name() == "" then
			-- add a workaround for TNT, since overwriting the registered node seems not to work
			if itemstack:get_name() == "tnt:tnt" or itemstack:get_name() == "tnt:tnt_burning" then
				local pos = pointed_thing.above
				local temp_pos = pos
				temp_pos.x = pos.x + 2
				if name ~= landrush.get_owner( temp_pos ) then
					minetest.chat_send_player( name, "Do not place TNT near claimed areas..." )
					return itemstack
				end
				temp_pos.x = pos.x - 2
				if name ~= landrush.get_owner( temp_pos ) then
					minetest.chat_send_player( name, "Do not place TNT near claimed areas..." )
					return itemstack
				end
				temp_pos.z = pos.z + 2
				if name ~= landrush.get_owner( temp_pos ) then
					minetest.chat_send_player( name, "Do not place TNT near claimed areas..." )
					return itemstack
				end
				temp_pos.z = pos.z - 2
				if name ~= landrush.get_owner( temp_pos ) then
					minetest.chat_send_player( name, "Do not place TNT near claimed areas..." )
					return itemstack
				end
			end
			-- end of the workaround
			return landrush.default_place(itemstack, placer, pointed_thing)
		else
			if ( owner ~= nil ) then
				minetest.chat_send_player(name, "Area owned by "..owner)
				return itemstack
			else
				minetest.chat_send_player(name,"Area unclaimed, claim this area to build")
				return itemstack
			end
		end
end