· 8 years ago · May 02, 2018, 03:34 PM
1MySQL = module("vrp_mysql", "MySQL")
2
3local Proxy = module("lib/Proxy")
4local Tunnel = module("lib/Tunnel")
5local Lang = module("lib/Lang")
6Debug = module("lib/Debug")
7
8local config = module("cfg/base")
9local version = module("version")
10Debug.active = config.debug
11MySQL.debug = config.debug
12
13-- open MySQL connection
14MySQL.createConnection("vRP", config.db.host,config.db.user,config.db.password,config.db.database)
15
16-- versioning
17print("[vRP] launch version "..version)
18--[[
19PerformHttpRequest("https://raw.githubusercontent.com/ImagicTheCat/vRP/master/vrp/version.lua",function(err,text,headers)
20 if err == 0 then
21 text = string.gsub(text,"return ","")
22 local r_version = tonumber(text)
23 if version ~= r_version then
24 print("[vRP] WARNING: A new version of vRP is available here https://github.com/ImagicTheCat/vRP, update to benefit from the last features and to fix exploits/bugs.")
25 end
26 else
27 print("[vRP] unable to check the remote version")
28 end
29end, "GET", "")
30--]]
31
32local whiteList_state = config.whitelist
33
34vRP = {}
35Proxy.addInterface("vRP",vRP)
36
37tvRP = {}
38Tunnel.bindInterface("vRP",tvRP) -- listening for client tunnel
39
40-- load language
41local dict = module("cfg/lang/"..config.lang) or {}
42vRP.lang = Lang.new(dict)
43
44-- init
45vRPclient = Tunnel.getInterface("vRP","vRP") -- server -> client tunnel
46
47vRP.users = {} -- will store logged users (id) by first identifier
48vRP.rusers = {} -- store the opposite of users
49vRP.user_tables = {} -- user data tables (logger storage, saved to database)
50vRP.user_tmp_tables = {} -- user tmp data tables (logger storage, not saved)
51vRP.user_sources = {} -- user sources
52
53-- queries
54MySQL.createCommand("vRP/base_tables",[[
55CREATE TABLE IF NOT EXISTS vrp_users(
56 id INTEGER AUTO_INCREMENT,
57 last_login VARCHAR(255),
58 whitelisted BOOLEAN,
59 banned BOOLEAN,
60 CONSTRAINT pk_user PRIMARY KEY(id)
61);
62
63CREATE TABLE IF NOT EXISTS vrp_bans(
64 user_id BIGINT PRIMARY KEY,
65 author text,
66 date text,
67 reason text
68);
69
70CREATE TABLE IF NOT EXISTS vrp_user_ids(
71 identifier VARCHAR(255),
72 user_id INTEGER,
73 CONSTRAINT pk_user_ids PRIMARY KEY(identifier),
74 CONSTRAINT fk_user_ids_users FOREIGN KEY(user_id) REFERENCES vrp_users(id) ON DELETE CASCADE
75);
76
77CREATE TABLE IF NOT EXISTS vrp_user_data(
78 user_id INTEGER,
79 dkey VARCHAR(255),
80 dvalue TEXT,
81 Permis INTEGER,
82 CONSTRAINT pk_user_data PRIMARY KEY(user_id,dkey),
83 CONSTRAINT fk_user_data_users FOREIGN KEY(user_id) REFERENCES vrp_users(id) ON DELETE CASCADE
84);
85
86CREATE TABLE IF NOT EXISTS vrp_srv_data(
87 dkey VARCHAR(255),
88 dvalue TEXT,
89 CONSTRAINT pk_srv_data PRIMARY KEY(dkey)
90);
91]])
92
93MySQL.createCommand("vRP/create_user","INSERT INTO vrp_users(whitelisted,banned) VALUES(false,false); SELECT LAST_INSERT_ID() AS id")
94MySQL.createCommand("vRP/add_identifier","INSERT INTO vrp_user_ids(identifier,user_id) VALUES(@identifier,@user_id)")
95MySQL.createCommand("vRP/userid_byidentifier","SELECT user_id FROM vrp_user_ids WHERE identifier = @identifier")
96
97MySQL.createCommand("vRP/set_userdata","REPLACE INTO vrp_user_data(user_id,dkey,dvalue) VALUES(@user_id,@key,@value)")
98MySQL.createCommand("vRP/get_userdata","SELECT dvalue FROM vrp_user_data WHERE user_id = @user_id AND dkey = @key")
99
100MySQL.createCommand("vRP/set_srvdata","REPLACE INTO vrp_srv_data(dkey,dvalue) VALUES(@key,@value)")
101MySQL.createCommand("vRP/get_srvdata","SELECT dvalue FROM vrp_srv_data WHERE dkey = @key")
102--Not original vRP system, edited by serrat
103MySQL.createCommand("vRP/get_banned","SELECT * FROM vrp_bans WHERE user_id = @user_id")
104MySQL.createCommand("vRP/set_banned","INSERT INTO vrp_bans (user_id,author,date,reason) VALUES (@user_id,@author,@ban_day,@reason) ON DUPLICATE KEY UPDATE user_id=@user_id,author=@author,date=@ban_day,reason=@reason")
105MySQL.createCommand("vRP/del_banned","DELETE FROM vrp_bans WHERE user_id = @user_id")
106-- TODO, delete ban
107--End of modification
108MySQL.createCommand("vRP/get_whitelisted","SELECT whitelisted FROM vrp_users WHERE id = @user_id")
109MySQL.createCommand("vRP/set_whitelisted","UPDATE vrp_users SET whitelisted = @whitelisted WHERE id = @user_id")
110MySQL.createCommand("vRP/set_last_login","UPDATE vrp_users SET last_login = @last_login WHERE id = @user_id")
111MySQL.createCommand("vRP/get_last_login","SELECT last_login FROM vrp_users WHERE id = @user_id")
112
113
114-- init tables
115print("[vRP] init base tables")
116MySQL.query("vRP/base_tables")
117
118-- identification system
119
120--- sql.
121-- cbreturn user id or nil in case of error (if not found, will create it)
122function vRP.getUserIdByIdentifiers(ids, cbr)
123 local task = Task(cbr)
124
125 if ids ~= nil and #ids then
126 local i = 0
127
128 -- search identifiers
129 local function search()
130 i = i+1
131 if i <= #ids then
132 if not config.ignore_ip_identifier or (string.find(ids[i], "ip:") == nil) then -- ignore ip identifier
133 MySQL.query("vRP/userid_byidentifier", {identifier = ids[i]}, function(rows, affected)
134 if #rows > 0 then -- found
135 task({rows[1].user_id})
136 else -- not found
137 search()
138 end
139 end)
140 else
141 search()
142 end
143 else -- no ids found, create user
144 MySQL.query("vRP/create_user", {}, function(rows, affected)
145 if #rows > 0 then
146 local user_id = rows[1].id
147 -- add identifiers
148 for l,w in pairs(ids) do
149 if not config.ignore_ip_identifier or (string.find(w, "ip:") == nil) then -- ignore ip identifier
150 MySQL.query("vRP/add_identifier", {user_id = user_id, identifier = w})
151 end
152 end
153
154 task({user_id})
155 else
156 task()
157 end
158 end)
159 end
160 end
161
162 search()
163 else
164 task()
165 end
166end
167
168-- return identification string for the source (used for non vRP identifications, for rejected players)
169function vRP.getSourceIdKey(source)
170 local ids = GetPlayerIdentifiers(source)
171 local idk = "idk_"
172 for k,v in pairs(ids) do
173 idk = idk..v
174 end
175
176 return idk
177end
178
179function vRP.getPlayerEndpoint(player) -- Fonction filtre
180 return GetPlayerEP(player) or "0.0.0.0"
181 end
182
183 function vRP.getPlayerName(player) -- Fonction filtre
184 return GetPlayerName(player) or "unknown"
185 end
186
187 function vRP.getRUsersTable()
188 return vRP.rusers
189 end
190
191 function vRP.getUserSourceTable()
192 return vRP.user_sources
193 end
194
195--- sql
196function vRP.isBanned(user_id, cbr)
197 local task = Task(cbr, {nil})
198
199 MySQL.query("vRP/get_banned", {user_id = user_id}, function(rows, affected)
200 if #rows > 0 then
201 task({rows[1]})
202 else
203 task()
204 end
205 end)
206end
207
208--- sql
209function vRP.setBanned(user_id,author,ban_day,reason)
210 MySQL.query("vRP/set_banned", {user_id = user_id, author = author, ban_day = ban_day, reason = reason})
211end
212
213function vRP.delBanned(user_id)
214 MySQL.query("vRP/del_banned", {user_id = user_id})
215end
216
217--- sql
218function vRP.isWhitelisted(user_id, cbr)
219 local task = Task(cbr, {false})
220
221 MySQL.query("vRP/get_whitelisted", {user_id = user_id}, function(rows, affected)
222 if #rows > 0 then
223 task({rows[1].whitelisted})
224 else
225 task()
226 end
227 end)
228end
229
230--- sql
231function vRP.setWhitelisted(user_id,whitelisted)
232 MySQL.query("vRP/set_whitelisted", {user_id = user_id, whitelisted = whitelisted})
233end
234
235--- sql
236function vRP.getLastLogin(user_id, cbr)
237 local task = Task(cbr,{""})
238 MySQL.query("vRP/get_last_login", {user_id = user_id}, function(rows, affected)
239 if #rows > 0 then
240 task({rows[1].last_login})
241 else
242 task()
243 end
244 end)
245end
246
247function vRP.setUData(user_id,key,value)
248 MySQL.query("vRP/set_userdata", {user_id = user_id, key = key, value = value})
249end
250
251function vRP.getUData(user_id,key,cbr)
252 local task = Task(cbr,{""})
253
254 MySQL.query("vRP/get_userdata", {user_id = user_id, key = key}, function(rows, affected)
255 if #rows > 0 then
256 task({rows[1].dvalue})
257 else
258 task()
259 end
260 end)
261end
262
263function vRP.setSData(key,value)
264 MySQL.query("vRP/set_srvdata", {key = key, value = value})
265end
266
267function vRP.getSData(key, cbr)
268 local task = Task(cbr,{""})
269
270 MySQL.query("vRP/get_srvdata", {key = key}, function(rows, affected)
271 if #rows > 0 then
272 task({rows[1].dvalue})
273 else
274 task()
275 end
276 end)
277end
278
279-- return user data table for vRP internal persistant connected user storage
280function vRP.getUserDataTable(user_id)
281 return vRP.user_tables[user_id]
282end
283
284function vRP.setUserDataTable(user_id, dataTable)
285 vRP.user_tables[user_id] = dataTable
286end
287
288function vRP.getUserTmpTable(user_id)
289 return vRP.user_tmp_tables[user_id]
290end
291
292function vRP.isConnected(user_id)
293 return vRP.rusers[user_id] ~= nil
294end
295
296function vRP.isFirstSpawn(user_id)
297 local tmp = vRP.getUserTmpTable(user_id)
298 return tmp and tmp.spawns == 1
299end
300
301function vRP.getUserId(source)
302 if source ~= nil then
303 local ids = GetPlayerIdentifiers(source)
304 if ids ~= nil and #ids > 0 then
305 return vRP.users[ids[1]]
306 end
307 end
308
309 return nil
310end
311
312-- return map of user_id -> player source
313function vRP.getUsers()
314 local users = {}
315 for k,v in pairs(vRP.user_sources) do
316 users[k] = v
317 end
318
319 return users
320end
321
322-- return source or nil
323function vRP.getUserSource(user_id)
324 return vRP.user_sources[user_id]
325end
326
327function vRP.ban(id,reason,author,ban_day)
328 local source = vRP.getUserSource(id)
329 if id ~= nil then
330 vRP.setBanned(id,author,ban_day,reason)
331 end
332 if source ~= nil then
333 vRP.kick(source,"[Banned] "..reason)
334 end
335end
336
337
338function vRP.kick(source,reason)
339 DropPlayer(source,reason)
340end
341
342-- tasks
343
344function task_save_datatables()
345 TriggerEvent("vRP:save")
346
347 Debug.pbegin("vRP save datatables")
348 for k,v in pairs(vRP.user_tables) do
349 vRP.setUData(k,"vRP:datatable",json.encode(v))
350 end
351
352 Debug.pend()
353 SetTimeout(config.save_interval*1000, task_save_datatables)
354end
355task_save_datatables()
356
357-- Added by bloopis
358-- enable to save manually user data
359function vRP.manual_save_datatables(_player)
360 local user_id = vRP.getUserId(_player)
361 if user_id ~= nil then
362 Debug.pbegin("vRP manual save datatables for user : "..tostring(user_id))
363 -- save money
364 TriggerEvent("vRP:saveOne",user_id)
365
366 -- save weapon
367 vRP.setUData(user_id,"vRP:datatable",json.encode(vRP.getUserDataTable(user_id)))
368 Debug.pend()
369 end
370end
371
372local max_pings = math.ceil(config.ping_timeout*60/30)+1
373function task_timeout() -- kick users not sending ping event in 2 minutes
374 local users = vRP.getUsers()
375 for k,v in pairs(users) do
376 local tmpdata = vRP.getUserTmpTable(tonumber(k))
377 if tmpdata.pings == nil then
378 tmpdata.pings = 0
379 end
380
381 tmpdata.pings = tmpdata.pings+1
382 if tmpdata.pings >= max_pings then
383 vRP.kick(v,"[vRP] Ping timeout.")
384 end
385 end
386
387 SetTimeout(300000, task_timeout)
388end
389task_timeout()
390
391function tvRP.ping()
392 local user_id = vRP.getUserId(source)
393 if user_id ~= nil then
394 local tmpdata = vRP.getUserTmpTable(user_id)
395 tmpdata.pings = 0 -- reinit ping countdown
396 end
397end
398
399-- handlers
400
401local rejects = {}
402
403-- AddEventHandler("playerConnecting",function(name,setMessage,deferrals)
404AddEventHandler("playerConnectingQueue",function(name,setMessage,deferrals,source)
405 local source = source
406 Debug.pbegin("playerConnecting")
407 local ids = GetPlayerIdentifiers(source)
408 local client_deferrals = deferrals
409 local _name = name
410
411 local idk = vRP.getSourceIdKey(source)
412 -- reject someone
413 local function reject(reason)
414 rejects[idk] = reason
415 end
416
417 if client_deferrals then
418 if ids ~= nil and #ids > 0 then
419 if(string.sub(ids[1], 1, 5) == "steam") then
420 vRP.getUserIdByIdentifiers(ids, function(user_id)
421 -- if user_id ~= nil and vRP.rusers[user_id] == nil then -- check user validity and if not already connected (old way, disabled until playerDropped is sure to be called)
422 if user_id ~= nil then -- check user validity
423 vRP.isBanned(user_id, function(ban)
424 if ban == nil then
425 vRP.isWhitelisted(user_id, function(whitelisted)
426 if not whiteList_state or whitelisted then
427 Debug.pbegin("playerConnecting_delayed")
428 if vRP.rusers[user_id] == nil then -- not present on the server, init
429 -- init entries
430 vRP.users[ids[1]] = user_id
431 vRP.rusers[user_id] = ids[1]
432 vRP.user_tables[user_id] = {}
433 vRP.user_tmp_tables[user_id] = {}
434 vRP.user_sources[user_id] = source
435
436 -- load user data table
437 vRP.getUData(user_id, "vRP:datatable", function(sdata)
438 local data = json.decode(sdata)
439 if type(data) == "table" then vRP.user_tables[user_id] = data end
440
441 -- init user tmp table
442 local tmpdata = vRP.getUserTmpTable(user_id)
443
444 vRP.getLastLogin(user_id, function(last_login)
445 tmpdata.last_login = last_login or ""
446 tmpdata.spawns = 0
447
448 -- set last login
449 local ep = vRP.getPlayerEndpoint(source)
450 local last_login_stamp = ep.." "..os.date("%H:%M:%S %d/%m/%Y")
451 --MySQL.query("vRP/set_last_login", {user_id = user_id, last_login = last_login_stamp})
452
453 -- trigger join
454 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") joined (user_id = "..user_id..")")
455 TriggerEvent("vRP:playerJoin", user_id, source, _name, tmpdata.last_login)
456 client_deferrals.done()
457 end)
458 end)
459 else -- already connected
460 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") re-joined (user_id = "..user_id..")")
461 TriggerEvent("vRP:playerRejoin", user_id, source, _name)
462 client_deferrals.done()
463
464 -- reset first spawn
465 local tmpdata = vRP.getUserTmpTable(user_id)
466 tmpdata.spawns = 0
467 end
468
469 Debug.pend()
470 else
471 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: not whitelisted (user_id = "..user_id..")")
472 Citizen.Wait(200)
473 client_deferrals.done("[vRP] Not whitelisted (user_id = "..user_id..").")
474 end
475 end)
476 else
477 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: banned (user_id = "..user_id..")")
478 Citizen.Wait(200)
479 client_deferrals.done("[vRP] Banned (user_id = "..user_id.."). Raison : "..ban.reason..". Banni par "..ban.author.."")
480 end
481 end)
482 else
483 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: identification error")
484 Citizen.Wait(200)
485 client_deferrals.done("[vRP] Identification error.")
486 end
487 end)
488 else
489 Citizen.Wait(200)
490 client_deferrals.done("Steam doit être lancé avant de rejoindre le serveur.")
491 end
492 else
493 print("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: missing identifiers")
494 Citizen.Wait(200)
495 client_deferrals.done("[vRP] Identifiants invalides.")
496 end
497 end
498 Debug.pend()
499end)
500
501AddEventHandler("playerDropped",function(reason)
502 local source = source
503 Debug.pbegin("playerDropped")
504
505 rejects[source] = nil
506 -- remove player from connected clients
507 vRPclient.removePlayer(-1,{source})
508
509
510 local user_id = vRP.getUserId(source)
511
512 if user_id ~= nil then
513 TriggerEvent("vRP:playerLeave", user_id, source)
514
515 -- save user data table
516 vRP.setUData(user_id,"vRP:datatable",json.encode(vRP.getUserDataTable(user_id)))
517
518 print("[vRP] "..vRP.getPlayerEndpoint(source).." disconnected (user_id = "..user_id..")")
519 vRP.users[vRP.rusers[user_id]] = nil
520 vRP.rusers[user_id] = nil
521 vRP.user_tables[user_id] = nil
522 vRP.user_tmp_tables[user_id] = nil
523 vRP.user_sources[user_id] = nil
524 end
525
526 playerDropped(source,reason,user_id)
527 Debug.pend()
528end)
529
530RegisterServerEvent("vRPcli:playerSpawned")
531AddEventHandler("vRPcli:playerSpawned", function()
532 Debug.pbegin("playerSpawned")
533 -- register user sources and then set first spawn to false
534 local user_id = vRP.getUserId(source)
535 local player = source
536 if user_id ~= nil then
537 vRP.user_sources[user_id] = source
538 local tmp = vRP.getUserTmpTable(user_id)
539 tmp.spawns = tmp.spawns+1
540 local first_spawn = (tmp.spawns == 1)
541
542 if first_spawn then
543 -- first spawn, reference player
544 -- send players to new player
545 for k,v in pairs(vRP.user_sources) do
546 vRPclient.addPlayer(source,{v})
547 end
548 -- send new player to all players
549 vRPclient.addPlayer(-1,{source})
550 end
551 -- set if new user or not
552 if vRP.user_tables[user_id].firstCo == nil or vRP.user_tables[user_id].firstCo then
553 vRP.user_tables[user_id].firstCo = true -- init FirstCo
554 TriggerClientEvent("state:setFirstSpawn", source)
555 else
556 if vRP.user_tables[user_id].firstSkin == nil or vRP.user_tables[user_id].firstSkin then
557 vRP.user_tables[user_id].firstSkin = true -- init Firskin
558 TriggerClientEvent("skin:firstSkin", source)
559 end
560 end
561
562
563
564 -- set client tunnel delay at first spawn
565 Tunnel.setDestDelay(player, config.load_delay)
566
567 -- show loading
568 vRPclient.setProgressBar(player,{"vRP:loading", "botright", "Chargement...", 0,0,0, 100})
569 TriggerClientEvent("disclaimer:called", source)
570
571 SetTimeout(2000, function() -- trigger spawn event
572 TriggerEvent("vRP:playerSpawn",user_id,player,first_spawn)
573
574 SetTimeout(config.load_duration*1000, function() -- set client delay to normal delay
575 Tunnel.setDestDelay(player, config.global_delay)
576 vRPclient.removeProgressBar(player,{"vRP:loading"})
577 end)
578 end)
579 end
580
581 -- reject
582 local idk = vRP.getSourceIdKey(player)
583 local reason = rejects[idk]
584 if reason then
585 vRP.kick(player, reason)
586 rejects[idk] = nil
587 end
588
589 Debug.pend()
590end)
591
592--RegisterServerEvent("vRP:playerDied")
593
594local players_number = {}
595RegisterServerEvent("playerNumber:getPlayersNumber")
596AddEventHandler("playerNumber:getPlayersNumber", function()
597 local user_id = vRP.getUserId(source)
598 if user_id ~= nil then
599 if players_number[source] then -- hide
600 players_number[source] = nil
601 vRPclient.removeDiv(source,{"players_number"})
602 else -- show
603 local count = 0
604 local cop = 0
605 local ems = 0
606 local repair = 0
607 local taxi = 0
608 local uber = 0
609 local livreur = 0
610 local press = 0
611 local content = ""
612 local data
613
614 for k,v in pairs(vRP.rusers) do
615
616 data = vRP.getUserDataTable(k)
617 if data then
618 if data.groups then
619 if data.groups["user"] then
620 count = count+1
621 if not vRP.getModState(k) then
622 if data.not_working == nil then
623 -- only if player isn't in moderation mode and working
624 if (data.groups["Police"]) or data.groups["Fbi"] or data.groups["sheriff"] then
625 -- cop
626 cop = cop+1
627 elseif data.groups["Ambulancier"] then
628 -- health
629 ems = ems+1
630 elseif data.groups["Mecano"] then
631 -- repair
632 repair = repair+1
633 elseif data.groups["Taxi"] then
634 -- taxi
635 taxi = taxi+1
636 -- Uber
637 elseif data.groups["Uber"] then
638 uber = uber+1
639 elseif data.groups["Livreur"] then
640 -- Livreur
641 livreur = livreur+1
642 elseif data.groups["Journaliste"] then
643 -- Journaliste
644 press = press+1
645 end
646 end
647 end
648
649 end
650 end
651 end
652
653 end
654
655 if vRP.getModState(user_id) then
656 -- in moderation, admin can have cops number
657 content = content.."<span class=\"colum\"><span class=\"icon\">👮</span><br /><span class=\"cop\">Policiers : "..tostring(cop).."</span></span>"
658 else
659 -- show job count
660 content = content.."<span class=\"colum\"><span class=\"icon\">👮</span><br /><span class=\"cop\">Policiers :<span class=\"on\"> Recrutement ON</span></span></span>"
661
662 end
663 content = content.."<span class=\"icon\">🚑</span><br /><span class=\"ems\">Ambulanciers : "..tostring(ems).."</span><br />"
664 content = content.."<br /><span class=\"colum\"><span class=\"icon\">🚧</span><br /><span class=\"rep\">Dépanneur : "..tostring(repair).."</span></span>"
665 content = content.."<span class=\"icon\">🚖</span><br /><span class=\"tax\">Chauffeurs de taxi : "..tostring(taxi).."</span><br /><span class=\"colum2\" style=\"margin-right:35px;\">Chauffeurs Uber : "..tostring(uber).."</span><br />"
666 content = content.."<br /><span class=\"colum\"><span class=\"icon\">🚚</span><br /><span class=\"delivery\">Livreur : "..tostring(livreur).."</span></span>"
667 content = content.."<span class=\"icon\">🎥</span><br /><span class=\"press\">Journaliste : "..tostring(press).."</span>"
668
669 content = content.."<br /><br />Nombre de joueurs en ligne : <span class=\"num\">"..tostring(count).."</span>"
670 content = content.."<br /><br /> 🔙 <small>".."APPUYEZ SUR [BACKSPACE] POUR FERMER".."</small><br />"
671 players_number[source] = true
672 vRPclient.setDiv(source,{"players_number", config.css_player_number, content})
673 end
674 end
675end)
676
677-- Added by Bloopis
678-- enable to receive user event to clear user list view
679RegisterServerEvent('players_number:removeDiv')
680AddEventHandler('players_number:removeDiv', function()
681 if players_number[source] then
682 players_number[source] = nil
683 vRPclient.removeDiv(source,{"players_number"})
684 end
685end)
686
687-- Added by Bloopis
688-- enable to receive user event to manually save data
689RegisterServerEvent('save:manualSave')
690AddEventHandler('save:manualSave', function()
691 local _source = source
692 vRP.manual_save_datatables(_source)
693end)
694
695--Added by serrat
696RegisterServerEvent("kickForBeingAnAFKDouchebag")
697AddEventHandler("kickForBeingAnAFKDouchebag", function()
698 local _source = source
699 local user_id = vRP.getUserId(_source)
700 data = vRP.getUserDataTable(user_id)
701 if data then
702 if data.groups then
703 if not data.groups["admin"] then
704 DropPlayer(_source, "AFK - Inactif trop longtemps...")
705 end
706 end
707 end
708end)
709
710-- CONFIG --
711
712-- Ping Limit
713pingLimit = 400
714thresholdPing = 200
715
716pingDuration=5000
717counter_kick_limit = 0
718
719
720-- CODE --
721
722RegisterServerEvent("checkMyPingBro")
723AddEventHandler("checkMyPingBro", function()
724 local _source = source
725 ping = GetPlayerPing(_source)
726 if ping >= pingLimit then
727 TriggerEvent("checkMyPingBroPeriod", _source)
728 end
729end)
730
731-- Added By bloopis
732-- check ping during period !!!
733AddEventHandler("checkMyPingBroPeriod", function(_source)
734 Citizen.CreateThread(function()
735 local timer = 0
736 local count_kick = 0
737 local incr_val = 1
738 local ping = 0
739 local _source = source
740 local user_id = vRP.getUserId(_source)
741 data = vRP.getUserDataTable(user_id)
742
743 while timer <= pingDuration do
744 Wait(500)
745 timer = timer + 500
746 ping = GetPlayerPing(_source)
747 if ping < thresholdPing then
748 -- under limit
749 incr_val = -1
750 elseif ping >= pingLimit then
751 -- over limit then + 1
752 incr_val = 1
753 end
754
755 count_kick = count_kick + incr_val
756 end
757
758 if count_kick > counter_kick_limit then
759 if data then
760 if data.groups then
761 if not data.groups["admin"]then
762 DropPlayer(_source, "Ping trop haut (Limite : " .. pingLimit .. ")")
763 end
764
765 end
766 end
767 end
768 end)
769end)
770
771
772function vRP.setWhiteListState(state)
773 whiteList_state = state
774end
775
776function vRP.getWhiteListState()
777 return whiteList_state
778end
779
780--====================================================================================
781--
782--
783--
784-- QUEUE SYSTEM
785--
786--
787--
788--====================================================================================
789-- Created by : Nick78111 - https://github.com/Nick78111/ConnectQueue/tree/testing
790-- Reworked by : Bloopis
791
792local Config = {}
793----------------------------------------------------------------------------------------------------------------------
794-- Priority list can be any identifier. (hex steamid, steamid32, ip) Integer = power over other priorities
795Config.Priority = {
796 -- ["STEAM_0:1:#######"] = 50,
797 -- ["steam:110000######"] = 25,
798 -- ["ip:127.0.0.0"] = 85,
799 ["steam:1100001069c7ed2"] = 1000, -- Serrat
800 ["steam:110000105622f86"] = 1000, -- Wave
801 ["steam:110000102e76eec"] = 1000, -- Antow
802 ["steam:11000010a07fe9a"] = 1000, -- Graincheux
803 ["steam:110000102b3dfbb"] = 1000, --Sadick
804 --["steam:1100001042fa3e0"] = 1000, -- Capo
805 ["steam:110000106a9e49e"] = 1000, -- PisseBleu
806 ["steam:110000102503649"] = 1000, -- Ladislol
807 ["steam:1100001013df8c5"] = 1000, -- carenne
808 ["steam:11000010a51b319"] = 1000, -- Croft
809 ["steam:110000102503649"] = 1000 -- Ladislol
810}
811
812Config.RequireSteam = true
813Config.PriorityOnly = false -- whitelist only server
814
815-- easy localization
816Config.Language = {
817 joining = "Preparation...",
818 connecting = "Connexion...",
819 err = "[CLUBV-QUEUE] Impossible de trouver votre ID. Essayez de vous reconnecter.",
820 _err = "[CLUBV-AIRLINES] Une erreur est intervenue sur votre avion..",
821 pos = "[CLUBV-AIRLINES] Vous êtes actuellement en transit. En attente de débarquement, voyageur : %d/%d",
822 connectingerr = "[CLUBV-AIRLINES] Une erreur est survenue lors de votre embarquement dans l'avion..",
823 steam = "Steam doit être lancé avant de rejoindre le serveur.",
824 priorityList = "Votre avion accuse d'un léger retard...(%d place(s) prioritaire(s), temps estimé : %d minutes et %d secondes)",
825 cleanQueue = "[CLUBV-AIRLINES] Nous vous informons que le contrôleur aérien a refusé notre demande d'atterrissage. Veuillez essayer à nouveau..",
826 prio = "You must be whitelisted to join this server. You may apply at www.whatever.net"
827}
828
829-----------------------------------------------------------------------------------------------------------------------
830
831local Queue = {}
832Queue.QueueList = {}
833Queue.PlayerList = {}
834Queue.PlayerCount = 0
835Queue.Priority = {}
836Queue.PriorityList = {}
837Queue.Connecting = {}
838Queue.ThreadCount = 0
839Queue.currentPriorityTime = 0
840Queue.WaitingID = {}
841Queue.WaitingTimes = {}
842
843local debug = true
844local displayQueue = false
845local initHostName = false
846local maxPlayers = 32
847local serverMaxPlayers = 32
848
849local tostring = tostring
850local tonumber = tonumber
851local ipairs = ipairs
852local pairs = pairs
853local print = print
854local string_sub = string.sub
855local string_format = string.format
856local string_lower = string.lower
857local math_abs = math.abs
858local math_floor = math.floor
859local os_time = os.time
860local table_insert = table.insert
861local table_remove = table.remove
862
863for k,v in pairs(Config.Priority) do
864 Queue.Priority[string_lower(k)] = v
865end
866
867-- converts hex steamid to SteamID 32
868function Queue:HexIdToSteamId(hexId)
869 local cid = math_floor(tonumber(string_sub(hexId, 7), 16))
870 local steam64 = math_floor(tonumber(string_sub( cid, 2)))
871 local a = steam64 % 2 == 0 and 0 or 1
872 local b = math_floor(math_abs(6561197960265728 - steam64 - a) / 2)
873 local sid = "steam_0:"..a..":"..(a == 1 and b -1 or b)
874 return sid
875end
876
877function Queue:IsSteamRunning(src)
878 for k,v in ipairs(GetPlayerIdentifiers(src)) do
879 if string.sub(v, 1, 5) == "steam" then
880 return true
881 end
882 end
883
884 return false
885end
886
887function Queue:DebugPrint(msg)
888 if debug then
889 msg = "SERRBLOOP_QUEUE: " .. tostring(msg)
890 print(msg)
891 if config.is_server_prod then
892 msg = os.date("[%d/%m/%Y %H:%M:%S] => ")..msg
893 PerformHttpRequest('https://discordapp.com/api/webhooks/382596667775516682/zy6G7eR5E-jd3sUHiizLfODpVHqFEBWyeGfo1inueYdLzSHoG74GXGk2Bjvhkvwy5EJJ', function(err, text, headers) end, 'POST',
894 json.encode({username = "Queue DEBUG", content = msg}), { ['Content-Type'] = 'application/json' })
895 end
896 end
897end
898
899function Queue:IsInQueue(ids, rtnTbl, bySource, connecting)
900 for k,v in ipairs(connecting and self.Connecting or self.QueueList) do
901 local inQueue = false
902
903 if not bySource then
904 for i,j in ipairs(v.ids) do
905 if inQueue then break end
906
907 for q,e in ipairs(ids) do
908 if e == j then inQueue = true break end
909 end
910 end
911 else
912 inQueue = ids == v.source
913 end
914
915 if inQueue then
916 if rtnTbl then
917 return k, connecting and self.Connecting[k] or self.QueueList[k]
918 end
919
920 return true
921 end
922 end
923
924 return false
925end
926
927function Queue:IsPriority(ids)
928 for k,v in ipairs(ids) do
929 v = string_lower(v)
930
931 if string_sub(v, 1, 5) == "steam" and not self.Priority[v] then
932 local steamid = self:HexIdToSteamId(v)
933 if self.Priority[steamid] then return self.Priority[steamid] ~= nil and self.Priority[steamid] or false end
934 end
935
936 if self.Priority[v] then return self.Priority[v] ~= nil and self.Priority[v] or false end
937 end
938end
939
940function Queue:AddToQueue(ids, connectTime, name, src, deferrals, prio)
941 if self:IsInQueue(ids) then return end
942
943 local tmp = {
944 source = src,
945 ids = ids,
946 name = name,
947 firstconnect = connectTime,
948 priority = self:IsPriority(ids) or (src == "debug" and math.random(0, 15)),
949 timeout = 0,
950 deferrals = deferrals
951 }
952
953 if not tmp.priority then
954 -- user don't have priority yet (not VIP)
955 -- we need to check if user is whitelisted if yes
956 -- then whistlisted user is most prior than not whitelisted user
957 if prio ~= 0 then
958 -- user is whitelisted adding priority value
959 tmp.priority = prio
960 end
961 end
962
963 local _pos = false
964 local queueCount = self:GetSize() + 1
965
966 for k,v in ipairs(self.QueueList) do
967 if tmp.priority then
968 if not v.priority then
969 _pos = k
970 else
971 if tmp.priority > v.priority then
972 _pos = k
973 end
974 end
975
976 if _pos then
977 self:DebugPrint(string_format("%s[%s] a ete place en priorite dans la liste d'attente. Position : %d/%d", tmp.name, ids[1], _pos, queueCount))
978 break
979 end
980 end
981 end
982
983 if not _pos then
984 _pos = self:GetSize() + 1
985 self:DebugPrint(string_format("%s[%s] a ete place dans la liste d'attente. Position : %d/%d", tmp.name, ids[1], _pos, queueCount))
986 end
987
988 table_insert(self.QueueList, _pos, tmp)
989end
990
991function Queue:RemoveFromQueue(ids, bySource)
992 if self:IsInQueue(ids, false, bySource) then
993 local pos, data = self:IsInQueue(ids, true, bySource)
994 table_remove(self.QueueList, pos)
995 end
996end
997
998function Queue:GetSize()
999 return #self.QueueList
1000end
1001
1002function Queue:ConnectingSize()
1003 return #self.Connecting
1004end
1005
1006function Queue:IsInConnecting(ids, bySource, refresh)
1007 local inConnecting, tbl = self:IsInQueue(ids, refresh and true or false, bySource and true or false, true)
1008
1009 if not inConnecting then return false end
1010
1011 if refresh and inConnecting and tbl then
1012 self.Connecting[inConnecting].timeout = 0
1013 end
1014
1015 return true
1016end
1017
1018function Queue:RemoveFromConnecting(ids, bySource)
1019 for k,v in ipairs(self.Connecting) do
1020 local inConnecting = false
1021
1022 if not bySource then
1023 for i,j in ipairs(v.ids) do
1024 if inConnecting then break end
1025
1026 for q,e in ipairs(ids) do
1027 if e == j then inConnecting = true break end
1028 end
1029 end
1030 else
1031 inConnecting = ids == v.source
1032 end
1033
1034 if inConnecting then
1035 table_remove(self.Connecting, k)
1036 return true
1037 end
1038 end
1039
1040 return false
1041end
1042
1043function Queue:AddToConnecting(ids, ignorePos, autoRemove, done)
1044 local function removeFromQueue()
1045 if not autoRemove then return end
1046
1047 done(Config.Language.connectingerr)
1048 self:RemoveFromConnecting(ids)
1049 self:RemoveFromQueue(ids)
1050 self:DebugPrint("Le joueur n'as pas pu être ajouté a la liste de connexion")
1051 end
1052
1053 if self:ConnectingSize() >= 5 then removeFromQueue() return false end
1054 if ids[1] == "debug" then
1055 table_insert(self.Connecting, {source = ids[1], ids = ids, name = ids[1], firstconnect = ids[1], priority = ids[1], timeout = 0})
1056 return true
1057 end
1058
1059 if self:IsInConnecting(ids) then self:RemoveFromConnecting(ids) end
1060
1061 local pos, data = self:IsInQueue(ids, true)
1062 if not ignorePos and (not pos or pos > 1) then removeFromQueue() return false end
1063
1064 table_insert(self.Connecting, data)
1065 self:RemoveFromQueue(ids)
1066 Queue.WaitingID[ids[1]] = {ids[1],data.name}
1067 return true
1068end
1069
1070function Queue:GetIds(src)
1071 local ids = GetPlayerIdentifiers(src)
1072 ids = (ids and ids[1]) and ids or {"ip:" .. GetPlayerEP(src)}
1073 ids = ids ~= nil and ids or false
1074
1075 if ids and #ids > 1 then
1076 for k,v in ipairs(ids) do
1077 if string.sub(v, 1, 3) == "ip:" then table_remove(ids, k) end
1078 end
1079 end
1080
1081 return ids
1082end
1083
1084function Queue:AddPriority(id, power)
1085 if not id then return false end
1086
1087 if type(id) == "table" then
1088 for k, v in pairs(id) do
1089 if k and type(k) == "string" and v and type(v) == "number" then
1090 self.Priority[k] = v
1091 else
1092 self:DebugPrint("Une erreur est survenue lors de la definition de la priorite, donnee invalides !")
1093 return false
1094 end
1095 end
1096
1097 return true
1098 end
1099
1100 power = (power and type(power) == "number") and power or 10
1101 self.Priority[string_lower(id)] = power
1102
1103 return true
1104end
1105
1106function Queue:RemovePriority(id)
1107 if not id then return false end
1108 self.Priority[id] = nil
1109 return true
1110end
1111
1112function Queue:UpdatePosData(src, ids, deferrals)
1113 local pos, data = self:IsInQueue(ids, true)
1114 self.QueueList[pos].source = src
1115 self.QueueList[pos].ids = ids
1116 self.QueueList[pos].timeout = 0
1117 self.QueueList[pos].deferrals = deferrals
1118end
1119
1120function Queue:NotFull(firstJoin)
1121 local canJoin = self.PlayerCount + self:ConnectingSize() < maxPlayers and self:ConnectingSize() < 5
1122 canJoin = firstJoin and (self:GetSize() <= 1 and canJoin) or canJoin
1123 return canJoin
1124end
1125
1126function Queue:IsVip(ids)
1127 -- VIPs are allowed to join server while player number ar under server max (32 currently)
1128 if Queue.Priority[ids] and ((self.PlayerCount + self:ConnectingSize() < serverMaxPlayers)) then
1129 return true
1130 end
1131
1132 -- all 32 slots are full then admin will be send in queue bug with higher priority
1133 return false
1134end
1135
1136function Queue:CheckPrio()
1137 return (maxPlayers - (self.PlayerCount + self:ConnectingSize())) - #Queue.PriorityList >= 1
1138end
1139
1140function Queue:PlayerInPrio(ids)
1141 -- check if user is in priority list
1142 for _,k in pairs(Queue.PriorityList) do
1143 if(k==ids[1]) then
1144 return true
1145 end
1146 end
1147
1148 return false
1149end
1150
1151function Queue:SetPos(ids, newPos)
1152 local pos, data = self:IsInQueue(ids, true)
1153
1154 table_remove(self.QueueList, pos)
1155 table_insert(self.QueueList, newPos, data)
1156
1157 Queue:DebugPrint("Set " .. data.name .. "[" .. data.ids[1] .. "] pos to " .. newPos)
1158end
1159
1160-- export
1161function AddPriority(id, power)
1162 return Queue:AddPriority(id, power)
1163end
1164
1165-- export
1166function RemovePriority(id)
1167 return Queue:RemovePriority(id)
1168end
1169
1170function vrpID(ids,_name,source, cbr)
1171 local task = Task(cbr)
1172
1173 vRP.getUserIdByIdentifiers(ids, function(user_id)
1174 if user_id ~= nil then -- check user validity
1175 task({user_id})
1176 else
1177 Queue:DebugPrint("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: identification error")
1178 task({nil})
1179 end
1180 end)
1181end
1182
1183function vrpBanned(user_id,_name,source, cbr)
1184 local task = Task(cbr)
1185
1186 vRP.isBanned(user_id, function(ban)
1187 if ban == nil then
1188 task({ban})
1189 else
1190 Queue:DebugPrint("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: banned (user_id = "..user_id..")")
1191 task({"[vRP] Banned (user_id = "..user_id.."). Raison : "..ban.reason..". Banni par "..ban.author..""})
1192 end
1193 end)
1194end
1195
1196function vrpWL(user_id,_name,source, cbr)
1197 local task = Task(cbr)
1198
1199 vRP.isWhitelisted(user_id, function(whitelisted)
1200 if not whiteList_state or whitelisted then
1201 if whitelisted then
1202 -- player is white listed
1203 task({{nil,true}})
1204 else
1205 -- player is allowed in server because whitelist system is OFF but he's not whitelisted then less prior
1206 task({{nil,false}})
1207 end
1208 else
1209 Queue:DebugPrint("[vRP] ".._name.." ("..vRP.getPlayerEndpoint(source)..") rejected: not whitelisted (user_id = "..user_id..")")
1210 task({{"[vRP] Not whitelisted (user_id = "..user_id..").",nil}})
1211 end
1212 end)
1213end
1214
1215Citizen.CreateThread(function()
1216 local function playerConnect(name, setKickReason, deferrals)
1217 maxPlayers = 32
1218 debug = GetConvar("sv_debugqueue", "true") == "true" and true or false
1219 displayQueue = GetConvar("sv_displayqueue", "true") == "true" and true or false
1220 initHostName = not initHostName and GetConvar("sv_hostname") or initHostName
1221
1222 local src = source
1223 local ids = Queue:GetIds(src)
1224 local connectTime = os_time()
1225 local connecting = true
1226
1227 deferrals.defer()
1228
1229 Citizen.CreateThread(function()
1230 while connecting do
1231 Citizen.Wait(500)
1232 if not connecting then return end
1233 deferrals.update(Config.Language.connecting)
1234 end
1235 end)
1236
1237 Citizen.Wait(1000)
1238
1239 local function done(msg)
1240 connecting = false
1241 if not msg then deferrals.done() else deferrals.done(tostring(msg) and tostring(msg) or "") CancelEvent() end
1242 end
1243
1244 local function update(msg)
1245 connecting = false
1246 deferrals.update(tostring(msg) and tostring(msg) or "")
1247 end
1248
1249 if not ids then
1250 -- prevent joining
1251 done(Config.Language.err)
1252 CancelEvent()
1253 Queue:DebugPrint("Dropped " .. name .. ", couldn't retrieve any of their id's")
1254 return
1255 end
1256
1257 if Config.RequireSteam and not Queue:IsSteamRunning(src) then
1258 done(Config.Language.steam)
1259 CancelEvent()
1260 return
1261 end
1262
1263 -- vrp verifications
1264 -- those cheks are duplicate from base event check but necessary (we need to check BEFORE queue start)
1265 local rejected
1266 local msgRejected = ""
1267 local user_id
1268 local player_priority = 0
1269 vrpID(ids,name,src, function(result)
1270 -- local result = nil
1271 if result == nil then
1272 msgRejected = "[vRP] Identification error."
1273 rejected = true
1274 Queue:RemoveFromQueue(ids)
1275 Queue:RemoveFromConnecting(ids)
1276 else
1277 user_id = result
1278 rejected = false
1279 end
1280 end)
1281
1282 while rejected == nil do Citizen.Wait(0) end
1283 if rejected then Citizen.Wait(200) done(msgRejected) CancelEvent() return end
1284
1285 rejected = nil
1286 vrpWL(user_id,name,src, function(result)
1287 -- local result = nil
1288 if result[1] ~= nil then
1289 msgRejected = result[1]
1290 rejected = true
1291 Queue:RemoveFromQueue(ids)
1292 Queue:RemoveFromConnecting(ids)
1293 else
1294 if result[2] then
1295 Queue:DebugPrint(string_format("%s[%s] est whiteliste, de ce fait une priorite est applique", name, ids[1]))
1296 -- player is whitlisted then we give him a priority number
1297 player_priority = 100
1298 end
1299 rejected = false
1300 end
1301 end)
1302
1303 while rejected == nil do Citizen.Wait(0) end
1304 if rejected then Citizen.Wait(200) done(msgRejected) CancelEvent() return end
1305
1306 rejected = nil
1307 vrpBanned(user_id,name,src, function(result)
1308 -- local result = nil
1309 if result ~= nil then
1310 msgRejected = result
1311 rejected = true
1312 Queue:RemoveFromQueue(ids)
1313 Queue:RemoveFromConnecting(ids)
1314 else
1315 rejected = false
1316 end
1317 end)
1318
1319 while rejected == nil do Citizen.Wait(0) end
1320 if rejected then Citizen.Wait(200) done(msgRejected) CancelEvent() return end
1321
1322
1323 -- apply priority if player is in priority list
1324 if Queue:PlayerInPrio(ids) then
1325 Queue:DebugPrint(string_format("%s[%s] est prioritaire (crash), de ce fait une priorite plus forte est applique", name, ids[1]))
1326 -- player is whitlisted then we give him better priority number
1327 player_priority = 300
1328 end
1329
1330
1331 local reason = "You were kicked from joining the queue"
1332
1333 local function setReason(msg)
1334 reason = tostring(msg)
1335 end
1336
1337 TriggerEvent("queue:playerJoinQueue", src, setReason)
1338
1339 if WasEventCanceled() then
1340 done(reason)
1341
1342 Queue:RemoveFromQueue(ids)
1343 Queue:RemoveFromConnecting(ids)
1344
1345 CancelEvent()
1346 return
1347 end
1348
1349 if Config.PriorityOnly and not Queue:IsPriority(ids) then done(Config.Language.prio) return end
1350
1351 local rejoined = false
1352
1353 if Queue:IsInQueue(ids) then
1354 rejoined = true
1355 Queue:UpdatePosData(src, ids, deferrals)
1356 Queue:DebugPrint(string_format("%s[%s] a rejoint la liste d'attente après avoir annule", name, ids[1]))
1357 else
1358 Queue:AddToQueue(ids, connectTime, name, src, deferrals,player_priority)
1359 end
1360
1361 if Queue:IsInConnecting(ids, false, true) then
1362 Queue:RemoveFromConnecting(ids)
1363
1364 if Queue:NotFull() then
1365 local added = Queue:AddToConnecting(ids, true, true, done)
1366 if not added then CancelEvent() return end
1367
1368
1369 TriggerEvent("playerConnectingQueue", name,setKickReason,deferrals,src)
1370 -- done()
1371
1372 return
1373 else
1374 Queue:AddToQueue(ids, connectTime, name, src, deferrals,player_priority)
1375 Queue:SetPos(ids, 1)
1376 end
1377 end
1378
1379 local pos, data = Queue:IsInQueue(ids, true)
1380
1381 if not pos or not data then
1382 done(Config.Language._err .. "[3]")
1383
1384 RemoveFromQueue(ids)
1385 RemoveFromConnecting(ids)
1386
1387 CancelEvent()
1388 return
1389 end
1390
1391 if Queue:NotFull(true) and (#Queue.PriorityList == 0 or Queue:CheckPrio()) then
1392 -- let them in the server
1393 local added = Queue:AddToConnecting(ids, true, true, done)
1394 if not added then CancelEvent() return end
1395
1396 TriggerEvent("playerConnectingQueue", name,setKickReason,deferrals,src)
1397 -- done()
1398 Queue:DebugPrint(name .. "[" .. ids[1] .. "] charge le serveur sans passer par la queue")
1399
1400 return
1401 end
1402
1403 if Queue:IsVip(ids[1]) then
1404 local added = Queue:AddToConnecting(ids, true, true, done)
1405 if not added then CancelEvent() return end
1406
1407 TriggerEvent("playerConnectingQueue", name,setKickReason,deferrals,src)
1408 -- done()
1409 Queue:DebugPrint(name .. "[" .. ids[1] .. "] charge le serveur en tant que VIP")
1410 end
1411
1412 update(string_format(Config.Language.pos, pos, Queue:GetSize()))
1413
1414 Citizen.CreateThread(function()
1415 if rejoined then return end
1416
1417 Queue.ThreadCount = Queue.ThreadCount + 1
1418 local dotCount = 0
1419 local PrioListActivated = false
1420
1421 while true do
1422 Citizen.Wait(1000)
1423
1424 local dots = " "
1425
1426 dotCount = dotCount + 1
1427 if dotCount > 3 then dotCount = 0 end
1428
1429 -- hopefully people will notice this and realize they don't have to keep reconnecting...
1430 for i = 1 , dotCount do
1431 if i < dotCount then
1432 dots = dots .. "âž–"
1433 else
1434 dots = dots .. "➖✈"
1435 end
1436 end
1437
1438 local pos, data = Queue:IsInQueue(ids, true)
1439
1440 -- will return false if not in queue; timed out?
1441 if not pos or not data then
1442 if data and data.deferrals then data.deferrals.done(Config.Language._err) end
1443 CancelEvent()
1444 Queue:RemoveFromQueue(ids)
1445 Queue:RemoveFromConnecting(ids)
1446 Queue.ThreadCount = Queue.ThreadCount - 1
1447 return
1448 end
1449
1450 local authorized = false
1451 local playerWasPrio = false
1452
1453 -- check if player is allowed to log into the server !
1454 if #Queue.PriorityList == 0 then
1455 PrioListActivated = false
1456 if (pos <= 1 or Queue:IsVip(ids[1])) and Queue:NotFull() then
1457 authorized = true
1458 end
1459 else
1460 PrioListActivated = true
1461 -- at least 1 player is disconnected then we wait 3 mins / player
1462 local isIn = Queue:PlayerInPrio(ids)
1463
1464 if((isIn and Queue:NotFull()) or Queue:IsVip(ids[1])) then
1465 -- allow connection only if server isn't full
1466 Queue:DebugPrint(name .. "[" .. ids[1] .. "] autorise a se connecter en mode priorite")
1467 authorized = true
1468 else
1469 if isIn then
1470 playerWasPrio = true
1471 end
1472 end
1473 end
1474
1475
1476 if authorized then
1477 -- let them in the server
1478 local added = Queue:AddToConnecting(ids)
1479
1480 data.deferrals.update(Config.Language.joining)
1481 Citizen.Wait(500)
1482
1483 if not added then
1484 data.deferrals.done(Config.Language.connectingerr)
1485 CancelEvent()
1486 Queue.ThreadCount = Queue.ThreadCount - 1
1487 return
1488 end
1489
1490 TriggerEvent("playerConnectingQueue", data.name,setKickReason,data.deferrals,data.source)
1491 -- data.deferrals.done()
1492
1493 Queue:RemoveFromQueue(ids)
1494 Queue.ThreadCount = Queue.ThreadCount - 1
1495 Queue:DebugPrint(name .. "[" .. ids[1] .. "] charge le serveur")
1496
1497 return
1498 else
1499 -- send status update
1500 local msg
1501 if PrioListActivated and playerWasPrio == false then
1502 local raw_minutes = Queue.currentPriorityTime/60
1503 local minutes = stringsplit(raw_minutes, ".")[1]
1504 local seconds = stringsplit(Queue.currentPriorityTime-(minutes*60), ".")[1]
1505 msg = string_format(Config.Language.priorityList, #Queue.PriorityList, minutes, seconds)
1506 else
1507 msg = string_format(Config.Language.pos .. "%s", pos, Queue:GetSize(), dots)
1508 end
1509 data.deferrals.update(msg)
1510 end
1511
1512 end
1513 end)
1514 end
1515
1516 AddEventHandler("playerConnecting", playerConnect)
1517
1518 local function checkTimeOuts()
1519 local i = 1
1520
1521 while i <= Queue:GetSize() do
1522 local data = Queue.QueueList[i]
1523 local lastMsg = GetPlayerLastMsg(data.source)
1524
1525 if lastMsg == 0 or lastMsg >= 30000 then
1526 data.timeout = data.timeout + 1
1527 else
1528 data.timeout = 0
1529 end
1530
1531 -- check just incase there is invalid data
1532 if not data.ids or not data.name or not data.firstconnect or data.priority == nil or not data.source then
1533 data.deferrals.done(Config.Language._err .. "[1]")
1534 table_remove(Queue.QueueList, i)
1535 Queue:DebugPrint(tostring(data.name) .. "[" .. tostring(data.ids[1]) .. "] a ete enleve des listes d'attentes a cause de donnes invalides")
1536 elseif (data.timeout >= 120) and data.source ~= "debug" and os_time() - data.firstconnect > 5 then
1537 -- remove by source incase they rejoined and were duped in the queue somehow
1538 data.deferrals.done(Config.Language._err .. "[2]")
1539 Queue:RemoveFromQueue(data.source, true)
1540 Queue:RemoveFromConnecting(data.source, true)
1541 Queue:DebugPrint(data.name .. "[" .. data.ids[1] .. "] a ete enleve de la liste d'attente suite a un timeout")
1542 else
1543 i = i + 1
1544 end
1545 end
1546
1547 i = 1
1548
1549 while i <= Queue:ConnectingSize() do
1550 local data = Queue.Connecting[i]
1551 local lastMsg = GetPlayerLastMsg(data.source)
1552 data.timeout = data.timeout + 1
1553
1554 if ((data.timeout >= 300 and lastMsg >= 35000) or data.timeout >= 340) and data.source ~= "debug" and os_time() - data.firstconnect > 5 then
1555 Queue:RemoveFromQueue(data.source, true)
1556 Queue:RemoveFromConnecting(data.source, true)
1557 Queue:DebugPrint(data.name .. "[" .. data.ids[1] .. "] a ete enleve de la liste de connexion suite a un timeout")
1558 else
1559 i = i + 1
1560 end
1561 end
1562
1563 local qCount = Queue:GetSize()
1564
1565 -- show queue count in server name
1566 -- if displayQueue and initHostName then SetConvar("sv_hostname", (qCount > 0 and "[" .. tostring(qCount) .. "] " or "") .. initHostName) end
1567
1568 SetTimeout(1000, checkTimeOuts)
1569 end
1570
1571 checkTimeOuts()
1572
1573 local function cleanQueue(player)
1574 -- Le nettoyage de queue s'applique uniwuement lorsque le joueur est en attente ! Pas lors du chargement !
1575 Queue:DebugPrint("[BEFORE CLEAN] Queue size : "..Queue:GetSize())
1576 local i = 1
1577 local run = true
1578
1579 while i <= 100 do
1580 local data = Queue.QueueList[Queue:GetSize()]
1581
1582 -- check just incase there is invalid data
1583 if data and not data.ids or not data.name or not data.firstconnect or data.priority == nil or not data.source then
1584 Citizen.Wait(200)
1585 data.deferrals.done(Config.Language._err .. "[1]")
1586 table_remove(Queue.QueueList, Queue:GetSize())
1587 Queue:DebugPrint(tostring(data.name) .. "[" .. tostring(data.ids[1]) .. "] a ete enleve des listes d'attentes a cause de donnes invalides")
1588 else
1589 table_remove(Queue.QueueList, Queue:GetSize())
1590 Citizen.Wait(200)
1591 data.deferrals.done(Config.Language.cleanQueue)
1592 Queue:RemoveFromQueue(data.source, true)
1593 Queue:RemoveFromConnecting(data.source, true)
1594 Queue:DebugPrint(data.name .. "[" .. data.ids[1] .. "] a ete enleve de la liste d'attente -> CLEAN QUEUE")
1595 end
1596 i = i + 1
1597
1598 if Queue:GetSize() == 0 then
1599 -- if queue is empty then quit
1600 break
1601 end
1602 end
1603
1604 Queue.PriorityList = {}
1605
1606 vRPclient.notify(player,{"~g~Queue nettoyée avec succès !"})
1607 Queue:DebugPrint("[AFTER CLEAN] Queue size : "..Queue:GetSize())
1608 end
1609
1610 AddEventHandler("queue:cleanQueueAdmin", cleanQueue)
1611
1612end)
1613
1614local function playerActivated()
1615 local src = source
1616 local ids = Queue:GetIds(src)
1617
1618 if not Queue.PlayerList[src] then
1619 Queue.PlayerCount = Queue.PlayerCount + 1
1620 Queue.PlayerList[src] = true
1621 Queue:RemoveFromQueue(ids)
1622 Queue:RemoveFromConnecting(ids)
1623 end
1624
1625 for i,k in ipairs(Queue.PriorityList) do
1626 if(k==ids[1]) then
1627 if Queue.WaitingTimes[ids[1]] then
1628 -- remove left time from global value
1629 Queue.currentPriorityTime = Queue.currentPriorityTime - (180 - Queue.WaitingTimes[ids[1]])
1630 Queue.WaitingTimes[ids[1]] = nil
1631 end
1632
1633 if Queue.currentPriorityTime < 0 then
1634 -- security check
1635 Queue.currentPriorityTime = 0
1636 end
1637
1638 table.remove(Queue.PriorityList, i)
1639 Queue:DebugPrint("[" .. ids[1] .. "] a ete sorti de la file de priorite.")
1640 break
1641 end
1642 end
1643end
1644
1645RegisterServerEvent("Queue:playerActivated")
1646AddEventHandler("Queue:playerActivated", playerActivated)
1647
1648function playerDropped(source, reason, user_id)
1649 local src = source
1650 local ids = Queue:GetIds(src)
1651
1652 if Queue.PlayerList[src] then
1653 Queue.PlayerCount = Queue.PlayerCount - 1
1654 Queue.PlayerList[src] = nil
1655 Queue:RemoveFromQueue(ids)
1656 Queue:RemoveFromConnecting(ids)
1657 end
1658
1659 if src ~= nil then
1660 local steamID = GetPlayerIdentifiers(src)[1] or false
1661 if steamID and Queue.WaitingID[steamID] then
1662 -- Exiting (quitter menu echap)
1663 -- Disconnected. (deconnexion menu echap)
1664 if(reason ~= "Disconnected." and reason ~= "Exiting") then
1665 local allowed_prio = true
1666 if user_id ~= nil then
1667 local wait
1668 vrpWL(user_id,"Unknow",src, function(result)
1669 -- local result = nil
1670 if result[1] ~= nil then
1671 -- not whitelisted
1672 allowed_prio = false
1673 else
1674 -- whitelisted or whitelist disable but it's ok
1675 allowed_prio = true
1676 end
1677 wait = true
1678 end)
1679
1680 while wait == nil do Citizen.Wait(0) end
1681 end
1682
1683 if allowed_prio then
1684
1685 -- temporise player count resfresh to make sure user is added in priority
1686 -- list and waiting player don't receive order to connect (very smal window but possible)
1687 deco_wait = true
1688 local identifier = Queue.WaitingID[steamID][1]
1689 local playerName = Queue.WaitingID[steamID][2]
1690 local isInPriorityList = false
1691
1692 -- check if user is already in priority list
1693 for i = 1, #Queue.PriorityList, 1 do
1694 if Queue.PriorityList[i] == identifier then
1695 isInPriorityList = true
1696 Queue:DebugPrint(playerName.."["..identifier.."] est deja dans la file de priorite.")
1697 break
1698 end
1699 end
1700
1701 if not isInPriorityList then
1702 table.insert(Queue.PriorityList, identifier)
1703 Queue.WaitingTimes[identifier] = 0
1704 Queue:DebugPrint(playerName .. " [" .. identifier .. "] a ete ajoute à la file de priorite.")
1705 end
1706
1707 -- init priority countdown only if user isn't already in
1708 deco_wait = false
1709 if not isInPriorityList then
1710 -- active wait time only if user is set in list (and not already in)
1711 -- give 3 minutes in priority list for crashed user
1712 local timeToWait = 180
1713 Queue.currentPriorityTime = Queue.currentPriorityTime + timeToWait
1714
1715 for i=0,timeToWait, 1 do
1716 Wait(1000)
1717 Queue.currentPriorityTime = Queue.currentPriorityTime -1
1718 if Queue.WaitingTimes[identifier] then
1719 Queue.WaitingTimes[identifier] = Queue.WaitingTimes[identifier] + 1
1720 end
1721 -- print(currentPriorityTime)
1722 -- print(#PriorityList)
1723
1724 if #Queue.PriorityList == 0 then
1725 Queue.currentPriorityTime = 0
1726 break
1727 end
1728
1729 if(i >= timeToWait) or Queue.currentPriorityTime <= 0 then
1730 for i = 1, #Queue.PriorityList, 1 do
1731 if Queue.PriorityList[i] == identifier then
1732 Queue.WaitingTimes[identifier] = nil
1733 table.remove(Queue.PriorityList, i)
1734 Queue:DebugPrint(playerName .. " [" .. identifier .. "] a ete sorti de la file de priorite.")
1735 Queue.WaitingID[steamID] = nil
1736 end
1737 end
1738 end
1739 end
1740 end
1741 else
1742 Queue:DebugPrint("Le joueur [" .. steamID .. "] n'as pas ete ajoute a la liste prioritaire car non prioritaire (non whitelite avec WL ON)")
1743 -- clear waiting id
1744 Queue.WaitingID[steamID] = nil
1745 end
1746 else
1747 -- clear waiting id
1748 Queue.WaitingID[steamID] = nil
1749 end
1750 else
1751 Queue:DebugPrint("Impossible d'obtenir le STEAM_ID du joueur s'ayant déconnecté..")
1752 end
1753 else
1754 Queue:DebugPrint("Impossible d'obtenir la source du joueur s'ayant déconnecté..")
1755 end
1756end
1757
1758-- AddEventHandler("playerDropped", playerDropped)
1759
1760Citizen.CreateThread(function()
1761 while true do
1762 Citizen.Wait(0)
1763 if exports and exports.connectqueue then TriggerEvent("queue:onReady") return end
1764 end
1765end)
1766
1767function stringsplit(inputstr, sep)
1768 if sep == nil then
1769 sep = "%s"
1770 end
1771 local t={} ; i=1
1772 for str in string.gmatch(inputstr, "([^"..sep.."]+)") do
1773 t[i] = str
1774 i = i + 1
1775 end
1776 return t
1777end
1778
1779--====================================================================================
1780--
1781--
1782--
1783-- RCON TOOL SYSTEM
1784--
1785--
1786--
1787--====================================================================================
1788
1789AddEventHandler('rconCommand', function(commandName, args)
1790 local time = "["..os.date("%H:%M:%S %d/%m/%Y").."] "
1791 if commandName:lower() == 'setstatuswl' then
1792 -- change wl state by given option
1793 local state = table.remove(args, 1)
1794
1795 if state and state == "off" then
1796 vRP.setWhiteListState(false)
1797 else
1798 vRP.setWhiteListState(true)
1799 end
1800
1801 local current_state = vRP.getWhiteListState()
1802 if current_state then
1803 RconPrint(time.."Rcon admin &|& on\n")
1804 else
1805 RconPrint(time.."Rcon admin &|& off\n")
1806 end
1807
1808 CancelEvent()
1809 elseif commandName:lower() == 'statuswl' then
1810 local current_state = vRP.getWhiteListState()
1811 if current_state then
1812 RconPrint(time.."Rcon admin &|& on\n")
1813 else
1814 RconPrint(time.."Rcon admin &|& off\n")
1815 end
1816
1817 CancelEvent()
1818 end
1819end)