forked from Simnation/Main
ed
This commit is contained in:
parent
510e3ffcf2
commit
f43cf424cf
305 changed files with 34683 additions and 0 deletions
|
@ -0,0 +1,324 @@
|
|||
local Entities = {}
|
||||
local isServer = IsDuplicityVersion()
|
||||
local registeredFunctions = {}
|
||||
ReboundEntities = {}
|
||||
|
||||
function ReboundEntities.AddFunction(func)
|
||||
assert(func, "Func is nil")
|
||||
table.insert(registeredFunctions, func)
|
||||
return #registeredFunctions
|
||||
end
|
||||
|
||||
function ReboundEntities.RemoveFunction(id)
|
||||
assert(id and registeredFunctions[id], "Invalid ID")
|
||||
registeredFunctions[id] = false
|
||||
end
|
||||
|
||||
function FireFunctions(...)
|
||||
for _, func in pairs(registeredFunctions) do
|
||||
func(...)
|
||||
end
|
||||
end
|
||||
|
||||
function ReboundEntities.Register(entityData)
|
||||
assert(entityData and entityData.position, "Invalid entity data")
|
||||
entityData.id = entityData.id or Ids.CreateUniqueId(Entities)
|
||||
entityData.isServer = isServer
|
||||
setmetatable(entityData, { __tostring = function() return entityData.id end })
|
||||
Entities[entityData.id] = entityData
|
||||
FireFunctions(entityData)
|
||||
return entityData
|
||||
end
|
||||
|
||||
local function Unregister(id)
|
||||
Entities[id] = nil
|
||||
end
|
||||
|
||||
function ReboundEntities.GetSyncData(entityData, key)
|
||||
return entityData[key]
|
||||
end
|
||||
|
||||
function ReboundEntities.GetAll()
|
||||
return Entities
|
||||
end
|
||||
|
||||
function ReboundEntities.GetById(id)
|
||||
return Entities[tostring(id)]
|
||||
end
|
||||
|
||||
function ReboundEntities.GetByModel(model)
|
||||
local entities = {}
|
||||
for _, entity in pairs(Entities) do
|
||||
if entity.model == model then
|
||||
table.insert(entities, entity)
|
||||
end
|
||||
end
|
||||
return entities
|
||||
end
|
||||
|
||||
function ReboundEntities.GetClosest(pos)
|
||||
local closest, closestDist = nil, 9999
|
||||
for _, entity in pairs(Entities) do
|
||||
local dist = #(pos - entity.position)
|
||||
if dist < closestDist then
|
||||
closest, closestDist = entity, dist
|
||||
end
|
||||
end
|
||||
return closest
|
||||
end
|
||||
|
||||
function ReboundEntities.GetWithinRadius(pos, radius)
|
||||
local entities = {}
|
||||
for _, entity in pairs(Entities) do
|
||||
if #(pos - entity.position) < radius then
|
||||
table.insert(entities, entity)
|
||||
end
|
||||
end
|
||||
return entities
|
||||
end
|
||||
|
||||
function ReboundEntities.SetOnSyncKeyChange(entityData, cb)
|
||||
local data = ReboundEntities.GetById(entityData.id or entityData)
|
||||
assert(data, "Entity not found")
|
||||
data.onSyncKeyChange = cb
|
||||
end
|
||||
|
||||
exports('ReboundEntities', ReboundEntities)
|
||||
|
||||
if not isServer then goto client end
|
||||
|
||||
function ReboundEntities.Create(entityData, src)
|
||||
local entity = ReboundEntities.Register(entityData)
|
||||
assert(entity and entity.position, "Invalid entity data")
|
||||
entity.rotation = entity.rotation or vector3(0, 0, entityData.heading or 0)
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:CreateReboundEntity", src or -1, entity)
|
||||
return entity
|
||||
end
|
||||
|
||||
|
||||
function ReboundEntities.SetCheckRestricted(entityData, cb)
|
||||
assert(type(cb) == "function", "Check restricted is not a function")
|
||||
entityData.restricted = cb
|
||||
end
|
||||
|
||||
|
||||
function ReboundEntities.CheckRestricted(src, entityData)
|
||||
return entityData.restricted and entityData.restricted(tonumber(src), entityData) or false
|
||||
end
|
||||
|
||||
function ReboundEntities.Refresh(src)
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:CreateReboundEntities", tonumber(src), ReboundEntities.GetAccessibleList(src))
|
||||
end
|
||||
|
||||
function ReboundEntities.Delete(id)
|
||||
Unregister(id)
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:DeleteReboundEntity", -1, id)
|
||||
end
|
||||
|
||||
function ReboundEntities.DeleteMultiple(entityDatas)
|
||||
local ids = {}
|
||||
for _, data in pairs(entityDatas) do
|
||||
Unregister(data.id)
|
||||
table.insert(ids, data.id)
|
||||
end
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:DeleteReboundEntities", -1, ids)
|
||||
end
|
||||
|
||||
function ReboundEntities.CreateMultiple(entityDatas, src, restricted)
|
||||
local _entityDatas = {}
|
||||
for _, data in pairs(entityDatas) do
|
||||
local entity = ReboundEntities.Register(data)
|
||||
assert(entity and entity.position, "Invalid entity data")
|
||||
entity.rotation = entity.rotation or vector3(0, 0, 0)
|
||||
if restricted then ReboundEntities.SetCheckRestricted(entity, restricted) end
|
||||
if not ReboundEntities.CheckRestricted(src, entity) then
|
||||
_entityDatas[entity.id] = entity
|
||||
end
|
||||
end
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:CreateReboundEntities", src or -1, _entityDatas)
|
||||
return _entityDatas
|
||||
end
|
||||
|
||||
function ReboundEntities.SetSyncData(entityData, key, value)
|
||||
entityData[key] = value
|
||||
if entityData.onSyncKeyChange then
|
||||
entityData.onSyncKeyChange(entityData, key, value)
|
||||
end
|
||||
TriggerClientEvent(GetCurrentResourceName() .. ":client:SetReboundSyncData", -1, entityData.id, key, value)
|
||||
end
|
||||
|
||||
function ReboundEntities.GetAccessibleList(src)
|
||||
local list = {}
|
||||
for _, data in pairs(ReboundEntities.GetAll()) do
|
||||
if not ReboundEntities.CheckRestricted(src, data) then
|
||||
list[data.id] = data
|
||||
end
|
||||
end
|
||||
return list
|
||||
end
|
||||
|
||||
RegisterNetEvent("playerJoining", function()
|
||||
ReboundEntities.Refresh(source)
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStart', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then return end
|
||||
Wait(1000)
|
||||
for _, src in pairs(GetPlayers()) do
|
||||
ReboundEntities.Refresh(src)
|
||||
end
|
||||
end)
|
||||
|
||||
::client::
|
||||
if isServer then return ReboundEntities end
|
||||
|
||||
function ReboundEntities.LoadModel(model)
|
||||
assert(model, "Model is nil")
|
||||
model = type(model) == "number" and model or GetHashKey(model) -- Corrected to GetHashKey
|
||||
RequestModel(model)
|
||||
for i = 1, 100 do
|
||||
if HasModelLoaded(model) then return model end
|
||||
Wait(100)
|
||||
end
|
||||
error(string.format("Failed to load model %s", model))
|
||||
end
|
||||
|
||||
function ReboundEntities.Spawn(entityData)
|
||||
local model = entityData.model
|
||||
local position = entityData.position
|
||||
assert(position, "Position is nil")
|
||||
local rotation = entityData.rotation or vector3(0, 0, 0)
|
||||
local entity = model and CreateObject(ReboundEntities.LoadModel(model), position.x, position.y, position.z, false, false, false)
|
||||
if entity then SetEntityRotation(entity, rotation.x, rotation.y, rotation.z) end
|
||||
if entityData.onSpawn then entity = entityData.onSpawn(entityData, entity) or entity end
|
||||
return entity, true
|
||||
end
|
||||
|
||||
function ReboundEntities.SetOnSpawn(id, cb)
|
||||
local entity = ReboundEntities.GetById(tostring(id))
|
||||
assert(entity, "Entity not found")
|
||||
entity.onSpawn = cb
|
||||
return true
|
||||
end
|
||||
|
||||
function ReboundEntities.Despawn(entityData)
|
||||
local entity = entityData.entity
|
||||
if entityData.onDespawn then entityData.onDespawn(entityData, entity) end
|
||||
if entity and DoesEntityExist(entity) then DeleteEntity(entity) end
|
||||
return nil, nil
|
||||
end
|
||||
|
||||
function ReboundEntities.SetOnDespawn(id, cb)
|
||||
local entity = ReboundEntities.GetById(tostring(id))
|
||||
assert(entity, "Entity not found")
|
||||
entity.onDespawn = cb
|
||||
return true
|
||||
end
|
||||
|
||||
local spawnLoopRunning = false
|
||||
|
||||
function ReboundEntities.SpawnLoop(distanceToCheck, waitTime)
|
||||
if spawnLoopRunning then return end
|
||||
spawnLoopRunning = true
|
||||
distanceToCheck = distanceToCheck or 50
|
||||
waitTime = waitTime or 2500
|
||||
CreateThread(function()
|
||||
while spawnLoopRunning do
|
||||
for _, entity in pairs(Entities) do
|
||||
local pos = GetEntityCoords(PlayerPedId())
|
||||
local position = vector3(entity.position.x, entity.position.y, entity.position.z)
|
||||
local dist = #(pos - position)
|
||||
if dist <= distanceToCheck and not entity.entity then
|
||||
entity.entity, entity.inRange = ReboundEntities.Spawn(entity)
|
||||
elseif dist > distanceToCheck and entity.entity then
|
||||
entity.entity, entity.inRange = ReboundEntities.Despawn(entity)
|
||||
end
|
||||
end
|
||||
Wait(waitTime)
|
||||
end
|
||||
end)
|
||||
end
|
||||
|
||||
function ReboundEntities.GetByEntity(entity)
|
||||
for _, data in pairs(Entities) do
|
||||
if data.entity == entity then return data end
|
||||
end
|
||||
end
|
||||
|
||||
function ReboundEntities.CreateClient(entityData)
|
||||
local entity = ReboundEntities.Register(entityData)
|
||||
if entity then ReboundEntities.SpawnLoop() end
|
||||
return entity
|
||||
end
|
||||
|
||||
function ReboundEntities.DeleteClient(id)
|
||||
local entityData = ReboundEntities.GetById(tostring(id))
|
||||
assert(not entityData.isServer, "Cannot delete server entity from client")
|
||||
if entityData.entity then ReboundEntities.Despawn(entityData) end
|
||||
Unregister(id)
|
||||
return true
|
||||
end
|
||||
|
||||
function ReboundEntities.CreateMultipleClient(entityDatas)
|
||||
local _entityDatas = {}
|
||||
for _, data in pairs(entityDatas) do
|
||||
local entityData = ReboundEntities.CreateClient(data)
|
||||
_entityDatas[entityData.id] = entityData
|
||||
end
|
||||
return _entityDatas
|
||||
end
|
||||
|
||||
function ReboundEntities.DeleteMultipleClient(ids)
|
||||
for _, id in pairs(ids) do
|
||||
ReboundEntities.DeleteClient(id)
|
||||
end
|
||||
end
|
||||
|
||||
local function DeleteFromServer(id)
|
||||
local entityData = ReboundEntities.GetById(tostring(id))
|
||||
if entityData then
|
||||
entityData.isServer = nil
|
||||
ReboundEntities.DeleteClient(id)
|
||||
end
|
||||
end
|
||||
|
||||
local function DeleteMultipleFromServer(ids)
|
||||
for _, id in pairs(ids) do
|
||||
DeleteFromServer(id)
|
||||
end
|
||||
end
|
||||
|
||||
RegisterNetEvent(GetCurrentResourceName() .. ":client:CreateReboundEntity", function(entityData)
|
||||
ReboundEntities.CreateClient(entityData)
|
||||
end)
|
||||
|
||||
RegisterNetEvent(GetCurrentResourceName() .. ":client:DeleteReboundEntity", function(id)
|
||||
DeleteFromServer(id)
|
||||
end)
|
||||
|
||||
RegisterNetEvent(GetCurrentResourceName() .. ":client:CreateReboundEntities", function(entityDatas)
|
||||
ReboundEntities.CreateMultipleClient(entityDatas)
|
||||
end)
|
||||
|
||||
RegisterNetEvent(GetCurrentResourceName() .. ":client:DeleteReboundEntities", function(ids)
|
||||
ReboundEntities.DeleteMultipleClient(ids)
|
||||
end)
|
||||
|
||||
RegisterNetEvent(GetCurrentResourceName() .. ":client:SetReboundSyncData", function(id, key, value)
|
||||
local entityData = ReboundEntities.GetById(id)
|
||||
if not entityData then return end
|
||||
entityData[key] = value
|
||||
if entityData.onSyncKeyChange then
|
||||
entityData.onSyncKeyChange(entityData, key, value)
|
||||
end
|
||||
end)
|
||||
|
||||
AddEventHandler('onResourceStop', function(resource)
|
||||
if resource ~= GetCurrentResourceName() then return end
|
||||
spawnLoopRunning = false
|
||||
for _, entity in pairs(Entities) do
|
||||
if entity.entity then DeleteEntity(tonumber(entity.entity)) end
|
||||
end
|
||||
end)
|
||||
|
||||
return ReboundEntities
|
Loading…
Add table
Add a link
Reference in a new issue