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
Changes from 7 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
224 changes: 223 additions & 1 deletion lua/wire/wirenet.lua
Original file line number Diff line number Diff line change
Expand Up @@ -207,4 +207,226 @@ function Net.Trivial.Receive(name, callback)
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:send(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
thegrb93 marked this conversation as resolved.
Show resolved Hide resolved
ent:SerializeFullMemory(ss, sizeleft)
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:send(v, ply, #snapshots)
end
end,
thegrb93 marked this conversation as resolved.
Show resolved Hide resolved
send = function(self, data, ply, snapshots)
net.Start("WirelibSyncEntities")
net.WriteUInt(self.syncid, 16)
if ply then
net.WriteBool(true)
net.WriteUInt(snapshots, 32)
net.WriteStream(data)
net.Send(ply)
else
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
end,
receive = function(self)
local snapshots
local id = net.ReadUInt(16)
if net.ReadBool() then
snapshots = net.ReadUInt(32)
end
net.ReadStream(function(data)
self:applyReceivedData(id, data, snapshots)
end)
end,
applyReceivedData = function(self, id, data, snapshots)
if id==self.syncid or snapshots then
if snapshots then
self.snapshotsreceived = self.snapshotsreceived + 1
if self.snapshotsreceived == snapshots then
self.syncid = id
end
else
self.syncid = (self.syncid + 1) % 65536
end
if data then
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
thegrb93 marked this conversation as resolved.
Show resolved Hide resolved
ent:DeserializeMemory(ss)
else
ss:skip(size)
end
end
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
for i, v in ipairs(self.syncwaitlist) do
if v[1] == self.syncid then
self:applyReceivedData(unpack(table.remove(self.syncwaitlist, i)))
break
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