Permalink
Browse files

Saves are now sent in chunks

Fixes big saves being corrupt.

This needs to be done to Duplicator too, but there's another problem
with dupes.
  • Loading branch information...
1 parent 5d4700d commit 9a8d4cdeecfcab57265f5939bf257fcebd47e920 @robotboy655 robotboy655 committed May 8, 2015
Showing with 50 additions and 35 deletions.
  1. +50 −35 garrysmod/gamemodes/sandbox/gamemode/save_load.lua
@@ -1,5 +1,4 @@
-
if ( SERVER ) then
--
@@ -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!" )
@@ -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.