0.0.1
This commit is contained in:
155
resources/[core]/es_extended/server/modules/callback.lua
Normal file
155
resources/[core]/es_extended/server/modules/callback.lua
Normal file
@@ -0,0 +1,155 @@
|
||||
---@diagnostic disable: duplicate-set-field
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Variables
|
||||
-- =============================================
|
||||
|
||||
Callbacks = {}
|
||||
|
||||
Callbacks.requests = {}
|
||||
Callbacks.storage = {}
|
||||
Callbacks.id = 0
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Internal Functions
|
||||
-- =============================================
|
||||
|
||||
function Callbacks:Register(name, resource, cb)
|
||||
self.storage[name] = {
|
||||
resource = resource,
|
||||
cb = cb
|
||||
}
|
||||
end
|
||||
|
||||
function Callbacks:Execute(cb, ...)
|
||||
local success, errorString = pcall(cb, ...)
|
||||
|
||||
if not success then
|
||||
print(("[^1ERROR^7] Failed to execute Callback with RequestId: ^5%s^7"):format(self.currentId))
|
||||
print("^3Callback Error:^7 " .. tostring(errorString)) -- just log, don't throw
|
||||
self.currentId = nil
|
||||
return
|
||||
end
|
||||
|
||||
self.currentId = nil
|
||||
end
|
||||
|
||||
function Callbacks:Trigger(player, event, cb, invoker, ...)
|
||||
self.requests[self.id] = {
|
||||
await = type(cb) == "boolean",
|
||||
cb = cb or promise:new()
|
||||
}
|
||||
local table = self.requests[self.id]
|
||||
|
||||
TriggerClientEvent("esx:triggerClientCallback", player, event, self.id, invoker, ...)
|
||||
|
||||
self.id += 1
|
||||
|
||||
return table.cb
|
||||
end
|
||||
|
||||
function Callbacks:ServerRecieve(player, event, requestId, invoker, ...)
|
||||
self.currentId = requestId
|
||||
|
||||
if not self.storage[event] then
|
||||
return error(("Server Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(event, invoker))
|
||||
end
|
||||
|
||||
local returnCb = function(...)
|
||||
TriggerClientEvent("esx:serverCallback", player, requestId, invoker, ...)
|
||||
end
|
||||
local callback = self.storage[event].cb
|
||||
|
||||
self:Execute(callback, player, returnCb, ...)
|
||||
end
|
||||
|
||||
function Callbacks:RecieveClient(requestId, invoker, ...)
|
||||
self.currentId = requestId
|
||||
|
||||
if not self.requests[self.currentId] then
|
||||
return error(("Client Callback with requestId ^5%s^1 Was Called by ^5%s^1 but does not exist."):format(self.currentId, invoker))
|
||||
end
|
||||
|
||||
local callback = self.requests[self.currentId]
|
||||
|
||||
self.requests[requestId] = nil
|
||||
if callback.await then
|
||||
callback.cb:resolve({ ... })
|
||||
else
|
||||
self:Execute(callback.cb, ...)
|
||||
end
|
||||
end
|
||||
|
||||
-- =============================================
|
||||
-- MARK: ESX Functions
|
||||
-- =============================================
|
||||
|
||||
---@param player number playerId
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
---@param ... any
|
||||
function ESX.TriggerClientCallback(player, eventName, callback, ...)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Trigger(player, eventName, callback, invoker, ...)
|
||||
end
|
||||
|
||||
---@param player number playerId
|
||||
---@param eventName string
|
||||
---@param ... any
|
||||
---@return ...
|
||||
function ESX.AwaitClientCallback(player, eventName, ...)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
local p = Callbacks:Trigger(player, eventName, false, invoker, ...)
|
||||
if not p then return end
|
||||
|
||||
SetTimeout(15000, function()
|
||||
if p.state == "pending" then
|
||||
p:reject("Server Callback Timed Out")
|
||||
end
|
||||
end)
|
||||
|
||||
Citizen.Await(p)
|
||||
|
||||
return table.unpack(p.value)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@param callback function
|
||||
---@return nil
|
||||
function ESX.RegisterServerCallback(eventName, callback)
|
||||
local invokingResource = GetInvokingResource()
|
||||
local invoker = (invokingResource and invokingResource ~= "Unknown") and invokingResource or "es_extended"
|
||||
|
||||
Callbacks:Register(eventName, invoker, callback)
|
||||
end
|
||||
|
||||
---@param eventName string
|
||||
---@return boolean
|
||||
function ESX.DoesServerCallbackExist(eventName)
|
||||
return Callbacks.storage[eventName] ~= nil
|
||||
end
|
||||
|
||||
-- =============================================
|
||||
-- MARK: Events
|
||||
-- =============================================
|
||||
|
||||
RegisterNetEvent("esx:clientCallback", function(requestId, invoker, ...)
|
||||
Callbacks:RecieveClient(requestId, invoker, ...)
|
||||
end)
|
||||
|
||||
RegisterNetEvent("esx:triggerServerCallback", function(eventName, requestId, invoker, ...)
|
||||
local source = source
|
||||
Callbacks:ServerRecieve(source, eventName, requestId, invoker, ...)
|
||||
end)
|
||||
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
for k, v in pairs(Callbacks.storage) do
|
||||
if v.resource == resource then
|
||||
Callbacks.storage[k] = nil
|
||||
end
|
||||
end
|
||||
end)
|
||||
774
resources/[core]/es_extended/server/modules/commands.lua
Normal file
774
resources/[core]/es_extended/server/modules/commands.lua
Normal file
@@ -0,0 +1,774 @@
|
||||
ESX.RegisterCommand(
|
||||
{ "setcoords", "tp" },
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
xPlayer.setCoords({ x = args.x, y = args.y, z = args.z })
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Set Coordinates /setcoords Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "X Coord", value = args.x, inline = true },
|
||||
{ name = "Y Coord", value = args.y, inline = true },
|
||||
{ name = "Z Coord", value = args.z, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
false,
|
||||
{
|
||||
help = TranslateCap("command_setcoords"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "x", help = TranslateCap("command_setcoords_x"), type = "coordinate" },
|
||||
{ name = "y", help = TranslateCap("command_setcoords_y"), type = "coordinate" },
|
||||
{ name = "z", help = TranslateCap("command_setcoords_z"), type = "coordinate" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"setjob",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not ESX.DoesJobExist(args.job, args.grade) then
|
||||
return showError(TranslateCap("command_setjob_invalid"))
|
||||
end
|
||||
|
||||
args.playerId.setJob(args.job, args.grade)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Set Job /setjob Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Job", value = args.job, inline = true },
|
||||
{ name = "Grade", value = args.grade, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_setjob"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "job", help = TranslateCap("command_setjob_job"), type = "string" },
|
||||
{ name = "grade", help = TranslateCap("command_setjob_grade"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
local upgrades = Config.SpawnVehMaxUpgrades and {
|
||||
plate = "ADMINCAR",
|
||||
modEngine = 3,
|
||||
modBrakes = 2,
|
||||
modTransmission = 2,
|
||||
modSuspension = 3,
|
||||
modArmor = true,
|
||||
windowTint = 1,
|
||||
} or {}
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"car",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not xPlayer then
|
||||
return showError("[^1ERROR^7] The xPlayer value is nil")
|
||||
end
|
||||
|
||||
local playerPed = GetPlayerPed(xPlayer.source)
|
||||
local playerCoords = GetEntityCoords(playerPed)
|
||||
local playerHeading = GetEntityHeading(playerPed)
|
||||
local playerVehicle = GetVehiclePedIsIn(playerPed, false)
|
||||
|
||||
if not args.car or type(args.car) ~= "string" then
|
||||
args.car = "adder"
|
||||
end
|
||||
|
||||
if playerVehicle then
|
||||
DeleteEntity(playerVehicle)
|
||||
end
|
||||
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Spawn Car /car Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Vehicle", value = args.car, inline = true },
|
||||
})
|
||||
end
|
||||
|
||||
local xRoutingBucket = GetPlayerRoutingBucket(xPlayer.source)
|
||||
|
||||
ESX.OneSync.SpawnVehicle(args.car, playerCoords, playerHeading, upgrades, function(networkId)
|
||||
if networkId then
|
||||
local vehicle = NetworkGetEntityFromNetworkId(networkId)
|
||||
|
||||
if xRoutingBucket ~= 0 then
|
||||
SetEntityRoutingBucket(vehicle, xRoutingBucket)
|
||||
end
|
||||
|
||||
for _ = 1, 100 do
|
||||
Wait(0)
|
||||
SetPedIntoVehicle(playerPed, vehicle, -1)
|
||||
|
||||
if GetVehiclePedIsIn(playerPed, false) == vehicle then
|
||||
break
|
||||
end
|
||||
end
|
||||
|
||||
if GetVehiclePedIsIn(playerPed, false) ~= vehicle then
|
||||
showError("[^1ERROR^7] The player could not be seated in the vehicle")
|
||||
end
|
||||
end
|
||||
end)
|
||||
end,
|
||||
false,
|
||||
{
|
||||
help = TranslateCap("command_car"),
|
||||
validate = false,
|
||||
arguments = {
|
||||
{ name = "car", validate = false, help = TranslateCap("command_car_car"), type = "string" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
{ "cardel", "dv" },
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
local ped = GetPlayerPed(xPlayer.source)
|
||||
local pedVehicle = GetVehiclePedIsIn(ped, false)
|
||||
|
||||
if DoesEntityExist(pedVehicle) then
|
||||
DeleteEntity(pedVehicle)
|
||||
end
|
||||
|
||||
local coords = GetEntityCoords(ped)
|
||||
local Vehicles = ESX.OneSync.GetVehiclesInArea(coords, tonumber(args.radius) or 5.0)
|
||||
for i = 1, #Vehicles do
|
||||
local Vehicle = NetworkGetEntityFromNetworkId(Vehicles[i])
|
||||
if DoesEntityExist(Vehicle) then
|
||||
DeleteEntity(Vehicle)
|
||||
end
|
||||
end
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Delete Vehicle /dv Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
false,
|
||||
{
|
||||
help = TranslateCap("command_cardel"),
|
||||
validate = false,
|
||||
arguments = {
|
||||
{ name = "radius", validate = false, help = TranslateCap("command_cardel_radius"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
{ "fix", "repair" },
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
local xTarget = args.playerId
|
||||
local ped = GetPlayerPed(xTarget.source)
|
||||
local pedVehicle = GetVehiclePedIsIn(ped, false)
|
||||
if not pedVehicle or GetPedInVehicleSeat(pedVehicle, -1) ~= ped then
|
||||
showError(TranslateCap("not_in_vehicle"))
|
||||
return
|
||||
end
|
||||
xTarget.triggerEvent("esx:repairPedVehicle")
|
||||
xPlayer.showNotification(TranslateCap("command_repair_success"), true, false, 140)
|
||||
if xPlayer.source ~= xTarget.source then
|
||||
xTarget.showNotification(TranslateCap("command_repair_success_target"), true, false, 140)
|
||||
end
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Fix Vehicle /fix Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = xTarget.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_repair"),
|
||||
validate = false,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"setaccountmoney",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not args.playerId.getAccount(args.account) then
|
||||
return showError(TranslateCap("command_giveaccountmoney_invalid"))
|
||||
end
|
||||
args.playerId.setAccountMoney(args.account, args.amount, "Government Grant")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Set Account Money /setaccountmoney Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Account", value = args.account, inline = true },
|
||||
{ name = "Amount", value = args.amount, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_setaccountmoney"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "account", help = TranslateCap("command_giveaccountmoney_account"), type = "string" },
|
||||
{ name = "amount", help = TranslateCap("command_setaccountmoney_amount"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"giveaccountmoney",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not args.playerId.getAccount(args.account) then
|
||||
return showError(TranslateCap("command_giveaccountmoney_invalid"))
|
||||
end
|
||||
args.playerId.addAccountMoney(args.account, args.amount, "Government Grant")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Give Account Money /giveaccountmoney Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Account", value = args.account, inline = true },
|
||||
{ name = "Amount", value = args.amount, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_giveaccountmoney"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "account", help = TranslateCap("command_giveaccountmoney_account"), type = "string" },
|
||||
{ name = "amount", help = TranslateCap("command_giveaccountmoney_amount"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"removeaccountmoney",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not args.playerId.getAccount(args.account) then
|
||||
return showError(TranslateCap("command_removeaccountmoney_invalid"))
|
||||
end
|
||||
args.playerId.removeAccountMoney(args.account, args.amount, "Government Tax")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Remove Account Money /removeaccountmoney Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Account", value = args.account, inline = true },
|
||||
{ name = "Amount", value = args.amount, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_removeaccountmoney"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "account", help = TranslateCap("command_removeaccountmoney_account"), type = "string" },
|
||||
{ name = "amount", help = TranslateCap("command_removeaccountmoney_amount"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
if not Config.CustomInventory then
|
||||
ESX.RegisterCommand(
|
||||
"giveitem",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
args.playerId.addInventoryItem(args.item, args.count)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Give Item /giveitem Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Item", value = args.item, inline = true },
|
||||
{ name = "Quantity", value = args.count, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_giveitem"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "item", help = TranslateCap("command_giveitem_item"), type = "item" },
|
||||
{ name = "count", help = TranslateCap("command_giveitem_count"), type = "number", Validator = {
|
||||
validate = function(x) return x > 0 end,
|
||||
err = TranslateCap("commanderror_argumentmismatch_positive_number", "count")
|
||||
}},
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"giveweapon",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if args.playerId.hasWeapon(args.weapon) then
|
||||
return showError(TranslateCap("command_giveweapon_hasalready"))
|
||||
end
|
||||
args.playerId.addWeapon(args.weapon, args.ammo)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Give Weapon /giveweapon Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Weapon", value = args.weapon, inline = true },
|
||||
{ name = "Ammo", value = args.ammo, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_giveweapon"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "weapon", help = TranslateCap("command_giveweapon_weapon"), type = "weapon" },
|
||||
{ name = "ammo", help = TranslateCap("command_giveweapon_ammo"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"giveammo",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if not args.playerId.hasWeapon(args.weapon) then
|
||||
return showError(TranslateCap("command_giveammo_noweapon_found"))
|
||||
end
|
||||
args.playerId.addWeaponAmmo(args.weapon, args.ammo)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Give Ammunition /giveammo Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Weapon", value = args.weapon, inline = true },
|
||||
{ name = "Ammo", value = args.ammo, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_giveweapon"),
|
||||
validate = false,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "weapon", help = TranslateCap("command_giveammo_weapon"), type = "weapon" },
|
||||
{ name = "ammo", help = TranslateCap("command_giveammo_ammo"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"giveweaponcomponent",
|
||||
"admin",
|
||||
function(xPlayer, args, showError)
|
||||
if args.playerId.hasWeapon(args.weaponName) then
|
||||
local component = ESX.GetWeaponComponent(args.weaponName, args.componentName)
|
||||
|
||||
if component then
|
||||
if args.playerId.hasWeaponComponent(args.weaponName, args.componentName) then
|
||||
showError(TranslateCap("command_giveweaponcomponent_hasalready"))
|
||||
else
|
||||
args.playerId.addWeaponComponent(args.weaponName, args.componentName)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Give Weapon Component /giveweaponcomponent Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Weapon", value = args.weaponName, inline = true },
|
||||
{ name = "Component", value = args.componentName, inline = true },
|
||||
})
|
||||
end
|
||||
end
|
||||
else
|
||||
showError(TranslateCap("command_giveweaponcomponent_invalid"))
|
||||
end
|
||||
else
|
||||
showError(TranslateCap("command_giveweaponcomponent_missingweapon"))
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_giveweaponcomponent"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "weaponName", help = TranslateCap("command_giveweapon_weapon"), type = "weapon" },
|
||||
{ name = "componentName", help = TranslateCap("command_giveweaponcomponent_component"), type = "string" },
|
||||
},
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
ESX.RegisterCommand({ "clear", "cls" }, "user", function(xPlayer)
|
||||
xPlayer.triggerEvent("chat:clear")
|
||||
end, false, { help = TranslateCap("command_clear") })
|
||||
|
||||
ESX.RegisterCommand({ "clearall", "clsall" }, "admin", function(xPlayer)
|
||||
TriggerClientEvent("chat:clear", -1)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Clear Chat /clearall Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
})
|
||||
end
|
||||
end, true, { help = TranslateCap("command_clearall") })
|
||||
|
||||
ESX.RegisterCommand("refreshjobs", "admin", function()
|
||||
ESX.RefreshJobs()
|
||||
end, true, { help = TranslateCap("command_clearall") })
|
||||
|
||||
if not Config.CustomInventory then
|
||||
ESX.RegisterCommand("refreshitems", "admin", function(xPlayer)
|
||||
local itemCount = ESX.RefreshItems()
|
||||
|
||||
xPlayer.showNotification(Translate("command_refreshitems_success", itemCount), true, false, 140)
|
||||
end, true, { help = TranslateCap("command_refreshitems") })
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"clearinventory",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
for _, v in ipairs(args.playerId.inventory) do
|
||||
if v.count > 0 then
|
||||
args.playerId.setInventoryItem(v.name, 0)
|
||||
end
|
||||
end
|
||||
TriggerEvent("esx:playerInventoryCleared", args.playerId)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Clear Inventory /clearinventory Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_clearinventory"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"clearloadout",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
for i = #args.playerId.loadout, 1, -1 do
|
||||
args.playerId.removeWeapon(args.playerId.loadout[i].name)
|
||||
end
|
||||
TriggerEvent("esx:playerLoadoutCleared", args.playerId)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "/clearloadout Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_clearloadout"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
end
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"setgroup",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
if not args.playerId then
|
||||
args.playerId = xPlayer.source
|
||||
end
|
||||
if args.group == "superadmin" then
|
||||
args.group = "admin"
|
||||
print("[^3WARNING^7] ^5Superadmin^7 detected, setting group to ^5admin^7")
|
||||
end
|
||||
args.playerId.setGroup(args.group)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "/setgroup Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Group", value = args.group, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_setgroup"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "group", help = TranslateCap("command_setgroup_group"), type = "string" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"save",
|
||||
"admin",
|
||||
function(_, args)
|
||||
Core.SavePlayer(args.playerId)
|
||||
print(("[^2Info^0] Saved Player - ^5%s^0"):format(args.playerId.source))
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_save"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand("saveall", "admin", function()
|
||||
Core.SavePlayers()
|
||||
end, true, { help = TranslateCap("command_saveall") })
|
||||
|
||||
ESX.RegisterCommand("group", { "user", "admin" }, function(xPlayer, _, _)
|
||||
print(("%s, you are currently: ^5%s^0"):format(xPlayer.getName(), xPlayer.getGroup()))
|
||||
end, true)
|
||||
|
||||
ESX.RegisterCommand("job", { "user", "admin" }, function(xPlayer, _, _)
|
||||
local job = xPlayer.getJob()
|
||||
|
||||
print(("%s, your job is: ^5%s^0 - ^5%s^0 - ^5%s^0"):format(xPlayer.getName(), job.name, job.grade_label, job.onDuty and "On Duty" or "Off Duty"))
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand("info", { "user", "admin" }, function(xPlayer)
|
||||
local job = xPlayer.getJob().name
|
||||
print(("^2ID: ^5%s^0 | ^2Name: ^5%s^0 | ^2Group: ^5%s^0 | ^2Job: ^5%s^0"):format(xPlayer.source, xPlayer.getName(), xPlayer.getGroup(), job))
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand("playtime", { "user", "admin" }, function(xPlayer)
|
||||
local playtime = xPlayer.getPlayTime()
|
||||
local days = math.floor(playtime / 86400)
|
||||
local hours = math.floor((playtime % 86400) / 3600)
|
||||
local minutes = math.floor((playtime % 3600) / 60)
|
||||
print(("Playtime: ^5%s^0 Days | ^5%s^0 Hours | ^5%s^0 Minutes"):format(days, hours, minutes))
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand("coords", "admin", function(xPlayer)
|
||||
local ped = GetPlayerPed(xPlayer.source)
|
||||
local coords = GetEntityCoords(ped, false)
|
||||
local heading = GetEntityHeading(ped)
|
||||
print(("Coords - Vector3: ^5%s^0"):format(vector3(coords.x, coords.y, coords.z)))
|
||||
print(("Coords - Vector4: ^5%s^0"):format(vector4(coords.x, coords.y, coords.z, heading)))
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand("tpm", "admin", function(xPlayer)
|
||||
xPlayer.triggerEvent("esx:tpm")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin Teleport /tpm Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
})
|
||||
end
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"goto",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
local targetCoords = args.playerId.getCoords()
|
||||
local srcDim = GetPlayerRoutingBucket(xPlayer.source)
|
||||
local targetDim = GetPlayerRoutingBucket(args.playerId.source)
|
||||
|
||||
if srcDim ~= targetDim then
|
||||
SetPlayerRoutingBucket(xPlayer.source, targetDim)
|
||||
end
|
||||
xPlayer.setCoords(targetCoords)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin Teleport /goto Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Target Coords", value = targetCoords, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
false,
|
||||
{
|
||||
help = TranslateCap("command_goto"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"bring",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
local targetCoords = args.playerId.getCoords()
|
||||
local playerCoords = xPlayer.getCoords()
|
||||
local targetDim = GetPlayerRoutingBucket(args.playerId.source)
|
||||
local srcDim = GetPlayerRoutingBucket(xPlayer.source)
|
||||
|
||||
if targetDim ~= srcDim then
|
||||
SetPlayerRoutingBucket(args.playerId.source, srcDim)
|
||||
end
|
||||
args.playerId.setCoords(playerCoords)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin Teleport /bring Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Target Coords", value = targetCoords, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
false,
|
||||
{
|
||||
help = TranslateCap("command_bring"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"kill",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
args.playerId.triggerEvent("esx:killPlayer")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Kill Command /kill Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_kill"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"freeze",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
args.playerId.triggerEvent("esx:freezePlayer", "freeze")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin Freeze /freeze Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_freeze"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
"unfreeze",
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
args.playerId.triggerEvent("esx:freezePlayer", "unfreeze")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin UnFreeze /unfreeze Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_unfreeze"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
ESX.RegisterCommand("noclip", "admin", function(xPlayer)
|
||||
xPlayer.triggerEvent("esx:noclip")
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin NoClip /noclip Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
})
|
||||
end
|
||||
end, false)
|
||||
|
||||
ESX.RegisterCommand("players", "admin", function()
|
||||
local xPlayers = ESX.GetExtendedPlayers() -- Returns all xPlayers
|
||||
print(("^5%s^2 online player(s)^0"):format(#xPlayers))
|
||||
for i = 1, #xPlayers do
|
||||
local xPlayer = xPlayers[i]
|
||||
print(("^1[^2ID: ^5%s^0 | ^2Name : ^5%s^0 | ^2Group : ^5%s^0 | ^2Identifier : ^5%s^1]^0\n"):format(xPlayer.source, xPlayer.getName(), xPlayer.getGroup(), xPlayer.identifier))
|
||||
end
|
||||
end, true)
|
||||
|
||||
ESX.RegisterCommand(
|
||||
{"setdim", "setbucket"},
|
||||
"admin",
|
||||
function(xPlayer, args)
|
||||
SetPlayerRoutingBucket(args.playerId.source, args.dimension)
|
||||
if Config.AdminLogging then
|
||||
ESX.DiscordLogFields("UserActions", "Admin Set Dim /setdim Triggered!", "pink", {
|
||||
{ name = "Player", value = xPlayer and xPlayer.name or "Server Console", inline = true },
|
||||
{ name = "ID", value = xPlayer and xPlayer.source or "Unknown ID", inline = true },
|
||||
{ name = "Target", value = args.playerId.name, inline = true },
|
||||
{ name = "Dimension", value = args.dimension, inline = true },
|
||||
})
|
||||
end
|
||||
end,
|
||||
true,
|
||||
{
|
||||
help = TranslateCap("command_setdim"),
|
||||
validate = true,
|
||||
arguments = {
|
||||
{ name = "playerId", help = TranslateCap("commandgeneric_playerid"), type = "player" },
|
||||
{ name = "dimension", help = TranslateCap("commandgeneric_dimension"), type = "number" },
|
||||
},
|
||||
}
|
||||
)
|
||||
101
resources/[core]/es_extended/server/modules/createJob.lua
Normal file
101
resources/[core]/es_extended/server/modules/createJob.lua
Normal file
@@ -0,0 +1,101 @@
|
||||
|
||||
local NOTIFY_TYPES = {
|
||||
INFO = "^5[%s]^7-^6[INFO]^7 %s",
|
||||
SUCCESS = "^5[%s]^7-^2[SUCCESS]^7 %s",
|
||||
ERROR = "^5[%s]^7-^1[ERROR]^7 %s"
|
||||
}
|
||||
|
||||
local function doesJobAndGradesExist(name, grades)
|
||||
if not ESX.Jobs[name] then
|
||||
return false
|
||||
end
|
||||
|
||||
for _, grade in ipairs(grades) do
|
||||
if not ESX.DoesJobExist(name, grade.grade) then
|
||||
return false
|
||||
end
|
||||
end
|
||||
|
||||
return true
|
||||
end
|
||||
|
||||
local function generateNewJobTable(name, label, grades, jobType)
|
||||
local job = { name = name, label = label, type = jobType, grades = {} }
|
||||
for _, v in pairs(grades) do
|
||||
job.grades[tostring(v.grade)] = { job_name = name, grade = v.grade, name = v.name, label = v.label, salary = v.salary, skin_male = v.skin_male or '{}', skin_female = v.skin_female or '{}' }
|
||||
end
|
||||
|
||||
return job
|
||||
end
|
||||
|
||||
local function notify(notifyType,resourceName,message,...)
|
||||
local formattedMessage = string.format(message, ...)
|
||||
|
||||
if not NOTIFY_TYPES[notifyType] then
|
||||
return print(NOTIFY_TYPES.INFO:format(resourceName,formattedMessage))
|
||||
end
|
||||
|
||||
return print(NOTIFY_TYPES[notifyType]:format(resourceName,formattedMessage))
|
||||
end
|
||||
|
||||
--- Create Job at Runtime
|
||||
--- @param name string
|
||||
--- @param label string
|
||||
--- @param grades table
|
||||
--- @param jobType string
|
||||
function ESX.CreateJob(name, label, grades, jobType)
|
||||
local currentResourceName = GetInvokingResource()
|
||||
local success = false
|
||||
|
||||
if not name or name == '' then
|
||||
notify("ERROR",currentResourceName, 'Missing argument `name`')
|
||||
return success
|
||||
end
|
||||
|
||||
if not label or label == '' then
|
||||
notify("ERROR",currentResourceName, 'Missing argument `label`')
|
||||
return success
|
||||
end
|
||||
|
||||
if not grades or not next(grades) then
|
||||
notify("ERROR",currentResourceName, 'Missing argument `grades`')
|
||||
return success
|
||||
end
|
||||
|
||||
if type(jobType) ~= "string" then
|
||||
jobType = "civ"
|
||||
end
|
||||
|
||||
local currentJobExist = doesJobAndGradesExist(name, grades)
|
||||
|
||||
if currentJobExist then
|
||||
notify("ERROR",currentResourceName, 'Job or grades already exists: `%s`', name)
|
||||
return success
|
||||
end
|
||||
|
||||
local queries = {
|
||||
{ query = 'INSERT INTO `jobs` (`name`, `label`, `type`) VALUES (?, ?, ?)', values = { name, label, jobType } }
|
||||
}
|
||||
|
||||
for _, grade in pairs(grades) do
|
||||
queries[#queries + 1] = {
|
||||
query = 'INSERT INTO job_grades (job_name, grade, name, label, salary, skin_male, skin_female) VALUES (?, ?, ?, ?, ?, ?, ?)',
|
||||
values = { name, grade.grade, grade.name, grade.label, grade.salary, grade.skin_male and json.encode(grade.skin_male) or '{}', grade.skin_female and json.encode(grade.skin_female) or '{}' }
|
||||
}
|
||||
end
|
||||
|
||||
success = exports.oxmysql:transaction_async(queries)
|
||||
|
||||
if not success then
|
||||
notify("ERROR", currentResourceName, 'Failed to insert one or more grades for job: `%s`', name)
|
||||
return success
|
||||
end
|
||||
|
||||
ESX.Jobs[name] = generateNewJobTable(name, label, grades, jobType)
|
||||
|
||||
notify("SUCCESS", currentResourceName, 'Job created successfully: `%s`', name)
|
||||
|
||||
TriggerEvent('esx:jobCreated', name, ESX.Jobs[name])
|
||||
|
||||
return success
|
||||
end
|
||||
52
resources/[core]/es_extended/server/modules/npwd.lua
Normal file
52
resources/[core]/es_extended/server/modules/npwd.lua
Normal file
@@ -0,0 +1,52 @@
|
||||
local npwd = GetResourceState("npwd"):find("start") and exports.npwd or nil
|
||||
|
||||
AddEventHandler("onServerResourceStart", function(resource)
|
||||
if resource ~= "npwd" then
|
||||
return
|
||||
end
|
||||
|
||||
npwd = GetResourceState("npwd"):find("start") and exports.npwd or nil
|
||||
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
for _, xPlayer in pairs(ESX.Players) do
|
||||
npwd:newPlayer({
|
||||
source = xPlayer.source,
|
||||
identifier = xPlayer.identifier,
|
||||
firstname = xPlayer.get("firstName"),
|
||||
lastname = xPlayer.get("lastName"),
|
||||
})
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("onServerResourceStop", function(resource)
|
||||
if resource == "npwd" then
|
||||
npwd = nil
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:playerLoaded", function(playerId, xPlayer)
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
|
||||
if not xPlayer then
|
||||
xPlayer = ESX.GetPlayerFromId(playerId)
|
||||
end
|
||||
|
||||
npwd:newPlayer({
|
||||
source = playerId,
|
||||
identifier = xPlayer.identifier,
|
||||
firstname = xPlayer.get("firstName"),
|
||||
lastname = xPlayer.get("lastName"),
|
||||
})
|
||||
end)
|
||||
|
||||
AddEventHandler("esx:playerLogout", function(playerId)
|
||||
if not npwd then
|
||||
return
|
||||
end
|
||||
|
||||
npwd:unloadPlayer(playerId)
|
||||
end)
|
||||
387
resources/[core]/es_extended/server/modules/onesync.lua
Normal file
387
resources/[core]/es_extended/server/modules/onesync.lua
Normal file
@@ -0,0 +1,387 @@
|
||||
ESX.OneSync = {}
|
||||
|
||||
---@param source number|vector3
|
||||
---@param closest boolean
|
||||
---@param distance? number
|
||||
---@param ignore? table
|
||||
---@param routingBucket? number
|
||||
local function getNearbyPlayers(source, closest, distance, ignore, routingBucket)
|
||||
local result = {}
|
||||
local count = 0
|
||||
local playerPed
|
||||
local playerCoords
|
||||
ignore = ignore or {}
|
||||
|
||||
if not distance then
|
||||
distance = 100
|
||||
end
|
||||
|
||||
if type(source) == "number" then
|
||||
playerPed = GetPlayerPed(source)
|
||||
|
||||
if not source then
|
||||
error("Received invalid first argument (source); should be playerId")
|
||||
end
|
||||
|
||||
playerCoords = GetEntityCoords(playerPed)
|
||||
|
||||
if not playerCoords then
|
||||
error("Received nil value (playerCoords); perhaps source is nil at first place?")
|
||||
end
|
||||
end
|
||||
|
||||
if type(source) == "vector3" then
|
||||
playerCoords = source
|
||||
|
||||
if not playerCoords then
|
||||
error("Received nil value (playerCoords); perhaps source is nil at first place?")
|
||||
end
|
||||
end
|
||||
|
||||
for _, xPlayer in pairs(ESX.Players) do
|
||||
if not ignore[xPlayer.source] and (not routingBucket or GetPlayerRoutingBucket(xPlayer.source) == routingBucket) then
|
||||
local entity = GetPlayerPed(xPlayer.source)
|
||||
local coords = GetEntityCoords(entity)
|
||||
|
||||
if not closest then
|
||||
local dist = #(playerCoords - coords)
|
||||
if dist <= distance then
|
||||
count = count + 1
|
||||
result[count] = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
|
||||
end
|
||||
else
|
||||
if xPlayer.source ~= source then
|
||||
local dist = #(playerCoords - coords)
|
||||
if dist <= (result.dist or distance) then
|
||||
result = { id = xPlayer.source, ped = NetworkGetNetworkIdFromEntity(entity), coords = coords, dist = dist }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
---@param source vector3|number playerId or vector3 coordinates
|
||||
---@param maxDistance number
|
||||
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
|
||||
---@param routingBucket? number
|
||||
function ESX.OneSync.GetPlayersInArea(source, maxDistance, ignore, routingBucket)
|
||||
return getNearbyPlayers(source, false, maxDistance, ignore, routingBucket)
|
||||
end
|
||||
|
||||
---@param source vector3|number playerId or vector3 coordinates
|
||||
---@param maxDistance number
|
||||
---@param ignore? table playerIds to ignore, where the key is playerId and value is true
|
||||
---@param routingBucket? number
|
||||
function ESX.OneSync.GetClosestPlayer(source, maxDistance, ignore, routingBucket)
|
||||
return getNearbyPlayers(source, true, maxDistance, ignore, routingBucket)
|
||||
end
|
||||
|
||||
---@param vehicleModel number|string
|
||||
---@param coords vector3|table
|
||||
---@param heading number
|
||||
---@param vehicleProperties table
|
||||
---@param cb? fun(netId: number)
|
||||
---@param vehicleType string?
|
||||
---@return number? netId
|
||||
function ESX.OneSync.SpawnVehicle(vehicleModel, coords, heading, vehicleProperties, cb, vehicleType)
|
||||
if cb and not ESX.IsFunctionReference(cb) then
|
||||
error("Invalid callback function")
|
||||
end
|
||||
|
||||
vehicleModel = joaat(vehicleModel)
|
||||
|
||||
local promise = not cb and promise.new()
|
||||
|
||||
local function resolve(result)
|
||||
if promise then
|
||||
promise:resolve(result)
|
||||
elseif cb then
|
||||
cb(result)
|
||||
end
|
||||
|
||||
return result
|
||||
end
|
||||
|
||||
local function reject(err)
|
||||
if promise then
|
||||
promise:reject(err)
|
||||
end
|
||||
error(err)
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
if not vehicleType then
|
||||
local xPlayer = ESX.GetExtendedPlayers()[1]
|
||||
if xPlayer then
|
||||
vehicleType = ESX.GetVehicleType(vehicleModel, xPlayer.source)
|
||||
end
|
||||
end
|
||||
|
||||
if not vehicleType then
|
||||
return reject("No players found nearby to check vehicle type! Alternatively, you can specify the vehicle type manually.")
|
||||
end
|
||||
|
||||
local createdVehicle = CreateVehicleServerSetter(vehicleModel, vehicleType, coords.x, coords.y, coords.z, heading)
|
||||
local tries = 0
|
||||
|
||||
local hasNetOwner = next(ESX.OneSync.GetClosestPlayer(coords, 300, nil, 0) or {}) ~= nil
|
||||
|
||||
while not createdVehicle or createdVehicle == 0
|
||||
or (hasNetOwner and NetworkGetEntityOwner(createdVehicle) == -1)
|
||||
or (not hasNetOwner and not DoesEntityExist(createdVehicle)) do
|
||||
Wait(200)
|
||||
tries = tries + 1
|
||||
if tries > 40 then
|
||||
return reject(("Could not spawn vehicle - ^5%s^7!"):format(vehicleModel))
|
||||
end
|
||||
end
|
||||
|
||||
-- luacheck: ignore
|
||||
SetEntityOrphanMode(createdVehicle, 2)
|
||||
local networkId = NetworkGetNetworkIdFromEntity(createdVehicle)
|
||||
Entity(createdVehicle).state:set("VehicleProperties", vehicleProperties, true)
|
||||
|
||||
resolve(networkId)
|
||||
end)
|
||||
|
||||
if promise then
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
end
|
||||
|
||||
---@param model number|string
|
||||
---@param coords vector3|table
|
||||
---@param heading number
|
||||
---@param cb? fun(netId: number)
|
||||
---@return number? netId
|
||||
function ESX.OneSync.SpawnObject(model, coords, heading, cb)
|
||||
if type(model) == "string" then
|
||||
model = joaat(model)
|
||||
end
|
||||
|
||||
local promise = not cb and promise.new()
|
||||
local objectCoords = type(coords) == "vector3" and coords or vector3(coords.x, coords.y, coords.z)
|
||||
|
||||
local function resolve(result)
|
||||
if promise then
|
||||
promise:resolve(result)
|
||||
elseif cb then
|
||||
cb(result)
|
||||
end
|
||||
end
|
||||
|
||||
local function reject(err)
|
||||
if promise then
|
||||
promise:reject(err)
|
||||
end
|
||||
error(err)
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
local entity = CreateObject(model, objectCoords.x, objectCoords.y, objectCoords.z, true, true, false)
|
||||
local tries = 0
|
||||
|
||||
while not DoesEntityExist(entity) do
|
||||
Wait(200)
|
||||
|
||||
tries = tries + 1
|
||||
|
||||
if tries > 40 then
|
||||
return reject(("Could not spawn object - ^5%s^7!"):format(entity))
|
||||
end
|
||||
end
|
||||
|
||||
local networkId = NetworkGetNetworkIdFromEntity(entity)
|
||||
|
||||
SetEntityHeading(entity, heading)
|
||||
resolve(networkId)
|
||||
end)
|
||||
|
||||
if promise then
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
end
|
||||
|
||||
---@param model number|string
|
||||
---@param coords vector3|table
|
||||
---@param heading number
|
||||
---@param cb? fun(netId: number)
|
||||
---@return number? netId
|
||||
function ESX.OneSync.SpawnPed(model, coords, heading, cb)
|
||||
if type(model) == "string" then
|
||||
model = joaat(model)
|
||||
end
|
||||
|
||||
local promise = not cb and promise.new()
|
||||
|
||||
local function resolve(result)
|
||||
if promise then
|
||||
promise:resolve(result)
|
||||
elseif cb then
|
||||
cb(result)
|
||||
end
|
||||
end
|
||||
|
||||
local function reject(err)
|
||||
if promise then
|
||||
promise:reject(err)
|
||||
end
|
||||
error(err)
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
local entity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, true, true)
|
||||
local tries = 0
|
||||
|
||||
while not DoesEntityExist(entity) do
|
||||
Wait(200)
|
||||
|
||||
tries = tries + 1
|
||||
|
||||
if tries > 40 then
|
||||
return reject(("Could not spawn ped - ^5%s^7!"):format(model))
|
||||
end
|
||||
end
|
||||
|
||||
local networkId = NetworkGetNetworkIdFromEntity(entity)
|
||||
resolve(networkId)
|
||||
end)
|
||||
|
||||
if promise then
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
end
|
||||
|
||||
---@param model number|string
|
||||
---@param vehicle number entityId
|
||||
---@param seat number
|
||||
---@param cb? fun(netId: number)
|
||||
---@return number? netId
|
||||
function ESX.OneSync.SpawnPedInVehicle(model, vehicle, seat, cb)
|
||||
if type(model) == "string" then
|
||||
model = joaat(model)
|
||||
end
|
||||
|
||||
local promise = not cb and promise.new()
|
||||
|
||||
local function resolve(result)
|
||||
if promise then
|
||||
promise:resolve(result)
|
||||
elseif cb then
|
||||
cb(result)
|
||||
end
|
||||
end
|
||||
|
||||
local function reject(err)
|
||||
if promise then
|
||||
promise:reject(err)
|
||||
end
|
||||
error(err)
|
||||
end
|
||||
|
||||
CreateThread(function()
|
||||
local entity = CreatePedInsideVehicle(vehicle, 1, model, seat, true, true)
|
||||
local tries = 0
|
||||
|
||||
while not DoesEntityExist(entity) do
|
||||
Wait(200)
|
||||
|
||||
tries = tries + 1
|
||||
|
||||
if tries > 40 then
|
||||
reject(("Could not spawn ped - ^5%s^7!"):format(model))
|
||||
end
|
||||
end
|
||||
|
||||
local networkId = NetworkGetNetworkIdFromEntity(entity)
|
||||
resolve(networkId)
|
||||
end)
|
||||
|
||||
if promise then
|
||||
return Citizen.Await(promise)
|
||||
end
|
||||
end
|
||||
|
||||
local function getNearbyEntities(entities, coords, modelFilter, maxDistance, isPed)
|
||||
local nearbyEntities = {}
|
||||
coords = type(coords) == "number" and GetEntityCoords(GetPlayerPed(coords)) or vector3(coords.x, coords.y, coords.z)
|
||||
for _, entity in pairs(entities) do
|
||||
if not isPed or (isPed and not IsPedAPlayer(entity)) then
|
||||
if not modelFilter or modelFilter[GetEntityModel(entity)] then
|
||||
local entityCoords = GetEntityCoords(entity)
|
||||
if not maxDistance or #(coords - entityCoords) <= maxDistance then
|
||||
nearbyEntities[#nearbyEntities + 1] = NetworkGetNetworkIdFromEntity(entity)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return nearbyEntities
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param maxDistance number
|
||||
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
|
||||
---@return table
|
||||
function ESX.OneSync.GetPedsInArea(coords, maxDistance, modelFilter)
|
||||
return getNearbyEntities(GetAllPeds(), coords, modelFilter, maxDistance, true)
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param maxDistance number
|
||||
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
|
||||
---@return table
|
||||
function ESX.OneSync.GetObjectsInArea(coords, maxDistance, modelFilter)
|
||||
return getNearbyEntities(GetAllObjects(), coords, modelFilter, maxDistance)
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param maxDistance number
|
||||
---@param modelFilter table | nil models to ignore, where the key is the model hash and the value is true
|
||||
---@return table
|
||||
function ESX.OneSync.GetVehiclesInArea(coords, maxDistance, modelFilter)
|
||||
return getNearbyEntities(GetAllVehicles(), coords, modelFilter, maxDistance)
|
||||
end
|
||||
|
||||
local function getClosestEntity(entities, coords, modelFilter, isPed)
|
||||
local distance, closestEntity, closestCoords = 100, 0, vector3(0, 0, 0)
|
||||
coords = type(coords) == "number" and GetEntityCoords(GetPlayerPed(coords)) or vector3(coords.x, coords.y, coords.z)
|
||||
|
||||
for _, entity in pairs(entities) do
|
||||
if not isPed or (isPed and not IsPedAPlayer(entity)) then
|
||||
if not modelFilter or modelFilter[GetEntityModel(entity)] then
|
||||
local entityCoords = GetEntityCoords(entity)
|
||||
local dist = #(coords - entityCoords)
|
||||
if dist < distance then
|
||||
closestEntity, distance, closestCoords = entity, dist, entityCoords
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
return NetworkGetNetworkIdFromEntity(closestEntity), distance, closestCoords
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
|
||||
---@return number entityId, number distance, vector3 coords
|
||||
function ESX.OneSync.GetClosestPed(coords, modelFilter)
|
||||
return getClosestEntity(GetAllPeds(), coords, modelFilter, true)
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
|
||||
---@return number entityId, number distance, vector3 coords
|
||||
function ESX.OneSync.GetClosestObject(coords, modelFilter)
|
||||
return getClosestEntity(GetAllObjects(), coords, modelFilter)
|
||||
end
|
||||
|
||||
---@param coords vector3
|
||||
---@param modelFilter table models to ignore, where the key is the model hash and the value is true
|
||||
---@return number entityId, number distance, vector3 coords
|
||||
function ESX.OneSync.GetClosestVehicle(coords, modelFilter)
|
||||
return getClosestEntity(GetAllVehicles(), coords, modelFilter)
|
||||
end
|
||||
71
resources/[core]/es_extended/server/modules/paycheck.lua
Normal file
71
resources/[core]/es_extended/server/modules/paycheck.lua
Normal file
@@ -0,0 +1,71 @@
|
||||
function StartPayCheck()
|
||||
CreateThread(function()
|
||||
while true do
|
||||
Wait(Config.PaycheckInterval)
|
||||
for player, xPlayer in pairs(ESX.Players) do
|
||||
local jobLabel = xPlayer.job.label
|
||||
local job = xPlayer.job.grade_name
|
||||
local onDuty = xPlayer.job.onDuty
|
||||
local salary = (job == "unemployed" or onDuty) and xPlayer.job.grade_salary or ESX.Math.Round(xPlayer.job.grade_salary * Config.OffDutyPaycheckMultiplier)
|
||||
|
||||
if xPlayer.paycheckEnabled then
|
||||
if salary > 0 then
|
||||
if job == "unemployed" then -- unemployed
|
||||
xPlayer.addAccountMoney("bank", salary, "Welfare Check")
|
||||
TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_help", salary), "CHAR_BANK_MAZE", 9)
|
||||
if Config.LogPaycheck then
|
||||
ESX.DiscordLogFields("Paycheck", "Paycheck - Unemployment Benefits", "green", {
|
||||
{ name = "Player", value = xPlayer.name, inline = true },
|
||||
{ name = "ID", value = xPlayer.source, inline = true },
|
||||
{ name = "Amount", value = salary, inline = true },
|
||||
})
|
||||
end
|
||||
elseif Config.EnableSocietyPayouts then -- possibly a society
|
||||
TriggerEvent("esx_society:getSociety", xPlayer.job.name, function(society)
|
||||
if society ~= nil then -- verified society
|
||||
TriggerEvent("esx_addonaccount:getSharedAccount", society.account, function(account)
|
||||
if account.money >= salary then -- does the society money to pay its employees?
|
||||
xPlayer.addAccountMoney("bank", salary, "Paycheck")
|
||||
account.removeMoney(salary)
|
||||
if Config.LogPaycheck then
|
||||
ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", {
|
||||
{ name = "Player", value = xPlayer.name, inline = true },
|
||||
{ name = "ID", value = xPlayer.source, inline = true },
|
||||
{ name = "Amount", value = salary, inline = true },
|
||||
})
|
||||
end
|
||||
|
||||
TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9)
|
||||
else
|
||||
TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), "", TranslateCap("company_nomoney"), "CHAR_BANK_MAZE", 1)
|
||||
end
|
||||
end)
|
||||
else -- not a society
|
||||
xPlayer.addAccountMoney("bank", salary, "Paycheck")
|
||||
if Config.LogPaycheck then
|
||||
ESX.DiscordLogFields("Paycheck", "Paycheck - " .. jobLabel, "green", {
|
||||
{ name = "Player", value = xPlayer.name, inline = true },
|
||||
{ name = "ID", value = xPlayer.source, inline = true },
|
||||
{ name = "Amount", value = salary, inline = true },
|
||||
})
|
||||
end
|
||||
TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9)
|
||||
end
|
||||
end)
|
||||
else -- generic job
|
||||
xPlayer.addAccountMoney("bank", salary, "Paycheck")
|
||||
if Config.LogPaycheck then
|
||||
ESX.DiscordLogFields("Paycheck", "Paycheck - Generic", "green", {
|
||||
{ name = "Player", value = xPlayer.name, inline = true },
|
||||
{ name = "ID", value = xPlayer.source, inline = true },
|
||||
{ name = "Amount", value = salary, inline = true },
|
||||
})
|
||||
end
|
||||
TriggerClientEvent("esx:showAdvancedNotification", player, TranslateCap("bank"), TranslateCap("received_paycheck"), TranslateCap("received_salary", salary), "CHAR_BANK_MAZE", 9)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
end)
|
||||
end
|
||||
Reference in New Issue
Block a user