From 09d76deef3457761441e8d63fc278e5b9452623d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9mie=20N=27gadi?= Date: Sat, 12 Aug 2017 11:35:52 +0200 Subject: [PATCH] Add files --- __resource.lua | 23 +++++ client/main.lua | 97 +++++++++++++++++++ config.lua | 5 + esx_status.sql | 3 + html/css/app.css | 20 ++++ html/scripts/app.js | 57 +++++++++++ html/ui.html | 14 +++ server/classes/status.lua | 52 ++++++++++ server/main.lua | 198 ++++++++++++++++++++++++++++++++++++++ 9 files changed, 469 insertions(+) create mode 100644 __resource.lua create mode 100644 client/main.lua create mode 100644 config.lua create mode 100644 esx_status.sql create mode 100644 html/css/app.css create mode 100644 html/scripts/app.js create mode 100644 html/ui.html create mode 100644 server/classes/status.lua create mode 100644 server/main.lua diff --git a/__resource.lua b/__resource.lua new file mode 100644 index 00000000..f3fe55e6 --- /dev/null +++ b/__resource.lua @@ -0,0 +1,23 @@ +resource_manifest_version '44febabe-d386-4d18-afbe-5e627f4af937' + +description 'ESX Status' + +server_scripts { + '@mysql-async/lib/MySQL.lua', + 'config.lua', + 'server/classes/status.lua', + 'server/main.lua' +} + +client_scripts { + 'config.lua', + 'client/main.lua' +} + +ui_page 'html/ui.html' + +files { + 'html/ui.html', + 'html/css/app.css', + 'html/scripts/app.js' +} \ No newline at end of file diff --git a/client/main.lua b/client/main.lua new file mode 100644 index 00000000..fd69e2e4 --- /dev/null +++ b/client/main.lua @@ -0,0 +1,97 @@ +local Status = {} +local loaded = false + +RegisterNetEvent('esx_status:update') +AddEventHandler('esx_status:update', function(status) + + Status = status + + SendNUIMessage({ + update = true, + status = Status + }) + + if not loaded then + TriggerEvent('esx_status:loaded') + loaded = true + end + +end) + +AddEventHandler('esx_status:getStatus', function(name, cb) + + for i=1, #Status, 1 do + if Status[i].name == name then + cb(Status[i]) + return + end + end + +end) + +AddEventHandler('esx_status:setDisplay', function(val) + + SendNUIMessage({ + setDisplay = true, + display = val + }) + +end) + +-- Calculate status +Citizen.CreateThread(function() + while true do + + for i=1, #Status, 1 do + + if Status[i].clientAction.add ~= nil then + + local val = Status[i].clientAction.add + + if Status[i].val + val > Config.StatusMax then + Status[i].val = StatusMax + else + Status[i].val = Status[i].val + val + end + + end + + if Status[i].clientAction.remove ~= nil then + + local val = Status[i].clientAction.remove + + if Status[i].val - val < 0 then + Status[i].val = 0 + else + Status[i].val = Status[i].val - val + end + + end + + end + + SendNUIMessage({ + update = true, + status = Status + }) + + Citizen.Wait(Config.TickTime) + + end +end) + +-- Pause menu disable hud display +local isPaused = false + +Citizen.CreateThread(function() + while true do + Citizen.Wait(1) + if IsPauseMenuActive() and not isPaused then + isPaused = true + TriggerEvent('esx_status:setDisplay', 0.0) + elseif not IsPauseMenuActive() and isPaused then + isPaused = false + TriggerEvent('esx_status:setDisplay', 0.5) + end + end +end) \ No newline at end of file diff --git a/config.lua b/config.lua new file mode 100644 index 00000000..862ec1bd --- /dev/null +++ b/config.lua @@ -0,0 +1,5 @@ +Config = {} + +Config.StatusMax = 1000000 +Config.TickTime = 1000 +Config.UpdateClientTime = 60000 \ No newline at end of file diff --git a/esx_status.sql b/esx_status.sql new file mode 100644 index 00000000..b62fd8dd --- /dev/null +++ b/esx_status.sql @@ -0,0 +1,3 @@ +USE `essentialmode`; + +ALTER TABLE `users` ADD COLUMN `status` LONGTEXT NULL; diff --git a/html/css/app.css b/html/css/app.css new file mode 100644 index 00000000..d92580fa --- /dev/null +++ b/html/css/app.css @@ -0,0 +1,20 @@ +#status_list { + position: absolute; + left : 23; + bottom : 21%; + width : 14.5%; + opacity: 0.3; +} + +.status { + padding: 1px; + margin: 0.3em; +} + +.status_inner { + padding: 1px; +} + +.status_val { + height : 0.5em; +} \ No newline at end of file diff --git a/html/scripts/app.js b/html/scripts/app.js new file mode 100644 index 00000000..e009ce7e --- /dev/null +++ b/html/scripts/app.js @@ -0,0 +1,57 @@ +(function(){ + + let status = [] + + let renderStatus = function(){ + + $('#status_list').html(''); + + for(let i=0; i' + + '
' + + '
' + + '
' + + ''); + + statusDiv.find('.status_inner') + .css({'border' : '1px solid ' + status[i].color}) + ; + + statusDiv.find('.status_val') + .css({ + 'background-color' : status[i].color, + 'width' : (status[i].val / 10000) + '%' + }) + ; + + $('#status_list').append(statusDiv) + } + + } + + window.onData = function(data){ + + if(data.update){ + + status.length = 0; + + for(let i=0; i + + + + + + +
+ + + + + + \ No newline at end of file diff --git a/server/classes/status.lua b/server/classes/status.lua new file mode 100644 index 00000000..f400eb53 --- /dev/null +++ b/server/classes/status.lua @@ -0,0 +1,52 @@ +function CreateStatus(xPlayer, name, default, color, visible, tickCallback, clientAction) + + local self = {} + + self.val = default + self.xPlayer = xPlayer + self.name = name + self.default = default + self.color = color + self.visible = visible + self.tickCallback = tickCallback + self.clientAction = clientAction + + self._set = function(k, v) + self[k] = v + end + + self._get = function(k) + return self[k] + end + + self.onTick = function() + self.tickCallback(self) + end + + self.set = function(val) + self.val = val + end + + self.add = function(val) + if self.val + val > Config.StatusMax then + self.val = StatusMax + else + self.val = self.val + val + end + end + + self.remove = function(val) + if self.val - val < 0 then + self.val = 0 + else + self.val = self.val - val + end + end + + self.updateClient = function() + TriggerEvent('esx_status:updateClient', self.xPlayer.source) + end + + return self + +end diff --git a/server/main.lua b/server/main.lua new file mode 100644 index 00000000..6358de60 --- /dev/null +++ b/server/main.lua @@ -0,0 +1,198 @@ +ESX = nil +local RegisteredStatus = {} + +TriggerEvent('esx:getSharedObject', function(obj) ESX = obj end) + +AddEventHandler('esx_status:registerStatus', function(name, default, color, visible, tickCallback, clientAction) + + table.insert(RegisteredStatus, { + name = name, + default = default, + color = color, + visible = visible, + tickCallback = tickCallback, + clientAction = clientAction + }) + +end) + +AddEventHandler('esx:playerLoaded', function(source) + + local _source = source + local xPlayer = ESX.GetPlayerFromId(_source) + + MySQL.Async.fetchAll( + 'SELECT * FROM users WHERE identifier = @identifier', + { + ['@identifier'] = xPlayer.identifier + }, + function(result) + + local data = {} + local savedStatus = {} + + if result[1].status ~= nil then + data = json.decode(result[1].status) + end + + for i=1, #data, 1 do + savedStatus[data[i].name] = data[i] + end + + local status = {} + + for i=1, #RegisteredStatus, 1 do + + local s = RegisteredStatus[i] + local default = nil + + if savedStatus[s.name] ~= nil then + default = savedStatus[s.name].val + else + default = s.default + end + + table.insert(status, CreateStatus(xPlayer, s.name, default, s.color, s.visible, s.tickCallback, s.clientAction)) + end + + xPlayer.set('status', status) + + TriggerEvent('esx_status:updateClient', _source) + + end + ) + +end) + +AddEventHandler('esx:playerDropped', function(source) + + local xPlayer = ESX.GetPlayerFromId(source) + + local data = {} + local status = xPlayer.get('status') + + for i=1, #status, 1 do + + local s = status[i] + + table.insert(data, { + name = s._get('name'), + val = s._get('val') + }) + end + + MySQL.Async.execute( + 'UPDATE users SET status = @status WHERE identifier = @identifier', + { + ['@status'] = json.encode(data), + ['@identifier'] = xPlayer.identifier + } + ) + +end) + +AddEventHandler('esx_status:getStatus', function(playerId, statusName, cb) + + local xPlayer = ESX.GetPlayerFromId(playerId) + local status = xPlayer.get('status') + + for i=1, #status, 1 do + if status[i]._get('name') == statusName then + cb(status[i]) + break + end + end + +end) + +AddEventHandler('esx_status:updateClient', function(playerId) + + local xPlayer = ESX.GetPlayerFromId(playerId) + local data = {} + local status = xPlayer.get('status') + + for i=1, #status, 1 do + table.insert(data, { + name = status[i]._get('name'), + val = status[i]._get('val'), + color = status[i]._get('color'), + visible = status[i]._get('visible')(status[i]), + clientAction = status[i]._get('clientAction'), + max = Config.StatusMax + }) + end + + TriggerClientEvent('esx_status:update', playerId, data) + +end) + +function TickStatus() + + local xPlayers = ESX.GetPlayers() + + for k,v in pairs(xPlayers) do + + local status = v.get('status') + + if status ~= nil then + + for i=1, #status, 1 do + status[i]._get('onTick')() + end + + end + + end + + SetTimeout(Config.TickTime, TickStatus) + +end + +function UpdateClients() + + local xPlayers = ESX.GetPlayers() + + for k,v in pairs(xPlayers) do + TriggerEvent('esx_status:updateClient', v.source) + end + + SetTimeout(Config.UpdateClientTime, UpdateClients) + +end + +function SaveData() + + local xPlayers = ESX.GetPlayers() + + for k,v in pairs(xPlayers) do + + local data = {} + local status = v.get('status') + + for i=1, #status, 1 do + + local s = status[i] + + table.insert(data, { + name = s._get('name'), + val = s._get('val') + }) + end + + MySQL.Async.execute( + 'UPDATE users SET status = @status WHERE identifier = @identifier', + { + ['@status'] = json.encode(data), + ['@identifier'] = v.identifier + } + ) + + end + + SetTimeout(60000, SaveData) + +end + +TickStatus() +UpdateClients() +SaveData() \ No newline at end of file