diff --git a/client/main.lua b/client/main.lua index e910ae3..2bbaf21 100644 --- a/client/main.lua +++ b/client/main.lua @@ -183,7 +183,13 @@ RegisterNUICallback('onStartup', function(data, cb) end) RegisterNUICallback('jobcenter_JoinTheGroup', function(data, cb) - TriggerServerEvent('slrn_groups:server:jobcenter_JoinTheGroup', data) + local message = lib.callback.await('slrn_groups:server:jobcenter_JoinTheGroup') + + exports['lb-phone']:SendNotification({ + app = identifier, + content = message, + }) + cb('ok') end) @@ -195,24 +201,37 @@ RegisterNetEvent('slrn_groups:client:CustomNotification', function(header, msg) }) end) -RegisterNUICallback('jobcenter_leave_grouped', function(data, cb) - if not data then return end +RegisterNUICallback('jobcenter_leave_grouped', function(_, cb) + local success = PhoneNotification('Job Center', 'Are you sure you want to leave the group?', 'Accept', 'Deny') + if success then - TriggerServerEvent('slrn_groups:server:jobcenter_leave_grouped', data) + local message = lib.callback.await('slrn_groups:server:jobcenter_leave_grouped') + + exports['lb-phone']:SendNotification({ + app = identifier, + content = message, + }) end + cb('ok') end) RegisterNUICallback('jobcenter_DeleteGroup', function(data, cb) - TriggerServerEvent('slrn_groups:server:jobcenter_DeleteGroup', data) + local message = lib.callback.await('slrn_groups:server:jobcenter_DeleteGroup') + + exports['lb-phone']:SendNotification({ + app = identifier, + content = message, + }) + cb('ok') end) RegisterNUICallback('jobcenter_CheckPlayerNames', function(data, cb) - lib.callback('slrn_groups:server:jobcenter_CheckPlayerNames', false, function(HasName) - cb(HasName) - end, data.id) + local groupNames = lib.callback.await('slrn_groups:server:jobcenter_CheckPlayerNames') + + cb(groupNames) end) RegisterCommand('testpass', function() diff --git a/server/api.lua b/server/api.lua new file mode 100644 index 0000000..7408d32 --- /dev/null +++ b/server/api.lua @@ -0,0 +1,404 @@ +local group_class = require 'server.groups' +local utils = require 'server.utils' + +---@type table +local groups = {} + +local api = {} + +--- Notifies all members of a group with a message +---@param groupID number +---@param msg string +---@param type string +function api.NotifyGroup(groupID, msg, type) + local group = groups[groupID] + + if not group then + return lib.print.error('NotifyGroup was sent an invalid groupID :'..groupID) + end + + for i = 1, #group.members do + utils.notify(group.members[i].Player, msg, type) + end +end +utils.exportHandler('NotifyGroup', api.NotifyGroup) + +--- Notifies all members of a group with a custom notification +---@param groupID number +---@param header string +---@param msg string +function api.pNotifyGroup(groupID, header, msg) + local group = groups[groupID] + + if not group then + return lib.print.error('pNotifyGroup was sent an invalid groupID :'..groupID) + end + + lib.triggerClientEvent('slrn_groups:client:CustomNotification', group:getGroupMembers(), + header or 'NO HEADER', + msg or 'NO MSG' + ) +end +utils.exportHandler('pNotifyGroup', api.pNotifyGroup) + +---@class BlipData +---@field entity number +---@field netId number +---@field radius number +---@field coords vector3 +---@field color number +---@field alpha number +---@field sprite number +---@field scale number +---@field label string +---@field route boolean +---@field routeColor number + +--- Creates a blip for all members of a group +---@param groupID number +---@param name string +---@param data BlipData +function api.CreateBlipForGroup(groupID, name, data) + local group = groups[groupID] + + if not group then + return lib.print.error('CreateBlipForGroup was sent an invalid groupID :'..groupID) + end + + lib.triggerClientEvent('groups:createBlip', group:getGroupMembers(), name, data) +end +utils.exportHandler('CreateBlipForGroup', api.CreateBlipForGroup) + +--- Removes a blip for all members of a group +---@param groupID number +---@param name string +function api.RemoveBlipForGroup(groupID, name) + local group = groups[groupID] + + if not group then + return lib.print.error('RemoveBlipForGroup was sent an invalid groupID :'..groupID) + end + + lib.triggerClientEvent('slrn_groups:client:RemoveBlipForGroup', group:getGroupMembers(), name) +end +utils.exportHandler('RemoveBlipForGroup', api.RemoveBlipForGroup) + +--- Returns the group ID by member's source +---@param src number +---@return number? +function api.GetGroupByMembers(src) + if src then + for i = 1, #groups do + for j = 1, #groups[i].members do + if groups[i].members[j].Player == src then + return i + end + end + end + end +end +utils.exportHandler('GetGroupByMembers', api.GetGroupByMembers) + +--- Returns the group members of a given group +---@param groupID number +---@return number[]? +function api.getGroupMembers(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('getGroupMembers was sent an invalid groupID :'..groupID) + end + + return group:getGroupMembers() +end +utils.exportHandler('getGroupMembers', api.getGroupMembers) + +--- Returns the number of members in a given group +---@param groupID number +---@return number? +function api.getGroupSize(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('getGroupSize was sent an invalid groupID :'..groupID) + end + + return #group.members +end +utils.exportHandler('getGroupSize', api.getGroupSize) + +--- Returns the leader of a group +---@param groupID number +---@return number? +function api.GetGroupLeader(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('GetGroupLeader was sent an invalid groupID :'..groupID) + end + + return group.leader +end +utils.exportHandler('GetGroupLeader', api.GetGroupLeader) + +--- Destroys a group and removes it from the array +---@param groupID number +function api.DestroyGroup(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('DestroyGroup was sent an invalid groupID :'..groupID) + end + + -- If more than just the leader is in the group, notify all members that the group has been disbanded + if #group.members > 1 then + for i = 1, #group.members do + local source = group.members[i].Player + + if source ~= group.leader then + utils.notify(group.members[i].Player, 'The group has been disbanded', 'error') + end + end + end + + table.remove(groups, groupID) + + TriggerEvent('slrn_groups:server:GroupDeleted', groupID, groups:getGroupMembers()) + TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, groups) +end +utils.exportHandler('DestroyGroup', api.DestroyGroup) + +function api.AddMember(groupID, source) + local group = groups[groupID] + + if not group then + return lib.print.error('AddMember was sent an invalid groupID :'..groupID) + end + + group:addMember(source) + + TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, groups) +end +utils.exportHandler('AddMember', api.AddMember) + +---Checks if the password a user entered is the same as the group password +---@param groupId number +---@param password string +---@return boolean? +function api.isPasswordCorrect(groupId, password) + local group = groups?[groupId] + + if not group then + return lib.print.error('isPasswordCorrect was sent an invalid groupID :'..groupId) + end + + return groups:getPassword() == password +end + + + +--- Checks if the player is the leader in the group +---@param src number +---@param groupID number +---@return boolean? +function api.isGroupLeader(src, groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('isGroupLeader was sent an invalid groupID :'..groupID) + end + + return group.leader == src +end +utils.exportHandler('isGroupLeader', api.isGroupLeader) + + +---Removes a player from a group +---@param source number +---@param groupID number +---@return boolean? +function api.RemovePlayerFromGroup(source, groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('RemovePlayerFromGroup was sent an invalid groupID :'..groupID) + end + + + local memberCount = #group.members + for i = 1, memberCount do + local member = group.members[i] + + if member.Player == source then + table.remove(group.members, i) + + TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, groups) + + -- There are no more members in the group, destroy it + if memberCount == 1 then + api.DestroyGroup(groupID) + end + + return true + end + end + + return false +end + +--- Sets the group status and stages +---@param groupID number +---@param status 'WAITING' | 'IN_PROGRESS' | 'DONE' +---@param stages {id: number, name: string, isDone: boolean}[] +function api.setJobStatus(groupID, status, stages) + local group = groups[groupID] + + if not group then + return lib.print.error('setJobStatus was sent an invalid groupID :'..groupID) + end + + group.status = status + group.stage = stages + + lib.triggerClientEvent('slrn_groups:client:AddGroupStage', group:getGroupMembers(), status, stages) +end +utils.exportHandler('setJobStatus', api.setJobStatus) + +--- Returns the group status +---@param groupID number +---@return 'WAITING' | 'IN_PROGRESS' | 'DONE' | nil +function api.getJobStatus(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('getJobStatus was sent an invalid groupID :'..groupID) + end + + return group.status +end +utils.exportHandler('getJobStatus', api.getJobStatus) + +--- Resets the group status and stages +---@param groupID number +function api.resetJobStatus(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('resetJobStatus was sent an invalid groupID :'..groupID) + end + + group.status = 'WAITING' + group.stage = {} + + group:refreshGroupStages() +end +utils.exportHandler('resetJobStatus', api.resetJobStatus) + +--- Returns the group current stages +---@param groupID number +---@return {id: number, name: string, isDone: boolean}[]? +function api.GetGroupStages(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('GetGroupStages was sent an invalid groupID :'..groupID) + end + + return group.stage +end +utils.exportHandler('GetGroupStages', api.GetGroupStages) + +--- Returns whether or not the group is created by a script +---@param groupID number +---@return boolean? +function api.isGroupTemp(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('isGroupTemp was sent an invalid groupID :'..groupID) + end + + return group.ScriptCreated or false +end +utils.exportHandler('isGroupTemp', api.isGroupTemp) + + +---Gets all the groups thats currently running in the server +---@return {id: number, name: string, memberCount: number}[] +function api.GetAllGroups() + local data = {} + + for i = 1, #groups do + data[i] = groups[i].getClientData() + end + + return data +end +utils.exportHandler('getAllGroups', api.GetAllGroups) + +--- Returns the group member names +---@param groupId number +---@return string[]? +function api.GetGroupMembersNames(groupId) + local group = groups[groupId] + + if not group then + return lib.print.error('GetGroupMembersNames was sent an invalid groupID :'..groupId) + end + + local names = {} + local amount = 0 + + for i = 1, #group.members do + amount += 1 + names[amount] = group.members[i].name + end + + return names +end +utils.exportHandler('GetGroupMembersNames', api.GetGroupMembersNames) + +--- Changes the leader of a group +---@param groupID number +---@return boolean? +function api.ChangeGroupLeader(groupID) + local group = groups[groupID] + + if not group then + return lib.print.error('ChangeGroupLeader was sent an invalid groupID :'..groupID) + end + + local members = group.members + + if #members > 1 then + for i = 1, #members do + if members[i].Player ~= group.leader then + group.leader = members[i].Player + return true + end + end + end + + return false +end + +--- Creates a new group +---@param src number +---@param name string +---@param password string? +---@return number +function api.CreateGroup(src, name, password) + local id = #groups + 1 + + local group = group_class:new(id, name, password, src, true) + + groups[id] = group + + -- Send non-sensitive data to all clients (id, name, memberCount) + TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, group.getClientData()) + + return id +end +utils.exportHandler('CreateGroup', api.CreateGroup) + +return api diff --git a/server/groups.lua b/server/groups.lua new file mode 100644 index 0000000..da65165 --- /dev/null +++ b/server/groups.lua @@ -0,0 +1,100 @@ +---@class groups : OxClass +---@field public id number +---@field public name string +---@field public leader number +---@field public ScriptCreated boolean +---@field public status string +---@field public stage {id: number, name: string, isDone: boolean}[] +---@field public members {name: string, CID: number, Player: number}[] +---@field private private {password: string} +local groups = lib.class('groups') + + + +---Constructs a new instance of the groups class. +---@param id number +---@param name string +---@param password string? +---@param leader number +---@param ScriptCreated boolean +function groups:constructor(id, name, password, leader, ScriptCreated) + self.id = id + self.name = name + self.private.password = password or lib.string.random('1111111') + self.leader = leader + self.ScriptCreated = ScriptCreated + self.members = { + { + name = GetPlayerName(leader), + Player = leader, + } + } + self.stage = {} + self.status = 'WAITING' +end + + +---Adds a member to the group. +---@param source number +function groups:addMember(source) + -- #TODO: Get the name and CID from the bridge + self.members[#self.members+1] = { + name = GetPlayerName(source), + CID = Player.PlayerData.citizenid, + Player = source + } +end + + +---Gets the non-sensitive data of the group. +---@return {id: number, name: string, memberCount: number} +function groups:getClientData() + return { + id = self.id, + name = self.name, + memberCount = #self.members + } +end + +---Refreshes the group stages for all members. +function groups:refreshGroupStages() + -- #TODO: remove the need of doing this, just alert that something changed and whenever they open the app do a callback? + for i=1, #self.members do + if self.members[i] then + local source = self.members[i].Player + + TriggerClientEvent('slrn_groups:client:AddGroupStage', source, self.status, self.stage) + TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', source, self:getClientData(), true) + end + end +end + + +---Gets the group member sources. +---@return number[] +function groups:getGroupMembers() + local members = {} + + for i = 1, #self.members do + members[i] = self.members[i].Player + end + + return members +end + +---Gets the password of a group +---@return string +function groups:getPassword() + return self.private.password +end + + + + + + + + + + +return groups \ No newline at end of file diff --git a/server/main.lua b/server/main.lua index 30b3e37..4fbc0ee 100644 --- a/server/main.lua +++ b/server/main.lua @@ -1,362 +1,115 @@ ----@diagnostic disable: lowercase-global -if not lib then return end +local api = require 'server.api' -lib.versionCheck('solareon/slrn_groups') -if GetCurrentResourceName() ~= 'slrn_groups' then - lib.print.error('The resource needs to be named ^slrn_groups^7.') - return -end -local playerData = {} -local playerGroup = {} +lib.callback.register('slrn_groups:server:jobcenter_DeleteGroup', function(source) + local groupId = api.GetGroupByMembers(source) -local function exportHandler(exportName, func) - AddEventHandler(('__cfx_export_qb-phone_%s'):format(exportName), function(setCB) - setCB(func) - end) - exports(exportName, func) -- support modern exports -end + if groupId then + if api.isGroupLeader(source, groupId) then + api.DestroyGroup(groupId) --- Bridge -if GetResourceState('qbx_core') == 'started' then - - function getPlayer(id) - return exports.qbx_core:GetPlayer(id) - end - - function doNotification(src, text, nType) - exports.qbx_core:Notify(src, text, nType) - end -else -- Switch to QBox and save your sanity - local QBCore = exports['qb-core']:GetCoreObject() - - function getPlayer(id) - return QBCore.Functions.GetPlayer(id) - end - - function doNotification(src, text, nType) - TriggerClientEvent('QBCore:Notify', src, text, nType) - end -end - --- Utility functions -local function GetPlayerCharName(src) - local player = getPlayer(src) - return player.PlayerData.charinfo.firstname..' '..player.PlayerData.charinfo.lastname -end - -local function NotifyGroup(group, msg, type) - if not group or not playerGroup[group] then return lib.print.error('Group not found...') end - for _, v in pairs(playerGroup[group].members) do - doNotification(v.Player, msg, type) - end -end -exportHandler('NotifyGroup', NotifyGroup) - -local function pNotifyGroup(group, header, msg) - if not group or not playerGroup[group] then return lib.print.error('Group not found...') end - for _, v in pairs(playerGroup[group].members) do - TriggerClientEvent('slrn_groups:client:CustomNotification', v.Player, - header or 'NO HEADER', - msg or 'NO MSG' - ) - end -end -exportHandler('pNotifyGroup', pNotifyGroup) - -local function CreateBlipForGroup(groupID, name, data) - if not groupID then return lib.print.error('CreateBlipForGroup was sent an invalid groupID :'..groupID) end - - for i=1, #playerGroup[groupID].members do - TriggerClientEvent('groups:createBlip', playerGroup[groupID].members[i].Player, name, data) - end -end -exportHandler('CreateBlipForGroup', CreateBlipForGroup) - -local function RemoveBlipForGroup(groupID, name) - if not groupID then return lib.print.error('CreateBlipForGroup was sent an invalid groupID :'..groupID) end - - for i=1, #playerGroup[groupID].members do - TriggerClientEvent('groups:removeBlip', playerGroup[groupID].members[i].Player, name) - end -end -exportHandler('RemoveBlipForGroup', RemoveBlipForGroup) - - --- All group functions to get members leaders and size. -local function GetGroupByMembers(src) - if not playerData[src] then return nil end - for group, _ in pairs(playerGroup) do - for _, v in pairs (playerGroup[group].members) do - if v.Player == src then - return group - end - end - end -end -exportHandler('GetGroupByMembers', GetGroupByMembers) - -local function getGroupMembers(groupID) - if not groupID then return lib.print.error('getGroupMembers was sent an invalid groupID :'..groupID) end - local temp = {} - for _,v in pairs(playerGroup[groupID].members) do - temp[#temp+1] = v.Player - end - return temp -end -exportHandler('getGroupMembers', getGroupMembers) - -local function getGroupSize(groupID) - if not groupID then return lib.print.error('getGroupSize was sent an invalid groupID :'..groupID) end - if not playerGroup[groupID] then return lib.print.error('getGroupSize was sent an invalid groupID :'..groupID) end - return #playerGroup[groupID].members -end -exportHandler('getGroupSize', getGroupSize) - -local function GetGroupLeader(groupID) - if not groupID then return lib.print.error('GetGroupLeader was sent an invalid groupID :'..groupID) end - return playerGroup[groupID].leader -end -exportHandler('GetGroupLeader', GetGroupLeader) - -local function DestroyGroup(groupID) - if not playerGroup[groupID] then return lib.print.error('DestroyGroup was sent an invalid groupID :'..groupID) end - local members = getGroupMembers(groupID) - if members and #members > 0 then - for i = 1, #members do - if members[i] then - playerData[members[i]] = false + return 'Group Deleted' + else + if api.RemovePlayerFromGroup(source, groupId) then + return 'Left Group' end end end - exports['qb-phone']:resetJobStatus(groupID) - TriggerEvent('slrn_groups:server:GroupDeleted', groupID, members) - - playerGroup[groupID] = nil - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, playerGroup) + return 'Error leaving group' +end) -end -exportHandler('DestroyGroup', DestroyGroup) +lib.callback.reigster('slrn_groups:server:jobcenter_DeleteGroup', function(source) + local groupId = api.GetGroupByMembers(source) -local function RemovePlayerFromGroup(src, groupID, disconnected) - if not playerData[src] or not playerGroup[groupID] then return lib.print.error('RemovePlayerFromGroup was sent an invalid groupID :'..groupID) end - local g = playerGroup[groupID].members - for k,v in pairs(g) do - if v.Player == src then - table.remove(playerGroup[groupID].members, k) - playerGroup[groupID].Users -= 1 - playerData[src] = false - pNotifyGroup(groupID, 'Job Center', v.name..' Has left the group') - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, playerGroup) - if not disconnected then doNotification(src, 'You have left the group', 'primary') end + if groupId then + if api.isGroupLeader(source, groupId) then + api.DestroyGroup(groupId) - if playerGroup[groupID].Users <= 0 then - DestroyGroup(groupID) + return 'Group Deleted' + else + if api.RemovePlayerFromGroup(source, groupId) then + return 'Left Group' end - - return end end -end -local function ChangeGroupLeader(groupID) - local m = playerGroup[groupID].members - local l = GetGroupLeader(groupID) - if #m > 1 then - for i=1, #m do - if m[i].Player ~= l then - playerGroup[groupID].leader = m[i].Player - return true - end - end - end - return false -end + return 'Error leaving group' +end) -local function isGroupLeader(src, groupID) - if not groupID then return end - local grouplead = GetGroupLeader(groupID) - return grouplead == src or false -end -exportHandler('isGroupLeader', isGroupLeader) +---Joins a specific group if the password is correct +---@param source number +---@param data {id: number, pass: string} +lib.callback.register('slrn_groups:server:jobcenter_JoinTheGroup', function(source, data) + if api.isPasswordCorrect(data.id, data.pass) then + -- #TODO: Get the name from the bridge for the Notification + api.pNotifyGroup(data.id, 'Job Center', source..' Has joined the group') ----- All the job functions for the groups + api.addMember(data.id, source) -local function setJobStatus(groupID, status, stages) - if not groupID then return lib.print.error('setJobStatus was sent an invalid groupID :'..groupID) end - playerGroup[groupID].status = status - playerGroup[groupID].stage = stages - local m = getGroupMembers(groupID) - if not m then return end - for i=1, #m do - if m[i] then - TriggerClientEvent('slrn_groups:client:AddGroupStage', m[i], status, stages) - end + return 'You joined the group' + else + return 'Invalid Password' end -end -exportHandler('setJobStatus', setJobStatus) +end) -local function getJobStatus(groupID) - if not groupID then return lib.print.error('getJobStatus was sent an invalid groupID :'..groupID) end - return playerGroup[groupID].status -end -exportHandler('getJobStatus', getJobStatus) +lib.callback.register('slrn_groups:server:jobcenter_leave_grouped', function(source) + local groupID = api.GetGroupByMembers(source) -local function resetJobStatus(groupID) - if not groupID then return lib.print.error('setJobStatus was sent an invalid groupID :'..groupID) end - playerGroup[groupID].status = 'WAITING' - playerGroup[groupID].stage = {} - local m = getGroupMembers(groupID) - if not m then return end - for i=1, #m do - if m[i] then - TriggerClientEvent('slrn_groups:client:AddGroupStage', m[i], playerGroup[groupID].status, playerGroup[groupID].stage) - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', m[i], playerGroup, true) - end - end -end -exportHandler('resetJobStatus', resetJobStatus) - -AddEventHandler('playerDropped', function() - local src = source - local groupID = GetGroupByMembers(src) if groupID then - if isGroupLeader(src, groupID) then - if ChangeGroupLeader(groupID) then - RemovePlayerFromGroup(src, groupID, true) - else - DestroyGroup(groupID) - end - else - RemovePlayerFromGroup(src, groupID, true) - end + api.RemovePlayerFromGroup(source, groupID) + + return 'Left Group' end end) -RegisterNetEvent('slrn_groups:server:jobcenter_CreateJobGroup', function(data) - local src = source - assert(src ~= nil, 'invalid source') - local player = getPlayer(src) - if playerData[src] then doNotification(src, 'You have already created a group', 'error') return end - if not data or not data.pass or not data.name then return end - playerData[src] = true - local ID = #playerGroup+1 - playerGroup[ID] = { - id = ID, - status = 'WAITING', - GName = data.name, - GPass = data.pass, - Users = 1, - leader = src, - members = { - {name = GetPlayerCharName(src), CID = player.PlayerData.citizenid, Player = src} - }, - stage = {}, - } - - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, playerGroup) +---Creates a new group +---@param data {name: string, pass: string} +RegisterNetEvent('slrn_groups:server:jobcenter_CreateJobGroup', function(data) + api.CreateGroup(source, data.name, data.pass) end) -RegisterNetEvent('TestGroups', function() - local src = source - local TestTable = { - {name = 'Pick Up Truck', isDone = true, id = 1}, - {name = 'Pick up garbage', isDone = false , id = 2}, - {name = 'Drop off garbage', isDone = false , id = 3}, - } - setJobStatus((GetGroupByMembers(src)), 'garbage', TestTable) -end) +---Gets all the player names of the players in the group +---@param source number +---@return table? +lib.callback.register('slrn_groups:server:jobcenter_CheckPlayerNames', function(source) + local groupId = api.GetGroupByMembers(source) -RegisterNetEvent('slrn_groups:server:jobcenter_DeleteGroup', function(data) - local src = source - if not playerData[src] then return lib.print.error('You are not in a group?!?') end - if GetGroupLeader(data.delete) == src then - DestroyGroup(data.delete) - else - RemovePlayerFromGroup(src, data.delete) + if groupId then + return api.GetGroupMembersNames(groupId) end end) -lib.callback.register('slrn_groups:server:GetGroupsApp', function(_) - return playerGroup -end) - -RegisterNetEvent('slrn_groups:server:jobcenter_JoinTheGroup', function(data) - local src = source - assert(src ~= nil, 'invalid source') - - local player = getPlayer(src) - if playerData[src] then return doNotification(src, 'You are already a part of a group!', 'success') end - - local name = GetPlayerCharName(src) - pNotifyGroup(data.id, 'Job Center', name..' Has joined the group') - playerGroup[data.id].members[#playerGroup[data.id].members+1] = {name = name, CID = player.PlayerData.citizenid, Player = src} - playerGroup[data.id].Users += 1 - playerData[src] = true - doNotification(src, 'You joined the group', 'success') - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, playerGroup) -end) -local function GetGroupStages(groupID) - if not groupID then return lib.print.error('GetGroupStages was sent an invalid groupID :'..groupID) end - return playerGroup[groupID].stage -end -exportHandler('GetGroupStages', GetGroupStages) +---Get all groups +---@param source number lib.callback.register('slrn_groups:server:getAllGroups', function(source) - if playerData[source] then - return playerGroup, true, getJobStatus(GetGroupByMembers(source)), GetGroupStages(GetGroupByMembers(source)) + local groupId = api.GetGroupByMembers(source) + + if groupId then + return api.GetAllGroups(), true, api.getJobStatus(groupId), api.GetGroupStages(groupId) else - return playerGroup, false + return api.GetAllGroups(), false end end) -lib.callback.register('slrn_groups:server:jobcenter_CheckPlayerNames', function(_, csn) - local Names = {} - for _, v in pairs(playerGroup[csn].members) do - Names[#Names+1] = v.name - end - return Names -end) +AddEventHandler('playerDropped', function() + local groupId = api.GetGroupByMembers(source) -RegisterNetEvent('slrn_groups:server:jobcenter_leave_grouped', function(data) - local src = source - if not playerData[src] then return end - RemovePlayerFromGroup(src, data.id) + if groupId then + if api.isGroupLeader(source, groupId) then + if api.ChangeGroupLeader(groupId) then + api.RemovePlayerFromGroup(source, groupId) + else + api.DestroyGroup(groupId) + end + else + api.RemovePlayerFromGroup(source, groupId) + end + end end) - -local function isGroupTemp(groupID) - if not groupID or not playerGroup[groupID] then return lib.print.error('isGroupTemp was sent an invalid groupID :'..groupID) end - return playerGroup[groupID].ScriptCreated or false -end -exportHandler('isGroupTemp', isGroupTemp) - - -local function CreateGroup(src, name, password) - if not src or not name then return end - local Player = getPlayer(src) - playerData[src] = true - local id = #playerGroup+1 - playerGroup[id] = { - id = id, - status = 'WAITING', - GName = name, - GPass = password or lib.string.random('1111111'), - Users = 1, - leader = src, - members = { - {name = GetPlayerCharName(src), CID = Player.PlayerData.citizenid, Player = src} - }, - stage = {}, - ScriptCreated = true, - } - - TriggerClientEvent('slrn_groups:client:RefreshGroupsApp', -1, playerGroup) - return id -end -exportHandler('CreateGroup', CreateGroup) diff --git a/server/utils.lua b/server/utils.lua new file mode 100644 index 0000000..66c8199 --- /dev/null +++ b/server/utils.lua @@ -0,0 +1,37 @@ +local utils = {} + + + + + +---Notifies a player using ox_lib +---@param src number +---@param text string +---@param type string +function utils.notify(src, text, type) + lib.notify(src, { + description = text, + type = type, + duration = 5000 + }) +end + + +---Create backwards compatability for qb-phone exports +---@param exportName string +---@param func function +function utils.exportHandler(exportName, func) + AddEventHandler(('__cfx_export_qb-phone_%s'):format(exportName), function(setCB) + setCB(func) + end) + + exports(exportName, func) -- support modern exports +end + + + + + + + +return utils \ No newline at end of file