mirror of
https://github.com/lifestorm/wnsrc.git
synced 2025-12-17 13:53:45 +03:00
Upload
This commit is contained in:
436
lua/includes/modules/saverestore.lua
Normal file
436
lua/includes/modules/saverestore.lua
Normal file
@@ -0,0 +1,436 @@
|
||||
--[[
|
||||
| This file was obtained through the combined efforts
|
||||
| of Madbluntz & Plymouth Antiquarian Society.
|
||||
|
|
||||
| Credits: lifestorm, Gregory Wayne Rossel JR.,
|
||||
| Maloy, DrPepper10 @ RIP, Atle!
|
||||
|
|
||||
| Visit for more: https://plymouth.thetwilightzone.ru/
|
||||
--]]
|
||||
|
||||
|
||||
local Msg = Msg
|
||||
local type = type
|
||||
local pairs = pairs
|
||||
local gmod = gmod
|
||||
local table = table
|
||||
|
||||
--[[
|
||||
|
||||
This module is to help bind the engine's saverestore stuff to Lua.
|
||||
|
||||
This is so we can save Lua stuff in the save game file. The entities
|
||||
should automatically save most of their table contents to the save file.
|
||||
|
||||
!!Warning!!: Editing this file may render old saves useless.
|
||||
|
||||
You can hook into this system like so
|
||||
|
||||
local function MySaveFunction( save )
|
||||
saverestore.WriteTable( my_table, save )
|
||||
end
|
||||
|
||||
local function MyRestoreFunction( restore )
|
||||
my_table = saverestore.ReadTable( restore )
|
||||
end
|
||||
|
||||
saverestore.AddSaveHook( "HookNameHere", MySaveFunction )
|
||||
saverestore.AddRestoreHook( "HookNameHere", MyRestoreFunction )
|
||||
|
||||
--]]
|
||||
|
||||
module( "saverestore" )
|
||||
|
||||
local TYPE_NONE = 0
|
||||
local TYPE_FLOAT = 1 -- Treat all numbers as floats (they're all the same to Lua)
|
||||
local TYPE_STRING = 2
|
||||
local TYPE_ENTITY = 3
|
||||
local TYPE_VECTOR = 4
|
||||
local TYPE_TABLE = 5
|
||||
local TYPE_BOOL = 6
|
||||
local TYPE_ANGLE = 7
|
||||
|
||||
local SaveHooks = {}
|
||||
local RestoreHooks = {}
|
||||
local TableRefs = {}
|
||||
local TableRef = 1
|
||||
|
||||
function PreSave()
|
||||
|
||||
TableRefs = {}
|
||||
TableRef = 1
|
||||
|
||||
end
|
||||
|
||||
function PreRestore()
|
||||
|
||||
TableRefs = {}
|
||||
TableRef = 1
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetTypeStr
|
||||
Desc: Given a string returns a TYPE_
|
||||
-----------------------------------------------------------]]
|
||||
local function GetTypeStr( name )
|
||||
|
||||
if ( name == "function" ) then return TYPE_NONE end
|
||||
|
||||
if ( name == "number" ) then return TYPE_FLOAT end
|
||||
if ( name == "string" ) then return TYPE_STRING end
|
||||
if ( name == "Entity" ) then return TYPE_ENTITY end
|
||||
if ( name == "Vehicle" ) then return TYPE_ENTITY end
|
||||
if ( name == "NPC" ) then return TYPE_ENTITY end
|
||||
if ( name == "Player" ) then return TYPE_ENTITY end
|
||||
if ( name == "Weapon" ) then return TYPE_ENTITY end
|
||||
if ( name == "Vector" ) then return TYPE_VECTOR end
|
||||
if ( name == "Angle" ) then return TYPE_ANGLE end
|
||||
if ( name == "table" ) then return TYPE_TABLE end
|
||||
if ( name == "boolean" ) then return TYPE_BOOL end
|
||||
|
||||
-- These aren't saved
|
||||
if ( name == "ConVar" ) then return TYPE_NONE end
|
||||
if ( name == "PhysObj" ) then return TYPE_NONE end
|
||||
|
||||
-- Bitch about it incase I've forgot to hook a savable type up
|
||||
Msg( "Can't save unknown type " .. name .. "\n" )
|
||||
return TYPE_NONE
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: GetType
|
||||
Desc: Given a variable returns a TYPE_
|
||||
-----------------------------------------------------------]]
|
||||
local function GetType( var )
|
||||
|
||||
return GetTypeStr( type(var) )
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: IsWritable
|
||||
Desc: Returns true if we can save the K/V pair
|
||||
-----------------------------------------------------------]]
|
||||
local function IsWritable( k, v )
|
||||
|
||||
local itype = GetType( k )
|
||||
if ( itype == TYPE_NONE ) then return false end
|
||||
if ( itype == TYPE_STRING && k == "SR_Recursion" ) then return false end
|
||||
|
||||
local itype = GetType( v )
|
||||
if ( itype == TYPE_NONE ) then return false end
|
||||
|
||||
return true
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: WriteVar
|
||||
Desc: Writes a single variable to the save
|
||||
-----------------------------------------------------------]]
|
||||
function WritableKeysInTable( t )
|
||||
|
||||
local i = 0
|
||||
|
||||
for k, v in pairs( t ) do
|
||||
if ( IsWritable( k, v ) ) then
|
||||
i = i + 1
|
||||
end
|
||||
end
|
||||
|
||||
return i
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: WriteVar
|
||||
Desc: Writes a single variable to the save
|
||||
-----------------------------------------------------------]]
|
||||
function WriteVar( var, save )
|
||||
|
||||
local itype = GetType( var )
|
||||
if ( itype == TYPE_NONE ) then return end
|
||||
|
||||
save:StartBlock( type( var ) )
|
||||
|
||||
if ( itype == TYPE_FLOAT ) then
|
||||
save:WriteFloat( var )
|
||||
elseif ( itype == TYPE_BOOL ) then
|
||||
save:WriteBool( var )
|
||||
elseif ( itype == TYPE_STRING ) then
|
||||
save:WriteString( var )
|
||||
elseif ( itype == TYPE_ENTITY ) then
|
||||
save:WriteEntity( var )
|
||||
elseif ( itype == TYPE_ANGLE ) then
|
||||
save:WriteAngle( var )
|
||||
elseif ( itype == TYPE_VECTOR ) then
|
||||
save:WriteVector( var )
|
||||
elseif ( itype == TYPE_TABLE ) then
|
||||
WriteTable( var, save )
|
||||
else
|
||||
Msg( "Error! Saving unsupported Type: " .. type( var ) .. "\n" )
|
||||
end
|
||||
|
||||
save:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ReadVar
|
||||
Desc: Reads a single variable
|
||||
-----------------------------------------------------------]]
|
||||
function ReadVar( restore )
|
||||
|
||||
local retval = 0
|
||||
local typename = restore:StartBlock()
|
||||
|
||||
local itype = GetTypeStr( typename )
|
||||
|
||||
if ( itype == TYPE_FLOAT ) then
|
||||
retval = restore:ReadFloat()
|
||||
elseif ( itype == TYPE_BOOL ) then
|
||||
retval = restore:ReadBool()
|
||||
elseif ( itype == TYPE_STRING ) then
|
||||
retval = restore:ReadString()
|
||||
elseif ( itype == TYPE_ENTITY ) then
|
||||
retval = restore:ReadEntity()
|
||||
elseif ( itype == TYPE_ANGLE ) then
|
||||
retval = restore:ReadAngle()
|
||||
elseif ( itype == TYPE_VECTOR ) then
|
||||
retval = restore:ReadVector()
|
||||
elseif ( itype == TYPE_TABLE ) then
|
||||
retval = ReadTable( restore )
|
||||
else
|
||||
Msg( "Error! Loading unsupported Type: " .. typename .. "\n" )
|
||||
end
|
||||
|
||||
restore:EndBlock()
|
||||
|
||||
return retval
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: WriteTable
|
||||
Desc: Writes a table to the save
|
||||
-----------------------------------------------------------]]
|
||||
function WriteTable( tab, save )
|
||||
|
||||
-- Write a blank table (because read will be expecting one)
|
||||
if ( tab == nil ) then
|
||||
|
||||
save:StartBlock( "Table" )
|
||||
save:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
-- We have already saved this table
|
||||
if ( TableRefs[ tab ] ) then
|
||||
|
||||
save:StartBlock( "TableRef" )
|
||||
save:WriteInt( TableRefs[ tab ] )
|
||||
save:EndBlock()
|
||||
|
||||
return
|
||||
|
||||
end
|
||||
|
||||
TableRefs[ tab ] = TableRef
|
||||
|
||||
save:StartBlock( "Table" )
|
||||
|
||||
local iCount = WritableKeysInTable( tab )
|
||||
|
||||
save:WriteInt( TableRef )
|
||||
TableRef = TableRef + 1
|
||||
|
||||
save:WriteInt( iCount )
|
||||
|
||||
for k, v in pairs( tab ) do
|
||||
|
||||
if ( IsWritable( k, v ) ) then
|
||||
|
||||
WriteVar( k, save )
|
||||
WriteVar( v, save )
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
save:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: ReadTable
|
||||
Desc: Assumes a table is waiting to be read, returns a table
|
||||
-----------------------------------------------------------]]
|
||||
function ReadTable( restore )
|
||||
|
||||
local name = restore:StartBlock()
|
||||
local tab = {}
|
||||
|
||||
if ( name == "TableRef" ) then
|
||||
|
||||
local ref = restore:ReadInt()
|
||||
if ( !TableRefs[ ref ] ) then
|
||||
TableRefs[ ref ] = {}
|
||||
return
|
||||
end
|
||||
|
||||
tab = TableRefs[ ref ]
|
||||
|
||||
else
|
||||
|
||||
local iRef = restore:ReadInt()
|
||||
local iCount = restore:ReadInt()
|
||||
|
||||
if ( TableRefs[ iRef ] ) then
|
||||
tab = TableRefs[ iRef ]
|
||||
end
|
||||
|
||||
for i = 0, iCount - 1 do
|
||||
|
||||
local k = ReadVar( restore )
|
||||
local v = ReadVar( restore )
|
||||
tab[ k ] = v
|
||||
|
||||
end
|
||||
|
||||
TableRefs[ iRef ] = tab
|
||||
|
||||
end
|
||||
|
||||
restore:EndBlock()
|
||||
|
||||
return tab
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SaveEntity
|
||||
Desc: Called by the engine for each entity
|
||||
-----------------------------------------------------------]]
|
||||
function SaveEntity( ent, save )
|
||||
|
||||
save:StartBlock( "EntityTable" )
|
||||
|
||||
WriteTable( ent:GetTable(), save )
|
||||
|
||||
save:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: LoadEntity
|
||||
Desc: Called by the engine for each entity
|
||||
-----------------------------------------------------------]]
|
||||
function LoadEntity( ent, restore )
|
||||
|
||||
local EntTable = ent:GetTable()
|
||||
|
||||
local name = restore:StartBlock()
|
||||
|
||||
if ( name == "EntityTable" ) then
|
||||
|
||||
table.Merge( EntTable, ReadTable( restore ) )
|
||||
|
||||
end
|
||||
|
||||
restore:EndBlock()
|
||||
|
||||
ent:SetTable( EntTable )
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AddSaveHook
|
||||
Desc: Adds a hook enabling something to save something..
|
||||
-----------------------------------------------------------]]
|
||||
function AddSaveHook( name, func )
|
||||
|
||||
local h = {}
|
||||
h.Name = name
|
||||
h.Func = func
|
||||
SaveHooks[ name ] = h
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: AddRestoreHook
|
||||
Desc: Adds a hook enabling something to restore something..
|
||||
-----------------------------------------------------------]]
|
||||
function AddRestoreHook( name, func )
|
||||
|
||||
local h = {}
|
||||
h.Name = name
|
||||
h.Func = func
|
||||
RestoreHooks[ name ] = h
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: SaveGlobal
|
||||
Desc: Should save any Lua stuff that isn't entity based.
|
||||
-----------------------------------------------------------]]
|
||||
function SaveGlobal( save )
|
||||
|
||||
save:StartBlock( "GameMode" )
|
||||
WriteTable( gmod.GetGamemode(), save )
|
||||
save:EndBlock()
|
||||
|
||||
for k, v in pairs( SaveHooks ) do
|
||||
|
||||
save:StartBlock( v.Name )
|
||||
|
||||
v.Func( save )
|
||||
|
||||
save:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
--[[---------------------------------------------------------
|
||||
Name: LoadGlobal
|
||||
Desc: ...
|
||||
-----------------------------------------------------------]]
|
||||
function LoadGlobal( restore )
|
||||
|
||||
local name = restore:StartBlock()
|
||||
|
||||
if ( name == "GameMode" ) then
|
||||
table.Merge( gmod.GetGamemode(), ReadTable( restore ) )
|
||||
end
|
||||
|
||||
restore:EndBlock()
|
||||
|
||||
|
||||
while ( name != "EndGlobal" ) do
|
||||
|
||||
name = restore:StartBlock()
|
||||
|
||||
local tab = RestoreHooks[ name ]
|
||||
if ( tab ) then
|
||||
|
||||
tab.Func( restore )
|
||||
|
||||
end
|
||||
|
||||
restore:EndBlock()
|
||||
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user