236 lines
7.4 KiB
Lua
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
|