diff --git a/Attributions.md b/Attributions.md index 05b2092..83c022d 100644 --- a/Attributions.md +++ b/Attributions.md @@ -8,11 +8,11 @@ This project incorporates code from several libraries and resources licensed und - **Credit**: **r_bridge** inventory bridging code for codem-inventory is used in this. Targeting code still remains as is and is used. [\[r_bridge\]](https://github.com/rumaier/r_bridge) -## clean_lib +## dirk_lib - **Purpose**: Vehicle fuel, vehicle key bridging. - **Modifications to the code**: None. -- **Credit**: **clean_lib** client side code is used to manage vehicle fuel and keys, bridging these systems. - [\[clean_lib\]](https://github.com/Clean-Server-Pack/clean_lib) +- **Credit**: **dirk_lib** client side code is used to manage vehicle fuel and keys, bridging these systems. + [\[dirk_lib\]](https://github.com/DirkDigglerz/dirk_lib) ## ox_lib - **Purpose**: Utility functions for printing raycasting and point registering. @@ -34,4 +34,4 @@ This project incorporates code from several libraries and resources licensed und -Thank you to the creators and maintainers of these libraries/bridges/internet points for their hard work and contributions to the FiveM community. \ No newline at end of file +Thank you to the creators and maintainers of these libraries/bridges/internet points for their hard work and contributions to the FiveM community. diff --git a/fxmanifest.lua b/fxmanifest.lua index 8c28da5..4acca46 100644 --- a/fxmanifest.lua +++ b/fxmanifest.lua @@ -4,7 +4,7 @@ lua54 'yes' use_experimental_fxv2_oal 'yes' author 'The Order of the Sacred Framework' description 'A bridge made for the community to use as a base for their own projects. This bridge will allow a single format to work with nearly all commonly used systems while still offering expandability.' -version '0.4.0' +version '0.5.0' shared_scripts { '@ox_lib/init.lua', @@ -50,6 +50,7 @@ client_scripts { 'modules/notify/**/client.lua', 'modules/dialogue/**/client/*.lua', 'modules/shops/**/client.lua', + 'modules/accessibility/client.lua', 'init.lua', } @@ -60,9 +61,9 @@ files { 'web/dist/assets/*.css', 'web/dist/assets/*.js', 'locales/*.json', - 'lib/client/*.lua', - 'lib/shared/*.lua', - 'lib/server/*.lua', + 'lib/**/client/*.lua', + 'lib/**/shared/*.lua', + 'lib/**/server/*.lua', 'lib/init.lua', } diff --git a/init.lua b/init.lua index fc9ec63..3c6340b 100644 --- a/init.lua +++ b/init.lua @@ -79,6 +79,7 @@ if not IsDuplicityVersion() then goto client end Bridge.RegisterModule("SQL", cLib.SQL) Bridge.RegisterModule("Logs", cLib.Logs) +Bridge.RegisterModule("ItemsBuilder", cLib.ItemsBuilder) Bridge.RegisterModule("LootTables", cLib.LootTables) Bridge.RegisterModule("Version", Version) @@ -98,6 +99,7 @@ Bridge.RegisterModule("Weather", Weather) Bridge.RegisterModule("Target", Target) Bridge.RegisterModule("Menu", Menu) Bridge.RegisterModule("Dialogue", Dialogue) +Bridge.RegisterModule("Accessibility", Accessibility) -- new Bridge.RegisterModule("Utility", cLib.Utility) Bridge.RegisterModule("Placeable", cLib.Placeable)--new @@ -105,6 +107,8 @@ Bridge.RegisterModule("Gizmo", cLib.Gizmo) Bridge.RegisterModule("Scaleform", cLib.Scaleform) Bridge.RegisterModule("Raycast", cLib.Raycast) Bridge.RegisterModule("PlaceableObject", cLib.PlaceableObject) +Bridge.RegisterModule("Point", cLib.Point) +Bridge.RegisterModule("Object", cLib.Object) diff --git a/lib/entities/client/entity_base.lua b/lib/entities/client/entity_base.lua new file mode 100644 index 0000000..1ac6022 --- /dev/null +++ b/lib/entities/client/entity_base.lua @@ -0,0 +1,51 @@ +-- Objects +Utility = Utility or Require("lib/utility/client/utility.lua") +Ids = Ids or Require("lib/utility/shared/ids.lua") +Point = Point or Require("lib/points/client/points.lua") + +local Entities = {} +BaseEntity = {} + +function BaseEntity.Create(id, model, coords, rotation, meta) + local self = meta or {} + if id and type(id) == "table" then + self = id + self.id = id.id or Ids.CreateUniqueId(Entities) + self.rotation = id.rotation or vector3(0.0, 0.0, 0.0) + else + self.id = id or Ids.CreateUniqueId(Entities) + self.model = model + self.coords = coords + self.rotation = rotation or vector3(0.0, 0.0, 0.0) + end + assert(self.id, "ID Failed to generate") + assert(self.model, "Model is required for entity creation") + assert(self.coords, "Coords are required for entity creation") + + self.Spawn = self.Spawn or function() end + self.Remove = self.Remove or function() end + + return Point.Register(self.id, self.coords, 50.0, self.Spawn, self.Remove, nil, self) +end + +function BaseEntity.GetAll() + return Entities +end + +function BaseEntity.Get(id) + return Entities[id] +end + +function BaseEntity.Add(self) + Entities[self.id] = self +end + +function BaseEntity.Remove(id) + Entities[id] = nil +end + +function BaseEntity.LoadModel(model) + return Utility.LoadModel(model) +end + +return BaseEntity \ No newline at end of file diff --git a/lib/entities/client/entity_object.lua b/lib/entities/client/entity_object.lua new file mode 100644 index 0000000..ab6ee2d --- /dev/null +++ b/lib/entities/client/entity_object.lua @@ -0,0 +1,71 @@ +BaseEntity = BaseEntity or Require("lib/entities/client/entity_base.lua") +local Objects = {} + +Object = {} + +function Object.Create(id, model, coords, rotation, meta) + local base = meta or {} + if id and type(id) == "table" then + base = id + base.id = id.id or Ids.CreateUniqueId(Objects) + base.rotation = id.rotation or vector3(0.0, 0.0, 0.0) + else + base.id = id or Ids.CreateUniqueId(Objects) + base.model = model + base.coords = coords + base.rotation = rotation or vector3(0.0, 0.0, 0.0) + end + assert(base.id, "ID Failed to generate") + assert(base.model, "Model is required for entity creation") + assert(base.coords, "Coords are required for entity creation") + + base.Spawn = function(self) + print("Spawning object", self) + if not BaseEntity.LoadModel(self.model) then return end + self.entity = CreateObject(self.model, self.coords.x, self.coords.y, self.coords.z, false, false, false) + SetEntityRotation(self.entity, self.rotation.x, self.rotation.y, self.rotation.z, 2, false) + SetEntityAsMissionEntity(self.entity, true, true) + SetModelAsNoLongerNeeded(self.model) + if self.OnSpawn then self.OnSpawn(self, self.entity, self.coords, self.rotation) end + return self.entity + end + base.Remove = function(self) + DeleteEntity(self.entity) + if self.OnRemove then self.OnRemove(self, self.entity) end + self.entity = nil + end + Object.Add(base) + return BaseEntity.Create(base) +end + +function Object.GetAll() + return Objects +end + +function Object.Get(id) + return Objects[id] +end + +function Object.Add(self) + Objects[self.id] = self +end + +function Object.Remove(id) + Objects[id] = nil +end + +function Object.SetOnSpawn(id, callback) + local obj = Object.Get(id) + if not obj then return end + obj.OnSpawn = callback + return true +end + +function Object.SetOnRemove(id, callback) + local obj = Object.Get(id) + if not obj then return end + obj.OnRemove = callback + return true +end + +return Object \ No newline at end of file diff --git a/lib/entities/server/entity_relay.lua b/lib/entities/server/entity_relay.lua new file mode 100644 index 0000000..5c2f2d0 --- /dev/null +++ b/lib/entities/server/entity_relay.lua @@ -0,0 +1,65 @@ + +-- Objects +Ids = Ids or Require("lib/utility/shared/ids.lua") + + +local Entities = {} +EntityRelay = {} + +function EntityRelay.Create(id, model, coords, rotation, meta) + local self = meta or {} + if id and type(id) == "table" then + self = id + self.id = id.id or Ids.CreateUniqueId(Entities) + self.rotation = id.rotation or vector3(0.0, 0.0, 0.0) + else + self.id = id or Ids.CreateUniqueId(Entities) + self.model = model + self.coords = coords + self.rotation = rotation or vector3(0.0, 0.0, 0.0) + end + assert(self.id, "ID Failed to generate") + assert(self.model, "Model is required for entity creation") + assert(self.coords, "Coords are required for entity creation") + EntityRelay.Add(self) + TriggerClientEvent(GetCurrentResourceName() .. "client:CreateEntity", -1, self) +end + +function EntityRelay.GetAll() + return Entities +end + +function EntityRelay.Get(id) + return Entities[id] +end + +function EntityRelay.Add(self) + Entities[self.id] = self +end + +function EntityRelay.Remove(id) + Entities[id] = nil +end + +function EntityRelay.LoadModel(model) + return Utility.LoadModel(model) +end + +return EntityRelay + + + -- RegisterCommand("entityobj", function() + -- local entity = Bridge.Object.Create({ + -- id = "something", -- optional + -- model = "prop_beach_fire", + -- coords = GetEntityCoords(PlayerPedId()), + -- rotation = vector3(0.0, 0.0, 0.0), + -- }) + -- Bridge.Object.SetOnSpawn("something", function(self, coords, rotation) + -- print("Entity spawned") + -- end) + + -- Bridge.Object.SetOnRemove("something", function(self, entity) + -- print("Entity removed") + -- end) + -- end) \ No newline at end of file diff --git a/lib/shared/actions.lua b/lib/entities/shared/actions.lua similarity index 100% rename from lib/shared/actions.lua rename to lib/entities/shared/actions.lua diff --git a/lib/generators/server/ItemsBuilder.lua b/lib/generators/server/ItemsBuilder.lua new file mode 100644 index 0000000..c2c6b1c --- /dev/null +++ b/lib/generators/server/ItemsBuilder.lua @@ -0,0 +1,100 @@ +ItemsBuilder = ItemsBuilder or {} + +ItemsBuilder = {} + +---This will generate the items in the formats of qb_core, qb_core_old and ox_inventory. It will then build a lua file in the generateditems folder of the community_bridge. +---@param invoking string +---@param itemsTable table +ItemsBuilder.Generate = function(invoking, itemsTable) + if not invoking or not itemsTable then return end + + local resourcePath = GetResourcePath(GetCurrentResourceName()) .. "/generateditems/" + + local function fileExists(path) + local file = io.open(path, "r") + if file then + file:close() + return true + else + return false + end + end + + local qbOldFilePath = resourcePath .. invoking .. "_qb_core_old.lua" + local qbNewFilePath = resourcePath .. invoking .. "_qb_core_new.lua" + local oxInventoryFilePath = resourcePath .. invoking .. "_ox_inventory.lua" + + if fileExists(qbOldFilePath) or fileExists(qbNewFilePath) or fileExists(oxInventoryFilePath) then return end + + local qbOld = {} + for key, item in pairs(itemsTable) do + qbOld[key] = string.format( + "['%s'] = {label = '%s', weight = %d, stack = %s, close = %s, description = '%s'}", + key, item.label, item.weight, tostring(item.stack), tostring(item.close), item.description + ) + end + + local qbNew = {} + for key, item in pairs(itemsTable) do + qbNew[key] = string.format( + "%s = {label = '%s', weight = %d, stack = %s, close = %s, description = '%s'}", + key, item.label, item.weight, tostring(item.stack), tostring(item.close), item.description + ) + end + + local oxInventory = {} + for key, item in pairs(itemsTable) do + oxInventory[key] = { + label = item.label, + weight = item.weight, + stack = item.stack, + close = item.close + } + end + + local function writeInlineFile(fileName, content, useBrackets) + local filePath = resourcePath .. fileName + local file = io.open(filePath, "w") + if file then + for key, value in pairs(content) do + if useBrackets then + -- For qb_core_old with brackets + file:write(string.format("['%s'] = %s,\n", key, value)) + else + -- For qb_core_new without brackets + file:write(string.format("%s = %s,\n", key, value)) + end + end + file:close() + print("🌮 Items File Created: " .. filePath) + else + print("🌮 Something Broke for: " .. filePath) + end + end + + local function writeSimplifiedFile(fileName, content) + local filePath = resourcePath .. fileName + local file = io.open(filePath, "w") + if file then + for key, item in pairs(content) do + file:write(string.format('["%s"] = {\n', key)) + for k, v in pairs(item) do + local formattedValue = type(v) == "string" and string.format('"%s"', v) or tostring(v) + file:write(string.format(" %s = %s,\n", k, formattedValue)) + end + file:write("},\n") + end + file:close() + print("🌮 Items File Created: " .. filePath) + else + print("🌮 Something Broke for: " .. filePath) + end + end + + writeInlineFile(invoking.."_".."qb_core_old.lua", qbOld, true) + writeInlineFile(invoking.."_".."qb_core_new.lua", qbNew, false) + writeSimplifiedFile(invoking.."_".."ox_inventory.lua", oxInventory) +end + +exports('ItemsBuilder', ItemsBuilder) +return ItemsBuilder \ No newline at end of file diff --git a/lib/server/lootTables.lua b/lib/generators/server/lootTables.lua similarity index 100% rename from lib/server/lootTables.lua rename to lib/generators/server/lootTables.lua diff --git a/lib/init.lua b/lib/init.lua index a6cb9d3..32df25c 100644 --- a/lib/init.lua +++ b/lib/init.lua @@ -37,14 +37,14 @@ end cLib = { Require = Require, - Callback = Callback or Require("lib/shared/callbacks.lua"), - Ids = Ids or Require("lib/shared/ids.lua"), - ReboundEntities = ReboundEntities or Require("lib/shared/rebound_entities.lua"), - Tables = Tables or Require("lib/shared/tables.lua"), - Prints = Prints or Require("lib/shared/prints.lua"), - Math = Math or Require("lib/shared/math.lua"), - LA = LA or Require("lib/shared/la.lua"), - Perlin = Perlin or Require("lib/shared/perlin.lua"), + Callback = Callback or Require("lib/utility/shared/callbacks.lua"), + Ids = Ids or Require("lib/utility/shared/ids.lua"), + ReboundEntities = ReboundEntities or Require("lib/utility/shared/rebound_entities.lua"), + Tables = Tables or Require("lib/utility/shared/tables.lua"), + Prints = Prints or Require("lib/utility/shared/prints.lua"), + Math = Math or Require("lib/utility/shared/math.lua"), + LA = LA or Require("lib/utility/shared/la.lua"), + Perlin = Perlin or Require("lib/utility/shared/perlin.lua"), -- Actions = Actions or Require("lib/shared/actions.lua"), } @@ -52,18 +52,21 @@ exports('cLib', cLib) if not IsDuplicityVersion() then goto client end -cLib.SQL = SQL or Require("lib/server/sqlHandler.lua") -cLib.Logs = Logs or Require("lib/server/logs.lua") -cLib.LootTables = LootTables or Require("lib/server/lootTables.lua") +cLib.SQL = SQL or Require("lib/sql/server/sqlHandler.lua") +cLib.Logs = Logs or Require("lib/logs/server/logs.lua") +cLib.ItemsBuilder = ItemsBuilder or Require("lib/generators/server/ItemsBuilder.lua") +cLib.LootTables = LootTables or Require("lib/generators/server/lootTables.lua") if IsDuplicityVersion() then return cLib end ::client:: -cLib.Gizmo = Gizmo or Require("lib/client/gizmo.lua") -cLib.Scaleform = Scaleform or Require("lib/client/scaleform.lua") -cLib.Placeable = Placeable or Require("lib/client/object_placer.lua") -cLib.Utility = Utility or Require("lib/client/utility.lua") -cLib.PlaceableObject = PlaceableObject or Require("lib/client/placeable_object.lua") -cLib.Raycast = Raycast or Require("lib/client/raycast.lua") +cLib.Gizmo = Gizmo or Require("lib/placers/client/gizmo.lua") +cLib.Scaleform = Scaleform or Require("lib/scaleform/client/scaleform.lua") +cLib.Placeable = Placeable or Require("lib/placers/client/object_placer.lua") +cLib.Utility = Utility or Require("lib/utility/client/utility.lua") +cLib.PlaceableObject = PlaceableObject or Require("lib/placers/client/placeable_object.lua") +cLib.Raycast = Raycast or Require("lib/raycast/client/raycast.lua") +cLib.Point = Point or Require("lib/points/client/points.lua") +cLib.Object = Object or Require("lib/entities/client/entity_object.lua") return cLib \ No newline at end of file diff --git a/lib/server/logs.lua b/lib/logs/server/logs.lua similarity index 94% rename from lib/server/logs.lua rename to lib/logs/server/logs.lua index 4a89dd1..fa353f6 100644 --- a/lib/server/logs.lua +++ b/lib/logs/server/logs.lua @@ -3,6 +3,10 @@ Logs = Logs or {} local WebhookURL = "" local LogoForEmbed = "" +---This will send a log to the configured webhook or log system. +---@param src number +---@param message string +---@return nil Logs.Send = function(src, message) if not src or not message then return end if BridgeServerConfig.LogSystem == "builtin" then diff --git a/lib/client/markers.lua b/lib/markers/client/markers.lua similarity index 100% rename from lib/client/markers.lua rename to lib/markers/client/markers.lua diff --git a/lib/client/particles.lua b/lib/particles/client/particles.lua similarity index 99% rename from lib/client/particles.lua rename to lib/particles/client/particles.lua index 7fa6463..d920080 100644 --- a/lib/client/particles.lua +++ b/lib/particles/client/particles.lua @@ -1,4 +1,3 @@ - function CreateParticleFX(dict, ptfx, pos, rot, scale, color, looped, loopLength) CreateThread(function() local failed = 5 @@ -45,8 +44,6 @@ function CreateParticleFXOnEntityBone(dict, ptfx, entity, bone, offset, rot, sc return bleh end - - function PlayParticleFX(dict, name, looped, x, y, z, rotX, rotY, rotZ, scale) RequestNamedPtfxAsset(dict) while not HasNamedPtfxAssetLoaded(dict) do diff --git a/lib/client/dataview.lua b/lib/placers/client/dataview.lua similarity index 100% rename from lib/client/dataview.lua rename to lib/placers/client/dataview.lua diff --git a/lib/client/gizmo.lua b/lib/placers/client/gizmo.lua similarity index 99% rename from lib/client/gizmo.lua rename to lib/placers/client/gizmo.lua index b4612a2..7bb1010 100644 --- a/lib/client/gizmo.lua +++ b/lib/placers/client/gizmo.lua @@ -2,7 +2,7 @@ -- CREDITS -- Andyyy7666: https://github.com/overextended/ox_lib/pull/453 -- AvarianKnight: https://forum.cfx.re/t/allow-drawgizmo-to-be-used-outside-of-fxdk/5091845/8?u=demi-automatic -local dataview = Require("lib/client/dataview.lua") +local dataview = Require("lib/placers/client/dataview.lua") local enableScale = false -- allow scaling mode. doesnt scale collisions and resets when physics are applied it seems local gizmoEnabled = false local currentMode = 'translate' diff --git a/lib/client/object_Placer.lua b/lib/placers/client/object_Placer.lua similarity index 98% rename from lib/client/object_Placer.lua rename to lib/placers/client/object_Placer.lua index 5a65efb..a56dea8 100644 --- a/lib/client/object_Placer.lua +++ b/lib/placers/client/object_Placer.lua @@ -1,5 +1,5 @@ Placeable = Placeable or {} -Utility = Utility or Require("lib/client/utility.lua") +Utility = Utility or Require("lib/utility/client/utility.lua") local activePlacementProp = nil lib.locale() diff --git a/lib/client/placeable_object.lua b/lib/placers/client/placeable_object.lua similarity index 96% rename from lib/client/placeable_object.lua rename to lib/placers/client/placeable_object.lua index bfc684f..26b10c5 100644 --- a/lib/client/placeable_object.lua +++ b/lib/placers/client/placeable_object.lua @@ -1,7 +1,7 @@ -Scaleform = Scaleform or Require("lib/client/scaleform.lua") -Utility = Utility or Require("lib/client/utility.lua") -Gizmo = Gizmo or Require("lib/client/gizmo.lua") -Raycast = Raycast or Require("lib/client/raycast.lua") +Scaleform = Scaleform or Require("lib/scaleform/client/scaleform.lua") +Utility = Utility or Require("lib/utility/client/utility.lua") +Gizmo = Gizmo or Require("lib/placers/client/gizmo.lua") +Raycast = Raycast or Require("lib/raycast/client/raycast.lua") PlaceableObject = PlaceableObject or {} @@ -71,7 +71,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett {type = "SET_BACKGROUND_COLOUR"}, }) local heading = -GetEntityHeading(PlayerPedId()) - + local pos = PlaceableObject.Eyetrace(depth, disableSphere) if not data.spawned and model then --get player heading @@ -81,7 +81,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett assert(data.spawned, "Failed to create object") SetEntityCollision(data.spawned, false, false) SetEntityAlpha(data.spawned, 150, false) - + SetPedConfigFlag(PlayerPedId(), 146, true) SetCanClimbOnEntity(data.spawned, false) SetEntityCompletelyDisableCollision(data.spawned, true, false) @@ -96,7 +96,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett inBounds = true SetEntityDrawOutlineColor(0, 255, 0, 255) SetEntityDrawOutline(data.spawned, true) - end + end elseif inBounds then inBounds = false SetEntityDrawOutline(data.spawned, false) @@ -113,7 +113,7 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett DisableControlAction(0, 24, true) -- Attack DisableControlAction(0, 25, true) -- Aim DisableControlAction(0, 36, true) -- INPUT_DUCK. - + if IsDisabledControlJustPressed(0, 223) then -- left click if not inBounds then Notify.SendNotify("You can't place this object here", "error", 5000) @@ -190,6 +190,4 @@ function PlaceableObject.Create(data, model, onConfirm, onUpdate, onCancel, sett end) end -return PlaceableObject - - +return PlaceableObject \ No newline at end of file diff --git a/lib/points/client/points.lua b/lib/points/client/points.lua new file mode 100644 index 0000000..e5e23b5 --- /dev/null +++ b/lib/points/client/points.lua @@ -0,0 +1,266 @@ +-- Grid-based point system +Point = {} +local ActivePoints = {} +local GridCells = {} +local LoopStarted = false +local insidePoints = {} +local data = {} -- 👈 Move this outside the function + +-- Grid configuration +local GRID_SIZE = 500.0 -- Size of each grid cell +local CELL_BUFFER = 1 -- Number of adjacent cells to check + +-- Consider adding these optimizations +local ADAPTIVE_WAIT = true -- Adjust wait time based on player speed + +---This is an internal function, do not call this externally +function Point.GetCellKey(coords) + local cellX = math.floor(coords.x / GRID_SIZE) + local cellY = math.floor(coords.y / GRID_SIZE) + return cellX .. ":" .. cellY +end + +---This is an internal function, do not call this externally +function Point.RegisterInGrid(point) + local cellKey = Point.GetCellKey(point.coords) + + -- Initialize cell if it doesn't exist + GridCells[cellKey] = GridCells[cellKey] or { + points = {}, + count = 0 + } + + -- Add point to cell + GridCells[cellKey].points[point.id] = point + GridCells[cellKey].count = GridCells[cellKey].count + 1 + + -- Store cell reference in point + point.cellKey = cellKey +end + +---This is an internal function, do not call this externally +function Point.UpdateInGrid(point, oldCellKey) + -- Remove from old cell if cell key changed + if oldCellKey and oldCellKey ~= point.cellKey then + if GridCells[oldCellKey] and GridCells[oldCellKey].points[point.id] then + GridCells[oldCellKey].points[point.id] = nil + GridCells[oldCellKey].count = GridCells[oldCellKey].count - 1 + + -- Clean up empty cells + if GridCells[oldCellKey].count <= 0 then + GridCells[oldCellKey] = nil + end + end + + -- Add to new cell + Point.RegisterInGrid(point) + end +end + +---Gets nearby cells based on the coords +---@param coords table +---@return table +function Point.GetNearbyCells(coords) + local cellX = math.floor(coords.x / GRID_SIZE) + local cellY = math.floor(coords.y / GRID_SIZE) + local nearbyCells = {} + + -- Get current and adjacent cells + for x = cellX - CELL_BUFFER, cellX + CELL_BUFFER do + for y = cellY - CELL_BUFFER, cellY + CELL_BUFFER do + local key = x .. ":" .. y + if GridCells[key] then + table.insert(nearbyCells, key) + end + end + end + + return nearbyCells +end + +---Returns all points in the same cell as the given point +---This will require you to pass the point object +---@param point table +---@return table +function Point.CheckPointsInSameCell(point) + local cellKey = point.cellKey + if not GridCells[cellKey] then return {} end + + local nearbyPoints = {} + for id, otherPoint in pairs(GridCells[cellKey].points) do + if id ~= point.id then + local distance = #(point.coords - otherPoint.coords) + if distance < (point.distance + otherPoint.distance) then + nearbyPoints[id] = otherPoint + end + end + end + + return nearbyPoints +end + +---Internal function that starts the loop. Do not call this function directly. +function Point.StartLoop() + if LoopStarted then return false end + LoopStarted = true + -- Remove the "local data = {}" line from here + CreateThread(function() + while LoopStarted do + local playerPed = PlayerPedId() + while playerPed == -1 do + Wait(100) + playerPed = PlayerPedId() + end + local playerCoords = GetEntityCoords(playerPed) + local targetsExist = false + local playerCellKey = Point.GetCellKey(playerCoords) + local nearbyCells = Point.GetNearbyCells(playerCoords) + + local playerSpeed = GetEntitySpeed(playerPed) + local maxWeight = 1000 + local waitTime = ADAPTIVE_WAIT and math.max(maxWeight/10, maxWeight - playerSpeed * maxWeight/10) or maxWeight + -- Process only points in nearby cells + for _, cellKey in ipairs(nearbyCells) do + if GridCells[cellKey] then + for id, point in pairs(GridCells[cellKey].points) do + targetsExist = true + + -- Update entity position if needed + local oldCellKey = point.cellKey + if point.isEntity then + point.coords = GetEntityCoords(point.target) + point.cellKey = Point.GetCellKey(point.coords) + Point.UpdateInGrid(point, oldCellKey) + end + local coords = point.coords and vector3(point.coords.x, point.coords.y, point.coords.z) or vector3(0, 0, 0) + local distance = #(playerCoords - coords) + --local distance = #(playerCoords - point.coords) + + -- Check if player entered/exited the point + if distance < point.distance then + if not point.inside then + point.inside = true + data[point.id] = data[point.id] or point.args or {} + data[point.id] = point.onEnter(point, data[point.id]) + insidePoints[point.id] = point + end + -- Modified main loop exit handler + elseif point.inside then + point.inside = false + data[point.id] = data[point.id] or point.args or {} + local result = point.onExit(point, data[point.id]) + data[point.id] = result ~= nil and result or data[point.id] -- ← Use consistent fallback + point.args = data[point.id] -- ← Update point.args to match data[point.id] + insidePoints[point.id] = nil + end + + if point.onNearby then + point.onNearby(GridCells[cellKey]?.points, waitTime) + end + end + end + end + + for id, insidepoint in pairs(insidePoints) do + local pos = insidepoint.coords and vector3(insidepoint.coords.x, insidepoint.coords.y, insidepoint.coords.z) or vector3(0, 0, 0) + local dist = #(playerCoords - pos) + if dist > insidepoint.distance then + insidepoint.inside = false + data[insidepoint.id] = data[insidepoint.id] or insidepoint.args or {} + local result = insidepoint.onExit(insidepoint, data[insidepoint.id]) + data[insidepoint.id] = result ~= nil and result or data[insidepoint.id] + insidepoint.args = data[insidepoint.id] -- ← Keep data in sync + insidePoints[insidepoint.id] = nil + end + end + Wait(waitTime) -- Faster updates when moving quickly + end + end) + return true +end + +---Create a point based on a vector or entityID +---@param id string +---@param target number || vector3 +---@param distance number +---@param _onEnter function +---@param _onExit function +---@param _onNearby function +---@param data self +---@return table +function Point.Register(id, target, distance, args, _onEnter, _onExit, _onNearby) + local isEntity = type(target) == "number" + local coords = isEntity and GetEntityCoords(target) or target + + local self = {} + self.id = id + self.target = target -- Store entity ID or Vector3 + self.isEntity = isEntity + self.coords = coords + self.distance = distance + self.onEnter = _onEnter or function() end + self.onExit = _onExit or function() end + self.onNearby = _onNearby or function() end + self.inside = false -- Track if player is inside + self.args = args or {} + + ActivePoints[id] = self + Point.RegisterInGrid(self) + Point.StartLoop() + return self +end + +---Remove an exsisting point by its id +---@param id string +function Point.Remove(id) + local point = ActivePoints[id] + if point then + local cellKey = point.cellKey + if GridCells[cellKey] and GridCells[cellKey].points[id] then + GridCells[cellKey].points[id] = nil + GridCells[cellKey].count = GridCells[cellKey].count - 1 + + if GridCells[cellKey].count <= 0 then + GridCells[cellKey] = nil + end + end + + ActivePoints[id] = nil + end +end + +---Returnes a point by its id +---@param id string +---@return table +function Point.Get(id) + return ActivePoints[id] +end + +---Returns all points +---@return table +function Point.GetAll() + return ActivePoints +end + +-- Usage example for checking nearby points +-- -- +-- ▀█▀ █▄█ █ ▄▀▀ █ ▄▀▀ █▀ █ █ ▄▀▀ █▄▀ █ █▄ █ ▄▀ █▄█ ▄▀▄ ▀█▀ █▀▄ ▄▀▄ █ █▄ █ ▀█▀ ▄▀▀ █▀ ▄▀▄ █▀▄ ▄▀▀ █▀▄ ▄▀▄ █ █ █ ██▀ ▀▄▀ +-- █ █ █ █ ▄█▀ █ ▄█▀ █▀ ▀▄█ ▀▄▄ █ █ █ █ ▀█ ▀▄█ █ █ ▀▄▀ █ ██ █▀ ▀▄▀ █ █ ▀█ █ ▄█▀ █▀ ▀▄▀ █▀▄ ▀▄▄ █▀▄ ▀▄▀ ▀▄▀▄▀ █▄▄ █▄▄ █ +--[[ +Point.Register("point1", vector3(100, 100, 30), 5.0, + function(point) + print("Entered point1") + end, + function(point) + print("Exited point1") + end, + function(nearbyPoints) + print("Point1 has nearby points:") + for id, point in pairs(nearbyPoints) do + print("- " .. id .. " at distance: " .. #(point.coords - ActivePoints["point1"].coords)) + end + end +) +--]] + +return Point \ No newline at end of file diff --git a/lib/client/raycast.lua b/lib/raycast/client/raycast.lua similarity index 98% rename from lib/client/raycast.lua rename to lib/raycast/client/raycast.lua index abc6bfe..f067f6e 100644 --- a/lib/client/raycast.lua +++ b/lib/raycast/client/raycast.lua @@ -3,12 +3,12 @@ Raycast = {} --Rework of oxs Raycast system function Raycast.GetForwardVector(rotation) local camRot = rotation or GetFinalRenderedCamRot(2) - + -- Convert each component to radians local rx = math.rad(camRot.x) local ry = math.rad(camRot.y) local rz = math.rad(camRot.z) - + -- Calculate sin and cos for each axis local sx = math.sin(rx) local cx = math.cos(rx) @@ -16,12 +16,12 @@ function Raycast.GetForwardVector(rotation) local cy = math.cos(ry) local sz = math.sin(rz) local cz = math.cos(rz) - + -- Create forward vector components local x = -sz * math.abs(cx) local y = cz * math.abs(cx) local z = sx - + return vector3(x, y, z) end @@ -34,7 +34,7 @@ function Raycast.ToCoords(startCoords, endCoords, flag, ignore) retval, entity, finalCoords, normals, material = GetShapeTestResultIncludingMaterial(probe) timeout = timeout - 1 Wait(0) - end + end return retval, entity, finalCoords, normals, material end diff --git a/lib/client/scaleform.lua b/lib/scaleform/client/scaleform.lua similarity index 100% rename from lib/client/scaleform.lua rename to lib/scaleform/client/scaleform.lua diff --git a/lib/shared/callbacks.lua b/lib/shared/callbacks.lua deleted file mode 100644 index 88a228a..0000000 --- a/lib/shared/callbacks.lua +++ /dev/null @@ -1,144 +0,0 @@ -Callbacks = {} -cbData = {} -Callback = Callback or {} - ---======================================= --- ▀█▀ █▄█ █ █▄ █ █▄▀ ▄▀▄ ██▄ ▄▀▄ █ █ ▀█▀ ▄▀▄ █▀▄ █▀▄ █ █▄ █ ▄▀ █▀▄ █▀▄ ▄▀▄ █▄ ▄█ █ ▄▀▀ ██▀ ▄▀▀ ▀█▀ ▄▀▄ ▄▀▀ ▄▀▄ █ █ ██▄ ▄▀▄ ▄▀▀ █▄▀ ▄▀▀ --- █ █ █ █ █ ▀█ █ █ █▀█ █▄█ ▀▄▀ ▀▄█ █ █▀█ █▄▀ █▄▀ █ █ ▀█ ▀▄█ █▀ █▀▄ ▀▄▀ █ ▀ █ █ ▄█▀ █▄▄ ▄█▀ █ ▀▄▀ ▀▄▄ █▀█ █▄▄ █▄▄ █▄█ █▀█ ▀▄▄ █ █ ▄█▀ ---======================================= - -local resource = GetCurrentResourceName() or 'unknown' - -local clientToServerName = resource .. ':server:CS:TriggerCallback' -local clientToServerBackToClientName = resource .. ':client:CSC:TriggerCallback' - - -local serverToClientName = resource .. ':client:SC:TriggerCallback' -local serverToClientBackToServerName = resource .. ':server:SCS:TriggerCallback' - - -exports('Callback', Callback) - -if not IsDuplicityVersion() then goto client end - --- -- -- -- -- -- -- -- -- -- --- ▄▀▀ ██▀ █▀▄ █ █ ██▀ █▀▄ --- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄ --- -- -- -- -- -- -- -- -- -- - - - --- client to server rebound -function Callback.Register(name, callback, all) - Callback[name] = { - callback = callback, - toAll = all - } -end - -RegisterNetEvent(clientToServerName, function(name, ...) - local src = source - local data = Callback[name] - if not data then return end - local func = data.callback - if not func then return end - local toAll = data.toAll and -1 or src - local cb = function(...) - TriggerClientEvent(clientToServerBackToClientName, toAll, name, ...) - end - func(src, cb, ...) -end) ------------------------------ - --- server to client rebound - -function Callback.Trigger(name, src, func, ...) - if src == nil then src = -1 end - local p = promise.new() - cbData[name] = {cb = func, p = p} - if type(src) == 'table' then - for i, d in pairs(src) do - TriggerClientEvent(serverToClientName, tonumber(d), name, ...) - end - return Citizen.Await(p) - end - TriggerClientEvent(serverToClientName, tonumber(src), name, ...) - return Citizen.Await(p) -end - -RegisterNetEvent(serverToClientBackToServerName, function(name, ...) - print('Rebound') - local data = cbData[name] - if not data then return end - local func = data.cb - if not func then return end - data.p:resolve(func(...) or true) - cbData[name] = nil -end) ------------------------------ -exports('RegisterCallback', Callback.Register) -exports('TriggerCallback', Callback.Trigger) - - --- -- -- -- -- -- -- -- -- -- --- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀ --- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █ --- -- -- -- -- -- -- -- -- -- -if IsDuplicityVersion() then return Callback end -::client:: - - -cbRebounds = {} -function Callback.Register(name, callback, all) - Callback[name] = { - callback = callback, - } -end - - -function Callback.RegisterRebound(name, callback) - cbRebounds[name] = callback -end - - --- client to server rebound -function Callback.Trigger(name, func, ...) - local p = promise.new() - TriggerServerEvent(clientToServerName, name, ...) - cbData[name] = {cb = func, p = p} - - return Citizen.Await(p) -end - -RegisterNetEvent(clientToServerBackToClientName, function(name, ...) - local clientRebound = cbRebounds[name] - if clientRebound then - clientRebound(...) - end - local data = cbData[name] - if not data then return end - local func = data.cb - if not func then return end - data.p:resolve(func(...) or true) - cbData[name] = nil -end) ------------------------------ - --- server to client rebound -RegisterNetEvent(serverToClientName, function(name, ...) - local data = Callback[name] - if not data then return end - local func = data.callback - if not func then return end - local cb = function(...) - TriggerServerEvent(serverToClientBackToServerName, name, ...) - end - func(cb, ...) -end) ------------------------------ - -exports('RegisterCallback', Callback.Register) -exports('RegisterRebound', Callback.RegisterRebound) -exports('TriggerCallback', Callback.Trigger) - -return Callback \ No newline at end of file diff --git a/lib/shared/rebound_entitiy_actions.lua b/lib/shared/rebound_entitiy_actions.lua deleted file mode 100644 index ba45e1f..0000000 --- a/lib/shared/rebound_entitiy_actions.lua +++ /dev/null @@ -1,35 +0,0 @@ -local ReboundEntities = ReboundEntities or Require("shared/rebound_entities.lua") -local Actions = Actions or Require("shared/actions.lua") -local LA = LA or Require("shared/la.lua") - -REA = {} - -if not IsDuplicityVersion() then goto client end - - - -if IsDuplicityVersion() then return end -::client:: - -local ActionsInProgress = {} - - -Action.Create("LerpToPosition", function(reboundId, start, position, duration, shouldRepeat, overrideStartTime) - local re = ReboundEntities.Get(reboundId) - assert(re, "Rebound entity not found") - local entity = re and re.entity - if not entity then return end - local startTime = GetGameTimer() - local endTime = overrideStartTime or startTime + duration - ActionsInProgress[reboundId] = {reboundId, start, position, duration, shouldRepeat, startTime} - local t = 0 - CreateThread(function() - while shouldRepeat or t < 1 do - t = (GetGameTimer() - startTime) / duration - local lerpPosition = LA.LerpVector(start, position, t) - SetEntityCoords(entity, lerpPosition) - Wait(0) - - end - end) -end) diff --git a/lib/server/sqlHandler.lua b/lib/sql/server/sqlHandler.lua similarity index 100% rename from lib/server/sqlHandler.lua rename to lib/sql/server/sqlHandler.lua diff --git a/lib/client/utility.lua b/lib/utility/client/utility.lua similarity index 58% rename from lib/client/utility.lua rename to lib/utility/client/utility.lua index d023f07..2b7f62f 100644 --- a/lib/client/utility.lua +++ b/lib/utility/client/utility.lua @@ -1,20 +1,43 @@ Utility = Utility or {} local blipIDs = {} local spawnedPeds = {} -local ActivePoints = {} +---commentThis will create a prop with the passed model string at the coords and heading specified optionally networked or not. +---@param model string | number +---@param coords table +---@param heading number +---@param networked boolean +---@return number | nil Utility.CreateProp = function(model, coords, heading, networked) Utility.LoadModel(model) - if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + if not HasModelLoaded(model) then return nil, Prints.Error("Model Has Not Loaded") end local propEntity = CreateObject(model, coords.x, coords.y, coords.z, networked, false, false) SetEntityHeading(propEntity, heading) SetModelAsNoLongerNeeded(model) return propEntity end +---This will get the street name and crossing name at the specified coordinates. +---@param coords table +---@return string +---@return string +Utility.GetStreetNameAtCoords = function(coords) + local streetHash, crossingHash = GetStreetNameAtCoord(coords.x, coords.y, coords.z) + local streetName = GetStreetNameFromHashKey(streetHash) + local crossingName = GetStreetNameFromHashKey(crossingHash) + return streetName, crossingName +end + +---This will create a vehicle with the passed model string at the coords and heading specified. +---@param model string +---@param coords table +---@param heading number +---@param networked boolean +---@return number| nil +---@return table Utility.CreateVehicle = function(model, coords, heading, networked) Utility.LoadModel(model) - if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + if not HasModelLoaded(model) then return nil, {}, Prints.Error("Model Has Not Loaded") end local vehicle = CreateVehicle(model, coords.x, coords.y, coords.z, heading, networked, false) SetVehicleHasBeenOwnedByPlayer(vehicle, true) SetVehicleNeedsToBeHotwired(vehicle, false) @@ -23,15 +46,24 @@ Utility.CreateVehicle = function(model, coords, heading, networked) return vehicle, { networkid = NetworkGetNetworkIdFromEntity(vehicle) or 0, coords = GetEntityCoords(vehicle), heading = GetEntityHeading(vehicle), } end +---This will create a ped with the passed model string at the coords and heading specified. +---@param model string +---@param coords table +---@param heading number +---@param networked boolean +---@return number| nil Utility.CreatePed = function(model, coords, heading, networked, settings) Utility.LoadModel(model) - if not HasModelLoaded(model) then return Prints.Error("Model Has Not Loaded") end + if not HasModelLoaded(model) then return nil, Prints.Error("Model Has Not Loaded") end local spawnedEntity = CreatePed(0, model, coords.x, coords.y, coords.z, heading, networked, false) SetModelAsNoLongerNeeded(model) table.insert(spawnedPeds, spawnedEntity) return spawnedEntity end +---This will display a busy spinner with the passed text. +---@param text string +---@return boolean Utility.StartBusySpinner = function(text) AddTextEntry(text, text) BeginTextCommandBusyString(text) @@ -40,6 +72,8 @@ Utility.StartBusySpinner = function(text) return true end +---This will stop a busy spinner if one is currently active. +---@return boolean Utility.StopBusySpinner = function() if BusyspinnerIsOn() then BusyspinnerOff() @@ -48,6 +82,15 @@ Utility.StopBusySpinner = function() return false end +---comment Creates a blip at the specified coordinates with the specified parameters. If sprite/color/scale/label are not provided, default values will be used. +---@param coords table +---@param sprite number +---@param color number +---@param scale number +---@param label string +---@param shortRange boolean +---@param displayType number +---@return integer Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange, displayType) local blip = AddBlipForCoord(coords.x, coords.y, coords.z) SetBlipSprite(blip, sprite or 8) @@ -62,6 +105,9 @@ Utility.CreateBlip = function(coords, sprite, color, scale, label, shortRange, d return blip end +---This will remove a blip if it exists in the blipIDs table. +---@param blip number +---@return boolean Utility.RemoveBlip = function(blip) local success = false for i, storedBlip in ipairs(blipIDs) do @@ -75,6 +121,9 @@ Utility.RemoveBlip = function(blip) return success end +---Loads a model into memory. If the model is not valid or not in the game files, it will return false. +---@param model string | number +---@return boolean Utility.LoadModel = function(model) if type(model) ~= 'number' then model = joaat(model) end if not IsModelValid(model) and not IsModelInCdimage(model) then return false end @@ -87,6 +136,9 @@ Utility.LoadModel = function(model) return HasModelLoaded(model) end +---This function will request an animation dictionary and wait until it is loaded. If the dictionary is not valid, it will return false. +---@param dict string +---@return boolean Utility.RequestAnimDict = function(dict) RequestAnimDict(dict) local count = 0 @@ -97,6 +149,9 @@ Utility.RequestAnimDict = function(dict) return HasAnimDictLoaded(dict) end +---This will remove a ped if it exists in the spawnedPeds table. It will also delete the entity if it exists. +---@param entity number +---@return boolean Utility.RemovePed = function(entity) local success = false if DoesEntityExist(entity) then @@ -112,6 +167,10 @@ Utility.RemovePed = function(entity) return success end +---This will use a native text input menu to allow the user to enter text. It will return the entered text or false if cancelled. +---@param text string +---@param length number +---@return string Utility.NativeInputMenu = function(text, length) local maxLength = Math.Clamp(length, 1, 50) local menutText = text or 'enter text' @@ -128,6 +187,9 @@ Utility.NativeInputMenu = function(text, length) return false end +---This will get the current skin data of the entity passed. It will return a table with the clothing and props data. +---@param entity number +---@return table Utility.GetEntitySkinData = function(entity) local skinData = {} for i = 0, 11 do @@ -139,6 +201,10 @@ Utility.GetEntitySkinData = function(entity) return skinData end +---This will set the skin data of the entity passed. It will set the clothing and props data from the skinData table. +---@param entity number +---@param skinData table +---@return boolean Utility.SetEntitySkinData = function(entity, skinData) for i = 0, 11 do SetPedComponentVariation(entity, i, skinData.clothing[i][1], skinData.clothing[i][2], 0) @@ -149,6 +215,8 @@ Utility.SetEntitySkinData = function(entity, skinData) return true end +---This will reload the skin data of the entity passed. It will set the clothing and props data from the skinData table and delete any attached objects. +---@return boolean Utility.ReloadSkin = function() local skinData = Utility.GetEntitySkinData(cache.ped) Utility.SetEntitySkinData(cache.ped, skinData) @@ -162,18 +230,47 @@ Utility.ReloadSkin = function() return true end +---This will display a native help text on the screen. It will add a text entry and display it for the specified duration. +---@param text string +---@param duration number Utility.HelpText = function(text, duration) AddTextEntry(text, text) BeginTextCommandDisplayHelp(text) EndTextCommandDisplayHelp(0, false, true, duration or 5000) end +---This will display 3D help text at the specified coordinates. +---@param coords table +---@param text string +---@param scale number +Utility.Draw3DHelpText = function(coords, text, scale) + local onScreen, x, y = GetScreenCoordFromWorldCoord(coords.x, coords.y, coords.z) + if onScreen then + SetTextScale(scale or 0.35, scale or 0.35) + SetTextFont(4) + SetTextProportional(1) + SetTextColour(255, 255, 255, 215) + SetTextEntry("STRING") + SetTextCentre(1) + AddTextComponentString(text) + DrawText(x, y) + local factor = (string.len(text)) / 370 + DrawRect(x, y + 0.0125, 0.015 + factor, 0.03, 41, 11, 41, 100) + end +end + +---This will display a native help text on the screen. It will add a text entry and display it for the specified duration. +---@param text string Utility.NotifyText = function(text) AddTextEntry(text, text) SetNotificationTextEntry(text) DrawNotification(false, true) end +---This will teleport a player to the specified coordinates. If a condition function is passed it will verify that condition is met and then it will fade the screen out and in, freeze the player during the teleport to allow for collisions to load, and call the afterTeleportFunction if provided. +---@param coords table +---@param conditionFunction function | optional +---@param afterTeleportFunction function | optional Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFunction) if conditionFunction ~= nil then if not conditionFunction() then @@ -200,11 +297,21 @@ Utility.TeleportPlayer = function(coords, conditionFunction, afterTeleportFuncti end end +---This will get a model hash from a string or number. +---@param model string | number +---@return number Utility.GetEntityHashFromModel = function(model) if type(model) ~= 'number' then model = joaat(model) end return model end +---commentThis will get the closest player, the distance to that player from the coords and the server ID of that player. +---@param coords table +---@param distanceScope number +---@param includeMe boolean +---@return integer +---@return integer +---@return integer Utility.GetClosestPlayer = function(coords, distanceScope, includeMe) local players = GetActivePlayers() local closestPlayer = 0 @@ -227,7 +334,7 @@ Utility.GetClosestPlayer = function(coords, distanceScope, includeMe) return closestPlayer, closestDistance, GetPlayerServerId(closestPlayer) end ----This function is used to register a point on the map, functions are fired when in the distance/exiting the area +---This function is is deprecated and will be removed in the future. Please use Pont.Register instead. ---@param pointID string ---@param pointCoords table ---@param pointDistance number @@ -235,39 +342,26 @@ end ---@param _onExit function ---@param _nearby function Utility.RegisterPoint = function(pointID, pointCoords, pointDistance, _onEnter, _onExit, _nearby) - ActivePoints[pointID] = lib.points.new({ - coords = pointCoords, - distance = pointDistance, - onEnter = function(self) - _onEnter(self) - end, - onExit = function(self) - _onExit(self) - end, - nearby = function(self) - _nearby(self) - end - }) + return Point.Register(pointID, pointCoords, pointDistance, nil, _onEnter, _onExit, _nearby) end --- Function to retrieve the zone by the pointID +---This function is is deprecated and will be removed in the future. Please use Point.Get instead. ---@param pointID string Utility.GetPointById = function(pointID) - return ActivePoints[pointID] + return Point.Get(pointID) end +---This function is is deprecated and will be removed in the future. Please use Point.GetAll instead. ---@return table | nil Utility.GetActivePoints = function() - return ActivePoints + return Point.GetAll() end ----Pass the point ID to remove the point from the map + +---This function is is deprecated and will be removed in the future. Please use Point.Remove instead. ---@param pointID string ----@return boolean +---@return nil Utility.RemovePoint = function(pointID) - if not ActivePoints[pointID] then return false end - ActivePoints[pointID]:remove() - ActivePoints[pointID] = nil - return true + return Point.Remove(pointID) end AddEventHandler('onResourceStop', function(resource) diff --git a/lib/utility/shared/cache.lua b/lib/utility/shared/cache.lua new file mode 100644 index 0000000..e69de29 diff --git a/lib/utility/shared/callbacks.lua b/lib/utility/shared/callbacks.lua new file mode 100644 index 0000000..f0b7965 --- /dev/null +++ b/lib/utility/shared/callbacks.lua @@ -0,0 +1,197 @@ +Callbacks = {} +cbData = {} +Callback = Callback or {} + +--======================================= +-- ▀█▀ █▄█ █ █▄ █ █▄▀ ▄▀▄ ██▄ ▄▀▄ █ █ ▀█▀ ▄▀▄ █▀▄ █▀▄ █ █▄ █ ▄▀ █▀▄ █▀▄ ▄▀▄ █▄ ▄█ █ ▄▀▀ ██▀ ▄▀▀ ▀█▀ ▄▀▄ ▄▀▀ ▄▀▄ █ █ ██▄ ▄▀▄ ▄▀▀ █▄▀ ▄▀▀ +-- █ █ █ █ █ ▀█ █ █ █▀█ █▄█ ▀▄▀ ▀▄█ █ █▀█ █▄▀ █▄▀ █ █ ▀█ ▀▄█ █▀ █▀▄ ▀▄▀ █ ▀ █ █ ▄█▀ █▄▄ ▄█▀ █ ▀▄▀ ▀▄▄ █▀█ █▄▄ █▄▄ █▄█ █▀█ ▀▄▄ █ █ ▄█▀ +--======================================= + +local resource = GetCurrentResourceName() or 'unknown' + +local clientToServerName = resource .. ':server:CS:TriggerCallback' +local clientToServerBackToClientName = resource .. ':client:CSC:TriggerCallback' + +local serverToClientName = resource .. ':client:SC:TriggerCallback' +local serverToClientBackToServerName = resource .. ':server:SCS:TriggerCallback' + +exports('Callback', Callback) + +if not IsDuplicityVersion() then goto client end + +-- -- -- -- -- -- -- -- -- -- +-- ▄▀▀ ██▀ █▀▄ █ █ ██▀ █▀▄ +-- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄ +-- -- -- -- -- -- -- -- -- -- + +-- client to server rebound +function Callback.Register(name, callback, all) + Callback[name] = { + callback = callback, + toAll = all + } +end + +-- Handle client requests and send response back to client(s) +RegisterNetEvent(clientToServerName, function(name, cbId, ...) + local src = source + local data = Callback[name] + if not data then return end + local func = data.callback + if not func then return end + local toAll = data.toAll and -1 or src + + -- Create response handler + local packed = table.pack(func(src, ...)) + TriggerClientEvent(clientToServerBackToClientName, toAll, name, cbId, table.unpack(packed)) +end) + +-- Server to client trigger function - supports both callback and direct return +function Callback.Trigger(name, src, callbackOrArg, ...) + if src == nil then src = -1 end + + -- Determine if the third parameter is a callback function or an argument + local hasCallback = type(callbackOrArg) == 'function' or (type(callbackOrArg) == 'table' and rawget(callbackOrArg, '__cfx_functionReference')) + local callback = hasCallback and callbackOrArg or nil + -- Adjust args based on whether the callback is present + local args = hasCallback and {...} or {callbackOrArg, ...} + + local cbId = name .. '_' .. math.random(1000000, 9999999) + local p = promise.new() + + -- Store promise data + cbData[cbId] = { + cb = callback, + p = p + } + + -- Trigger for single player or multiple players + if type(src) == 'table' then + for i, d in pairs(src) do + TriggerClientEvent(serverToClientName, tonumber(d), name, cbId, table.unpack(args)) + end + else + TriggerClientEvent(serverToClientName, tonumber(src), name, cbId, table.unpack(args)) + end + + -- If no callback was provided, wait for the promise and return directly + + local result = Citizen.Await(p) + -- If there's only one value, return it directly + if #result == 1 then + return result[1] + else + return table.unpack(result or {}) + end + +end + +-- Handle responses to server requests +RegisterNetEvent(serverToClientBackToServerName, function(name, cbId, ...) + local data = cbData[cbId] + if not data then return end + + -- Process callback if provided + + if data.cb then + data.cb({...}) + end + -- Always resolve the promise with all args for direct returns + data.p:resolve({...}) + cbData[cbId] = nil +end) + +exports('RegisterCallback', Callback.Register) +exports('TriggerCallback', Callback.Trigger) + +-- -- -- -- -- -- -- -- -- -- +-- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀ +-- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █ +-- -- -- -- -- -- -- -- -- -- +if IsDuplicityVersion() then return Callback end +::client:: + +cbRebounds = {} +function Callback.Register(name, callback) + Callback[name] = { + callback = callback, + } +end + +function Callback.RegisterRebound(name, callback) + cbRebounds[name] = callback +end + +-- Client to server trigger - supports both callback and direct return +function Callback.Trigger(name, callbackOrArg, ...) + -- Determine if the second parameter is a callback function or an argument + local hasCallback = type(callbackOrArg) == 'function' or (type(callbackOrArg) == 'table' and rawget(callbackOrArg, '__cfx_functionReference')) + local callback = hasCallback and callbackOrArg or nil + -- Adjust args based on whether the callback is present + local args = hasCallback and {...} or {callbackOrArg, ...} + + local cbId = name .. '_' .. math.random(1000000, 9999999) + local p = promise.new() + + -- Store promise data + cbData[cbId] = { + cb = callback, + p = p + } + + -- Trigger the server event + TriggerServerEvent(clientToServerName, name, cbId, table.unpack(args)) + + -- If no callback was provided, wait for the promise and return directly + if not hasCallback then + local result = Citizen.Await(p) + -- If there's only one value, return it directly + if #result == 1 then + return result[1] + else + return table.unpack(result) + end + end + + -- Otherwise, return nothing (callback will handle it) + return nil +end + +-- Handle responses from server +RegisterNetEvent(clientToServerBackToClientName, function(name, cbId, ...) + -- Check for global rebounding callbacks + local clientRebound = cbRebounds[name] + if clientRebound then + clientRebound(...) + end + + -- Handle the specific callback instance + local data = cbData[cbId] + if not data then return end + + -- Process callback if provided + if data.cb then + data.cb(...) + end + + -- Always resolve the promise with all args for direct returns + data.p:resolve({...}) + cbData[cbId] = nil +end) + +-- Handle server requests to client +RegisterNetEvent(serverToClientName, function(name, cbId, ...) + local data = Callback[name] + if not data then return end + local func = data.callback + if not func then return end + + -- Create response handler + TriggerServerEvent(serverToClientBackToServerName, name, cbId, func(...)) +end) + +exports('RegisterCallback', Callback.Register) +exports('RegisterRebound', Callback.RegisterRebound) +exports('TriggerCallback', Callback.Trigger) + +return Callback \ No newline at end of file diff --git a/lib/shared/ids.lua b/lib/utility/shared/ids.lua similarity index 67% rename from lib/shared/ids.lua rename to lib/utility/shared/ids.lua index 3091b9b..f0ae840 100644 --- a/lib/shared/ids.lua +++ b/lib/utility/shared/ids.lua @@ -1,5 +1,11 @@ Ids = Ids or {} --- for unique ids + + +---This will generate a unique id. +---@param tbl table +---@param len number +---@param pattern string +---@return string Ids.CreateUniqueId = function(tbl, len, pattern) -- both optional tbl = tbl or {} -- table to check uniqueness. Ids to check against must be the key to the tables value len = len or 8 @@ -21,22 +27,43 @@ Ids.CreateUniqueId = function(tbl, len, pattern) -- both optional return id end + +---This will generate a unique id. +---@param tbl table +---@param len number +---@return string Ids.RandomUpper = function(tbl, len) return Ids.CreateUniqueId(tbl, len, "ABCDEFGHIJKLMNOPQRSTUVWXYZ") end +---This will generate a unique id. +---@param tbl table +---@param len number +---@return string Ids.RandomLower = function(tbl, len) return Ids.CreateUniqueId(tbl, len, "abcdefghijklmnopqrstuvwxyz") end +---This will generate a unique id. +---@param tbl table +---@param len number +---@return string Ids.RandomString = function(tbl, len) return Ids.CreateUniqueId(tbl, len, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ") end +---This will generate a unique id. +---@param tbl table +---@param len number +---@return string Ids.RandomNumber = function(tbl, len) return Ids.CreateUniqueId(tbl, len, "0123456789") end +---This will generate a unique id. +---@param tbl table +---@param len number +---@return string Ids.Random = function(tbl, len) return Ids.CreateUniqueId(tbl, len) end diff --git a/lib/shared/la.lua b/lib/utility/shared/la.lua similarity index 100% rename from lib/shared/la.lua rename to lib/utility/shared/la.lua diff --git a/lib/shared/math.lua b/lib/utility/shared/math.lua similarity index 100% rename from lib/shared/math.lua rename to lib/utility/shared/math.lua diff --git a/lib/shared/perlin.lua b/lib/utility/shared/perlin.lua similarity index 100% rename from lib/shared/perlin.lua rename to lib/utility/shared/perlin.lua diff --git a/lib/shared/prints.lua b/lib/utility/shared/prints.lua similarity index 56% rename from lib/shared/prints.lua rename to lib/utility/shared/prints.lua index 2fc00ef..6b73522 100644 --- a/lib/shared/prints.lua +++ b/lib/utility/shared/prints.lua @@ -6,18 +6,27 @@ local function printMessage(level, color, message) print(color .. '[' .. level .. ']:', message) end + +---This will print a colored message to the console with the designated prefix. +---@param message string Prints.Info = function(message) printMessage('INFO', '^5', message) end +---This will print a colored message to the console with the designated prefix. +---@param message string Prints.Warn = function(message) printMessage('WARN', '^3', message) end +---This will print a colored message to the console with the designated prefix. +---@param message string Prints.Error = function(message) printMessage('ERROR', '^1', message) end +---This will print a colored message to the console with the designated prefix. +---@param message string Prints.Debug = function(message) printMessage('DEBUG', '^2', message) end diff --git a/lib/shared/rebound_entities.lua b/lib/utility/shared/rebound_entities.lua similarity index 100% rename from lib/shared/rebound_entities.lua rename to lib/utility/shared/rebound_entities.lua diff --git a/lib/utility/shared/rebound_entitiy_actions.lua b/lib/utility/shared/rebound_entitiy_actions.lua new file mode 100644 index 0000000..552bd8f --- /dev/null +++ b/lib/utility/shared/rebound_entitiy_actions.lua @@ -0,0 +1,35 @@ +-- local ReboundEntities = ReboundEntities or Require("shared/rebound_entities.lua") +-- local Actions = Actions or Require("shared/actions.lua") +-- local LA = LA or Require("shared/la.lua") + +-- REA = {} + +-- if not IsDuplicityVersion() then goto client end + + + +-- if IsDuplicityVersion() then return end +-- ::client:: + +-- local ActionsInProgress = {} + + +-- Action.Create("LerpToPosition", function(reboundId, start, position, duration, shouldRepeat, overrideStartTime) +-- local re = ReboundEntities.Get(reboundId) +-- assert(re, "Rebound entity not found") +-- local entity = re and re.entity +-- if not entity then return end +-- local startTime = GetGameTimer() +-- local endTime = overrideStartTime or startTime + duration +-- ActionsInProgress[reboundId] = {reboundId, start, position, duration, shouldRepeat, startTime} +-- local t = 0 +-- CreateThread(function() +-- while shouldRepeat or t < 1 do +-- t = (GetGameTimer() - startTime) / duration +-- local lerpPosition = LA.LerpVector(start, position, t) +-- SetEntityCoords(entity, lerpPosition) +-- Wait(0) + +-- end +-- end) +-- end) diff --git a/lib/shared/tables.lua b/lib/utility/shared/tables.lua similarity index 94% rename from lib/shared/tables.lua rename to lib/utility/shared/tables.lua index 26c5888..6feeb1a 100644 --- a/lib/shared/tables.lua +++ b/lib/utility/shared/tables.lua @@ -46,6 +46,14 @@ Table.TableContainsKey = function(tbl, search) return false end +Table.TableGetKeys = function(tbl) + local keys = {} + for k ,_ in pairs(tbl) do + table.insert(keys,k) + end + return keys +end + Table.GetClosest = function(coords, tbl) local closestPoint = nil local dist = math.huge diff --git a/locales/en.json b/locales/en.json index 6b04803..fef60d1 100644 --- a/locales/en.json +++ b/locales/en.json @@ -1,16 +1,45 @@ { - "locale-unit-test": "This is a test string", - "place_object_place": "[E] Place \n", - "place_object_cancel": "[X] Cancel \n", - "place_object_scroll_up": "[SCROLL UP] Turn right \n", - "place_object_scroll_down": "[SCROLL DOWN] Turn left", - "enter_text": "Enter Text", - "no_prop_defined": "You didnt define any object to place", - "Shops": {"NotEnoughMoney": "You dont have enough money to buy this item", "Input":"Amount Input", "PurchaseAmount":"Purchase Quanity","PurchasedItem": "You Have Purchased ", "CurrencySymbol": "$", "Confirm":"Confirm Purchase","AreYouSure":"Are you sure you want to purchase a ", "PayByCash": "Pay by cash", "PayByCard": "Pay by card" }, + "locale-unit-test": "This is a test string", + "place_object_place": "[E] Place \n", + "place_object_cancel": "[X] Cancel \n", + "place_object_scroll_up": "[SCROLL UP] Turn right \n", + "place_object_scroll_down": "[SCROLL DOWN] Turn left", + "enter_text": "Enter Text", + "no_prop_defined": "You didnt define any object to place", + "Shops": { + "NotEnoughMoney": "You dont have enough money to buy this item", + "Input": "Amount Input", + "PurchaseAmount": "Purchase Quanity", + "PurchasedItem": "You Have Purchased ", + "CurrencySymbol": "$", + "Confirm": "Confirm Purchase", + "AreYouSure": "Are you sure you want to purchase a ", + "PayByCash": "Pay by cash", + "PayByCard": "Pay by card" + }, + "UNITTEST": { + "UNITTESTA": "Im a %s %s", "UNITTEST": { - "UNITTESTA": "Im a %s %s", - "UNITTEST": { - "UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #" - } - } -} \ No newline at end of file + "UNITTESTA": "\n.-._ _,-,\n`._`-._ _,-'_,'\n `._ `-._ _,-' _,'\n `._ `-._ __.-----.__ _,-' _,'\n `._ `#===\\\"\\\"\\\" \\\"\\\"\\\"===#' _,'\n `._/) ._ _. (\\_,'\n )*' **.__ __.** '*(\n # .==..__ \\\"\\\" \\\"\\\" __..==, #\n # `\\\"._(_). .(_)_.\\\"' #" + } + }, + "accessibility": { + "cb_command": "colourblindness", + "cb_title": "Colourblindness Options", + "cb_desc": "Select your type of colourblindness\nCurrent Colourblindness: %s", + "cb_none": "None", + "cb_updated": "Colourblindness has been updated to %s", + "cb_default_title": "No Colourblindness", + "cb_default_desc": "No colourblindness.\nThis is the default option.", + "cb_protanomaly_title": "Protanomaly", + "cb_protanomaly_desc": "Red-green color blindness.\nMakes certain shades of red look more green and less bright.\nThis type is mild and usually doesn’t get in the way of normal activities.", + "cb_deuteranomaly_title": "Deuteranomaly", + "cb_deuteranomaly_desc": "Red-green color blindness.\nIt makes certain shades of green look more red.\nThis type is mild and doesn’t usually get in the way of normal activities.", + "cb_dual_title": "Protanopia and Deuteranopia", + "cb_dual_desc": "Red-green color blindness.\nMakes someone unable to tell the difference between red and green at all.", + "cb_tritanopia_title": "Tritanopia", + "cb_tritanopia_desc": "Blue-yellow color blindness that makes someone unable to tell the difference between blue and green, purple and red, and yellow and pink.\nIt also makes colors look less bright.", + "cb_tritanomaly_title": "Tritanomaly", + "cb_tritanomaly_desc": "Blue-yellow color blindness makes it hard to tell the difference between blue and green and between yellow and red." + } +} diff --git a/locales/pt.json b/locales/pt.json index 498a81f..2c5e0a8 100644 --- a/locales/pt.json +++ b/locales/pt.json @@ -5,5 +5,24 @@ "place_object_scroll_up": "[SCROLL UP] Direita\n", "place_object_scroll_down": "[SCROLL DOWN] Esquerda", "enter_text": "Inserir Texto", - "no_prop_defined": "Não definiu nenhum objeto para colocar" + "no_prop_defined": "Não definiu nenhum objeto para colocar", + "accessibility": { + "cb_command": "daltônico", + "cb_title": "Opções de daltonismo", + "cb_desc": "Selecione seu tipo de daltonismo\nDaltonismo atual: %s", + "cb_none": "Nenhum", + "cb_updated": "O daltonismo foi atualizado para %s", + "cb_default_title": "Sem daltonismo", + "cb_default_desc": "Sem daltonismo.\nEsta é a opção padrão.", + "cb_protanomaly_title": "Protanomalia", + "cb_protanomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de vermelho pareçam mais verdes e menos brilhantes.\nEste tipo é leve e geralmente não atrapalha as atividades normais.", + "cb_deuteranomaly_title": "Deuteranomalia", + "cb_deuteranomaly_desc": "Daltonismo vermelho-verde.\nFaz com que certos tons de verde pareçam mais vermelhos.\nEste tipo é leve e geralmente não atrapalha as atividades normais.", + "cb_dual_title": "Protanopia e Deuteranopia", + "cb_dual_desc": "Daltonismo vermelho-verde.\nFaz com que alguém não consiga distinguir entre vermelho e verde.", + "cb_tritanopia_title": "Tritanopia", + "cb_tritanopia_desc": "Daltonismo azul-amarelo que faz com que alguém não consiga distinguir a diferença entre azul e verde, roxo e vermelho, e amarelo e rosa.\nTambém faz com que as cores pareçam menos brilhantes.", + "cb_tritanomaly_title": "Tritanomalia", + "cb_tritanomaly_desc": "O daltonismo azul-amarelo dificulta a distinção entre azul e verde e entre amarelo e vermelho.", + } } \ No newline at end of file diff --git a/modules/accessibility/client.lua b/modules/accessibility/client.lua new file mode 100644 index 0000000..a284ca6 --- /dev/null +++ b/modules/accessibility/client.lua @@ -0,0 +1,210 @@ +local colourblind = GetResourceKvpString('colourblind') or "default" +local QB = false +if (BridgeClientConfig.MenuSystem == "auto" and GetResourceState("qb-menu") ~= "started") or (BridgeClientConfig.MenuSystem ~= "auto" and BridgeClientConfig.MenuSystem == "qb-menu") then + QB = true +end + +Accessibility = Accessibility or {} + +RegisterCommand(locale("accessibility.cb_command"), function() + Accessibility.updatecolourblindness() +end, false) + +Accessibility.updatecolourblindness = function() + local currentCB = locale("accessibility.cb_"..colourblind.."_title") + local cbIcon = "fas fa-eye-low-vision" + Menu.Open({ + id = 'colourblind_update', + title = locale("accessibility.cb_title"), + options = { + { + title = locale("accessibility.cb_title"), + description = locale("accessibility.cb_desc"):format(currentCB), + disabled = true, + }, + { + title = locale("accessibility.cb_default_title"), + description = locale("accessibility.cb_default_desc"), + icon = "fas fa-eye", + onSelect = function() + colourblind = "default" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_protanomaly_title"), + description = locale("accessibility.cb_protanomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "protanomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_deuteranomaly_title"), + description = locale("accessibility.cb_deuteranomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "deuteranomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale('accessibility.cb_dual_title'), + description = locale("accessibility.cb_dual_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "dual" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_tritanopia_title"), + description = locale("accessibility.cb_tritanopia_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "tritanopia" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + { + title = locale("accessibility.cb_tritanomaly_title"), + description = locale("accessibility.cb_tritanomaly_desc"), + icon = cbIcon, + onSelect = function() + colourblind = "tritanomaly" + SetResourceKvp('colourblind', colourblind) + Notify.SendNotify(locale("accessibility.cb_updated"):format(locale("accessibility.cb_"..colourblind.."_title")), 'success', 3000) + end + }, + }},QB) +end +Accessibility.hexToRgb = function(hex) + hex = hex:gsub("#", "") + local r,g,b = tonumber("0x" .. hex:sub(1, 2)),tonumber("0x" .. hex:sub(3, 4)),tonumber("0x" .. hex:sub(5, 6)) + return r, g, b +end + +Accessibility.rgbToHex = function(r, g, b) + return string.format("#%02x%02x%02x", r, g, b) +end + +Accessibility.rgbToHsl = function(r, g, b) + r = r / 255 + g = g / 255 + b = b / 255 + local max = math.max(r, g, b) + local min = math.min(r, g, b) + local h, s, l = 0, 0, (max + min) / 2 + + if max == min then + h, s = 0, 0 -- achromatic + else + local d = max - min + s = l > 0.5 and d / (2 - max - min) or d / (max + min) + if max == r then + h = (g - b) / d + (g < b and 6 or 0) + elseif max == g then + h = (b - r) / d + 2 + elseif max == b then + h = (r - g) / d + 4 + end + h = h / 6 + end + return h, s, l +end + +Accessibility.hslToRgb = function(h, s, l) + local r, g, b + if s == 0 then + r, g, b = l, l, l -- achromatic + else + local function hue2rgb(p, q, t) + if t < 0 then t = t + 1 end + if t > 1 then t = t - 1 end + if t < 1 / 6 then return p + (q - p) * 6 * t end + if t < 1 / 2 then return q end + if t < 2 / 3 then return p + (q - p) * (2 / 3 - t) * 6 end + return p + end + + local q = l < 0.5 and l * (1 + s) or l + s - l * s + local p = 2 * l - q + r = hue2rgb(p, q, h + 1 / 3) + g = hue2rgb(p, q, h) + b = hue2rgb(p, q, h - 1 / 3) + end + return math.floor(r * 255), math.floor(g * 255), math.floor(b * 255) +end + +Accessibility.adjustColourForColourblindness = function(num, returnAsRGB) + local r, g, b + if type(num) ~= "table" and num:match("^#%x%x%x%x%x%x$") then + r, g, b = Accessibility.hexToRgb(num) -- Convert hex to RGB + else + r, g, b = num.r, num.g, num.b -- If it's already RGB, use it directly + end + local h, s, l = Accessibility.rgbToHsl(r, g, b) -- Convert RGB to HSL + -- Adjust hue values based on colourblindness type + if colourblind == "protanomaly" then -- Red-blind + -- Shift towards blue/cyan + h = (h + 0.5) % 1 -- Shift by 180 degrees + elseif colourblind == "deuteranomaly" then -- Green-blind + -- Shift towards blue/magenta + h = (h + 0.33) % 1 -- Shift by 120 degrees + elseif colourblind == "dual" then -- Protanopia and Deuteranopia (Red-Green blind) + -- More significant shift towards blue/yellow + -- This is a more drastic shift to maximize contrast + if h < 0.166 then -- Reddish hues + h = 0.66 -- Shift to blue + elseif h < 0.5 then -- Greenish hues + h = 0.166 -- Shift to yellow + else + h = h -- Leave blue/purple hues alone + end + -- Increase saturation and lightness to make colours more distinct + s = math.min(s * 1.5, 1) + l = math.min(l * 1.2, 1) + elseif colourblind == "tritanopia" then -- Blue-blind + -- Shift towards red/yellow + h = (h + 0.16) % 1 -- Shift by 60 degrees + elseif colourblind == "tritanomaly" then + h = (h + 0.08) % 1 + end + + -- Convert back to RGB + r, g, b = Accessibility.hslToRgb(h, s, l) + if returnAsRGB then + return {r = r, g = g, b = b} + else + -- Convert back to HEX + local newHex = Accessibility.rgbToHex(r, g, b) + return newHex + end +end + +---@returns a colour adjusted for colourblindness in HEX if variable `returnAsRGB` is false +---@param colourName string Colour name in HEX format or RGB format +-- This is the trigger function for altering colours for colourblindness :D +Accessibility.getAdjustedColour = function(colourName, returnAsRGB) + local originalHex = colourName + if originalHex then + if colourblind == "default" then + if type(colourName) == "table" and not returnAsRGB then + return Accessibility.rgbToHex(colourName.r, colourName.g, colourName.b) + else + return originalHex + end + else + return Accessibility.adjustColourForColourblindness(originalHex, returnAsRGB) + end + else + Prints.Error("Invalid Colour Name^0] [^3"..colourName.."^0") + return "#FFFFFF" -- Default to white if the colour name is invalid + end +end \ No newline at end of file diff --git a/modules/clothing/_default/client.lua b/modules/clothing/_default/client.lua index 9d72391..bd35793 100644 --- a/modules/clothing/_default/client.lua +++ b/modules/clothing/_default/client.lua @@ -1,22 +1,34 @@ +--[[This module is incomplete]]-- + Clothing = Clothing or {} ClothingBackup = {} + +---This will set the peds skin data to the specified table. It will also store previous skin in the event it needs returned to original. +---@param data table +---@return boolean Clothing.SetAppearance = function(data) ClothingBackup = Clothing.GetAppearance() Utility.SetEntitySkinData(cache.ped, data) return true end +---This will return a table of the players ped appearance +---@return table Clothing.GetAppearance = function() return Utility.GetEntitySkinData(cache.ped) end +---This will return the peds clothing to the previously stored clothing +---@return boolean Clothing.RestoreAppearance = function() Utility.SetEntitySkinData(cache.ped, ClothingBackup) return true end +---This will reload the peds skin data from the backup table. This is used when the skin data is changed and needs to be reloaded. +---@return boolean Clothing.ReloadSkin = function() Utility.SetEntitySkinData(cache.ped, ClothingBackup) return true diff --git a/modules/clothing/_default/server.lua b/modules/clothing/_default/server.lua index 2ec1460..8689800 100644 --- a/modules/clothing/_default/server.lua +++ b/modules/clothing/_default/server.lua @@ -1,3 +1,5 @@ +--[[This module is incomplete]]-- + Clothing = Clothing or {} Clothing.SetAppearance = function(src, data) @@ -13,8 +15,6 @@ Clothing.ReloadSkin = function(src) end - - RegisterNetEvent('community_bridge:client:SetAppearance', function(data) Clothing.SetAppearance(data) end) diff --git a/modules/clothing/esx_skin/client.lua b/modules/clothing/esx_skin/client.lua deleted file mode 100644 index d3261e0..0000000 --- a/modules/clothing/esx_skin/client.lua +++ /dev/null @@ -1,142 +0,0 @@ -if GetResourceState('esx_skin') ~= 'started' then return end - -Clothing = Clothing or {} - -local clothingData = { - male = { - components = { - face = {component_id = 0, texture = 0, drawable = 2}, - mask = {component_id = 1, texture = 0, drawable = 2}, - hair = {component_id = 2, texture = 0, drawable = 2}, - arms = {component_id = 3, texture = 0, drawable = 2}, - pants = {component_id = 4, texture = 0, drawable = 22}, - bag = {component_id = 5, texture = 1, drawable = 33}, - shoes = {component_id = 6, texture = 1, drawable = 33}, - accessory = {component_id = 7, texture = 1, drawable = 33}, - shirt = {component_id = 8, texture = 1, drawable = 11}, - bodyarmor = {component_id = 9, texture = 1, drawable = 33}, - decals = {component_id = 10, texture = 1, drawable = 33}, - jacket = {component_id = 11, texture = 2, drawable = 4}, - }, - props = { - hats = {prop_id = 0, texture = 2, drawable = 4}, - glasses = {prop_id = 1, texture = 2, drawable = 4}, - ears = {prop_id = 2, texture = 2, drawable = 4}, - watches = {prop_id = 6, texture = 2, drawable = 4}, - bracelets = {prop_id = 7, texture = 2, drawable = 4}, - } - }, - female = { - components = { - face = {component_id = 0, texture = 0, drawable = 2}, - mask = {component_id = 1, texture = 0, drawable = 2}, - hair = {component_id = 2, texture = 0, drawable = 2}, - arms = {component_id = 3, texture = 0, drawable = 2}, - pants = {component_id = 4, texture = 0, drawable = 22}, - bag = {component_id = 5, texture = 1, drawable = 33}, - shoes = {component_id = 6, texture = 1, drawable = 33}, - accessory = {component_id = 7, texture = 1, drawable = 33}, - shirt = {component_id = 8, texture = 1, drawable = 11}, - bodyarmor = {component_id = 9, texture = 1, drawable = 33}, - decals = {component_id = 10, texture = 1, drawable = 33}, - jacket = {component_id = 11, texture = 2, drawable = 4}, - }, - props = { - hats = {prop_id = 0, texture = 2, drawable = 4}, - glasses = {prop_id = 1, texture = 2, drawable = 4}, - ears = {prop_id = 2, texture = 2, drawable = 4}, - watches = {prop_id = 6, texture = 2, drawable = 4}, - bracelets = {prop_id = 7, texture = 2, drawable = 4}, - } - }, -} - -local function convertDataToFormat(characterData) - local gender = characterData.sex - - local repackedClothingData = { - [gender] = { - components = {}, - props = {} - } - } - - local componentMap = { - tshirt_1 = 8, -- shirt - torso_1 = 11, -- jacket - decals_1 = 10, -- decals - arms = 3, -- arms - pants_1 = 4, -- pants - shoes_1 = 6, -- shoes - mask_1 = 1, -- mask - bproof_1 = 9, -- body armor - chain_1 = 7, -- accessory (could be a necklace) - bags_1 = 5, -- bag - } - - for componentName, componentId in pairs(componentMap) do - if characterData[componentName] then - repackedClothingData[gender].components[componentName] = { - component_id = componentId, - texture = characterData[componentName.."_2"], - drawable = characterData[componentName.."_1"], - } - end - end - - local propMap = { - {"helmet_1", 0}, -- helmet - {"glasses_1", 1}, -- glasses - {"ears_1", 2}, -- ears - {"watches_1", 6}, -- watches - {"bracelets_1", 7} -- bracelets - } - - for _, prop in ipairs(propMap) do - local propName = prop[1] - local propId = prop[2] - - if characterData[propName] then - repackedClothingData[gender].props[propName] = { - prop_id = propId, - texture = characterData[propName.."_2"], - drawable = characterData[propName.."_1"], - } - end - end - return repackedClothingData -end - -Clothing.SetAppearance = function(clothingData) - if GetEntityModel(cache.ped) == `mp_m_freemode_01` then - clothingData = clothingData.male - clothingData.sex = 0 - else - clothingData = clothingData.female - clothingData.sex = 1 - end - local repackedClothingData = convertDataToFormat(clothingData) - StoredOldClothing = Clothing.GetAppearance - TriggerEvent('skinchanger:loadSkin', repackedClothingData) - return true -end - -Clothing.GetAppearance = function() - ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) - StoredOldClothing = skin - end) - return true -end - -Clothing.RestoreAppearance = function() - ESX.TriggerServerCallback('esx_skin:getPlayerSkin', function(skin) - TriggerEvent('skinchanger:loadSkin', skin) - end) - return true -end - -Clothing.ReloadSkin = function() - local tableCheck = Table.TableContains(StoredOldClothing, "sex") - if not tableCheck then return Clothing.RestoreAppearance() end - return TriggerEvent('skinchanger:loadSkin', StoredOldClothing) -end \ No newline at end of file diff --git a/modules/clothing/fivem-appearance/client.lua b/modules/clothing/fivem-appearance/client.lua deleted file mode 100644 index 96dc98f..0000000 --- a/modules/clothing/fivem-appearance/client.lua +++ /dev/null @@ -1,31 +0,0 @@ -if GetResourceState('fivem-appearance') ~= 'started' then return end -Clothing = Clothing or {} - -Clothing.SetAppearance = function(data) - local clothing = {} - if GetEntityModel(cache.ped) == `mp_m_freemode_01` then - clothing = data.male - else - clothing = data.female - end - ClothingBackup = exports['fivem-appearance']:getPedAppearance(cache.ped) - exports['fivem-appearance']:setPedAppearance(cache.ped, clothing) - return true -end - -Clothing.GetAppearance = function() - return exports['fivem-appearance']:getPedAppearance(cache.ped) -end - -Clothing.RestoreAppearance = function() - if not next(ClothingBackup) then - return false - end - exports['fivem-appearance']:setPedAppearance(cache.ped, ClothingBackup) - return true -end - -Clothing.ReloadSkin = function() - TriggerEvent("fivem-appearance:client:reloadSkin", true) - return true -end \ No newline at end of file diff --git a/modules/clothing/illenium-appearance/client.lua b/modules/clothing/illenium-appearance/client.lua deleted file mode 100644 index 92736ab..0000000 --- a/modules/clothing/illenium-appearance/client.lua +++ /dev/null @@ -1,42 +0,0 @@ -if GetResourceState('illenium-appearance') ~= 'started' then return end -Clothing = Clothing or {} - -Clothing.SetAppearance = function(clothingData) - local clothing = {} - if GetEntityModel(cache.ped) == `mp_m_freemode_01` then - clothingData = clothingData.male - else - clothingData = clothingData.female - end - clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped) - clothing.props = exports['illenium-appearance']:getPedProps(cache.ped) - - Prints.Debug(json.encode(clothingData, {indent = true})) - ClothingBackup = clothing - exports['illenium-appearance']:setPedComponents(cache.ped, clothingData.components) - exports['illenium-appearance']:setPedProp(cache.ped, clothingData.props) - return true -end - -Clothing.GetAppearance = function() - local clothing = {} - if GetEntityModel(cache.ped) == `mp_m_freemode_01` then - clothing = clothing.male - else - clothing = clothing.female - end - clothing.components = exports['illenium-appearance']:getPedComponents(cache.ped) - clothing.props = exports['illenium-appearance']:getPedProps(cache.ped) - - return clothing -end - -Clothing.RestoreAppearance = function() - exports['illenium-appearance']:setPedComponents(cache.ped, ClothingBackup.components) - exports['illenium-appearance']:setPedProp(cache.ped, ClothingBackup.props) - return true -end - -Clothing.ReloadSkin = function() - TriggerEvent("illenium-appearance:client:reloadSkin", true) -end diff --git a/modules/clothing/qb-clothing/client.lua b/modules/clothing/qb-clothing/client.lua deleted file mode 100644 index 6d96122..0000000 --- a/modules/clothing/qb-clothing/client.lua +++ /dev/null @@ -1,75 +0,0 @@ -if GetResourceState('qb-clothing') ~= 'started' then return end - -Clothing = Clothing or {} - -Clothing.SetAppearance = function(data) - local clothingData = {} - local repackedTable = {} - if GetEntityModel(cache.ped) == `mp_m_freemode_01` then - clothingData = data.male - else - clothingData = data.female - end - ClothingBackup = Clothing.GetAppearance - local componentMap = { - [1] = 'mask', - [3] = 'arms', - [4] = 'pants', - [5] = 'bag', - [6] = 'shoes', - [7] = 'accessory', - [8] = 't-shirt', - [9] = 'vest', - [10] = 'decals', - [11] = 'torso2' - } - - local propMap = { - [0] = 'hat', - [1] = 'glass', - [2] = 'ear', - [6] = 'watch', - [7] = 'bracelet' - } - - local specialMap = { - eye_color_id = 'eye_color', - moles_id = 'moles', - ageing_id = 'ageing', - hair_id = 'hair', - face_id = 'face' - } - - for _, v in pairs(clothingData) do - if componentMap[v.component_id] then - repackedTable[componentMap[v.component_id]] = {drawable = v.drawable, texture = v.texture} - elseif propMap[v.prop_id] then - repackedTable[propMap[v.prop_id]] = {drawable = v.drawable, texture = v.texture} - elseif specialMap[v.eye_color_id] then - repackedTable[specialMap[v.eye_color_id]] = {drawable = v.drawable, texture = v.texture} - elseif specialMap[v.moles_id] then - repackedTable[specialMap[v.moles_id]] = {drawable = v.drawable, texture = v.texture} - elseif specialMap[v.ageing_id] then - repackedTable[specialMap[v.ageing_id]] = {drawable = v.drawable, texture = v.texture} - elseif specialMap[v.hair_id] then - repackedTable[specialMap[v.hair_id]] = {drawable = v.drawable, texture = v.texture} - elseif specialMap[v.face_id] then - repackedTable[specialMap[v.face_id]] = {drawable = v.drawable, texture = v.texture} - end - end - TriggerEvent('qb-clothing:client:loadOutfit', repackedTable) - return true -end - -Clothing.GetAppearance = function() - ClothingBackup = Utility.GetEntitySkinData(cache.ped) - return Utility.GetEntitySkinData(cache.ped) -end - -Clothing.RestoreAppearance = function() - return Utility.SetEntitySkinData(cache.ped, ClothingBackup) -end - -Clothing.ReloadSkin = function() - return exports['qb-clothing']:reloadSkin(GetEntityHealth(cache.ped)) -end \ No newline at end of file diff --git a/modules/clothing/qb-clothing/server.lua b/modules/clothing/qb-clothing/server.lua deleted file mode 100644 index c95f1bc..0000000 --- a/modules/clothing/qb-clothing/server.lua +++ /dev/null @@ -1,8 +0,0 @@ -if GetResourceState('qb-clothing') ~= 'started' then return end - -RegisterNetEvent('qb-clothing:saveSkin', function(model, skin) - local src = source - if model and skin then - TriggerClientEvent('community_bridge:client:updateClothingBackup', src, skin) - end -end) \ No newline at end of file diff --git a/modules/dialogue/default/client/client.lua b/modules/dialogue/default/client/client.lua index c00ed6d..97ce769 100644 --- a/modules/dialogue/default/client/client.lua +++ b/modules/dialogue/default/client/client.lua @@ -1,3 +1,6 @@ +--[[This module is incomplete]]-- + + local promises = {} local activeDialogue = nil local pendingCameraDestroy = false @@ -59,7 +62,7 @@ function Dialogue.Open( name, dialogue, characterOptions, dialogueOptions, onSel local offsetY = math.cos(angleRad) * 1.5 -- Get position in front of ped based on their heading - local endLocation = GetEntityCoords(entity) + vector3(offsetX, offsetY, 0.5) + offset + local endLocation = GetEntityCoords(entity) + vector3(offsetX * offset.x, offsetY * offset.y, 0.5) if not cam then cam = CreateCam("DEFAULT_SCRIPTED_CAMERA", 1) end local camPos = GetCamCoord(cam) diff --git a/modules/dispatch/_default/client/client.lua b/modules/dispatch/_default/client/client.lua index a787258..eeffe67 100644 --- a/modules/dispatch/_default/client/client.lua +++ b/modules/dispatch/_default/client/client.lua @@ -1,5 +1,8 @@ Dispatch = Dispatch or {} +---This will send an alert to currently supported dispatch systems. +---@param data table The data to send to the dispatch system. +---@return nil Dispatch.SendAlert = function(data) TriggerServerEvent('community_bridge:Server:DispatchAlert', { sprite = data.blipData.sprite or 161, diff --git a/modules/dispatch/lb-tablet/client/client.lua b/modules/dispatch/lb-tablet/client/client.lua new file mode 100644 index 0000000..83aabee --- /dev/null +++ b/modules/dispatch/lb-tablet/client/client.lua @@ -0,0 +1,40 @@ +if GetResourceState('lb-tablet') ~= 'started' then return end +Dispatch = Dispatch or {} + +local function getPriorityLevel(priority) + if priority == 1 then + return 'low' + elseif priority == 2 then + return 'medium' + elseif priority == 3 then + return 'high' + else + return 'medium' + end +end + +---commentThis will send an alert to the passed jobs +---@param data table +Dispatch.SendAlert = function(data) + local streetName, _ = Utility.GetStreetNameAtCoords(data.coords) + local priority = getPriorityLevel(data.priority) + if type(data.jobs) == 'table' then + data.jobs = data.jobs[1] + end + if data.time and data.time > 1000 then + data.time = math.floor((data.time / 1000) + 0.5) + end + local alertData = { + priority = priority, + code = data.code or '10-80', + title = 'Dispatch Alert!', + description = data.message, + location = { + label = streetName, + coords = vec2(data.coords.x, data.coords.y) + }, + time = data.time or 10000, + job = data.jobs, + } + TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData) +end \ No newline at end of file diff --git a/modules/dispatch/lb-tablet/server/server.lua b/modules/dispatch/lb-tablet/server/server.lua new file mode 100644 index 0000000..ec8befc --- /dev/null +++ b/modules/dispatch/lb-tablet/server/server.lua @@ -0,0 +1,6 @@ +if GetResourceState('lb-tablet') ~= 'started' then return end +Dispatch = Dispatch or {} + +RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data) + exports["lb-tablet"]:AddDispatch(data) -- this has a return value but we dont really have a use for it atm. +end) \ No newline at end of file diff --git a/modules/dispatch/ps-dispatch/client/client.lua b/modules/dispatch/ps-dispatch/client/client.lua index 7a27093..cbf06a3 100644 --- a/modules/dispatch/ps-dispatch/client/client.lua +++ b/modules/dispatch/ps-dispatch/client/client.lua @@ -1,4 +1,5 @@ if GetResourceState('ps-dispatch') ~= 'started' then return end +if GetResourceState('lb-tablet') == 'started' then return end Dispatch = Dispatch or {} Dispatch.SendAlert = function(data) diff --git a/modules/dispatch/ps-dispatch/server/server.lua b/modules/dispatch/ps-dispatch/server/server.lua index b19a475..b75b55e 100644 --- a/modules/dispatch/ps-dispatch/server/server.lua +++ b/modules/dispatch/ps-dispatch/server/server.lua @@ -1,2 +1,3 @@ if GetResourceState('ps-dispatch') ~= 'started' then return end +if GetResourceState('lb-tablet') == 'started' then return end Dispatch = Dispatch or {} diff --git a/modules/dispatch/redutzu-mdt/client/client.lua b/modules/dispatch/redutzu-mdt/client/client.lua new file mode 100644 index 0000000..2314a7d --- /dev/null +++ b/modules/dispatch/redutzu-mdt/client/client.lua @@ -0,0 +1,14 @@ +if GetResourceState('redutzu-mdt') ~= 'started' then return end +Dispatch = Dispatch or {} + +Dispatch.SendAlert = function(data) + local streetName, _ = Utility.GetStreetNameAtCoords(data.coords) + local alertData = { + code = data.code or '10-80', + message = data.message or "Dispatch Alert", + street = streetName, + time = data.time or 10000, + coords = data.coords, + } + TriggerServerEvent("community_bridge:server:dispatch:sendAlert", alertData) +end \ No newline at end of file diff --git a/modules/dispatch/redutzu-mdt/server/server.lua b/modules/dispatch/redutzu-mdt/server/server.lua new file mode 100644 index 0000000..e07d799 --- /dev/null +++ b/modules/dispatch/redutzu-mdt/server/server.lua @@ -0,0 +1,12 @@ +if GetResourceState('redutzu-mdt') ~= 'started' then return end +Dispatch = Dispatch or {} + +RegisterNetEvent("community_bridge:server:dispatch:sendAlert", function(data) + TriggerEvent('redutzu-mdt:server:addDispatchToMDT', { + code = data.code, + title = data.message, + street = data.street, + duration = data.time, + coords = data.coords + }) +end) \ No newline at end of file diff --git a/modules/doorlock/doors_creator/server.lua b/modules/doorlock/doors_creator/server.lua index 0aee303..b9ae565 100644 --- a/modules/doorlock/doors_creator/server.lua +++ b/modules/doorlock/doors_creator/server.lua @@ -2,6 +2,11 @@ if GetResourceState('doors_creator') ~= 'started' then return end Doorlock = Doorlock or {} + +---This will toggle the lock status of the door. +---@param doorID string +---@param toggle boolean +---@return boolean Doorlock.ToggleDoorLock = function(doorID, toggle) local state = toggle if state then diff --git a/modules/doorlock/ox_doorlock/client.lua b/modules/doorlock/ox_doorlock/client.lua index b2dd1aa..3c25dd1 100644 --- a/modules/doorlock/ox_doorlock/client.lua +++ b/modules/doorlock/ox_doorlock/client.lua @@ -2,6 +2,8 @@ if GetResourceState('ox_doorlock') ~= 'started' then return end Doorlock = Doorlock or {} +---This will get the closest door to the ped +---@return string | nil Doorlock.GetClosestDoor = function() return exports.ox_doorlock:getClosestDoor() end diff --git a/modules/framework/es_extended/client.lua b/modules/framework/es_extended/client.lua index 9b6dd40..31bdd58 100644 --- a/modules/framework/es_extended/client.lua +++ b/modules/framework/es_extended/client.lua @@ -14,6 +14,11 @@ Framework.GetPlayerData = function() return ESX.PlayerData end +Framework.GetFrameworkJobs = function() + local jobs = lib.callback.await('community_bridge:Callback:GetFrameworkJobs', false) + return jobs +end + ---comment ---@return string Framework.GetPlayerDob = function() @@ -75,6 +80,15 @@ Framework.GetPlayerInventory = function() return playerData.inventory end +---comment +---@param item string +---@return number +Framework.GetItemCount = function(item) + local inventory = Framework.GetPlayerInventory() + if not inventory then return 0 end + return inventory[item].count or 0 +end + ---comment ---@return boolean Framework.GetIsPlayerDead = function() diff --git a/modules/framework/es_extended/server.lua b/modules/framework/es_extended/server.lua index 08b8dc9..b5c8359 100644 --- a/modules/framework/es_extended/server.lua +++ b/modules/framework/es_extended/server.lua @@ -23,6 +23,10 @@ Framework.GetPlayerIdentifier = function(src) return xPlayer.getIdentifier() end +Framework.GetFrameworkJobs = function() + return ESX.GetJobs() +end + -- Framework.GetPlayerName(src) -- Returns the first and last name of the player. Framework.GetPlayerName = function(src) @@ -259,6 +263,11 @@ Framework.RegisterUsableItem = function(itemName, cb) ESX.RegisterUsableItem(itemName, func) end +RegisterNetEvent("esx:playerLoaded", function() + local src = source + TriggerEvent("community_bridge:Server:OnPlayerLoaded", src) +end) + RegisterNetEvent("esx:playerLogout", function() local src = source TriggerEvent("community_bridge:Server:OnPlayerUnload", src) @@ -269,6 +278,10 @@ AddEventHandler("playerDropped", function() TriggerEvent("community_bridge:Server:OnPlayerUnload", src) end) +lib.callback.register('community_bridge:Callback:GetFrameworkJobs', function(source) + return Framework.GetFrameworkJobs() or {} +end) + Framework.Commands = {} Framework.Commands.Add = function(name, help, arguments, argsrequired, callback, permission, ...) ESX.RegisterCommand(name, permission, function(xPlayer, args, showError) diff --git a/modules/framework/qb-core/client.lua b/modules/framework/qb-core/client.lua index 67766e8..e9e9a04 100644 --- a/modules/framework/qb-core/client.lua +++ b/modules/framework/qb-core/client.lua @@ -5,6 +5,8 @@ QBCore = exports['qb-core']:GetCoreObject() Framework = {} +---This will get the name of the framework being used (if a supported framework). +---@return string Framework.GetFrameworkName = function() return 'qb-core' end @@ -13,12 +15,31 @@ Framework.GetPlayerData = function() return QBCore.Functions.GetPlayerData() end +---This will return a table of all the jobs in the framework. +---@return table +Framework.GetFrameworkJobs = function() + local jobs = {} + for k, v in pairs(QBCore.Shared.Jobs) do + table.insert(jobs, { + name = k, + label = v.label, + grade = v.grades + }) + end + return jobs +end + +---This will get the players birth date +---@return string Framework.GetPlayerDob = function() local player = QBCore.Functions.GetPlayerData() local playerData = player.PlayerData return playerData.charinfo.birthdate end +---This will return the players metadata for the specified metadata key. +---@param metadata table | string +---@return table | string | number | boolean Framework.GetPlayerMetaData = function(metadata) return QBCore.Functions.GetPlayerData().metadata[metadata] end @@ -49,15 +70,25 @@ Framework.GetItemInfo = function(item) return repackedTable end +---This will get the players identifier (citizenid) etc. +---@return string Framework.GetPlayerIdentifier = function() return QBCore.Functions.GetPlayerData().citizenid end +---This will get the players name (first and last). +---@return string +---@return string Framework.GetPlayerName = function() local playerData = QBCore.Functions.GetPlayerData() return playerData.charinfo.firstname, playerData.charinfo.lastname end +---This will return the players job name, job label, job grade name and job grade level. +---@return string +---@return string +---@return string +---@return string Framework.GetPlayerJob = function() local playerData = QBCore.Functions.GetPlayerData() return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level @@ -67,6 +98,20 @@ Framework.HasItem = function(item) return QBCore.Functions.HasItem(item) end +---comment +---@param item string +---@return number +Framework.GetItemCount = function(item) + local frameworkInv = QBCore.Functions.GetPlayerData().items + local count = 0 + for _, v in pairs(frameworkInv) do + if v.name == item then + count = count + v.amount + end + end + return count +end + Framework.GetPlayerInventory = function() local items = {} local frameworkInv = QBCore.Functions.GetPlayerData().items @@ -85,6 +130,8 @@ Framework.GetPlayerInventory = function() return items end +---This will get a players dead status. +---@return boolean Framework.GetIsPlayerDead = function() local playerData = QBCore.Functions.GetPlayerData() return playerData.metadata["isdead"] or playerData.metadata["inlaststand"] diff --git a/modules/framework/qb-core/server.lua b/modules/framework/qb-core/server.lua index 39629b5..d72ce64 100644 --- a/modules/framework/qb-core/server.lua +++ b/modules/framework/qb-core/server.lua @@ -18,8 +18,21 @@ Framework.GetPlayerIdentifier = function(src) return playerData.citizenid end +Framework.GetFrameworkJobs = function() + local jobs = {} + for k, v in pairs(QBCore.Shared.Jobs) do + table.insert(jobs, { + name = k, + label = v.label, + grade = v.grades + }) + end + return jobs +end + -- Framework.GetPlayerName(src) -- Returns the first and last name of the player. +---@return string, string Framework.GetPlayerName = function(src) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -27,6 +40,8 @@ Framework.GetPlayerName = function(src) return playerData.charinfo.firstname, playerData.charinfo.lastname end +---This will get the players birth date +---@return string Framework.GetPlayerDob = function(src) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -126,6 +141,7 @@ end -- Framework.SetMetadata(src, metadata, value) -- Adds the specified metadata key and number value to the player's data. +---@return boolean | nil Framework.SetPlayerMetadata = function(src, metadata, value) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -144,6 +160,7 @@ end -- Framework.AddStress(src, value) -- Adds the specified value to the player's stress level and updates the client HUD. +---@return number | nil Framework.AddStress = function(src, value) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -156,6 +173,7 @@ end -- Framework.RemoveStress(src, value) -- Removes the specified value from the player's stress level and updates the client HUD. +---@return number | nil Framework.RemoveStress = function(src, value) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -168,6 +186,7 @@ end -- Framework.AddHunger(src, value) -- Adds the specified value from the player's hunger level. +---@return number | nil Framework.AddHunger = function(src, value) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -180,6 +199,7 @@ end -- Framework.AddThirst(src, value) -- Adds the specified value from the player's thirst level. +---@return number | nil Framework.AddThirst = function(src, value) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -190,6 +210,9 @@ Framework.AddThirst = function(src, value) return newThirst end +---This will get the hunger of a player +---@param src any +---@return number | nil Framework.GetHunger = function(src) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -198,6 +221,10 @@ Framework.GetHunger = function(src) return newHunger end + +---This will get the thirst of a player +---@param src any +---@return number | nil Framework.GetThirst = function(src) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -224,8 +251,9 @@ Framework.GetPlayerGang = function(src) return playerData.gang.name end --- Framework.GetPlayersByJob(jobname) --- returns a table of player sources that have the specified job name. +---This will get a table of player sources that have the specified job name. +---@param job any +---@return table Framework.GetPlayersByJob = function(job) local players = QBCore.Functions.GetPlayers() local playerList = {} @@ -238,8 +266,12 @@ Framework.GetPlayersByJob = function(job) return playerList end --- Framework.GetPlayerJob(src) --- Returns the job name, label, grade name, and grade level of the player. +---This will get the players job info +---@param src number +---@return string +---@return string +---@return string +---@return string Framework.GetPlayerJob = function(src) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -247,14 +279,21 @@ Framework.GetPlayerJob = function(src) return playerData.job.name, playerData.job.label, playerData.job.grade.name, playerData.job.grade.level end --- Framework.SetPlayerJob(src, name, grade) -- Sets the player's job to the specified name and grade. +---@param src number +---@param name string +---@param grade string +---@return nil Framework.SetPlayerJob = function(src, name, grade) local player = QBCore.Functions.GetPlayer(src) if not player then return end return player.Functions.SetJob(name, grade) end +---This will toggle a players duty status +---@param src number +---@param status boolean +---@return nil Framework.ToggleDuty = function(src, status) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -262,8 +301,12 @@ Framework.ToggleDuty = function(src, status) TriggerEvent('QBCore:Server:SetDuty', src, player.PlayerData.job.onduty) end --- Framework.AddAccountBalance(src, _type, amount) --- Adds the specified amount to the player's account balance of the specified type. + +---This will add money based on the type of account (money/bank) +---@param src number +---@param _type string +---@param amount number +---@return boolean | nil Framework.AddAccountBalance = function(src, _type, amount) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -271,8 +314,11 @@ Framework.AddAccountBalance = function(src, _type, amount) return player.Functions.AddMoney(_type, amount) end --- Framework.RemoveAccountBalance(src, _type, amount) --- Removes the specified amount from the player's account balance of the specified type. +---This will remove money based on the type of account (money/bank) +---@param src number +---@param _type string +---@param amount number +---@return boolean | nil Framework.RemoveAccountBalance = function(src, _type, amount) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -280,8 +326,10 @@ Framework.RemoveAccountBalance = function(src, _type, amount) return player.Functions.RemoveMoney(_type, amount) end --- Framework.GetAccountBalance(src, _type) --- Returns the player's account balance of the specified type. +---This will remove money based on the type of account (money/bank) +---@param src number +---@param _type string +---@return string | nil Framework.GetAccountBalance = function(src, _type) local player = QBCore.Functions.GetPlayer(src) if not player then return end @@ -329,6 +377,9 @@ Framework.SetMetadata = function(src, item, slot, metadata) return player.Functions.AddItem(item, 1, freeSlot, metadata) end +---This will get all owned vehicles for the player +---@param src number +---@return table Framework.GetOwnedVehicles = function(src) local citizenId = Framework.GetPlayerIdentifier(src) local result = MySQL.Sync.fetchAll("SELECT vehicle, plate FROM player_vehicles WHERE citizenid = '" .. citizenId .. "'") @@ -352,7 +403,12 @@ Framework.RegisterUsableItem = function(itemName, cb) QBCore.Functions.CreateUseableItem(itemName, func) end -RegisterNetEvent("QBCore:Server:OnPlayerUnload", function() +RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function() + local src = source + TriggerEvent("community_bridge:Server:OnPlayerLoaded", src) +end) + +RegisterNetEvent("QBCore:Server:OnPlayerUnload", function(source) local src = source TriggerEvent("community_bridge:Server:OnPlayerUnload", src) end) diff --git a/modules/framework/qbx_core/client.lua b/modules/framework/qbx_core/client.lua index 5d17c3f..9e7564a 100644 --- a/modules/framework/qbx_core/client.lua +++ b/modules/framework/qbx_core/client.lua @@ -12,6 +12,10 @@ Framework.GetPlayerData = function() return QBox.GetPlayerData() end +Framework.GetFrameworkJobs = function() + return QBox.GetJobs() +end + Framework.GetPlayerDob = function() local playerData = QBox.GetPlayerData() return playerData.charinfo.birthdate @@ -40,6 +44,14 @@ Framework.GetPlayerInventory = function() return QBox.GetPlayerData().items end +---comment +---@param item string +---@return number +Framework.GetItemCount = function(item) + -- This seems to be exclusively for ox_inventory, if other inventories are used, they need to be bridged in the inventory module. Until then we will return 0 and a print. + return 0, print("Community_bridge:WARN: GetItemCount is not implemented for this framework, please use the inventory module to get the item count. If you are using a diffrent inventory please let us know so we can bridge it and have less nonsense.") +end + Framework.GetIsPlayerDead = function() local platerData = QBox.GetPlayerData() return platerData.metadata["isdead"] or platerData.metadata["inlaststand"] diff --git a/modules/framework/qbx_core/server.lua b/modules/framework/qbx_core/server.lua index 8d62d13..4e3540d 100644 --- a/modules/framework/qbx_core/server.lua +++ b/modules/framework/qbx_core/server.lua @@ -15,6 +15,10 @@ Framework.GetPlayerDob = function(src) return playerData.charinfo.birthdate end +Framework.GetFrameworkJobs = function() + return QBox.GetJobs() +end + -- Framework.GetPlayerIdentifier(src) -- Returns the citizen ID of the player. Framework.GetPlayerIdentifier = function(src) @@ -297,6 +301,11 @@ Framework.GetOwnedVehicles = function(src) return vehicles end +RegisterNetEvent("QBCore:Server:OnPlayerLoaded", function() + local src = source + TriggerEvent("community_bridge:Server:OnPlayerLoaded", src) +end) + RegisterNetEvent("QBCore:Server:OnPlayerUnload", function() local src = source TriggerEvent("community_bridge:Server:OnPlayerUnload", src) diff --git a/modules/fuel/_defualts/client.lua b/modules/fuel/_defualts/client.lua index b6213e5..b453052 100644 --- a/modules/fuel/_defualts/client.lua +++ b/modules/fuel/_defualts/client.lua @@ -1,11 +1,18 @@ Fuel = Fuel or {} -----print("Fuel: Loading Defualt") + +---This will get the fuel level of the vehicle. +---@param vehicle number The vehicle entity ID. +---@return number fuel The fuel level of the vehicle. Fuel.GetFuel = function(vehicle) if not DoesEntityExist(vehicle) then return 0.0 end return GetVehicleFuelLevel(vehicle) end -Fuel.SetFuel = function(vehicle, fuel, type) +---This will set the fuel level of the vehicle. +---@param vehicle number The vehicle entity ID. +---@param fuel number The fuel level to set. +---@return nil +Fuel.SetFuel = function(vehicle, fuel) if not DoesEntityExist(vehicle) then return end return SetVehicleFuelLevel(vehicle, fuel) end \ No newline at end of file diff --git a/modules/fuel/lc_fuel/client.lua b/modules/fuel/lc_fuel/client.lua index 235a12a..d455e9c 100644 --- a/modules/fuel/lc_fuel/client.lua +++ b/modules/fuel/lc_fuel/client.lua @@ -2,6 +2,7 @@ local resourceName = "lc_fuel" local configValue = BridgeClientConfig.Fuel if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end --print("Fuel: Loading lc_fuel") +if GetResourceState('lc_fuel') ~= 'started' then return end Fuel = Fuel or {} Fuel.GetFuel = function(vehicle) @@ -9,7 +10,8 @@ Fuel.GetFuel = function(vehicle) return exports["lc_fuel"]:GetFuel(vehicle) end -Fuel.SetFuel = function(vehicle, fuel) + +Fuel.SetFuel = function(vehicle, fuel, type) if not DoesEntityExist(vehicle) then return end return exports["lc_fuel"]:SetFuel(vehicle, fuel) -end \ No newline at end of file +end diff --git a/modules/inventory/_default/client.lua b/modules/inventory/_default/client.lua index 1cb439d..dc645f3 100644 --- a/modules/inventory/_default/client.lua +++ b/modules/inventory/_default/client.lua @@ -14,6 +14,10 @@ Inventory.HasItem = function(item) return Framework.HasItem(item) end +Inventory.GetItemCount = function(item) + return Framework.GetItemCount(item) +end + ---comment ---@param item string ---@return string diff --git a/modules/inventory/_default/server.lua b/modules/inventory/_default/server.lua index 18f5b23..d179eaf 100644 --- a/modules/inventory/_default/server.lua +++ b/modules/inventory/_default/server.lua @@ -83,4 +83,4 @@ end ---@return string Inventory.GetImagePath = function(item) return "https://avatars.githubusercontent.com/u/47620135" -end \ No newline at end of file +end diff --git a/modules/inventory/origen_inventory/client.lua b/modules/inventory/origen_inventory/client.lua index e355e7d..7f86414 100644 --- a/modules/inventory/origen_inventory/client.lua +++ b/modules/inventory/origen_inventory/client.lua @@ -27,6 +27,18 @@ Inventory.HasItem = function(item) return origin:HasItem(item) end +---comment +---@param item string +---@return number +Inventory.GetItemCount = function(item) + local searchItem = origin:Search('slots', item) + local count = 0 + for _, v in pairs(searchItem) do + count = count + v.count + end + return count +end + ---comment ---@param item string ---@return string diff --git a/modules/inventory/ox_inventory/client.lua b/modules/inventory/ox_inventory/client.lua index 709f477..721f8ca 100644 --- a/modules/inventory/ox_inventory/client.lua +++ b/modules/inventory/ox_inventory/client.lua @@ -29,6 +29,13 @@ Inventory.HasItem = function(item) return hasItem end +---comment +---@param item string +---@return number +Inventory.GetItemCount = function(item) + return ox_inventory:GetItemCount(item, nil, false) +end + ---comment ---@param item string ---@return string diff --git a/modules/inventory/ox_inventory/server.lua b/modules/inventory/ox_inventory/server.lua index 5749bcf..e16db1e 100644 --- a/modules/inventory/ox_inventory/server.lua +++ b/modules/inventory/ox_inventory/server.lua @@ -37,7 +37,7 @@ Inventory.GetItem = function(src, item, metadata) return ox_inventory:GetItem(src, item, metadata, false) end ----comment +---This will get the item from the specified slot. ---@param src number ---@param slot number ---@return table @@ -63,14 +63,14 @@ Inventory.HasItem = function(src, item) return count > 0 end ----comment +---This wil return the players inventory. ---@param src number ---@return table Inventory.GetPlayerInventory = function(src) return ox_inventory:GetInventoryItems(src, false) end ----comment +---This is to get if there is available space in the inventory. ---@param src number ---@param item string ---@param count number @@ -79,7 +79,7 @@ Inventory.CanCarryItem = function(src, item, count) return ox_inventory:CanCarryItem(src, item, count) end ----comment +---This will register a stash ---@param id number||string ---@param label string ---@param slots number @@ -106,7 +106,7 @@ Inventory.OpenStash = function(src, id, label, slots, weight, owner, groups, coo TriggerClientEvent('ox_inventory:openInventory', src, 'stash', 'stash_' .. id) end ----comment +---This will get the data about an item such as name, label, stack, weight, description and image. ---@param item string ---@return table Inventory.GetItemInfo = function(item) @@ -123,7 +123,7 @@ Inventory.GetItemInfo = function(item) return repackedTable end ----comment +---This will set the metadata of an item in the inventory. ---@param src number ---@param item string ---@param slot number @@ -133,7 +133,7 @@ Inventory.SetMetadata = function(src, item, slot, metadata) ox_inventory:SetMetadata(src, slot, metadata) end ----comment +---This will update the plate to the vehicle inside the inventory. (It will also update with jg-mechanic if using it) ---@param oldplate string ---@param newplate string ---@return boolean @@ -144,7 +144,7 @@ Inventory.UpdatePlate = function(oldplate, newplate) return true end ----comment +---This will get the image path for an item, it is an alternate option to GetItemInfo. If a image isnt found will revert to community_bridge logo (useful for menus) ---@param item string ---@return string Inventory.GetImagePath = function(item) diff --git a/modules/inventory/qs-inventory/client.lua b/modules/inventory/qs-inventory/client.lua index 797e9f3..99a9c8b 100644 --- a/modules/inventory/qs-inventory/client.lua +++ b/modules/inventory/qs-inventory/client.lua @@ -44,6 +44,14 @@ Inventory.GetImagePath = function(item) return imagePath or "https://avatars.githubusercontent.com/u/47620135" end +---comment +---@param item string +---@return number +Inventory.GetItemCount = function(item) + local searchItem = quasar:Search(item) + return searchItem or 0 +end + ---comment ---@return table Inventory.GetPlayerInventory = function() diff --git a/modules/inventory/tgiann-inventory/client.lua b/modules/inventory/tgiann-inventory/client.lua index 5407c52..93183fd 100644 --- a/modules/inventory/tgiann-inventory/client.lua +++ b/modules/inventory/tgiann-inventory/client.lua @@ -25,6 +25,14 @@ Inventory.GetItemInfo = function(item) return repackedTable end +---comment +---@param item string +---@return number +Inventory.GetItemCount = function(item) + local searchItem = tgiann:GetItemCount(item, nil, false) + return searchItem or 0 +end + ---This will return a boolean if the player has the item in the inventory ---@param item string ---@return boolean diff --git a/modules/locales/shared.lua b/modules/locales/shared.lua index 1e49843..4074ac2 100644 --- a/modules/locales/shared.lua +++ b/modules/locales/shared.lua @@ -47,29 +47,4 @@ function Language.Locale(str, ...) return current end - - - -if BridgeSharedConfig.DebugLevel == 2 then - -- if outside this resource, use local whatever = Require("modules/locales/shared.lua") - -- whatever.Locales("some-index-in-language-.json-file") - -- Files must be stored in "locales" folder, within the resource. - -- Instead of using Require you can also import it via the manifest. - -- The Lang variable is available globally, which tells you what the server is using. - -- print("Language: ", Lang) - -- print("Locale: ", Language.Locale("locale-unit-test")) - - -- Example outside community bridge resource: - - -- local Language = Require('modules/locales/shared.lua') - -- print("Language: ", Lang) - -- print("Locale: ", Language.Locale("locale-unit-test")) - RegisterCommand("lang", function(source, args, raw) - print(Language.Locale("UNITTEST.UNITTEST.UNITTESTA")) - print(Language.Locale("UNITTEST.UNITTESTA", "Devil", "GERRRRRRR!")) - - print( "Oh also this works", Language.Locale("place_object_scroll_down")) - end) -end - return Language \ No newline at end of file diff --git a/modules/managment/Renewed-Banking/server.lua b/modules/managment/Renewed-Banking/server.lua index 4a952de..3c4bf5b 100644 --- a/modules/managment/Renewed-Banking/server.lua +++ b/modules/managment/Renewed-Banking/server.lua @@ -1,14 +1,25 @@ if GetResourceState('Renewed-Banking') ~= 'started' then return end Managment = Managment or {} +---This will return a table with account details +---@param account string +---@return table Managment.GetAccountMoney = function(account) return exports['Renewed-Banking']:getAccountMoney(account) end +---This will add money to the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.AddAccountMoney = function(account, amount) return exports['Renewed-Banking']:addAccountMoney(account, amount) end +---This will remove money from the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.RemoveAccountMoney = function(account, amount) return exports['Renewed-Banking']:removeAccountMoney(account, amount) end \ No newline at end of file diff --git a/modules/managment/okokBanking/server.lua b/modules/managment/okokBanking/server.lua index 90ad050..34582c3 100644 --- a/modules/managment/okokBanking/server.lua +++ b/modules/managment/okokBanking/server.lua @@ -1,14 +1,25 @@ if GetResourceState('okokBanking') ~= 'started' then return end Managment = Managment or {} +---This will return a table with account details +---@param account string +---@return table Managment.GetAccountMoney = function(account) return exports['okokBanking']:GetAccount(account) end +---This will add money to the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.AddAccountMoney = function(account, amount) return exports['okokBanking']:AddMoney(account, amount) end +---This will remove money from the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.RemoveAccountMoney = function(account, amount) return exports['okokBanking']:RemoveMoney(account, amount) end \ No newline at end of file diff --git a/modules/managment/qb-banking/server.lua b/modules/managment/qb-banking/server.lua index 5a7facf..25d168a 100644 --- a/modules/managment/qb-banking/server.lua +++ b/modules/managment/qb-banking/server.lua @@ -1,14 +1,25 @@ if GetResourceState('qb-banking') ~= 'started' then return end Managment = Managment or {} +---This will return a table with account details +---@param account string +---@return table Managment.GetAccountMoney = function(account) return exports['qb-banking']:GetAccountBalance(account) end +---This will add money to the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.AddAccountMoney = function(account, amount) return exports['qb-banking']:AddMoney(account, amount) end +---This will remove money from the specified account of the passed amount +---@param account string +---@param amount number +---@return boolean Managment.RemoveAccountMoney = function(account, amount) return exports['qb-banking']:RemoveMoney(account, amount) end \ No newline at end of file diff --git a/modules/menu/_qb-menu.lua b/modules/menu/_qb-menu.lua index 511495a..411fd0e 100644 --- a/modules/menu/_qb-menu.lua +++ b/modules/menu/_qb-menu.lua @@ -18,6 +18,7 @@ function OxToQBMenu(id, menu) header = v.title, txt = v.description, icon = v.icon, + disabled = v.disabled, } if v.onSelect then diff --git a/modules/notify/_default/client.lua b/modules/notify/_default/client.lua index 743e348..a857aeb 100644 --- a/modules/notify/_default/client.lua +++ b/modules/notify/_default/client.lua @@ -2,7 +2,7 @@ Notify = Notify or {} local notifyType = BridgeClientConfig.NotifySystem local helptextType = BridgeClientConfig.ShowHelpText ----comment +---This will send a notify message of the type and time passed ---@param message string ---@param _type string ---@param time number @@ -34,7 +34,7 @@ Notify.SendNotify = function(message, _type, time) end end ----comment +---This will show a help text message at the screen position passed ---@param message string ---@param _position string ---@return nil @@ -61,6 +61,8 @@ Notify.ShowHelpText = function(message, _position) end end +---This will hide the help text message on the screen +---@return nil Notify.HideHelpText = function() if helptextType == 'ox' then return exports.ox_lib:hideTextUI() diff --git a/modules/notify/_default/server.lua b/modules/notify/_default/server.lua index 759bdb2..9f7cb47 100644 --- a/modules/notify/_default/server.lua +++ b/modules/notify/_default/server.lua @@ -1,6 +1,6 @@ Notify = Notify or {} ----comment +---This will send a notification to the specified player of the passed message and type ---@param src number ---@param message string ---@param _type string @@ -9,7 +9,7 @@ Notify.SendNotify = function(src, message, _type, time) TriggerClientEvent('community_bridge:Client:Notify', src, message, _type, time) end ----comment +---This will show a help text message to the specified player at the screen position passed ---@param src number ---@param message string ---@param position string @@ -17,6 +17,8 @@ Notify.ShowHelpText = function(src, message, position) TriggerClientEvent('community_bridge:Client:ShowHelpText', src, message, position) end +---This will hide the help text message on the screen for the specified player +---@param src number Notify.HideHelpText = function(src) TriggerClientEvent('community_bridge:Client:HideHelpText', src) end \ No newline at end of file diff --git a/modules/shops/_default/client.lua b/modules/shops/_default/client.lua index e68c3b4..cc7e377 100644 --- a/modules/shops/_default/client.lua +++ b/modules/shops/_default/client.lua @@ -7,30 +7,7 @@ RegisterNetEvent('community_bridge:openShop', function(_type, _title, shopData) Shops.OpenShop(_title, shopData.inventory) end) -Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price) - if not shopName and not item and not itemLabel and not price then return end - local generatedID = Ids.CreateUniqueId() - local buildMenu = { - { - title = locale('Shops.PayByCash')..tostring(price), - description = locale('Shops.AreYouSure') .. itemLabel, - icon = "fa-solid fa-money-bill-wave", - onSelect = function(_, __, ___) - TriggerServerEvent('community_bridge:completeCheckout', shopName, item, "cash") - end - }, - { - title = locale('Shops.PayByCard')..tostring(price), - description = locale('Shops.AreYouSure') .. itemLabel, - icon = "fa-solid fa-building-column", - onSelect = function(_, __, ___) - TriggerServerEvent('community_bridge:completeCheckout', shopName, item, "bank") - end - } - } - Bridge.Menu.Open({ id = generatedID, title = locale("Shops.Confirm"), options = buildMenu }, false) -end - +---This is an internal event that is used to complete a transaction and offer cash/card pay Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price, amount) if not shopName and not item and not itemLabel and not price then return end local mathStuff = tonumber(price) * tonumber(amount) @@ -56,6 +33,11 @@ Shops.FinalizeCheckOut = function(shopName, item, itemLabel, price, amount) Menu.Open({ id = generatedID, title = locale("Shops.Input"), options = buildMenu }, false) end +---This is an internal event that is used to open the amount select menu +---@param shopName string +---@param item string +---@param itemLabel string +---@param price number Shops.AmountSelect = function(shopName, item, itemLabel, price) if not shopName and not item and not itemLabel and not price then return end local numberOptions = {} @@ -71,6 +53,11 @@ Shops.AmountSelect = function(shopName, item, itemLabel, price) end end +---This will open a shop with the passed title and data. It will create a menu with the items in the shopData table. The items will be clickable and will open a checkout menu. +---This also verifies the shop exsists and was made first server side. This will not work when only used client side and the server side verifies the item exsists in the table as well as the shop id. +---@param title any +---@param shopData any +---@return nil Shops.OpenShop = function(title, shopData) if not title and not shopData and not title then return print("No Title Passed") end local generatedID = Ids.CreateUniqueId() diff --git a/modules/shops/_default/server.lua b/modules/shops/_default/server.lua index edf4737..708c6fd 100644 --- a/modules/shops/_default/server.lua +++ b/modules/shops/_default/server.lua @@ -2,20 +2,37 @@ Shops = Shops or {} local registeredShops = {} +---commentThis can open a shop for the client +---@param src number +---@param shopTitle string +---@return boolean Shops.OpenShop = function(src, shopTitle) if not shopTitle and not registeredShops[shopTitle] then return false end TriggerClientEvent('community_bridge:openShop', src, 'shop', shopTitle, registeredShops[shopTitle]) + return true end +---This will create a shop to use on the client side, shops must be registered server side and exsist in the shop inventory table to allow any purchases passed. +---@param shopTitle string +---@param shopInventory table +---@param shopCoords table +---@param shopGroups table +---@return boolean Shops.CreateShop = function(shopTitle, shopInventory, shopCoords, shopGroups) - if not shopTitle and not shopInventory and not shopCoords then return end + if not shopTitle and not shopInventory and not shopCoords then return false end if registeredShops[shopTitle] then return true end registeredShops[shopTitle] = {name = shopTitle, inventory = shopInventory, shopCoords = shopCoords, groups = shopGroups} return true end +---This is an internal event to complete a shop transaction, it will verify pass items and amounts are registered to the created shop. +---@param src number +---@param shopName string +---@param item string +---@param amount number +---@param paymentType string +---@return nil Shops.CompleteCheckout = function(src, shopName, item, amount, paymentType) - if not src and not shopName and not item and not amount and not paymentType then return end local ilocale = Language.Locale local shopData = registeredShops[shopName] diff --git a/modules/target/_defualt/client.lua b/modules/target/_defualt/client.lua index bc9b892..710c524 100644 --- a/modules/target/_defualt/client.lua +++ b/modules/target/_defualt/client.lua @@ -4,6 +4,20 @@ local function warnUser() print("Currently Only Targeting Is Supported By Community Bridge, You Are Using A Resource That Requires The Target Module To Be Used.") end +Target.FixOptions = function(options) + for k, v in pairs(options) do + local action = v.onSelect or v.action + local select = function(entityOrData) + if type(entityOrData) == 'table' then + return action(entityOrData.entity) + end + return action(entityOrData) + end + options[k].onSelect = select + end + return options +end + Target.AddGlobalPlayer = function(options) warnUser() end @@ -17,15 +31,94 @@ Target.RemoveGlobalVehicle = function(options) end Target.AddLocalEntity = function(entities, _options) - warnUser() + local fixedOptions = Target.FixOptions(_options) + if type(entities) == "string" or type(entities) == "number" then + entities = { entities } + end + for _, entity in pairs(entities) do + local id = Ids.RandomString() + local menuData = { id = id, title = "Options", options = {} } + for k, v in pairs(fixedOptions) do + table.insert(menuData.options, { + title = ("Option " .. k), + description = "No Description", + icon = v.icon or "fas fa-code-pull-request", + args = {}, + onSelect = function(selected, secondary, args) + if v.onSelect then + v.onSelect(selected, secondary, args) + end + end + }) + end + Point.Register(id, entity, 5, args, + function() + local coords = GetEntityCoords(entity) + local sleep = 3000 + while DoesEntityExist(entity) do + Wait(sleep) + local distance = #(coords - GetEntityCoords(PlayerPedId())) + if distance < 10 then + sleep = 0 + Utility.Draw3DHelpText(coords, "Press [E] To Interact", 0.35) + if IsControlJustPressed(0, 38) then + Menu.Open(menuData, false) + end + else + sleep = 3000 + end + end + end, + function() + Point.Remove(id) + end, function() + --No need for this in this one + end) + end end + Target.AddModel = function(models, options) warnUser() end Target.AddBoxZone = function(name, coords, size, heading, options) - warnUser() + local fixedOptions = Target.FixOptions(_options) + local id = Ids.RandomString() + local menuData = { id = id, title = "Options", options = {} } + for k, v in pairs(fixedOptions) do + table.insert(menuData.options, { + title = ("Option " .. k), + description = "No Description", + onSelect = function(selected, secondary, args) + if v.onSelect then + v.onSelect(selected, secondary, args) + end + end + }) + end + Point.Register(id, coords, 5, args, + function() + local sleep = 3000 + while true do + Wait(sleep) + local distance = #(coords - GetEntityCoords(PlayerPedId())) + if distance < 10 then + sleep = 0 + Utility.Draw3DHelpText(coords, "Press [E] To Interact", 0.35) + if IsControlJustPressed(0, 38) then + Menu.Open(menuData, false) + end + else + sleep = 3000 + end + end + end, + function() + Point.Remove(id) + end, function() + --No need for this in this one + end) end Target.RemoveGlobalPlayer = function() diff --git a/modules/target/ox_target/client.lua b/modules/target/ox_target/client.lua index 422a64e..10b7026 100644 --- a/modules/target/ox_target/client.lua +++ b/modules/target/ox_target/client.lua @@ -17,6 +17,9 @@ local targetZones = {} Target = Target or {} +---This is an internal function that is used to fix the options passed to fit alternative target systems, for example qb-ox or ox-qb etc. +---@param options table +---@return table Target.FixOptions = function(options) for k, v in pairs(options) do local action = v.onSelect or v.action @@ -31,25 +34,34 @@ Target.FixOptions = function(options) return options end ----comment +---This will add target options to players. ---@param options table ----@return nil Target.AddGlobalPlayer = function(options) options = Target.FixOptions(options) ox_target:addGlobalPlayer(options) end ----comment +---This will remove target options from all players. +Target.RemoveGlobalPlayer = function() +---@diagnostic disable-next-line: missing-parameter + ox_target:removeGlobalPlayer() +end + +---This will toggle the targeting system on or off. This is useful for when you want to disable the targeting system for a specific player entirely. +---@param bool boolean +Target.DisableTargeting = function(bool) + ox_target:disableTargeting(bool) +end + +---This will add taget options to all vehicles. ---@param options table ----@return nil Target.AddGlobalVehicle = function(options) options = Target.FixOptions(options) ox_target:addGlobalVehicle(options) end ----comment +---This will remove target options from all vehicles. ---@param options table ----@return nil Target.RemoveGlobalVehicle = function(options) local assembledLables = {} for k, v in pairs(options) do @@ -58,31 +70,40 @@ Target.RemoveGlobalVehicle = function(options) ox_target:removeGlobalVehicle(assembledLables) end ----comment ----@param entities table +---This will generate targets on non networked entites with the passed options. +---@param entities number | table ---@param options table ----@return nil Target.AddLocalEntity = function(entities, options) options = Target.FixOptions(options) ox_target:addLocalEntity(entities, options) end ----comment ----@param models table +---This will remove the target options from a local entity. This is useful for when you want to remove target options from a specific entity. +---@param entity any +Target.RemoveLocalEntity = function(entity) + ox_target:removeLocalEntity(entity) +end + +---This will add target options to all specified models. This is useful for when you want to add target options to all models of a specific type. +---@param models number | table ---@param options table ----@return nil Target.AddModel = function(models, options) options = Target.FixOptions(options) ox_target:addModel(models, options) end ----comment +---This will remove target options from all specified models. +---@param model number +Target.RemoveModel = function(model) + ox_target:removeModel(model) +end + +---This will add a box zone to the target system. This is useful for when you want to add target options to a specific area. ---@param name string ---@param coords table ---@param size table ---@param heading number ---@param options table ----@return number Target.AddBoxZone = function(name, coords, size, heading, options) options = Target.FixOptions(options) local target = ox_target:addBoxZone({ @@ -96,28 +117,28 @@ Target.AddBoxZone = function(name, coords, size, heading, options) return target end -Target.RemoveGlobalPlayer = function() - ox_target:removeGlobalPlayer() -end - ----comment ----@param entity number ----@return nil -Target.RemoveLocalEntity = function(entity) - ox_target:removeLocalEntity(entity) -end - ----comment ----@param model string ----@return nil -Target.RemoveModel = function(model) - ox_target:removeModel(model) -end - ----comment +---This will add a circle zone to the target system. This is useful for when you want to add target options to a specific area. +---@param name string +---@param coords table +---@param radius number +---@param options table +Target.AddSphereZone = function(name, coords, radius, heading, options) + options = Target.FixOptions(options) + local target = ox_target:addSphereZone({ + coords = coords, + radius = radius, + name = name, + debug = targetDebug, + options = options + }) + table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() }) + return target +end + +---This will remove target options from a specific zone. ---@param name string ----@return nil Target.RemoveZone = function(name) + if not name then return end for _, data in pairs(targetZones) do if data.name == name then ox_target:removeZone(data.id) @@ -128,12 +149,11 @@ Target.RemoveZone = function(name) end AddEventHandler('onResourceStop', function(resource) - if resource == GetCurrentResourceName() then - for _, target in pairs(targetZones) do - if target.creator == resource then - ox_target:removeZone(target.id) - end + if resource ~= GetCurrentResourceName() then return end + for _, target in pairs(targetZones) do + if target.creator == resource then + ox_target:removeZone(target.id) end - targetZones = {} end + targetZones = {} end) diff --git a/modules/target/qb-target/client.lua b/modules/target/qb-target/client.lua index bf627bb..00cc6ee 100644 --- a/modules/target/qb-target/client.lua +++ b/modules/target/qb-target/client.lua @@ -15,7 +15,12 @@ detectDebugEnabled() local targetZones = {} Target = Target or {} +local qb_target = exports['qb-target'] + +---This is an internal function that is used to fix the options passed to fit alternative target systems, for example qb-ox or ox-qb etc. +---@param options table +---@return table Target.FixOptions = function(options) for k, v in pairs(options) do local action = v.onSelect or v.action @@ -23,7 +28,7 @@ Target.FixOptions = function(options) if type(entityOrData) == 'table' then return action(entityOrData.entity) end - return action(entityOrData) + return action(entityOrData) end options[k].action = select options[k].job = v.job or v.groups @@ -31,50 +36,90 @@ Target.FixOptions = function(options) return options end +---This will toggle the targeting system on or off. This is useful for when you want to disable the targeting system for a specific player entirely. +---@param bool boolean +Target.DisableTargeting = function(bool) + qb_target:AllowTargeting(not bool) +end + +---This will add target options to players. +---@param options table Target.AddGlobalPlayer = function(options) options = Target.FixOptions(options) - exports['qb-target']:AddGlobalPlayer({ + qb_target:AddGlobalPlayer({ options = options, distance = options.distance or 1.5 }) end +---This will remove target options from all players. +Target.RemoveGlobalPlayer = function() + qb_target:RemoveGlobalPlayer() +end +---This will add taget options to all vehicles. +---@param options table Target.AddGlobalVehicle = function(options) options = Target.FixOptions(options) - exports['qb-target']:AddGlobalVehicle({ + qb_target:AddGlobalVehicle({ options = options, distance = options.distance or 1.5 }) end +---This will remove target options from all vehicles. +---@param options table Target.RemoveGlobalVehicle = function(options) local assembledLables = {} for k, v in pairs(options) do table.insert(assembledLables, v.label) end - exports['qb-target']:RemoveGlobalVehicle(assembledLables) + qb_target:RemoveGlobalVehicle(assembledLables) end +---This will generate targets on non networked entites with the passed options. +---@param entities number | table +---@param options table Target.AddLocalEntity = function(entities, options) options = Target.FixOptions(options) - exports['qb-target']:AddTargetEntity(entities, { + qb_target:AddTargetEntity(entities, { options = options, distance = options.distance or 1.5 }) end +---This will remove the target options from a local entity. This is useful for when you want to remove target options from a specific entity. +---@param entity any +Target.RemoveLocalEntity = function(entity) + qb_target:RemoveTargetEntity(entity) +end + +---This will add target options to all specified models. This is useful for when you want to add target options to all models of a specific type. +---@param models number | table +---@param options table Target.AddModel = function(models, options) options = Target.FixOptions(options) - exports['qb-target']:AddTargetModel(models, { + qb_target:AddTargetModel(models, { options = options, distance = options.distance or 1.5, }) end +---This will remove target options from all specified models. +---@param model number +Target.RemoveModel = function(model) + qb_target:RemoveTargetModel(model) +end + +---This will add a box zone to the target system. This is useful for when you want to add target options to a specific area. +---@param name string +---@param coords table +---@param size table +---@param heading number +---@param options table Target.AddBoxZone = function(name, coords, size, heading, options) options = Target.FixOptions(options) - exports['qb-target']:AddBoxZone(name, coords, size.x, size.y, { + qb_target:AddBoxZone(name, coords, size.x, size.y, { name = name, debugPoly = targetDebug, heading = heading, @@ -87,22 +132,30 @@ Target.AddBoxZone = function(name, coords, size, heading, options) table.insert(targetZones, { name = name, creator = GetInvokingResource() }) end -Target.RemoveGlobalPlayer = function() - exports['qb-target']:RemoveGlobalPlayer() -end - -Target.RemoveLocalEntity = function(entity) - exports['qb-target']:RemoveTargetEntity(entity) -end - -Target.RemoveModel = function(model) - exports['qb-target']:RemoveTargetModel(model) +---This will add a circle zone to the target system. This is useful for when you want to add target options to a specific area. +---@param name string +---@param coords table +---@param radius number +---@param options table +Target.AddSphereZone = function(name, coords, radius, options) + options = Target.FixOptions(options) + qb_target:AddCircleZone(name, coords, radius, { + name = name, + debugPoly = targetDebug, + }, { + options = options, + distance = options.distance or 1.5, + }) + table.insert(targetZones, { name = name, creator = GetInvokingResource() }) end +---This will remove target options from a specific zone. +---@param name string Target.RemoveZone = function(name) + if not name then return end for _, data in pairs(targetZones) do if data.name == name then - exports['qb-target']:RemoveZone(name) + qb_target:RemoveZone(name) table.remove(targetZones, _) break end @@ -110,12 +163,11 @@ Target.RemoveZone = function(name) end AddEventHandler('onResourceStop', function(resource) - if resource == GetCurrentResourceName() then - for _, target in pairs(targetZones) do - if target.creator == resource then - exports['qb-target']:RemoveZone(target.name) - end + if resource ~= GetCurrentResourceName() then return end + for _, target in pairs(targetZones) do + if target.creator == resource then + qb_target:RemoveZone(target.name) end - targetZones = {} end + targetZones = {} end) \ No newline at end of file diff --git a/modules/target/sleepless_interact/client.lua b/modules/target/sleepless_interact/client.lua index 01315b0..9ae72a3 100644 --- a/modules/target/sleepless_interact/client.lua +++ b/modules/target/sleepless_interact/client.lua @@ -2,10 +2,18 @@ local resourceName = "sleepless_interact" local configValue = BridgeClientConfig.TargetSystem if (configValue == "auto" and GetResourceState(resourceName) ~= "started") or (configValue ~= "auto" and configValue ~= resourceName) then return end ---if GetResourceState('sleepless_interact') ~= 'started' then return end --- This is only partially supported -local sleepless = exports.sleepless_interact +local targetDebug = false +local function detectDebugEnabled() + if BridgeClientConfig.DebugLevel == 2 then + targetDebug = true + end +end + +detectDebugEnabled() + +local sleepless_interact = exports.sleepless_interact +local targetZones = {} Target = Target or {} @@ -23,18 +31,111 @@ Target.FixOptions = function(options) return options end -Target.AddLocalEntity = function(entity, _options) - local options = Target.FixOptions(_options) - sleepless:addLocalEntity({ - id = entity, - entity = entity, - options = options, - renderDistance = 10.0, - activeDistance = 2.0, - cooldown = 1500 - }) +---comment +---@param options table +---@return nil +Target.AddGlobalPlayer = function(options) + options = Target.FixOptions(options) + sleepless_interact:addGlobalPlayer(options) end +Target.DisableTargeting = function(bool) + --sleepless_interact:disableTargeting(bool) + sleepless_interact:disableInteract(bool) +end + +---comment +---@param options table +---@return nil +Target.AddGlobalVehicle = function(options) + options = Target.FixOptions(options) + sleepless_interact:addGlobalVehicle(options) +end + +---comment +---@param options table +---@return nil +Target.RemoveGlobalVehicle = function(options) + local assembledLables = {} + for k, v in pairs(options) do + table.insert(assembledLables, v.name) + end + sleepless_interact:removeGlobalVehicle(assembledLables) +end + +---comment +---@param entities table +---@param options table +---@return nil +Target.AddLocalEntity = function(entities, options) + options = Target.FixOptions(options) + sleepless_interact:addLocalEntity(entities, options) +end + +---comment +---@param models table +---@param options table +---@return nil +Target.AddModel = function(models, options) + options = Target.FixOptions(options) + sleepless_interact:addModel(models, options) +end + +---comment +---@param name string +---@param coords table +---@param size table +---@param heading number +---@param options table +---@return number +Target.AddBoxZone = function(name, coords, size, heading, options) + options = Target.FixOptions(options) + local target = sleepless_interact:addCoords({ + coords = coords, + options = options, + }) + table.insert(targetZones, { name = name, id = target, creator = GetInvokingResource() }) + return target +end + +Target.RemoveGlobalPlayer = function() + sleepless_interact:removeGlobalPlayer() +end + +---comment +---@param entity number +---@return nil Target.RemoveLocalEntity = function(entity) - sleepless:removeLocalEntity(entity) -end \ No newline at end of file + sleepless_interact:removeLocalEntity(entity) +end + +---comment +---@param model string +---@return nil +Target.RemoveModel = function(model) + sleepless_interact:removeModel(model) +end + +---comment +---@param name string +---@return nil +Target.RemoveZone = function(name) + for _, data in pairs(targetZones) do + if data.name == name then + sleepless_interact:removeCoords(data.id) + table.remove(targetZones, _) + break + end + end +end + +AddEventHandler('onResourceStop', function(resource) + if resource == GetCurrentResourceName() then + for _, target in pairs(targetZones) do + if target.creator == resource then + sleepless_interact:removeZone(target.id) + end + end + targetZones = {} + end +end) diff --git a/modules/vehicleKey/_default/client/client.lua b/modules/vehicleKey/_default/client/client.lua index da6a547..5472dc7 100644 --- a/modules/vehicleKey/_default/client/client.lua +++ b/modules/vehicleKey/_default/client/client.lua @@ -1,9 +1,16 @@ VehicleKey = VehicleKey or {} +---This will give keys to the specifed vehicle/plate. +---@param vehicle number The vehicle entity ID. +---@param plate string The plate of the vehicle. VehicleKey.GiveKeys = function(vehicle, plate) return true, print("There Is No Vehicle Key System Installed") end +---This will remove keys from the specifed vehicle/plate. +---@param vehicle number The vehicle entity ID. +---@param plate string The plate of the vehicle. +---@return boolean | nil VehicleKey.RemoveKeys = function(vehicle, plate) return true, print("There Is No Vehicle Key System Installed") end \ No newline at end of file diff --git a/modules/weather/_default/client.lua b/modules/weather/_default/client.lua new file mode 100644 index 0000000..93a508a --- /dev/null +++ b/modules/weather/_default/client.lua @@ -0,0 +1,8 @@ +Weather = Weather or {} + +---This will toggle the players weather/time sync +---@param toggle boolean +---@return nil +Weather.ToggleSync = function(toggle) + +end \ No newline at end of file diff --git a/modules/weather/cd_easytime/client.lua b/modules/weather/cd_easytime/client.lua new file mode 100644 index 0000000..e3740dc --- /dev/null +++ b/modules/weather/cd_easytime/client.lua @@ -0,0 +1,8 @@ +if GetResourceState('cd_easytime') ~= 'started' then return end +Weather = Weather or {} + +---comment +---@param toggle boolean +Weather.ToggleSync = function(toggle) + TriggerEvent('cd_easytime:PauseSync', toggle) +end \ No newline at end of file diff --git a/modules/weather/qb-weathersync/client/client.lua b/modules/weather/qb-weathersync/client/client.lua index e669fac..d6eb030 100644 --- a/modules/weather/qb-weathersync/client/client.lua +++ b/modules/weather/qb-weathersync/client/client.lua @@ -1,5 +1,5 @@ if GetResourceState('qb-weathersync') ~= 'started' then return end -Weather = {} +Weather = Weather or {} ---comment ---@param toggle boolean diff --git a/modules/weather/renewed-weathersync/client/client.lua b/modules/weather/renewed-weathersync/client/client.lua index d6589c7..66bb585 100644 --- a/modules/weather/renewed-weathersync/client/client.lua +++ b/modules/weather/renewed-weathersync/client/client.lua @@ -1,5 +1,5 @@ if GetResourceState('Renewed-Weathersync') ~= 'started' then return end -Weather = {} +Weather = Weather or {} ---comment ---@param toggle boolean diff --git a/modules/weather/vSync/client/client.lua b/modules/weather/vSync/client/client.lua deleted file mode 100644 index e669fac..0000000 --- a/modules/weather/vSync/client/client.lua +++ /dev/null @@ -1,12 +0,0 @@ -if GetResourceState('qb-weathersync') ~= 'started' then return end -Weather = {} - ----comment ----@param toggle boolean -Weather.ToggleSync = function(toggle) - if toggle then - TriggerEvent("qb-weathersync:client:EnableSync") - else - TriggerEvent("qb-weathersync:client:DisableSync") - end -end \ No newline at end of file diff --git a/unit_tests/callbacks_test.lua b/unit_tests/callbacks_test.lua index de88fa2..55247cf 100644 --- a/unit_tests/callbacks_test.lua +++ b/unit_tests/callbacks_test.lua @@ -6,20 +6,19 @@ -- ▄█▀ █▄▄ █▀▄ ▀▄▀ █▄▄ █▀▄ -- -- -- -- -- -- -- -- -- -- if not IsDuplicityVersion() then goto client end -exports.community_bridge:RegisterCallback('ClientToServerToClient', function(src, cb, ftpcsftug) - cb(ftpcsftug, 'some random string') + +exports.community_bridge:RegisterCallback('callback_test1_name_here', function(src, var1) + if var1 == "herpaderpa" then + print("this is a test") + end + return 'some random string', "some other string" end) -RegisterCommand('cb_server_test', function(source) - local someData = exports.community_bridge:TriggerCallback('ServerToClientToServer', source, function(ftpcsftug, derpa) - print(ftpcsftug, derpa) - return "This data gets passed up the chain" - end,"herpaderpa") - print("print", someData) +RegisterCommand('callback_test2', function(source) + local someData, other = exports.community_bridge:TriggerCallback('callback_test2_name_here', source, "herpaderpa") + print("Data From Client: ", someData, other) end) - - -- -- -- -- -- -- -- -- -- -- -- ▄▀▀ █ █ ██▀ █▄ █ ▀█▀ -- ▀▄▄ █▄▄ █ █▄▄ █ ▀█ █ @@ -27,18 +26,15 @@ end) if IsDuplicityVersion() then return end ::client:: - -RegisterCommand('cb_client_test', function() - local someData = exports.community_bridge:TriggerCallback('ClientToServerToClient', function(ftpcsftug, derpa) - print(ftpcsftug, derpa, "This will fire on the player who triggered the event") - end,"herpaderpa") - print(someData) +RegisterCommand('callback_test1', function() + local somerandomstring, someotherrandomstring = exports.community_bridge:TriggerCallback('callback_test1_name_here', "herpaderpa") + print("Data From Server: ", somerandomstring, someotherrandomstring) end) -exports.community_bridge:RegisterRebound('ClientToServerToClient', function(src, cb, ftpcsftug) - print("this is a rebound from another player or himself") -end) +-- exports.community_bridge:RegisterRebound('callback_test1', function(src, cb, ftpcsftug) +-- print("this is a rebound to all players") +-- end) -exports.community_bridge:RegisterCallback('ServerToClientToServer', function(cb, ftpcsftug) - cb(ftpcsftug, 'TestyMcTesterton') +exports.community_bridge:RegisterCallback('callback_test2_name_here', function(ftpcsftug) + return ftpcsftug, 'TestyMcTesterton' end) diff --git a/unit_tests/locale_test.lua b/unit_tests/locale_test.lua new file mode 100644 index 0000000..3b55377 --- /dev/null +++ b/unit_tests/locale_test.lua @@ -0,0 +1,19 @@ +-- if outside this resource, use local whatever = Require("modules/locales/shared.lua") +-- whatever.Locales("some-index-in-language-.json-file") +-- Files must be stored in "locales" folder, within the resource. +-- Instead of using Require you can also import it via the manifest. +-- The Lang variable is available globally, which tells you what the server is using. +-- print("Language: ", Lang) +-- print("Locale: ", Language.Locale("locale-unit-test")) + +-- Example outside community bridge resource: + +-- local Language = Require('modules/locales/shared.lua') +-- print("Language: ", Lang) +-- print("Locale: ", Language.Locale("locale-unit-test")) +RegisterCommand("lang", function(source, args, raw) + print(Language.Locale("UNITTEST.UNITTEST.UNITTESTA")) + print(Language.Locale("UNITTEST.UNITTESTA", "Devil", "GERRRRRRR!")) + + print( "Oh also this works", Language.Locale("place_object_scroll_down")) +end, false) \ No newline at end of file