dobrograd-13-06-2022/garrysmod/addons/util-dlib/lua/dlib/classes/predictedvars.lua
Jonny_Bro (Nikita) e4d5311906 first commit
2023-11-16 15:01:19 +05:00

236 lines
7.4 KiB
Lua

local _OBJECTS = DLib.PredictedVarList and DLib.PredictedVarList._OBJECTS or { }
local plyMeta = FindMetaTable('Player')
local cl_showerror = GetConVar('cl_showerror')
do
local _class_0
local _base_0 = {
GetByName = function(self, id)
return self._OBJECTS[id]
end,
SetSyncTimer = function(self, stimer)
if stimer == nil then
stimer = self.sync_cooldown
end
if game.SinglePlayer() or self.smartSync then
return
end
self.sync_cooldown = assert(type(stimer) == 'number' and stimer >= 0, 'Time must be a positive number!')
return timer.Create('DLib.PredictedVarList.Sync', self.sync_cooldown, 0, function()
return ProtectedCall(self.sync_closure)
end)
end,
Sync = function(self, ply)
if CLIENT then
error('Invalid realm')
end
net.Start(self._nw)
ply.__dlib_predvars = ply.__dlib_predvars or { }
ply.__dlib_predvars[self.netname] = ply.__dlib_predvars[self.netname] or { }
net.WriteTable(ply.__dlib_predvars[self.netname])
return net.Send(ply)
end,
GetFrame = function(self)
return self.frame_id
end,
AddVar = function(self, identifier, def)
self.vars[identifier] = def
return self
end,
RegisterMeta = function(self, invalidateName, syncName)
local self2 = self
plyMeta[assert(invalidateName, 'Missing invalidate meta name')] = function(self, smart)
if smart == nil then
smart = false
end
return self2:Invalidate(self, smart)
end
plyMeta[assert(syncName, 'Missing sync meta name')] = function(self)
return self2:Sync(self)
end
for name, def in pairs(self.vars) do
plyMeta['Get' .. name] = function(self)
return self2:Get(self, name)
end
plyMeta['Set' .. name] = function(self, ...)
return self2:Set(self, name, ...)
end
plyMeta['Reset' .. name] = function(self)
return self2:Reset(self, name)
end
end
return self
end,
Invalidate = function(self, ply, smart)
if smart == nil then
smart = false
end
if SERVER then
self.frame_id = self.frame_id + 1
if not ply.__dlib_predvars then
ply.__dlib_predvars = { }
end
if not ply.__dlib_predvars[self.netname] then
ply.__dlib_predvars[self.netname] = { }
end
return
end
if smart and self.lastInvalidate == FrameNumber() then
return
end
self.lastInvalidate = FrameNumber()
if IsFirstTimePredicted() then
self.firstF = true
self.frame_id = self.frame_id + 1
for key, value in pairs(self.first) do
self.prev[key] = value
self.cur[key] = nil
self.first[key] = nil
end
return
end
self.firstF = false
for key in pairs(self.cur) do
self.cur[key] = nil
end
end,
Get = function(self, ply, identifier, def)
if def == nil then
def = self.vars[identifier]
end
if SERVER then
if not ply.__dlib_predvars or not ply.__dlib_predvars[self.netname] then
return def
end
local val = ply.__dlib_predvars[self.netname][identifier]
if val ~= nil then
return val
end
return def
end
assert(def ~= nil, 'Variable does not exist')
if self.firstF then
local val = self.first[identifier]
if val ~= nil then
return val
end
if self.prev[identifier] ~= nil then
return self.prev[identifier]
end
return def
end
local val = self.cur[identifier]
if val ~= nil then
return val
end
if self.prev[identifier] ~= nil then
return self.prev[identifier]
end
return def
end,
Set = function(self, ply, identifier, val)
if SERVER then
assert(assert(ply.__dlib_predvars, ':Invalidate() was never called with this player')[self.netname], ':Invalidate() was never called with this player')[identifier] = val
if game.SinglePlayer() then
self:Sync(ply)
end
return
end
assert(self.vars[identifier] ~= nil, 'Variable does not exist')
if self.firstF then
self.first[identifier] = val
return
end
self.cur[identifier] = val
end,
Reset = function(self, ply, identifier)
return self:Set(ply, identifier, self.vars[identifier])
end
}
_base_0.__index = _base_0
_class_0 = setmetatable({
__init = function(self, netname, smartSync)
if smartSync == nil then
smartSync = false
end
self.netname = assert(netname, 'Missing network name')
self.__class._OBJECTS[self.netname] = self
self.vars = { }
self.prev = { }
self.cur = { }
self.first = { }
self.frame_id = 0
self.firstF = true
self.sync_cooldown = 60
self.lastInvalidate = 0
self.smartSync = smartSync
self._nw = 'dlib_pred_' .. netname
if SERVER then
net.pool(self._nw)
if not game.SinglePlayer() then
if not smartSync then
self.sync_closure = function()
local _list_0 = player.GetAll()
for _index_0 = 1, #_list_0 do
local ply = _list_0[_index_0]
if ply.__dlib_predvars and ply.__dlib_predvars[self.netname] then
self:Sync(ply)
end
end
end
return timer.Create('DLib.PredictedVarList.' .. netname, self.sync_cooldown, 0, function()
return ProtectedCall(self.sync_closure)
end)
else
self.sync_closure = function()
local _list_0 = player.GetAll()
for _index_0 = 1, #_list_0 do
local ply = _list_0[_index_0]
local score = ply:PacketLoss():pow(2) / 30 + ply:Ping() / 10
ply['__dlib_psync_last_' .. netname] = (ply['__dlib_psync_last_' .. netname] or 400) - score
if ply['__dlib_psync_last_' .. netname] <= 0 then
ply['__dlib_psync_last_' .. netname] = 400
self:Sync(ply)
end
end
end
return timer.Create('DLib.PredictedVarList.' .. netname, 1, 0, function()
return ProtectedCall(self.sync_closure)
end)
end
end
else
return net.receive(self._nw, function()
local newR = net.ReadTable()
if cl_showerror:GetInt() >= 2 then
local num = 0
for k, v in pairs(newR) do
if v ~= self.prev[k] then
num = num + 1
local val = self.prev[k]
if val == nil then
val = 'null'
end
DLib.Warning(string.format('%.3d %s:%s', num, netname, k), ' - variable differs (net: ', v, ' pred ', val, ')')
end
end
end
self.prev = newR
end)
end
end,
__base = _base_0,
__name = "PredictedVarList"
}, {
__index = _base_0,
__call = function(cls, ...)
local _self_0 = setmetatable({}, _base_0)
cls.__init(_self_0, ...)
return _self_0
end
})
_base_0.__class = _class_0
local self = _class_0
self._OBJECTS = _OBJECTS
DLib.PredictedVarList = _class_0
return _class_0
end