From d31d5d345e8c55736cf9a942e2d4531d87ade81a Mon Sep 17 00:00:00 2001 From: GoatGeek Date: Tue, 13 Apr 2021 21:25:01 -0700 Subject: [PATCH] 1.5.0 - Updated readme, separated code into files, Lua 5.4, and more documentation for the config --- README.md | 15 +++- cl.lua | 210 ++++-------------------------------------------- cl_commands.lua | 69 ++++++++++++++++ cl_dev.lua | 57 +++++++++++++ cl_render.lua | 79 ++++++++++++++++++ config.lua | 66 ++++++++++----- fxmanifest.lua | 20 +++-- sv.lua | 47 +++++------ version.json | 4 +- 9 files changed, 312 insertions(+), 255 deletions(-) create mode 100644 cl_commands.lua create mode 100644 cl_dev.lua create mode 100644 cl_render.lua diff --git a/README.md b/README.md index dfc8a12..c7d25a4 100644 --- a/README.md +++ b/README.md @@ -1,6 +1,6 @@ # Nearest Postals -This script displays a nearest postal next to where PLD would go and also has a command to draw a route to a specific postal +This script displays the nearest postal next to map, and allows you to navigate to specific postal codes with `/postal` ## Installation @@ -23,6 +23,15 @@ It will automatically remove the route when within 100m of the destination ## Updates +### 1.5 + +- Major performance improvements +- Added the `refreshRate` configuration option +- Simplified distance calculation logic +- Separated code into separate files +- Prebuild the postal list with vectors at startup +- Use FiveM Lua 5.4 + ### 1.4 - Performance Improvements @@ -58,8 +67,8 @@ It will automatically remove the route when within 100m of the destination This script provides a simple way of working on a new postal map -1. In the script, enabled the local variable `dev` near the bottom -2. Restart the script into game +1. In the resource `fxmanifest.lua` file, uncomment the `cl_dev.lua` requirement line +2. Do `refresh` and `restart nearest-postal` in-game 3. Teleport to the first postal code in numerical order 4. Type `/setnext [postalCode]` where postalCode is the postal that you are at 5. Type `/next` to insert it diff --git a/cl.lua b/cl.lua index 6a02ed2..a2dce5f 100644 --- a/cl.lua +++ b/cl.lua @@ -1,204 +1,22 @@ --- optimizations -local Wait = Wait -local format = string.format -local ipairs = ipairs -local RemoveBlip = RemoveBlip -local PlayerPedId = PlayerPedId -local IsHudHidden = IsHudHidden -local SetTextFont = SetTextFont -local SetTextScale = SetTextScale -local SetTextOutline = SetTextOutline -local GetEntityCoords = GetEntityCoords -local EndTextCommandDisplayText = EndTextCommandDisplayText -local BeginTextCommandDisplayText = BeginTextCommandDisplayText -local AddTextComponentSubstringPlayerName = AddTextComponentSubstringPlayerName -local vec = vec --- end optimizations - -local raw = LoadResourceFile(GetCurrentResourceName(), GetResourceMetadata(GetCurrentResourceName(), 'postal_file')) - ---@class PostalData : table ---@field code string ---@type table -local postals = json.decode(raw) -for i, postal in ipairs(postals) do postals[i] = { vec(postal.x, postal.y), code = postal.code } end - -local nearest = nil -local pBlip = nil -local nearestPostalText = "" - --- thread for nearest and blip +postals = nil CreateThread(function() - local config = config - local deleteDist = config.blip.distToDelete - local _total = #postals - - while true do - local coords = GetEntityCoords(PlayerPedId()) - local _nearestIndex, _nearestD - coords = vec(coords[1], coords[2]) - - for i = 1, _total do - local D = #(coords - postals[i][1]) - if not _nearestD or D < _nearestD then - _nearestIndex = i - _nearestD = D - end - end - - if pBlip and _nearestD < deleteDist then - -- delete blip if close - RemoveBlip(pBlip.hndl) - pBlip = nil - end - - nearest = { code = postals[_nearestIndex].code, dist = _nearestD } - Wait(250) - end -end) - -CreateThread(function() - local formatTemplate = config.text.format - while true do - if nearest then nearestPostalText = format(formatTemplate, nearest.code, nearest.dist) end - Wait(250) - end + postals = LoadResourceFile(GetCurrentResourceName(), GetResourceMetadata(GetCurrentResourceName(), 'postal_file')) + postals = json.decode(postals) + for i, postal in ipairs(postals) do postals[i] = { vec(postal.x, postal.y), code = postal.code } end end) --- text display thread -CreateThread(function() - local posX = config.text.posX - local posY = config.text.posY - local _string = "STRING" - local _scale = 0.42 - local _font = 4 - while true do - if nearest and not IsHudHidden() then - SetTextScale(_scale, _scale) - SetTextFont(_font) - SetTextOutline() - BeginTextCommandDisplayText(_string) - AddTextComponentSubstringPlayerName(nearestPostalText) - EndTextCommandDisplayText(posX, posY) - end - Wait(0) - end -end) - -RegisterCommand('postal', function(source, args, raw) - if #args < 1 then - if pBlip then - RemoveBlip(pBlip.hndl) - pBlip = nil - TriggerEvent('chat:addMessage', { - color = { 255, 0, 0 }, - args = { - 'Postals', - config.blip.deleteText - } - }) - end - return - end - local n = string.upper(args[1]) - - local fp = nil - for _, p in ipairs(postals) do - if string.upper(p.code) == n then - fp = p - break - end - end - - if fp then - if pBlip then - RemoveBlip(pBlip.hndl) - end - pBlip = { hndl = AddBlipForCoord(fp.x, fp.y, 0.0), p = fp } - SetBlipRoute(pBlip.hndl, true) - SetBlipSprite(pBlip.hndl, config.blip.sprite) - SetBlipColour(pBlip.hndl, config.blip.color) - SetBlipRouteColour(pBlip.hndl, config.blip.color) - BeginTextCommandSetBlipName('STRING') - AddTextComponentSubstringPlayerName(config.blip.blipText:format(pBlip.p.code)) - EndTextCommandSetBlipName(pBlip.hndl) - - TriggerEvent('chat:addMessage', { - color = { 255, 0, 0 }, - args = { - 'Postals', - config.blip.drawRouteText:format(fp.code) - } - }) - else - TriggerEvent('chat:addMessage', { - color = { 255, 0, 0 }, - args = { - 'Postals', - config.blip.notExistText - } - }) - end -end) - ---[[Development shit]] -local dev = false -if dev then - local devLocal = json.decode(raw) - local next = 0 - - RegisterCommand('setnext', function(src, args, raw) - local n = tonumber(args[1]) - if n ~= nil then - next = n - print('next ' .. next) - return - end - print('invalid ' .. n) - end) - - RegisterCommand('next', function(src, args, raw) - for i, d in ipairs(devLocal) do - if d.code == tostring(next) then - print('duplicate ' .. next) - return - end - end - local coords = GetEntityCoords(GetPlayerPed(-1)) - table.insert(devLocal, { code = tostring(next), x = coords.x, y = coords.y }) - print('insert ' .. next) - next = next + 1 - end) - - RegisterCommand('rl', function(src, args, raw) - if #devLocal > 0 then - local data = table.remove(devLocal, #devLocal) - print('remove ' .. data.code) - print('next ' .. next) - next = next - 1 - else - print('invalid') - end - end) - - RegisterCommand('remove', function(src, args, raw) - if #args < 1 then - print('invalid') - else - for i, d in ipairs(devLocal) do - if d.code == args[1] then - table.remove(devLocal, i) - print('remove ' .. d.code) - return - end - end - print('invalid') - end - end) - - RegisterCommand('json', function(src, args, raw) - print(json.encode(devLocal)) - end) -end +---@class NearestResult +---@field code string +---@field dist number +nearest = nil + +---@class PostalBlip +---@field 1 vec +---@field p PostalData +---@field hndl number +pBlip = nil exports('getPostal', function() return nearest and nearest.code or nil end) diff --git a/cl_commands.lua b/cl_commands.lua new file mode 100644 index 0000000..7ce1796 --- /dev/null +++ b/cl_commands.lua @@ -0,0 +1,69 @@ +-- optimizations +local ipairs = ipairs +local upper = string.upper +local format = string.format +-- end optimizations + +--- +--- [[ Nearest Postal Commands ]] --- +--- + +TriggerEvent('chat:addSuggestion', '/postal', 'Set the GPS to a specific postal', + { { name = 'Postal Code', help = 'The postal code you would like to go to' } }) + +RegisterCommand('postal', function(_, args) + if #args < 1 then + if pBlip then + RemoveBlip(pBlip.hndl) + pBlip = nil + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0 }, + args = { + 'Postals', + config.blip.deleteText + } + }) + end + return + end + + local userPostal = upper(args[1]) + local foundPostal + + for _, p in ipairs(postals) do + if upper(p.code) == userPostal then + foundPostal = p + break + end + end + + if foundPostal then + if pBlip then RemoveBlip(pBlip.hndl) end + local blip = AddBlipForCoord(foundPostal[1][1], foundPostal[1][2], 0.0) + pBlip = { hndl = blip, p = foundPostal } + SetBlipRoute(blip, true) + SetBlipSprite(blip, config.blip.sprite) + SetBlipColour(blip, config.blip.color) + SetBlipRouteColour(blip, config.blip.color) + BeginTextCommandSetBlipName('STRING') + AddTextComponentSubstringPlayerName(format(config.blip.blipText, pBlip.p.code)) + EndTextCommandSetBlipName(blip) + + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0 }, + args = { + 'Postals', + format(config.blip.drawRouteText, foundPostal.code) + } + }) + else + TriggerEvent('chat:addMessage', { + color = { 255, 0, 0 }, + args = { + 'Postals', + config.blip.notExistText + } + }) + end +end) + diff --git a/cl_dev.lua b/cl_dev.lua new file mode 100644 index 0000000..1b891f3 --- /dev/null +++ b/cl_dev.lua @@ -0,0 +1,57 @@ +--- [[ Development shit ]] + +local devLocal = json.decode(raw) +local next = 0 + +RegisterCommand('setnext', function(_, args) + local n = tonumber(args[1]) + if n ~= nil then + next = n + print('next ' .. next) + return + end + print('invalid ' .. n) +end) + +RegisterCommand('next', function() + for _, d in ipairs(devLocal) do + if d.code == tostring(next) then + print('duplicate ' .. next) + return + end + end + local coords = GetEntityCoords(PlayerPedId()) + insert(devLocal, { code = tostring(next), x = coords.x, y = coords.y }) + print('insert ' .. next) + next = next + 1 +end) + +RegisterCommand('rl', function() + if #devLocal > 0 then + local data = remove(devLocal, #devLocal) + print('remove ' .. data.code) + print('next ' .. next) + next = next - 1 + else + print('invalid') + end +end) + +RegisterCommand('remove', function(_, args) + if #args < 1 then + print('invalid') + else + for i, d in ipairs(devLocal) do + if d.code == args[1] then + table.remove(devLocal, i) + print('remove ' .. d.code) + return + end + end + print('invalid') + end +end) + +RegisterCommand('json', function() + print(json.encode(devLocal)) +end) diff --git a/cl_render.lua b/cl_render.lua new file mode 100644 index 0000000..91f47e4 --- /dev/null +++ b/cl_render.lua @@ -0,0 +1,79 @@ +-- optimizations +local vec = vec +local Wait = Wait +local format = string.format +local RemoveBlip = RemoveBlip +local PlayerPedId = PlayerPedId +local IsHudHidden = IsHudHidden +local SetTextFont = SetTextFont +local CreateThread = CreateThread +local SetTextScale = SetTextScale +local SetTextOutline = SetTextOutline +local GetEntityCoords = GetEntityCoords +local EndTextCommandDisplayText = EndTextCommandDisplayText +local BeginTextCommandDisplayText = BeginTextCommandDisplayText +local AddTextComponentSubstringPlayerName = AddTextComponentSubstringPlayerName +-- end optimizations + +local nearestPostalText = "" + +-- recalculate current postal +CreateThread(function() + -- wait for postals to load + while postals == nil do Wait(1) end + + local delay = math.max(config.updateDelay and tonumber(config.updateDelay) or 300, 50) + if not delay or tonumber(delay) <= 0 then + error("Invalid render delay provided, it must be a number > 0") + end + + local postals = postals + local deleteDist = config.blip.distToDelete + local formatTemplate = config.text.format + local _total = #postals + + while true do + local coords = GetEntityCoords(PlayerPedId()) + local _nearestIndex, _nearestD + coords = vec(coords[1], coords[2]) + + for i = 1, _total do + local D = #(coords - postals[i][1]) + if not _nearestD or D < _nearestD then + _nearestIndex = i + _nearestD = D + end + end + + if pBlip and #(pBlip.p[1] - coords) < deleteDist then + print("You've reached your postal destination!") + RemoveBlip(pBlip.hndl) + pBlip = nil + end + + local _code = postals[_nearestIndex].code + nearest = { code = _code, dist = _nearestD } + nearestPostalText = format(formatTemplate, _code, _nearestD) + Wait(delay) + end +end) + +-- text display thread +CreateThread(function() + local posX = config.text.posX + local posY = config.text.posY + local _string = "STRING" + local _scale = 0.42 + local _font = 4 + while true do + if nearest and not IsHudHidden() then + SetTextScale(_scale, _scale) + SetTextFont(_font) + SetTextOutline() + BeginTextCommandDisplayText(_string) + AddTextComponentSubstringPlayerName(nearestPostalText) + EndTextCommandDisplayText(posX, posY) + end + Wait(0) + end +end) diff --git a/config.lua b/config.lua index 0a39df9..3974a05 100644 --- a/config.lua +++ b/config.lua @@ -1,21 +1,49 @@ config = { - versionCheck = true, -- enables version checking (if this is enabled and there is no new version it won't display a message anyways) - text = { - format = '~y~Nearest Postal~w~: %s (~g~%.2fm~w~)', - -- ScriptHook PLD Position - --posX = 0.225, - --posY = 0.963, - -- vMenu PLD Position - posX = 0.22, - posY = 0.963 - }, - blip = { - blipText = 'Postal Route %s', - sprite = 8, - color = 3, -- default 3 (light blue) - distToDelete = 100.0, -- in meters - deleteText = 'Route deleted', - drawRouteText = 'Drawing a route to %s', - notExistText = "That postal doesn't exist" - } + -- enables version checking (if this is enabled and there is no new version it won't display a message anyways) + versionCheck = true, + + text = { + -- The text to display on-screen for the nearest postal. + -- Formatted using Lua strings, http://www.lua.org/pil/20.html + format = '~y~Nearest Postal~w~: %s (~g~%.2fm~w~)', + + -- ScriptHook PLD Position + --posX = 0.225, + --posY = 0.963, + + -- vMenu PLD Position + posX = 0.22, + posY = 0.963 + }, + + blip = { + -- The text to display in chat when setting a new route. + -- Formatted using Lua strings, http://www.lua.org/pil/20.html + blipText = 'Postal Route %s', + + -- The sprite ID to display, the list is available here: + -- https://docs.fivem.net/docs/game-references/blips/#blips + sprite = 8, + + -- The color ID to use (default is 3, light blue) + -- https://docs.fivem.net/docs/game-references/blips/#blip-colors + color = 3, + + -- When the player is this close (in meters) to the destination, + -- the blip will be removed. + distToDelete = 100.0, + + -- The text to display in chat when a route is deleted + deleteText = 'Route deleted', + + -- The text to display in chat when drawing a new route + drawRouteText = 'Drawing a route to %s', + + -- The text to display when a postal is not found. + notExistText = "That postal doesn't exist" + }, + + -- How often in milliseconds the postal code is updated on each client. + -- I wouldn't recommend anything lower than 50ms for performance reasons + updateDelay = nil, } diff --git a/fxmanifest.lua b/fxmanifest.lua index 3b07977..b2ad418 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -8,19 +8,27 @@ If you just want to change the postal file, **ONLY** change the above variable --]] fx_version 'cerulean' games { 'gta5' } +lua54 "yes" author 'blockba5her' -description 'This script displays a nearest postal next to where PLD would go and also has a command to draw a route to a specific postal' -version '1.4.2' +description 'This script displays the nearest postal next to map, and allows you to navigate to specific postal codes' +version '1.5.0' url 'https://github.com/blockba5her/nearest-postal' client_scripts { - 'config.lua', - 'cl.lua' + 'config.lua', + + 'cl.lua', + 'cl_commands.lua', + 'cl_render.lua', + + -- uncomment to enable dev tools + --'cl_dev.lua', } + server_scripts { - 'config.lua', - 'sv.lua' + 'config.lua', + 'sv.lua' } file(postalFile) diff --git a/sv.lua b/sv.lua index 7e4ef67..d416042 100644 --- a/sv.lua +++ b/sv.lua @@ -1,35 +1,24 @@ -- version check -Citizen.CreateThread( - function() - local vRaw = LoadResourceFile(GetCurrentResourceName(), 'version.json') - if vRaw and config.versionCheck then - local v = json.decode(vRaw) - PerformHttpRequest( - 'https://raw.githubusercontent.com/blockba5her/nearest-postal/master/version.json', - function(code, res, headers) - if code == 200 then - local rv = json.decode(res) - if rv.version ~= v.version then - print( - ([[ - +CreateThread(function() + local vRaw = LoadResourceFile(GetCurrentResourceName(), 'version.json') + if vRaw and config.versionCheck then + local v = json.decode(vRaw) + local url = 'https://raw.githubusercontent.com/blockba5her/nearest-postal/master/version.json' + PerformHttpRequest(url, function(code, res) + if code == 200 then + local rv = json.decode(res) + if rv.version ~= v.version then + print(([[ ------------------------------------------------------- nearest-postal UPDATE: %s AVAILABLE CHANGELOG: %s ------------------------------------------------------- -]]):format( - rv.version, - rv.changelog - ) - ) - end - else - print('nearest-postal unable to check version') - end - end, - 'GET' - ) - end - end -) +]]):format(rv.version, rv.changelog)) + end + else + print('nearest-postal was unable to check the version') + end + end, 'GET') + end +end) diff --git a/version.json b/version.json index 90415eb..842d4fc 100644 --- a/version.json +++ b/version.json @@ -1,4 +1,4 @@ { - "version": "1.4.2", - "changelog": "Changed __resource to fxmanifest" + "version": "1.5.0", + "changelog": "Rewrite and performance improvements" }