Skip to content

Commit

Permalink
Merge pull request #1568 from esx-framework/dev
Browse files Browse the repository at this point in the history
ESX Legacy v1.12 🚀  dev -> main
  • Loading branch information
Arctos2win authored Jan 1, 2025
2 parents 617bfb6 + 452877c commit 1895a91
Show file tree
Hide file tree
Showing 63 changed files with 2,604 additions and 892 deletions.
47 changes: 47 additions & 0 deletions CONTRIBUTING.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
# Contribution Guidelines

If you're planning to contribute, **please follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.**

Pull Requests (PRs) that do not adhere to this standard will **not be accepted**.

## Branch Requirements

- **All PRs must be based on the `dev` branch.**
- Merges will only occur into the `dev` branch before being released to the main branch.

## Commit Message Format

Ensure your commit messages and PR titles use the following format:

```
<type>(<scope>): <description>
```

For example:
```
feat(es_extended/client/main): sync where players look at
fix(es_extended/client/functions): validate model is a vehicle
refactor(es_extended/client/modules/death): replace gameEventTriggered
```

Common commit types include:
- **`feat`** for new features
- **`fix`** for bug fixes
- **`refactor`** for code improvements without functionality changes
- **`!`** to indicate breaking changes (e.g., `feat!` or `fix!`)

---

## PR Checklist

**Please include this in your PR.**
```
- [ ] My commit messages and PR title follow the [Conventional Commits](https://www.conventionalcommits.org/en/v1.0.0/) standard.
- [ ] My changes have been tested locally and function as expected.
- [ ] My PR does not introduce any breaking changes.
- [ ] I have provided a clear explanation of what my PR does, including the reasoning behind the changes and any relevant context.
```


# We value your contribution!
By adhering to these guidelines, we can ensure a clean and maintainable codebase. Thank you for contributing to ESX!
7 changes: 7 additions & 0 deletions [SQL]/legacy.sql
Original file line number Diff line number Diff line change
Expand Up @@ -821,6 +821,13 @@ ALTER TABLE `licenses`
ALTER TABLE `owned_vehicles`
ADD PRIMARY KEY (`plate`);

--
--
-- Indexes for table `vehicles`
--
ALTER TABLE `vehicles`
ADD PRIMARY KEY (`model`);

--
-- Indexes for table `rented_vehicles`
--
Expand Down
60 changes: 42 additions & 18 deletions [core]/cron/server/main.lua
Original file line number Diff line number Diff line change
@@ -1,51 +1,75 @@
local Jobs = {}
local LastTime = nil
---@class CronJob
---@field h number
---@field m number
---@field cb function|table

---@type CronJob[]
local cronJobs = {}
---@type number|false
local lastTimestamp = false

---@param h number
---@param m number
---@param cb function|table
function RunAt(h, m, cb)
Jobs[#Jobs + 1] = {
cronJobs[#cronJobs + 1] = {
h = h,
m = m,
cb = cb,
}
end

---@return number
function GetUnixTimestamp()
return os.time()
end

function OnTime(time)
for i = 1, #Jobs, 1 do
---@param timestamp number
function OnTime(timestamp)
for i = 1, #cronJobs, 1 do
local scheduledTimestamp = os.time({
hour = Jobs[i].h,
min = Jobs[i].m,
hour = cronJobs[i].h,
min = cronJobs[i].m,
sec = 0, -- Assuming tasks run at the start of the minute
day = os.date("%d", time),
month = os.date("%m", time),
year = os.date("%Y", time),
day = os.date("%d", timestamp),
month = os.date("%m", timestamp),
year = os.date("%Y", timestamp),
})

if time >= scheduledTimestamp and (not LastTime or LastTime < scheduledTimestamp) then
if timestamp >= scheduledTimestamp and (not lastTimestamp or lastTimestamp < scheduledTimestamp) then
local d = os.date('*t', scheduledTimestamp).wday
Jobs[i].cb(d, Jobs[i].h, Jobs[i].m)
cronJobs[i].cb(d, cronJobs[i].h, cronJobs[i].m)
end
end
end

---@return nil
function Tick()
local time = GetUnixTimestamp()
local timestamp = GetUnixTimestamp()

if not LastTime or os.date("%M", time) ~= os.date("%M", LastTime) then
OnTime(time)
LastTime = time
if not lastTimestamp or os.date("%M", timestamp) ~= os.date("%M", lastTimestamp) then
OnTime(timestamp)
lastTimestamp = timestamp
end

SetTimeout(60000, Tick)
end

LastTime = GetUnixTimestamp()

lastTimestamp = GetUnixTimestamp()
Tick()

---@param h number
---@param m number
---@param cb function|table
AddEventHandler("cron:runAt", function(h, m, cb)
local invokingResource = GetInvokingResource() or "Unknown"
local typeH = type(h)
local typeM = type(m)
local typeCb = type(cb)

assert(typeH == "number", ("Expected number for h, got %s. Invoking Resource: '%s'"):format(typeH, invokingResource))
assert(typeM == "number", ("Expected number for m, got %s. Invoking Resource: '%s'"):format(typeM, invokingResource))
assert(typeCb == "function" or (typeCb == "table" and type(getmetatable(cb)?.__call) == "function"), ("Expected function for cb, got %s. Invoking Resource: '%s'"):format(typeCb, invokingResource))

RunAt(h, m, cb)
end)
30 changes: 0 additions & 30 deletions [core]/es_extended/client/common.lua

This file was deleted.

34 changes: 28 additions & 6 deletions [core]/es_extended/client/functions.lua
Original file line number Diff line number Diff line change
Expand Up @@ -391,7 +391,7 @@ function ESX.UI.Menu.Close(menuType, namespace, name, cancel)
else
local menu = ESX.UI.Menu.Opened[i]
ESX.UI.Menu.RegisteredTypes[menu.type].close(menu.namespace, menu.name)

if type(menu.cancel) ~= "nil" then
menu.cancel(menu.data, menu)
end
Expand All @@ -412,7 +412,7 @@ function ESX.UI.Menu.CloseAll(cancel)
else
local menu = ESX.UI.Menu.Opened[i]
ESX.UI.Menu.RegisteredTypes[menu.type].close(menu.namespace, menu.name)

if type(menu.cancel) ~= "nil" then
menu.cancel(menu.data, menu)
end
Expand Down Expand Up @@ -530,10 +530,14 @@ end
---@param vehicleModel integer | string The vehicle to spawn
---@param coords table | vector3 The coords to spawn the vehicle at
---@param heading number The heading of the vehicle
---@param cb? function The callback function
---@param cb? fun(vehicle: number) The callback function
---@param networked? boolean Whether the vehicle should be networked
---@return nil
---@return number? vehicle
function ESX.Game.SpawnVehicle(vehicleModel, coords, heading, cb, networked)
if cb and not ESX.IsFunctionReference(cb) then
error("Invalid callback function")
end

local model = type(vehicleModel) == "number" and vehicleModel or joaat(vehicleModel)
local vector = type(coords) == "vector3" and coords or vec(coords.x, coords.y, coords.z)
local isNetworked = networked == nil or networked
Expand All @@ -549,8 +553,15 @@ function ESX.Game.SpawnVehicle(vehicleModel, coords, heading, cb, networked)
return error(("Resource ^5%s^1 Tried to spawn vehicle on the client but the position is too far away (Out of onesync range)."):format(executingResource))
end

local promise = not cb and promise.new()
CreateThread(function()
ESX.Streaming.RequestModel(model)
local modelHash = ESX.Streaming.RequestModel(model)
if not modelHash then
if promise then
return promise:reject(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
end
error(("Tried to spawn invalid vehicle - ^5%s^7!"):format(model))
end

local vehicle = CreateVehicle(model, vector.x, vector.y, vector.z, heading, isNetworked, true)

Expand All @@ -569,10 +580,16 @@ function ESX.Game.SpawnVehicle(vehicleModel, coords, heading, cb, networked)
Wait(0)
end

if cb then
if promise then
promise:resolve(vehicle)
elseif cb then
cb(vehicle)
end
end)

if promise then
return Citizen.Await(promise)
end
end

---@param vehicle integer The vehicle to spawn
Expand Down Expand Up @@ -1585,6 +1602,11 @@ function ESX.GetVehicleTypeClient(model)
if not IsModelInCdimage(model) then
return false
end

if not IsModelAVehicle(model) then
return false
end

if mismatchedTypes[model] then
return mismatchedTypes[model]
end
Expand Down
21 changes: 21 additions & 0 deletions [core]/es_extended/client/imports/class.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
local class = {}
class.__index = class

function class:new(...)
local instance = setmetatable({}, self)
if instance.constructor then
local ret = instance:constructor(...)
if type(ret) == 'table' then
return ret
end
end
return instance
end

function Class(body, heritage)
local prototype = body or {}
prototype.__index = prototype
return setmetatable(prototype, heritage or class)
end

return Class
53 changes: 53 additions & 0 deletions [core]/es_extended/client/imports/point.lua
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
local Point = ESX.Class()

local nearby, loop = {}

function Point:constructor(properties)
self.coords = properties.coords
self.hidden = properties.hidden
self.enter = properties.enter
self.leave = properties.leave
self.inside = properties.inside
self.handle = ESX.CreatePointInternal(properties.coords, properties.distance, properties.hidden, function()
nearby[self.handle] = self
if self.enter then
self:enter()
end
if not loop then
loop = true
CreateThread(function()
while loop do
local coords = GetEntityCoords(ESX.PlayerData.ped)
for handle, point in pairs(nearby) do
if point.inside then
point:inside(#(coords - point.coords))
end
end
Wait()
end
end)
end
end, function()
nearby[self.handle] = nil
if self.leave then
self:leave()
end
if #nearby == 0 then
loop = false
end
end)
end

function Point:delete()
ESX.RemovePointInternal(self.handle)
end

function Point:toggle(hidden)
if hidden == nil then
hidden = not self.hidden
end
self.hidden = hidden
ESX.HidePointInternal(self.handle, hidden)
end

return Point
Loading

0 comments on commit 1895a91

Please sign in to comment.