forked from Simnation/Main
red
This commit is contained in:
parent
9178871ecd
commit
640cdd069b
9 changed files with 583 additions and 269 deletions
|
@ -1,4 +1,5 @@
|
|||
local NextId = 1
|
||||
local Entities = {}
|
||||
|
||||
UtilityNet = UtilityNet or {}
|
||||
|
||||
|
@ -10,24 +11,27 @@ UtilityNet = UtilityNet or {}
|
|||
-- }
|
||||
|
||||
UtilityNet.CreateEntity = function(model, coords, options, callId)
|
||||
options = options or {}
|
||||
local hashmodel = nil
|
||||
|
||||
--#region Checks
|
||||
if not model or (type(model) ~= "string" and type(model) ~= "number") then
|
||||
error("Invalid model, got "..type(model).." expected string or number", 0)
|
||||
else
|
||||
if type(model) == "string" then
|
||||
model = GetHashKey(model)
|
||||
hashmodel = GetHashKey(model)
|
||||
else
|
||||
hashmodel = model
|
||||
end
|
||||
end
|
||||
|
||||
if not coords or type(coords) ~= "vector3" then
|
||||
error("Invalid coords, got "..type(coords).." expected vector3", 0)
|
||||
end
|
||||
|
||||
options = options or {}
|
||||
--#endregion
|
||||
|
||||
--#region Event
|
||||
TriggerEvent("Utility:Net:EntityCreating", model, coords, options)
|
||||
TriggerEvent("Utility:Net:EntityCreating", hashmodel, coords, options)
|
||||
|
||||
-- EntityCreating event can be canceled, in that case we dont create the entity
|
||||
if WasEventCanceled() then
|
||||
|
@ -35,29 +39,27 @@ UtilityNet.CreateEntity = function(model, coords, options, callId)
|
|||
end
|
||||
--#endregion
|
||||
|
||||
local entities = GlobalState.Entities
|
||||
local slice = GetSliceFromCoords(coords)
|
||||
|
||||
local object = {
|
||||
id = NextId,
|
||||
model = model,
|
||||
model = options.abstract and model or hashmodel,
|
||||
coords = coords,
|
||||
slice = slice,
|
||||
options = options,
|
||||
createdBy = options.resource or GetInvokingResource(),
|
||||
createdBy = options.createdBy or GetInvokingResource(),
|
||||
}
|
||||
|
||||
if not entities[slice] then
|
||||
entities[slice] = {}
|
||||
if not Entities[slice] then
|
||||
Entities[slice] = {}
|
||||
end
|
||||
|
||||
entities[slice][object.id] = object
|
||||
GlobalState.Entities = entities
|
||||
Entities[slice][object.id] = object
|
||||
|
||||
RegisterEntityState(object.id)
|
||||
NextId = NextId + 1
|
||||
|
||||
TriggerLatentClientEvent("Utility:Net:EntityCreated", -1, 5120, callId, object.id)
|
||||
TriggerLatentClientEvent("Utility:Net:EntityCreated", -1, 5120, callId, object)
|
||||
return object.id
|
||||
end
|
||||
|
||||
|
@ -85,103 +87,32 @@ UtilityNet.DeleteEntity = function(uNetId)
|
|||
--#endregion
|
||||
|
||||
|
||||
local entities = GlobalState.Entities
|
||||
local entity = UtilityNet.InternalFindFromNetId(uNetId)
|
||||
|
||||
if entity then
|
||||
entities[entity.slice][entity.id] = nil
|
||||
Entities[entity.slice][entity.id] = nil
|
||||
end
|
||||
|
||||
GlobalState.Entities = entities
|
||||
|
||||
TriggerLatentEventForListeners("Utility:Net:RequestDeletion", uNetId, 5120, uNetId)
|
||||
TriggerLatentClientEvent("Utility:Net:RequestDeletion", -1, 5120, uNetId)
|
||||
ClearEntityStates(uNetId) -- Clear states after trigger
|
||||
end
|
||||
|
||||
local queues = {
|
||||
ModelsRenderDistance = {},
|
||||
Entities = {},
|
||||
}
|
||||
|
||||
local function StartQueueUpdateLoop(bagkey)
|
||||
local queue = queues[bagkey]
|
||||
|
||||
Citizen.CreateThread(function()
|
||||
while queue.updateLoop do
|
||||
-- Nothing added in the last 100ms
|
||||
if (GetGameTimer() - queue.lastInt) > 200 then
|
||||
local old = GlobalState[bagkey]
|
||||
|
||||
if bagkey == "Entities" then
|
||||
UtilityNet.ForEachEntity(function(entity)
|
||||
if queue[entity.id] then
|
||||
-- Rotation need to be handled separately
|
||||
if queue[entity.id].rotation then
|
||||
old[entity.slice][entity.id].options.rotation = queue[entity.id].rotation
|
||||
queue[entity.id].rotation = nil
|
||||
end
|
||||
|
||||
for k,v in pairs(queue[entity.id]) do
|
||||
-- If slice need to be updated, move entity to new slice
|
||||
if k == "slice" and v ~= entity.slice then
|
||||
local newSlice = v
|
||||
|
||||
old[newSlice][entity.id] = old[entity.slice][entity.id] -- Copy to new slice
|
||||
old[entity.slice][entity.id] = nil -- Remove from old
|
||||
|
||||
entity = old[newSlice][entity.id] -- Update entity variable
|
||||
end
|
||||
|
||||
old[entity.slice][entity.id][k] = v
|
||||
end
|
||||
end
|
||||
end)
|
||||
else
|
||||
for k,v in pairs(old) do
|
||||
-- Net id need to be updated
|
||||
if queue[v.id] then
|
||||
-- Rotation need to be handled separately
|
||||
if queue[v.id].rotation then
|
||||
v.options.rotation = queue[v.id].rotation
|
||||
queue[v.id].rotation = nil
|
||||
end
|
||||
|
||||
for k2,v2 in pairs(queue[v.id]) do
|
||||
v[k2] = v2
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
-- Refresh GlobalState
|
||||
GlobalState[bagkey] = old
|
||||
|
||||
queues[bagkey].updateLoop = false
|
||||
queues[bagkey] = {}
|
||||
end
|
||||
Citizen.Wait(150)
|
||||
UtilityNet.InternalFindFromNetId = function(uNetId)
|
||||
for sliceI, slice in pairs(Entities) do
|
||||
if slice[uNetId] then
|
||||
return slice[uNetId], sliceI
|
||||
end
|
||||
end)
|
||||
end
|
||||
end
|
||||
|
||||
local function InsertValueInQueue(bagkey, id, value)
|
||||
-- If it is already in the queue with some values that need to be updated, we merge the 2 updates into 1
|
||||
if queues[bagkey][id] then
|
||||
queues[bagkey][id] = table.merge(queues[bagkey][id], value)
|
||||
UtilityNet.GetEntities = function(slice)
|
||||
if slice then
|
||||
return Entities[slice]
|
||||
else
|
||||
queues[bagkey][id] = value
|
||||
end
|
||||
|
||||
queues[bagkey].lastInt = GetGameTimer()
|
||||
|
||||
if not queues[bagkey].updateLoop then
|
||||
queues[bagkey].updateLoop = true
|
||||
StartQueueUpdateLoop(bagkey)
|
||||
return Entities
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
UtilityNet.SetModelRenderDistance = function(model, distance)
|
||||
if type(model) == "string" then
|
||||
model = GetHashKey(model)
|
||||
|
@ -192,30 +123,57 @@ UtilityNet.SetModelRenderDistance = function(model, distance)
|
|||
GlobalState.ModelsRenderDistance = _
|
||||
end
|
||||
|
||||
UtilityNet.SetEntityRotation = function(uNetId, newRotation)
|
||||
UtilityNet.SetEntityRotation = function(uNetId, newRotation, skipRotationUpdate)
|
||||
local source = source
|
||||
|
||||
if type(newRotation) ~= "vector3" then
|
||||
error("Invalid rotation, got "..type(newRotation).." expected vector3", 2)
|
||||
end
|
||||
|
||||
InsertValueInQueue("Entities", uNetId, {rotation = newRotation})
|
||||
if newRotation.x ~= newRotation.x or newRotation.y ~= newRotation.y or newRotation.z ~= newRotation.z then
|
||||
error("Invalid rotation, got "..type(newRotation).." (with NaN) expected vector3", 2)
|
||||
end
|
||||
|
||||
|
||||
local entity, slice = UtilityNet.InternalFindFromNetId(uNetId)
|
||||
|
||||
Entities[slice][uNetId].options.rotation = newRotation
|
||||
|
||||
-- Except caller since it will be already updated
|
||||
TriggerLatentEventForListenersExcept("Utility:Net:RefreshRotation", uNetId, 5120, source, uNetId, newRotation)
|
||||
TriggerLatentClientEvent("Utility:Net:RefreshRotation", -1, 5120, uNetId, newRotation, skipRotationUpdate)
|
||||
end
|
||||
|
||||
UtilityNet.SetEntityCoords = function(uNetId, newCoords)
|
||||
UtilityNet.SetEntityCoords = function(uNetId, newCoords, skipPositionUpdate)
|
||||
local source = source
|
||||
|
||||
if type(newCoords) ~= "vector3" then
|
||||
error("Invalid coords, got "..type(newCoords).." expected vector3", 2)
|
||||
end
|
||||
|
||||
InsertValueInQueue("Entities", uNetId, {coords = newCoords, slice = GetSliceFromCoords(newCoords)})
|
||||
if newCoords.x ~= newCoords.x or newCoords.y ~= newCoords.y or newCoords.z ~= newCoords.z then
|
||||
error("Invalid coords, got "..type(newCoords).." (with NaN) expected vector3", 2)
|
||||
end
|
||||
|
||||
local entity, slice = UtilityNet.InternalFindFromNetId(uNetId)
|
||||
local newSlice = GetSliceFromCoords(newCoords)
|
||||
|
||||
if newSlice ~= slice then
|
||||
local old = Entities[slice][uNetId]
|
||||
|
||||
if not Entities[newSlice] then
|
||||
Entities[newSlice] = {}
|
||||
end
|
||||
|
||||
Entities[slice][uNetId] = nil
|
||||
Entities[newSlice][uNetId] = old
|
||||
|
||||
slice = newSlice
|
||||
end
|
||||
Entities[slice][uNetId].coords = newCoords
|
||||
Entities[slice][uNetId].slice = GetSliceFromCoords(newCoords)
|
||||
|
||||
-- Except caller since it will be already updated
|
||||
TriggerLatentEventForListenersExcept("Utility:Net:RefreshCoords", uNetId, 5120, source, uNetId, newCoords)
|
||||
TriggerLatentClientEvent("Utility:Net:RefreshCoords", -1, 5120, uNetId, newCoords, skipPositionUpdate)
|
||||
end
|
||||
|
||||
UtilityNet.SetEntityModel = function(uNetId, model)
|
||||
|
@ -229,10 +187,12 @@ UtilityNet.SetEntityModel = function(uNetId, model)
|
|||
model = GetHashKey(model)
|
||||
end
|
||||
|
||||
InsertValueInQueue("Entities", uNetId, {model = model})
|
||||
local entity, slice = UtilityNet.InternalFindFromNetId(uNetId)
|
||||
|
||||
Entities[slice][uNetId].model = model
|
||||
|
||||
-- Except caller since it will be already updated
|
||||
TriggerLatentEventForListenersExcept("Utility:Net:RefreshModel", uNetId, 5120, source, uNetId, model)
|
||||
TriggerLatentClientEvent("Utility:Net:RefreshModel", -1, 5120, uNetId, model)
|
||||
end
|
||||
|
||||
--#region Events
|
||||
|
@ -244,7 +204,7 @@ UtilityNet.RegisterEvents = function()
|
|||
RegisterNetEvent("Utility:Net:DeleteEntity", function(uNetId)
|
||||
UtilityNet.DeleteEntity(uNetId)
|
||||
end)
|
||||
|
||||
|
||||
RegisterNetEvent("Utility:Net:SetModelRenderDistance", function(model, distance)
|
||||
UtilityNet.SetModelRenderDistance(model, distance)
|
||||
end)
|
||||
|
@ -274,13 +234,8 @@ UtilityNet.RegisterEvents = function()
|
|||
RegisterNetEvent("Utility:Net:SetEntityModel", UtilityNet.SetEntityModel)
|
||||
RegisterNetEvent("Utility:Net:SetEntityRotation", UtilityNet.SetEntityRotation)
|
||||
|
||||
-- Clear all entities on resource stop
|
||||
AddEventHandler("onResourceStop", function(resource)
|
||||
if resource == GetCurrentResourceName() then
|
||||
UtilityNet.ForEachEntity(function(v)
|
||||
TriggerLatentEventForListeners("Utility:Net:RequestDeletion", v, 5120, v)
|
||||
end)
|
||||
end
|
||||
RegisterNetEvent("Utility:Net:GetEntities", function()
|
||||
TriggerClientEvent("Utility:Net:GetEntities", source, UtilityNet.GetEntities())
|
||||
end)
|
||||
end
|
||||
--#endregion
|
||||
|
@ -289,6 +244,8 @@ end
|
|||
exports("CreateEntity", UtilityNet.CreateEntity)
|
||||
exports("DeleteEntity", UtilityNet.DeleteEntity)
|
||||
exports("SetModelRenderDistance", UtilityNet.SetModelRenderDistance)
|
||||
exports("GetEntities", UtilityNet.GetEntities)
|
||||
exports("InternalFindFromNetId", UtilityNet.InternalFindFromNetId)
|
||||
|
||||
exports("SetEntityModel", UtilityNet.SetEntityModel)
|
||||
exports("SetEntityCoords", UtilityNet.SetEntityCoords)
|
||||
|
|
|
@ -44,6 +44,7 @@ UpdateStateValueForListeners = function(uNetId, key, value)
|
|||
end
|
||||
|
||||
for k,v in pairs(EntitiesStates[uNetId].listeners) do
|
||||
TriggerEvent("Utility:Net:UpdateStateValue", uNetId, key, value)
|
||||
TriggerClientEvent("Utility:Net:UpdateStateValue", v, uNetId, key, value)
|
||||
end
|
||||
end
|
||||
|
@ -161,6 +162,7 @@ RegisterNetEvent("Utility:Net:GetState", function(uNetId)
|
|||
local source = source
|
||||
|
||||
if not EntitiesStates[uNetId] then
|
||||
warn("GetState: No state found for "..uNetId)
|
||||
TriggerClientEvent("Utility:Net:GetState"..uNetId, source, nil)
|
||||
return
|
||||
end
|
||||
|
@ -168,6 +170,19 @@ RegisterNetEvent("Utility:Net:GetState", function(uNetId)
|
|||
ListenStateUpdates(source, uNetId)
|
||||
TriggerClientEvent("Utility:Net:GetState"..uNetId, source, EntitiesStates[uNetId].states)
|
||||
end)
|
||||
|
||||
-- Single value
|
||||
RegisterNetEvent("Utility:Net:GetStateValue", function(uNetId, key)
|
||||
local source = source
|
||||
|
||||
if not EntitiesStates[uNetId] then
|
||||
warn("GetStateValue: No state found for "..uNetId)
|
||||
TriggerClientEvent("Utility:Net:GetStateValue"..uNetId, source, nil)
|
||||
return
|
||||
end
|
||||
|
||||
TriggerClientEvent("Utility:Net:GetStateValue"..uNetId, source, EntitiesStates[uNetId].states[key])
|
||||
end)
|
||||
--#endregion
|
||||
|
||||
-- On player disconnect remove all listeners of that player (prevent useless bandwidth usage)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue