Skip to content

Commit

Permalink
Saves are now sent in chunks
Browse files Browse the repository at this point in the history
Fixes big saves being corrupt.

This needs to be done to Duplicator too, but there's another problem
with dupes.
  • Loading branch information
robotboy655 committed May 8, 2015
1 parent 5d4700d commit 9a8d4cd
Showing 1 changed file with 50 additions and 35 deletions.
85 changes: 50 additions & 35 deletions garrysmod/gamemodes/sandbox/gamemode/save_load.lua
@@ -1,5 +1,4 @@


if ( SERVER ) then

--
Expand All @@ -13,44 +12,52 @@ if ( SERVER ) then
concommand.Add( "gm_save", function( ply, cmd, args )

if ( !IsValid( ply ) ) then return end
if ( !game.SinglePlayer() && !ply:IsAdmin() ) then return end -- gmsave.SaveMap is very expensive for big maps/lots of entities. Do not allow random ppl to save the map in multiplayer!
if ( ply.m_NextSave && ply.m_NextSave > CurTime() && !game.SinglePlayer() ) then

ServerLog( "Player is saving too quickly! " .. tostring( ply ) .. "\n" )

return end

ply.m_NextSave = CurTime() + 10;
ply.m_NextSave = CurTime() + 10

ServerLog( "Sending save to player " .. tostring( ply ) .. "\n" )


local save = gmsave.SaveMap( ply )
if ( !save ) then return end

local compressed_save = util.Compress( save )
if ( !compressed_save ) then compressed_save = save end

local len = string.len(compressed_save)
local len = string.len( compressed_save )
local send_size = 60000
local parts = math.ceil( len / send_size )

local ShowSave = 0
if ( args[ 1 ] == "spawnmenu" ) then ShowSave = 1 end

local start = 0
for i = 1, parts do

local ShowSave = 0;
if ( args[1] == 'spawnmenu' ) then ShowSave = 1 end
local endbyte = math.min( start + send_size, len )
local size = endbyte - start

net.Start( "GModSave" )
net.WriteUInt( len, 32 )
net.WriteData( compressed_save, len )
net.WriteUInt( ShowSave, 1 )
net.Send( ply )
net.Start( "GModSave" )
net.WriteBool( i == parts )
net.WriteBool( ShowSave )

net.WriteUInt( size, 16 )
net.WriteData( compressed_save:sub( start + 1, endbyte + 1 ), size )
net.Send( ply )

start = endbyte
end

end, nil, "", { FCVAR_DONTRECORD } )


hook.Add( "LoadGModSave", "LoadGModSave", function( savedata, mapname, maptime )

//MsgN( "SaveData: [", savedata, "]" );
//MsgN( "mapname: [", mapname, "]" );
//MsgN( "maptime: [", maptime, "]" );

savedata = util.Decompress( savedata );
savedata = util.Decompress( savedata )

if ( !isstring( savedata ) ) then
MsgN( "gm_load: Couldn't load save!" )
Expand All @@ -59,31 +66,39 @@ if ( SERVER ) then

gmsave.LoadMap( savedata, nil )

end );
end )

else

local buffer = ""
net.Receive( "GModSave", function( len, client )

local len = net.ReadUInt( 32 )
local data = net.ReadData( len )
local showsave = net.ReadUInt( 1 )
local done = net.ReadBool()
local showsave = net.ReadBool()

local len = net.ReadUInt( 16 )
local data = net.ReadData( len )

buffer = buffer .. data

if ( !done ) then return end

--MsgN( "Received Data ", len )
--MsgN( data )
MsgN( "Received save. Size: " .. buffer:len() )

local uncompressed = util.Decompress( data )
if ( !uncompressed ) then
Msg( "Received save - but couldn't decompress!?\n" );
return
end
local uncompressed = util.Decompress( buffer )

engine.WriteSave( data, game.GetMap() .." ".. util.DateStamp(), CurTime(), game.GetMap() );
if ( !uncompressed ) then
MsgN( "Received save - but couldn't decompress!?" )
buffer = ""
return
end

if ( showsave ) then
hook.Run( "PostGameSaved" );
end
engine.WriteSave( buffer, game.GetMap() .. " " .. util.DateStamp(), CurTime(), game.GetMap() )
buffer = ""

if ( showsave ) then
hook.Run( "PostGameSaved" )
end

end )

end
end

0 comments on commit 9a8d4cd

Please sign in to comment.