Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Started wire entity memory sync class #2979

Closed
wants to merge 11 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
236 changes: 235 additions & 1 deletion lua/wire/wirenet.lua
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,238 @@
update_handlers(name:lower(), callback)
end

Net.Receivers = registered_handlers
Net.Receivers = registered_handlers


local function writeUnboundedArray(ss, cb)
local sizepos = ss.index
ss:writeInt32(0)
local written = cb()
if written>0 then
ss.index = sizepos
ss:writeInt32(written)
ss.index = #ss+1
ss.subindex = 1
else
ss.index = sizepos
for i=sizepos, #ss do
ss[i] = nil
end
end
return written
end
local function calcWritten(ss, startpos)
local size = 0
for i=startpos, ss.index-1 do
size = size + #ss[i]
end
return size
end

local WireMemSyncer = {
__index = {
register = function(self, ent)
self.entities[ent] = true
end,
sync = function(self)
if not self.syncing then
self.syncing = true
timer.Simple(0.5, function() self.syncing = false self:dosync() end)
end
end,
dosync = function(self)
if self.sending then self:sync() return end
local ss = StringStream()
local sizeleft = net.Stream.SendSize*net.Stream.MaxServerChunks*0.5

if writeUnboundedArray(ss, function()
local numEntries = 0
for ent in pairs(self.entities) do
if ent:IsValid() then
if ent.MemoryDirty then

ss:writeInt16(ent:EntIndex())
local written = writeUnboundedArray(ss, function()
local startpos = ss.index
ent:SerializeMemory(ss, sizeleft)
return calcWritten(ss, startpos)
end)

if written>0 then
sizeleft = sizeleft - written - 6
numEntries = numEntries + 1
else
-- Delete the entIndex
ss.index = ss.index - 1
ss[ss.index] = nil
end

if sizeleft <= 0 then self:sync() break end
end
else
self.entities[ent] = nil
end
end
return numEntries
end) > 0 then
self:sendUpdate(ss:getString())
end

end,
fullsnapshot = function(self, ply)
local snapshots = {}
local curent = nil

while true do
local shouldBreak = true
local ss = StringStream()
local sizeleft = net.Stream.SendSize*net.Stream.MaxServerChunks*0.5

if writeUnboundedArray(ss, function()
local numEntries = 0
for ent, mem in next, self.entities, curent do
if ent:IsValid() then

ss:writeInt16(ent:EntIndex())
local written = writeUnboundedArray(ss, function()
local startpos = ss.index
ent:SerializeFullMemory(ss)
return calcWritten(ss, startpos)
end)

if written>0 then
sizeleft = sizeleft - written - 6
numEntries = numEntries + 1
if sizeleft <= 0 then
shouldBreak = false
curent = ent
break
end
else
-- Delete the entIndex
ss.index = ss.index - 1
ss[ss.index] = nil
end

else
self.entities[ent] = nil
end
end
return numEntries
end) > 0 then
snapshots[#snapshots + 1] = ss:getString()
end
if shouldBreak then break end
end

for _, v in ipairs(snapshots) do
self:sendSnapshot(v, ply, #snapshots)
end
end,
sendUpdate = function(self, data)
net.Start("WirelibSyncEntities")
net.WriteUInt(self.syncid, 16)
net.WriteBool(false)
local newid = (self.syncid + 1) % 65536
self.syncid = newid
net.WriteStream(data, function() if newid==self.syncid then self.sending = false end end)
net.Broadcast()
self.sending = true
end,
sendSnapshot(self, data, ply, snapshots)
net.Start("WirelibSyncEntities")

Check failure on line 349 in lua/wire/wirenet.lua

View workflow job for this annotation

GitHub Actions / lint

"Parse error"

unexpected net expecting function call or indexation
net.WriteUInt(self.syncid, 16)
net.WriteBool(true)
net.WriteUInt(snapshots, 32)
net.WriteStream(data)
net.Send(ply)
end,
receive = function(self)
local snapshots
local id = net.ReadUInt(16)
if net.ReadBool() then
snapshots = net.ReadUInt(32)
net.ReadStream(function(data)
self:receiveSnapshot(id, data, snapshots)
end)
else
net.ReadStream(function(data)
self:receiveUpdate(id, data)
end)
end
end,
receiveUpdate = function(self, id, data)
if id==self.syncid then
self.syncid = (self.syncid + 1) % 65536
if data then self:applyUpdate(data) end
else
self.syncwaitlist[#self.syncwaitlist + 1] = {id, data}
-- Must have missed one somehow, just take the lowest one and continue
if #self.syncwaitlist > 64 and self.syncid~=-1 then
local min = math.huge
for i, v in ipairs(self.syncwaitlist) do
if v[1] < min then min = v[1] end
end
self.syncid = min
end
end
self:processWaitlist()
end,
receiveSnapshot = function(self, id, data, snapshots)
if data then self:applyUpdate(data) end
self.snapshotsreceived = self.snapshotsreceived + 1
if self.snapshotsreceived == snapshots then
self.syncid = id
self:processWaitlist()
end
end,
processWaitlist = function(self)
for i, v in ipairs(self.syncwaitlist) do
if v[1] == self.syncid then
self:receiveUpdate(unpack(table.remove(self.syncwaitlist, i)))
break
end
end
end,
applyUpdate = function(self, data)
local ss = StringStream(data)
for i=1, ss:readUInt32() do
local ent = Entity(ss:readUInt16())
local size = ss:readUInt32()
if ent:IsValid() and ent.DeserializeMemory then
local pos = ss:tell()
ent:DeserializeMemory(ss)
ss:seek(pos+size)
else
ss:skip(size)
end
end
end,
},
__call = function(meta)
return setmetatable({
entities = {},
syncing = false,
sending = false,
syncid = 0,
syncwaitlist = {},
snapshotsreceived = 0
}, meta)
end
}
setmetatable(WireMemSyncer, WireMemSyncer)

WireLib.WireMemSyncer = WireMemSyncer()

if SERVER then
util.AddNetworkString("WirelibSyncEntities")
hook.Add("PlayerInitialSpawn", "WirelibSyncFullSnapshot",function(ply)
WireLib.WireMemSyncer:fullsnapshot(ply)
end)
else
WireLib.WireMemSyncer.syncid = -1 -- Wait for full snapshot
net.Receive("WirelibSyncEntities", function()
WireLib.WireMemSyncer:receive()
end)
end

Loading
Loading