-
Notifications
You must be signed in to change notification settings - Fork 4
/
Copy pathhooks.lua
281 lines (245 loc) · 11.7 KB
/
hooks.lua
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
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
function OnPlayerJoined(Player) -- This is called after connection
local UUID = Player:GetUUID();
local sql = "INSERT OR IGNORE INTO residents (player_uuid, player_name, first_joined) VALUES (?, ?, datetime(\"now\"))";
local parameters = {UUID, Player:GetName()};
if(ExecuteStatement(sql, parameters) == nil) then
LOG("Couldn't add player "..Player:GetName().." to the database!!!");
end
local sql = "UPDATE residents SET last_online = NULL WHERE player_uuid = ?";
local parameters = {UUID};
ExecuteStatement(sql, parameters);
Channel[UUID] = "global";
--Make sure if the town of the player has a new spawn since last join, to set the new spawn
local sql = "SELECT towns.town_spawnX, towns.town_spawnY, towns.town_spawnZ, towns.town_spawnWorld FROM towns INNER JOIN town_residents ON towns.town_id = town_residents.town_id WHERE town_residents.player_uuid = ?";
local parameter = {UUID};
local townSpawn = ExecuteStatement(sql, parameter)[1];
if (townSpawn) then
local spawnWorld = cRoot:Get():GetWorld(townSpawn[4]);
Player:SetBedPos(Vector3i(townSpawn[1], townSpawn[2], townSpawn[3]), spawnWorld);
else
local spawnWorld = cRoot:Get():GetDefaultWorld();
Player:SetBedPos(Vector3i(spawnWorld:GetSpawnX(), spawnWorld:GetSpawnY(), spawnWorld:GetSpawnZ()), spawnWorld);
end
return false;
end
function OnPlayerSpawned(Player) -- This is called after both connection and respawning
CheckPlayerInTown(Player, Player:GetChunkX(), Player:GetChunkZ());
return false;
end
function OnPlayerDestroyed(Player) -- This is called when a player that has been in the game disconnects
InTown[Player:GetUUID()] = nil; -- We set it to nil so Lua can garbage collect it and so the player gets the message on connection
local sql = "UPDATE residents SET last_online = datetime(\"now\") WHERE player_uuid = ?";
local parameters = {Player:GetUUID()};
ExecuteStatement(sql, parameters);
return false;
end
function OnPlayerMoving(Player, OldPosition, NewPosition)
CheckPlayerInTown(Player, Player:GetChunkX(), Player:GetChunkZ());
return false;
end
function OnPlayerBreakingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, BlockType, BlockMeta)
local sql = "SELECT towns.town_id, towns.nation_id, towns.town_permissions FROM plots INNER JOIN towns ON plots.town_id = towns.town_id WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if not (town) then --The block being broken is not part of a town, so breaking is allowed
return true;
else
if (town[1] == GetPlayerTown(Player:GetUUID())) then
return not CheckPermission(town[3], RESIDENTDESTROY);
else
if (town[2] == GetPlayerNation(Player:GetUUID())) then
return not CheckPermission(town[3], ALLYDESTROY);
else
return not CheckPermission(town[3], OUTSIDERDESTROY);
end
end
end
end
function OnPlayerPlacingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, BlockType, BlockMeta)
local sql = "SELECT towns.town_id, towns.nation_id, towns.town_permissions FROM plots INNER JOIN towns ON plots.town_id = towns.town_id WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if not (town) then --The block being broken is not part of a town, so placing is allowed
return true;
else
if (town[1] == GetPlayerTown(Player:GetUUID())) then
return not CheckPermission(town[3], RESIDENTBUILD);
else
if (town[2] == GetPlayerNation(Player:GetUUID())) then
return not CheckPermission(town[3], ALLYBUILD);
else
return not CheckPermission(town[3], OUTSIDERBUILD);
end
end
end
end
function OnPlayerUsingItem(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ, BlockType, BlockMeta)
local itemUsed = ItemToString(Player:GetEquippedItem());
--Since this hook is always called twice when using buckets, we need the 2nd call which has BlockFace at -1 parameters
if (BlockFace == -1) or (itemUsed == "lighter") or (itemUsed == "firecharge") then
local CallBacks = {
OnNextBlock = function(a_BlockX, a_BlockY, a_BlockZ, a_BlockType, a_BlockMeta) --The actual check if the item is allowed or not
local sql = "SELECT towns.town_id, towns.nation_id, towns.town_permissions, towns.town_features, plots.plot_features FROM plots INNER JOIN towns ON plots.town_id = towns.town_id WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(a_BlockX / 16), math.floor(a_BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if not (town) then --The item is used on a block that is not part of a town, so it's allowed
return false;
else
if (town[1] == GetPlayerTown(Player:GetUUID())) then
allowed = CheckPermission(town[3], RESIDENTITEMUSE);
else
if (town[2] == GetPlayerNation(Player:GetUUID())) then
allowed = CheckPermission(town[3], ALLYITEMUSE);
else
allowed = CheckPermission(town[3], OUTSIDERITEMUSE);
end
end
if (allowed == true) then
if (itemUsed == "lighter") or (itemUsed == "firecharge") then
if not (bit32.band(town[5], PLOTFIREINHERIT) == 0) then -- The plot inherits it's fire property from the town
if (bit32.band(town[4], TOWNFIREENABLED) == 0) then -- If fire is disabled in this town, prevent the fire from spreading
return false;
end
elseif (bit32.band(town[5], PLOTFIREENABLED) == 0) then -- Fire is disabled
return false;
end
return true;
else
return true; --Allow item use
end
else
return false; --Prevent item use
end
end
end
};
local EyePos = Player:GetEyePosition();
local LookVector = Player:GetLookVector();
LookVector:Normalize(); --Make the vector 1m long
local Start = EyePos + LookVector;
local End = EyePos + LookVector * 50;
return cLineBlockTracer.Trace(Player:GetWorld(), CallBacks, Start.x, Start.y, Start.z, End.x, End.y, End.z);
end
end
function OnPlayerUsingBlock(Player, BlockX, BlockY, BlockZ, BlockFace, CursorX, CursorY, CursorZ, BlockType, BlockMeta)
local sql = "SELECT towns.town_id, towns.nation_id, towns.town_permissions FROM plots INNER JOIN towns ON plots.town_id = towns.town_id WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), Player:GetWorld():GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if not (town) then --The block being used is not part of a town, so using is allowed
return true;
else
if (town[1] == GetPlayerTown(Player:GetUUID())) then
if (CheckPermission(town[3], RESIDENTSWITCH) == false) then
return true; --Prevent
else
return false; --Allow
end
else
if (town[2] == GetPlayerNation(Player:GetUUID())) then
if (CheckPermission(town[3], ALLYSWITCH) == false) then
return true; --Prevent
else
return false; --Allow
end
else
if (CheckPermission(town[3], OUTSIDERSWITCH) == false) then
return true; --Prevent
else
return false; --Allow
end
end
end
end
end
function OnBlockSpread(World, BlockX, BlockY, BlockZ, Source)
if (Source == ssFireSpread) then
local sql = "SELECT plots.plot_features, towns.town_features FROM plots INNER JOIN towns ON towns.town_id = plots.town_id WHERE plots.chunkX = ? AND plots.chunkZ = ? AND plots.world = ?";
local parameters = {math.floor(BlockX / 16), math.floor(BlockZ / 16), World:GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if (town) then -- Check if the block is in a plot
if not (bit32.band(town[1], PLOTFIREINHERIT) == 0) then -- The plot inherits it's fire property from the town
if (bit32.band(town[2], TOWNFIREENABLED) == 0) then -- If fire is disabled in this town, prevent the fire from spreading
return true;
end
elseif (bit32.band(town[1], PLOTFIREENABLED) == 0) then -- Fire is disabled
return true;
end
end
end
return false;
end
function OnExploding(World, ExplosionSize, CanCauseFire, X, Y, Z, Source, SourceData)
local sql = "SELECT plot_id, town_id FROM plots WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters = {math.floor(X/16), math.floor(Z/16), World:GetName()};
for a = -1, 1, 1 do
for b = -1, 1, 1 do
parameters[1] = parameters[1] + a;
parameters[2] = parameters[2] + b;
local plot = ExecuteStatement(sql, parameters)[1];
if (plot ~= nil) then
local sql = "SELECT plot_features FROM plots WHERE plot_id = ?";
local parameter = {plot[1]};
local explosions = ExecuteStatement(sql, parameter)[1][1];
if not (bit32.band(explosions, PLOTEXPLOSIONSINHERIT) == 0) then -- The plot inherit it's explosions property from the town
local sql = "SELECT town_features FROM towns WHERE town_id = ?";
local parameter = {plot[2]};
local explosions = ExecuteStatement(sql, parameter)[1][1];
if (bit32.band(explosions, TOWNEXPLOSIONSENABLED) == 0) then -- Explosions are disabled
return true;
end
elseif (bit32.band(explosions, PLOTEXPLOSIONSENABLED) == 0) then -- Explosions are disabled
return true;
end
-- If here, explosions are enabled
return false;
end
parameters[1] = parameters[1] - a; --reset chunks
parameters[2] = parameters[2] - b;
end
end
end
function OnTakeDamage(Receiver, TDI)
if Receiver:IsPlayer() and TDI.Attacker ~= nil and TDI.Attacker:IsPlayer() then
local sql = "SELECT plot_id, town_id FROM plots WHERE chunkX = ? AND chunkZ = ? AND world = ?";
local parameters_attacker = {TDI.Attacker:GetChunkX(), TDI.Attacker:GetChunkZ(), TDI.Attacker:GetWorld():GetName()};
local parameters_receiver = {Receiver:GetChunkX(), Receiver:GetChunkZ(), Receiver:GetWorld():GetName()};
local town_attacker = ExecuteStatement(sql, parameters_attacker)[1];
local town_receiver = ExecuteStatement(sql, parameters_receiver)[1];
if (town_attacker ~= nil) or (town_receiver ~= nil) then
if (town_attacker == nil) and not (town_receiver == nil) then
town_attacker = {town_receiver}; --Set it so we can use it in the query
end
local sql = "SELECT plot_features FROM plots WHERE plot_id = ?";
local parameter = {town_attacker[1]};
local pvp = ExecuteStatement(sql, parameter)[1][1];
if not (bit32.band(pvp, PLOTPVPINHERIT) == 0) then -- The plot inherits it's pvp property from the town
local sql = "SELECT town_features FROM towns WHERE town_id = ?";
local parameter = {town_attacker[2]};
local pvp = ExecuteStatement(sql, parameter)[1][1];
if (bit32.band(pvp, TOWNPVPENABLED) == 0) then --PVP is disabled by the town
return true;
end
elseif (bit32.band(pvp, PLOTPVPENABLED) == 0) then -- PVP is disabled
return true;
end
end
end
return false;
end
function OnSpawningMonster(World, Monster)
if (Monster:GetMobFamily() == 0) then --Check if the monster is hostile
local sql = "SELECT plots.plot_features, towns.town_features FROM towns INNER JOIN plots ON towns.town_id = plots.town_id WHERE plots.chunkX = ? AND plots.chunkZ = ? AND plots.world = ?";
local parameters = {Monster:GetChunkX(), Monster:GetChunkZ(), World:GetName()};
local town = ExecuteStatement(sql, parameters)[1];
if (town) then -- Check if the mob is in a plot
if not (bit32.band(town[1], PLOTMOBSINHERIT) == 0) then -- The plot inherits it's mob spawning property from the town
if (bit32.band(town[2], TOWNMOBSENABLED) == 0) then -- Mob spawning is not allowed by the town
return true;
end
elseif (bit32.band(town[1], PLOTMOBSENABLED) == 0) then -- Mob spawning is not allowed
return true;
end
end
end
return false;
end