From 3e34cb7cef24e6a433343132e4e4d50b2cd11eae Mon Sep 17 00:00:00 2001 From: zykem#0643 <86602828+Zykem@users.noreply.github.com> Date: Sat, 21 Dec 2024 19:16:50 +0100 Subject: [PATCH 1/3] Refactor fxmanifest.lua to include dynamic modules --- [core]/es_extended/fxmanifest.lua | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/[core]/es_extended/fxmanifest.lua b/[core]/es_extended/fxmanifest.lua index 7660407dc..acddf7c2e 100644 --- a/[core]/es_extended/fxmanifest.lua +++ b/[core]/es_extended/fxmanifest.lua @@ -73,6 +73,10 @@ files { 'html/fonts/pdown.ttf', 'html/fonts/bankgothic.ttf', + + -- Dynamic Modules + 'client/dynamicModules/*.lua', + 'server/dynamicModules/*.lua' } dependencies { From 13b229c4a832212e55e954dab9bb620899c80345 Mon Sep 17 00:00:00 2001 From: zykem#0643 <86602828+Zykem@users.noreply.github.com> Date: Sat, 21 Dec 2024 19:17:02 +0100 Subject: [PATCH 2/3] Add ESX.LoadModule function --- [core]/es_extended/imports.lua | 42 ++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/[core]/es_extended/imports.lua b/[core]/es_extended/imports.lua index c4bb76c77..37e00c1f0 100644 --- a/[core]/es_extended/imports.lua +++ b/[core]/es_extended/imports.lua @@ -22,3 +22,45 @@ if not IsDuplicityVersion() then -- Only register this event for the client ESX.PlayerData = {} end) end + + +local basePath = ('%s/dynamicModules'):format(IsDuplicityVersion() and 'server' or 'client') +local loadedModules = {} + +--- Load a module by its name. Make sure the specified resource has the module loaded via files {} in fxmanifest.lua (e.g files { 'modules/myModule.lua' }) +--- @param moduleName string The name of the module to load +--- @param path? string Optional. A sub-path relative to the resource's root or nil to use the default basePath +--- @param resourceName? string Optional. The resource name to load the module from. Default is 'es_extended' +--- @return unknown | boolean: Returns the result of the module or true if successful +function ESX.LoadModule(moduleName, path, resourceName) + ESX.AssertType(moduleName, 'string', 'moduleName should be a string.') + if path then + ESX.AssertType(path, 'string', 'path should be a string.') + end + if resourceName then + ESX.AssertType(resourceName, 'string', 'customResource should be a string.') + end + + resourceName = resourceName or 'es_extended' + + local moduleKey = ('%s-%s'):format(moduleName, path or '') + if loadedModules[moduleKey] then + print(('Module %s is already loaded'):format(moduleName)) + return true + end + + local modulePath = path and ('%s/%s.lua'):format(path, moduleName) or ('%s/%s.lua'):format(basePath, moduleName) + + local moduleCode = LoadResourceFile(resourceName, modulePath) + assert(moduleCode, 'moduleCode is nil, make sure your module path is correct. Note: Client-side modules can not be loaded from the server-side.') + + local func, err = load(moduleCode, ('@@%s/%s'):format(resourceName, modulePath)) + assert(func, ('Failed to load module %s: %s'):format(moduleName, err)) + + local success, result = pcall(func) + assert(success, ('Failed to execute module %s: %s'):format(moduleName, result)) + + loadedModules[moduleKey] = true + + return result or true +end \ No newline at end of file From 163b536a2a9cefe1d653cd4dcc6538eb50cf705b Mon Sep 17 00:00:00 2001 From: zykem#0643 <86602828+Zykem@users.noreply.github.com> Date: Sat, 21 Dec 2024 19:17:27 +0100 Subject: [PATCH 3/3] Add example usage of ESX.LoadModule (Blip Module) --- .../client/dynamicModules/blip.lua | 65 +++++++++++++++++++ 1 file changed, 65 insertions(+) create mode 100644 [core]/es_extended/client/dynamicModules/blip.lua diff --git a/[core]/es_extended/client/dynamicModules/blip.lua b/[core]/es_extended/client/dynamicModules/blip.lua new file mode 100644 index 000000000..23f70c21d --- /dev/null +++ b/[core]/es_extended/client/dynamicModules/blip.lua @@ -0,0 +1,65 @@ +-- inspired by: https://github.com/esx-framework/esx_core/pull/1490 + +local blips = {} + +---@class ESXBlip +---@field coords vector3 Blip coordinates +---@field sprite number Blip sprite. See https://docs.fivem.net/docs/game-references/blips/#blips +---@field label string Blip display name/label +---@field color? number Blip color. See https://docs.fivem.net/docs/game-references/blips/#blip-colors +---@field scale? number Blip scale. Defaults to 1.0 +---@field display? number Blip display type. Defaults to 4 +---@field shortRange? boolean Is Blip short range. Defaults to true + +--- Used to create static blips on the map. Blips are removed when the resource that created them is stopped. +---@param blipData ESXBlip +---@return number: The blip id. The blip can later be removed with DeleteBlip by passing the blip id as the first argument. +function CreateBlip(blipData) + ESX.AssertType(blipData, 'table') + ESX.AssertType(blipData.coords, 'vector3') + ESX.AssertType(blipData.sprite, 'number') + ESX.AssertType(blipData.label, 'string') + + local handle = ESX.Table.SizeOf(blips) + 1 + + local blip = AddBlipForCoord(blipData.coords.x, blipData.coords.y, blipData.coords.z) + + SetBlipSprite(blip, blipData.sprite) + SetBlipColour(blip, blipData.color or 1) + SetBlipScale(blip, blipData.scale or 1.0) + SetBlipDisplay(blip, blipData.display or 4) + SetBlipAsShortRange(blip, blipData.shortRange or true) + + local textEntry = ("esxBlip:%s"):format(handle) + + AddTextEntry(textEntry, blipData.label) + + BeginTextCommandSetBlipName(textEntry) + EndTextCommandSetBlipName(blip) + + blips[handle] = { + blipHandle = blip, + resource = GetInvokingResource() + } + + return handle +end + +---@param blipId number The blip id that is provided when creating the blip with CreateBlip +function DeleteBlip(blipId) + local blip = blips[blipId] + + if blip then + RemoveBlip(blip.blipHandle) + blips[blipId] = nil + end +end + +local function onResourceStop(resourceName) + for blipId, blipData in pairs(blips) do + if blipData.resource == resourceName then + DeleteBlip(blipId) + end + end +end +AddEventHandler('onResourceStop', onResourceStop) \ No newline at end of file