diff --git a/server/player.lua b/server/player.lua index b1fc17e..dcd99c9 100644 --- a/server/player.lua +++ b/server/player.lua @@ -189,261 +189,280 @@ end -- Don't touch any of this unless you know what you are doing -- Will cause major issues! -function QBCore.Player.CreatePlayer(PlayerData, Offline) - local self = {} - self.Functions = {} +local Player = {} +Player.__index = Player + +function Player.new(PlayerData, Offline) + local self = setmetatable({}, Player) self.PlayerData = PlayerData self.Offline = Offline - function self.Functions.UpdatePlayerData() - if self.Offline then return end - TriggerEvent('QBCore:Player:SetPlayerData', self.PlayerData) - TriggerClientEvent('QBCore:Player:SetPlayerData', self.PlayerData.source, self.PlayerData) - end - - function self.Functions.SetJob(job, grade) - job = job:lower() - grade = grade or '0' - if not QBCore.Shared.Jobs[job] then return false end - self.PlayerData.job = { - name = job, - label = QBCore.Shared.Jobs[job].label, - onduty = QBCore.Shared.Jobs[job].defaultDuty, - type = QBCore.Shared.Jobs[job].type or 'none', - grade = { - name = 'No Grades', - level = 0, - payment = 30, - isboss = false - } - } - local gradeKey = tostring(grade) - local jobGradeInfo = QBCore.Shared.Jobs[job].grades[gradeKey] - if jobGradeInfo then - self.PlayerData.job.grade.name = jobGradeInfo.name - self.PlayerData.job.grade.level = tonumber(gradeKey) - self.PlayerData.job.grade.payment = jobGradeInfo.payment - self.PlayerData.job.grade.isboss = jobGradeInfo.isboss or false - self.PlayerData.job.isboss = jobGradeInfo.isboss or false - end - - if not self.Offline then - self.Functions.UpdatePlayerData() - TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) - TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) - end - - return true - end - - function self.Functions.SetGang(gang, grade) - gang = gang:lower() - grade = grade or '0' - if not QBCore.Shared.Gangs[gang] then return false end - self.PlayerData.gang = { - name = gang, - label = QBCore.Shared.Gangs[gang].label, - grade = { - name = 'No Grades', - level = 0, - isboss = false - } - } - local gradeKey = tostring(grade) - local gangGradeInfo = QBCore.Shared.Gangs[gang].grades[gradeKey] - if gangGradeInfo then - self.PlayerData.gang.grade.name = gangGradeInfo.name - self.PlayerData.gang.grade.level = tonumber(gradeKey) - self.PlayerData.gang.grade.isboss = gangGradeInfo.isboss or false - self.PlayerData.gang.isboss = gangGradeInfo.isboss or false - end - - if not self.Offline then - self.Functions.UpdatePlayerData() - TriggerEvent('QBCore:Server:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang) - TriggerClientEvent('QBCore:Client:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang) - end - - return true - end - - function self.Functions.Notify(text, type, length) - TriggerClientEvent('QBCore:Notify', self.PlayerData.source, text, type, length) - end - - function self.Functions.HasItem(items, amount) - return QBCore.Functions.HasItem(self.PlayerData.source, items, amount) - end - - function self.Functions.GetName() - local charinfo = self.PlayerData.charinfo - return charinfo.firstname .. ' ' .. charinfo.lastname - end - - function self.Functions.SetJobDuty(onDuty) - self.PlayerData.job.onduty = not not onDuty - TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) - TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) - self.Functions.UpdatePlayerData() - end - - function self.Functions.SetPlayerData(key, val) - if not key or type(key) ~= 'string' then return end - self.PlayerData[key] = val - self.Functions.UpdatePlayerData() - end - - function self.Functions.SetMetaData(meta, val) - if not meta or type(meta) ~= 'string' then return end - if meta == 'hunger' or meta == 'thirst' then - val = val > 100 and 100 or val - end - self.PlayerData.metadata[meta] = val - self.Functions.UpdatePlayerData() - end - - function self.Functions.GetMetaData(meta) - if not meta or type(meta) ~= 'string' then return end - return self.PlayerData.metadata[meta] - end - - function self.Functions.AddRep(rep, amount) - if not rep or not amount then return end - local addAmount = tonumber(amount) - local currentRep = self.PlayerData.metadata['rep'][rep] or 0 - self.PlayerData.metadata['rep'][rep] = currentRep + addAmount - self.Functions.UpdatePlayerData() - end - - function self.Functions.RemoveRep(rep, amount) - if not rep or not amount then return end - local removeAmount = tonumber(amount) - local currentRep = self.PlayerData.metadata['rep'][rep] or 0 - if currentRep - removeAmount < 0 then - self.PlayerData.metadata['rep'][rep] = 0 - else - self.PlayerData.metadata['rep'][rep] = currentRep - removeAmount - end - self.Functions.UpdatePlayerData() - end - - function self.Functions.GetRep(rep) - if not rep then return end - return self.PlayerData.metadata['rep'][rep] or 0 - end - - function self.Functions.AddMoney(moneytype, amount, reason) - reason = reason or 'unknown' - moneytype = moneytype:lower() - amount = tonumber(amount) - if amount < 0 then return end - if not self.PlayerData.money[moneytype] then return false end - self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] + amount - - if not self.Offline then - self.Functions.UpdatePlayerData() - if amount > 100000 then - TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason, true) - else - TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) - end - TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, false) - TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason) - TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason) - end - - return true - end - - function self.Functions.RemoveMoney(moneytype, amount, reason) - reason = reason or 'unknown' - moneytype = moneytype:lower() - amount = tonumber(amount) - if amount < 0 then return end - if not self.PlayerData.money[moneytype] then return false end - for _, mtype in pairs(QBCore.Config.Money.DontAllowMinus) do - if mtype == moneytype then - if (self.PlayerData.money[moneytype] - amount) < 0 then - return false + -- Compatibility layer for legacy .Functions calls + self.Functions = setmetatable({}, { + __index = function(_, key) + return function(_, ...) + if Player[key] then + return Player[key](self, ...) + else + error("Attempt to call undefined function '" .. key .. "'") end end end - if self.PlayerData.money[moneytype] - amount < QBCore.Config.Money.MinusLimit then return false end - self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount + }) - if not self.Offline then - self.Functions.UpdatePlayerData() - if amount > 100000 then - TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason, true) - else - TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) - end - TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, true) - if moneytype == 'bank' then - TriggerClientEvent('qb-phone:client:RemoveBankMoney', self.PlayerData.source, amount) - end - TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason) - TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason) - end + return self +end - return true +function Player:UpdatePlayerData() + if self.Offline then return end + TriggerEvent('QBCore:Player:SetPlayerData', self.PlayerData) + TriggerClientEvent('QBCore:Player:SetPlayerData', self.PlayerData.source, self.PlayerData) +end + +function Player:SetJob(job, grade) + job = job:lower() + grade = grade or '0' + if not QBCore.Shared.Jobs[job] then return false end + self.PlayerData.job = { + name = job, + label = QBCore.Shared.Jobs[job].label, + onduty = QBCore.Shared.Jobs[job].defaultDuty, + type = QBCore.Shared.Jobs[job].type or 'none', + grade = { + name = 'No Grades', + level = 0, + payment = 30, + isboss = false + } + } + local gradeKey = tostring(grade) + local jobGradeInfo = QBCore.Shared.Jobs[job].grades[gradeKey] + if jobGradeInfo then + self.PlayerData.job.grade.name = jobGradeInfo.name + self.PlayerData.job.grade.level = tonumber(gradeKey) + self.PlayerData.job.grade.payment = jobGradeInfo.payment + self.PlayerData.job.grade.isboss = jobGradeInfo.isboss or false + self.PlayerData.job.isboss = jobGradeInfo.isboss or false end - function self.Functions.SetMoney(moneytype, amount, reason) - reason = reason or 'unknown' - moneytype = moneytype:lower() - amount = tonumber(amount) - if amount < 0 then return false end - if not self.PlayerData.money[moneytype] then return false end - local difference = amount - self.PlayerData.money[moneytype] - self.PlayerData.money[moneytype] = amount - - if not self.Offline then - self.Functions.UpdatePlayerData() - TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'SetMoney', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') set, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) - TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, math.abs(difference), difference < 0) - TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'set', reason) - TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'set', reason) - end - - return true + if not self.Offline then + self:UpdatePlayerData() + TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) + TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) end - function self.Functions.GetMoney(moneytype) - if not moneytype then return false end - moneytype = moneytype:lower() - return self.PlayerData.money[moneytype] + return true +end + +function Player:SetGang(gang, grade) + gang = gang:lower() + grade = grade or '0' + if not QBCore.Shared.Gangs[gang] then return false end + self.PlayerData.gang = { + name = gang, + label = QBCore.Shared.Gangs[gang].label, + grade = { + name = 'No Grades', + level = 0, + isboss = false + } + } + local gradeKey = tostring(grade) + local gangGradeInfo = QBCore.Shared.Gangs[gang].grades[gradeKey] + if gangGradeInfo then + self.PlayerData.gang.grade.name = gangGradeInfo.name + self.PlayerData.gang.grade.level = tonumber(gradeKey) + self.PlayerData.gang.grade.isboss = gangGradeInfo.isboss or false + self.PlayerData.gang.isboss = gangGradeInfo.isboss or false end - function self.Functions.Save() - if self.Offline then - QBCore.Player.SaveOffline(self.PlayerData) - else - QBCore.Player.Save(self.PlayerData.source) - end + if not self.Offline then + self:UpdatePlayerData() + TriggerEvent('QBCore:Server:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang) + TriggerClientEvent('QBCore:Client:OnGangUpdate', self.PlayerData.source, self.PlayerData.gang) end - function self.Functions.Logout() - if self.Offline then return end - QBCore.Player.Logout(self.PlayerData.source) - end + return true +end - function self.Functions.AddMethod(methodName, handler) - self.Functions[methodName] = handler - end +function Player:Notify(text, type, length) + TriggerClientEvent('QBCore:Notify', self.PlayerData.source, text, type, length) +end - function self.Functions.AddField(fieldName, data) - self[fieldName] = data - end +function Player:HasItem(items, amount) + return QBCore.Functions.HasItem(self.PlayerData.source, items, amount) +end - if self.Offline then - return self +function Player:GetName() + local charinfo = self.PlayerData.charinfo + return charinfo.firstname .. ' ' .. charinfo.lastname +end + +function Player:SetJobDuty(onDuty) + self.PlayerData.job.onduty = not not onDuty + TriggerEvent('QBCore:Server:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) + TriggerClientEvent('QBCore:Client:OnJobUpdate', self.PlayerData.source, self.PlayerData.job) + self:UpdatePlayerData() +end + +function Player:SetPlayerData(key, val) + if not key or type(key) ~= 'string' then return end + self.PlayerData[key] = val + self:UpdatePlayerData() +end + +function Player:SetMetaData(meta, val) + if not meta or type(meta) ~= 'string' then return end + if meta == 'hunger' or meta == 'thirst' then + val = val > 100 and 100 or val + end + self.PlayerData.metadata[meta] = val + self:UpdatePlayerData() +end + +function Player:GetMetaData(meta) + if not meta or type(meta) ~= 'string' then return end + return self.PlayerData.metadata[meta] +end + +function Player:AddRep(rep, amount) + if not rep or not amount then return end + local addAmount = tonumber(amount) + local currentRep = self.PlayerData.metadata['rep'][rep] or 0 + self.PlayerData.metadata['rep'][rep] = currentRep + addAmount + self:UpdatePlayerData() +end + +function Player:RemoveRep(rep, amount) + if not rep or not amount then return end + local removeAmount = tonumber(amount) + local currentRep = self.PlayerData.metadata['rep'][rep] or 0 + if currentRep - removeAmount < 0 then + self.PlayerData.metadata['rep'][rep] = 0 else - QBCore.Players[self.PlayerData.source] = self - QBCore.Player.Save(self.PlayerData.source) - TriggerEvent('QBCore:Server:PlayerLoaded', self) - self.Functions.UpdatePlayerData() + self.PlayerData.metadata['rep'][rep] = currentRep - removeAmount end + self:UpdatePlayerData() +end + +function Player:GetRep(rep) + if not rep then return end + return self.PlayerData.metadata['rep'][rep] or 0 +end + +function Player:AddMoney(moneytype, amount, reason) + reason = reason or 'unknown' + moneytype = moneytype:lower() + amount = tonumber(amount) + if amount < 0 then return end + if not self.PlayerData.money[moneytype] then return false end + self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] + amount + + if not self.Offline then + self:UpdatePlayerData() + if amount > 100000 then + TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason, true) + else + TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'AddMoney', 'lightgreen', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') added, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) + end + TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, false) + TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason) + TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'add', reason) + end + + return true +end + +function Player:RemoveMoney(moneytype, amount, reason) + reason = reason or 'unknown' + moneytype = moneytype:lower() + amount = tonumber(amount) + if amount < 0 then return end + if not self.PlayerData.money[moneytype] then return false end + for _, mtype in pairs(QBCore.Config.Money.DontAllowMinus) do + if mtype == moneytype then + if (self.PlayerData.money[moneytype] - amount) < 0 then + return false + end + end + end + if self.PlayerData.money[moneytype] - amount < QBCore.Config.Money.MinusLimit then return false end + self.PlayerData.money[moneytype] = self.PlayerData.money[moneytype] - amount + + if not self.Offline then + self:UpdatePlayerData() + if amount > 100000 then + TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason, true) + else + TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'RemoveMoney', 'red', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') removed, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) + end + TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, amount, true) + if moneytype == 'bank' then + TriggerClientEvent('qb-phone:client:RemoveBankMoney', self.PlayerData.source, amount) + end + TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason) + TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'remove', reason) + end + + return true +end + +function Player:SetMoney(moneytype, amount, reason) + reason = reason or 'unknown' + moneytype = moneytype:lower() + amount = tonumber(amount) + if amount < 0 then return false end + if not self.PlayerData.money[moneytype] then return false end + local difference = amount - self.PlayerData.money[moneytype] + self.PlayerData.money[moneytype] = amount + + if not self.Offline then + self:UpdatePlayerData() + TriggerEvent('qb-log:server:CreateLog', 'playermoney', 'SetMoney', 'green', '**' .. GetPlayerName(self.PlayerData.source) .. ' (citizenid: ' .. self.PlayerData.citizenid .. ' | id: ' .. self.PlayerData.source .. ')** $' .. amount .. ' (' .. moneytype .. ') set, new ' .. moneytype .. ' balance: ' .. self.PlayerData.money[moneytype] .. ' reason: ' .. reason) + TriggerClientEvent('hud:client:OnMoneyChange', self.PlayerData.source, moneytype, math.abs(difference), difference < 0) + TriggerClientEvent('QBCore:Client:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'set', reason) + TriggerEvent('QBCore:Server:OnMoneyChange', self.PlayerData.source, moneytype, amount, 'set', reason) + end + + return true +end + +function Player:GetMoney(moneytype) + if not moneytype then return false end + moneytype = moneytype:lower() + return self.PlayerData.money[moneytype] +end + +function Player:Save() + if self.Offline then + QBCore.Player.SaveOffline(self.PlayerData) + else + QBCore.Player.Save(self.PlayerData.source) + end +end + +function Player:Logout() + if self.Offline then return end + QBCore.Player.Logout(self.PlayerData.source) +end + +function Player:AddMethod(methodName, handler) + self.Functions[methodName] = handler +end + +function Player:AddField(fieldName, data) + self[fieldName] = data +end + +function QBCore.Player.CreatePlayer(PlayerData, Offline) + local player = Player.new(PlayerData, Offline) + if not Offline then + QBCore.Players[PlayerData.source] = player + QBCore.Player.Save(PlayerData.source) + TriggerEvent('QBCore:Server:PlayerLoaded', player) + player:UpdatePlayerData() + end + return player end -- Save player info to database (make sure citizenid is the primary key in your database)