wiremod-svn-archive/wire/lua/autorun/Beam_NetVars.lua

404 lines
12 KiB
Lua
Raw Permalink Normal View History

2008-06-14 00:55:20 +00:00
///////////////////////////////////////////////
// ===BeamNetVars=== //
// Custom Networked Vars Module //
// Based off Garry's Networked Vars Module //
// Modification by: TAD2020 //
///////////////////////////////////////////////
// How to use: //
// Just like NetVars, ent:SetNetworkedBeam* //
// and ent:GetNetworkedBeam* //
// Key should be short or a small number. //
// These functions should only be used instead //
// standard NetVars when very large quanity //
// of rarly updated values need to be sent with //
// low importantance. Mainly this is used by //
// wire's client side beams and rapidly updating //
// overlay text. //
// Data is sent at a tick interval, if too much //
// is in the outgoing query, the delay between //
// sends is increased. //
// On player joins, all current data is queried to //
// to send to them in the lowest priority stack. //
// Low priority stack sends a few entities's //
// vars each tick. //
///////////////////////////////////////////////
//RD header for multi distro-ablity
local ThisBeamNetVarsVersion = 0.71
if (BeamNetVars) and (BeamNetVars.Version) and (BeamNetVars.Version > ThisBeamNetVarsVersion) then
Msg("======== A Newer Version of BeamNetVars Detected ========\n"..
"======== This ver: "..ThisBeamNetVarsVersion.." || Detected ver: "..BeamNetVars.Version.." || Skipping\n")
return
elseif (BeamNetVars) and (BeamNetVars.Version) and (BeamNetVars.Version == ThisBeamNetVarsVersion) then
Msg("======== The Same Version of BeamNetVars Detected || Skipping ========\n")
return
elseif (BeamNetVars) and (BeamNetVars.Version) then
Msg("======== Am Older Version of BeamNetVars Detected ========\n"..
"======== This ver: "..ThisBeamNetVarsVersion.." || Detected ver: "..BeamNetVars.Version.." || Overriding\n")
end
AddCSLuaFile( "autorun/Beam_NetVars.lua" )
BeamNetVars = {}
BeamNetVars.Version = ThisBeamNetVarsVersion
if (SERVER) then
//we want this
//sv_usermessage_maxsize = 1024
game.ConsoleCommand( "sv_usermessage_maxsize 1024\n" )
end
local meta = FindMetaTable( "Entity" )
// Return if there's nothing to add on to
if (!meta) then return end
local Vector_Default = Vector(0,0,0)
local Angle_Default = Angle(0,0,0)
local NetworkVars = {}
local NetworkFunction = {}
local DelayedUpdates = {}
local DelayedUpdatesNum = 0
local ExtraDelayedUpdates = {}
local NextCleanup = CurTime()
if ( CLIENT ) then
local function Dump()
Msg("Networked Beam Vars...\n")
PrintTable( NetworkVars )
end
concommand.Add( "networkbeamvars_dump", Dump )
end
local function AttemptToSwitchTables( Ent, EntIndex )
if ( NetworkVars[ EntIndex ] == nil ) then return end
// We have an old entindex based entry! Move it over!
NetworkVars[ Ent ] = NetworkVars[ EntIndex ]
NetworkVars[ EntIndex ] = nil
end
local function CleaupNetworkVars()
if ( NextCleanup > CurTime() ) then return end
NextCleanup = CurTime() + 30
for k, v in pairs( NetworkVars ) do
if ( type( k ) != "number" && type( k ) != "string" ) then
if ( !k:IsValid() ) then
NetworkVars[ k ] = nil
end
end
end
end
local function GetNetworkTable( ent, name )
if ( CLIENT ) then
CleaupNetworkVars()
end
if ( !NetworkVars[ ent ] ) then
NetworkVars[ ent ] = {}
// This is the first time this entity has been created.
// Check whether we previously had an entindex based table
if ( CLIENT && type( ent ) != "number" && type( ent ) != "string" ) then
AttemptToSwitchTables( ent, ent:EntIndex() )
end
end
NetworkVars[ ent ][ name ] = NetworkVars[ ent ][ name ] or {}
return NetworkVars[ ent ][ name ]
end
local function SendNetworkUpdate( VarType, Index, Key, Value, Player )
if(Player and not (Player:IsValid() and Player:IsPlayer())) then return end // Be sure, Player is not a NULL-Entity, or the server will crash!
umsg.Start( "RcvEntityVarBeam_"..VarType, Player )
umsg.Short( Index )
umsg.String( Key )
umsg[ NetworkFunction[VarType].SetFunction ]( Value )
umsg.End()
end
local function AddDelayedNetworkUpdate( VarType, Ent, Key, Value )
if (Wire_FastOverlayTextUpdate) then
SendNetworkUpdate( VarType, Ent, Key, Value )
elseif (Ent) and (VarType) then
DelayedUpdates[Ent] = DelayedUpdates[Ent] or {}
DelayedUpdates[Ent][ VarType ] = DelayedUpdates[Ent][ VarType ] or {}
DelayedUpdates[Ent][ VarType ][Key] = Value
DelayedUpdatesNum = DelayedUpdatesNum + 1
if (ExtraDelayedUpdates[Ent])
and (ExtraDelayedUpdates[Ent][VarType])
and (ExtraDelayedUpdates[Ent][VarType][Key]) then
ExtraDelayedUpdates[Ent][VarType][Key] = nil
end
end
end
local function AddExtraDelayedNetworkUpdate( VarType, Ent, Key, Value, Player )
if (Wire_FastOverlayTextUpdate) then
SendNetworkUpdate( VarType, Ent, Key, Value )
elseif (Ent) and (VarType) and (Key) then
ExtraDelayedUpdates[Ent] = ExtraDelayedUpdates[Ent] or {}
ExtraDelayedUpdates[Ent][VarType] = ExtraDelayedUpdates[Ent][VarType] or {}
ExtraDelayedUpdates[Ent][VarType][Key] = ExtraDelayedUpdates[Ent][VarType][Key] or {}
ExtraDelayedUpdates[Ent][VarType][Key].Value = Value
ExtraDelayedUpdates[Ent][VarType][Key].Player = Player
--ExtraDelayedUpdatesNum = ExtraDelayedUpdatesNum + 1
end
end
//
// make all the ent.Get/SetNetworkedBeamVarCrap
//
local function AddNetworkFunctions( name, SetFunction, GetFunction, Default )
NetworkFunction[ name ] = {}
NetworkFunction[ name ].SetFunction = SetFunction
NetworkFunction[ name ].GetFunction = GetFunction
// SetNetworkedBlah
meta[ "SetNetworkedBeam" .. name ] = function ( self, key, value, urgent )
key = tostring(key)
// The same - don't waste our time.
if ( value == GetNetworkTable( self, name )[ key ] ) then return end
// Clients can set this too, but they should only really be setting it
// when they expect the exact same result coming over the wire (ie prediction)
GetNetworkTable( self, name )[key] = value
if ( SERVER ) then
local Index = self:EntIndex()
if (Index <= 0) then return end
if ( urgent ) then
SendNetworkUpdate( name, Index, key, value )
else
AddDelayedNetworkUpdate( name, Index, key, value )
end
end
end
meta[ "SetNWB" .. name ] = meta[ "SetNetworkedBeam" .. name ]
// GetNetworkedBlah
meta[ "GetNetworkedBeam" .. name ] = function ( self, key, default )
key = tostring(key)
local out = GetNetworkTable( self, name )[ key ]
if ( out != nil ) then return out end
if ( default == nil ) then return Default end
//default = default or Default
return default
end
meta[ "GetNWB" .. name ] = meta[ "GetNetworkedBeam" .. name ]
// SetGlobalBlah
_G[ "SetGlobalBeam"..name ] = function ( key, value, urgent )
key = tostring(key)
if ( value == GetNetworkTable( "G", name )[key] ) then return end
GetNetworkTable( "G", name )[key] = value
if ( SERVER ) then
if ( urgent ) then
SendNetworkUpdate( name, -1, key, value )
else
AddDelayedNetworkUpdate( name, -1, key, value )
end
end
end
// GetGlobalBlah
_G[ "GetGlobalBeam"..name ] = function ( key )
key = tostring(key)
local out = GetNetworkTable( "G", name )[key]
if ( out != nil ) then return out end
return Default
end
if ( SERVER ) then
// Pool the name of the function.
// Makes it send a number representing the string rather than the string itself.
// Only do this with strings that you send quite a bit and always stay the same.
umsg.PoolString( "RcvEntityBeamVar_"..name )
end
// Client Receive Function
if ( CLIENT ) then
local function RecvFunc( m )
local EntIndex = m:ReadShort()
local Key = m:ReadString()
local Value = m[GetFunction]( m )
local IndexKey
if ( EntIndex <= 0 ) then
IndexKey = "G"
else
IndexKey = Entity( EntIndex )
// No entity yet - store using entindex
if ( IndexKey == NULL ) then IndexKey = EntIndex end
end
GetNetworkTable( IndexKey, name )[Key] = Value
end
usermessage.Hook( "RcvEntityVarBeam_"..name, RecvFunc )
end
end
AddNetworkFunctions( "Vector", "Vector", "ReadVector", Vector_Default )
AddNetworkFunctions( "Angle", "Angle", "ReadAngle", Angle_Default )
AddNetworkFunctions( "Float", "Float", "ReadFloat", 0 )
AddNetworkFunctions( "Int", "Short", "ReadShort", 0 )
AddNetworkFunctions( "Entity", "Entity", "ReadEntity", NULL )
AddNetworkFunctions( "Bool", "Bool", "ReadBool", false )
AddNetworkFunctions( "String", "String", "ReadString", "" )
//
// We want our networked vars to save don't we? Yeah - we do - stupid.
//
local function Save( save )
// Remove baggage
for k, v in pairs(NetworkVars) do
if ( k == NULL ) then
NetworkVars[k] = nil
end
end
saverestore.WriteTable( NetworkVars, save )
end
local function Restore( restore )
NetworkVars = saverestore.ReadTable( restore )
//PrintTable(NetworkVars)
end
saverestore.AddSaveHook( "EntityNetworkedBeamVars", Save )
saverestore.AddRestoreHook( "EntityNetworkedBeamVars", Restore )
if (SERVER) then
//
// send the netvars queried in the stack
//
local NextBeamVarsDelayedSendTime = 0
local NormalOpMode = true
local function NetworkVarsSend()
if (CurTime() >= NextBeamVarsDelayedSendTime) then
if (NormalOpMode) and (DelayedUpdatesNum > 75) then
Msg("========BeamVars leaving NormalOpMode | "..DelayedUpdatesNum.."\n")
NormalOpMode = false
elseif (!NormalOpMode) and (DelayedUpdatesNum < 50) then
Msg("========BeamVars returning NormalOpMode | "..DelayedUpdatesNum.."\n")
NormalOpMode = true
end
if (DelayedUpdatesNum > 0) then
for Index, a in pairs(DelayedUpdates) do
for VarType, b in pairs(a) do
for Key, Value in pairs(b) do
SendNetworkUpdate( VarType, Index, Key, Value )
end
end
end
DelayedUpdatesNum = 0
DelayedUpdates = {}
end
//we send one entity's ExtraDelayedUpdates each tick
local i = 0
for Index, a in pairs(ExtraDelayedUpdates) do
for VarType, b in pairs(a) do
for Key, data in pairs(b) do
SendNetworkUpdate( VarType, Index, Key, data.Value, data.Player )
end
end
ExtraDelayedUpdates[Index] = nil
i = i + 1
if (i >= 2) then
break
end
end
if (!NormalOpMode) then
NextBeamVarsDelayedSendTime = CurTime() + .25
else
NextBeamVarsDelayedSendTime = CurTime() + .1
end
end
end
hook.Add("Think", "NetBeamLib_Think", NetworkVarsSend)
//
// Send a full update to player that have just joined the server
//
local function FullUpdateEntityNetworkVars( ply )
--Msg("==sending netbeamvar var data to "..tostring(ply).."\n")
--Msg("\n===Size: "..table.Count(NetworkVars).."\n")
for Ent, EntTable in pairs(NetworkVars) do
for Type, TypeTable in pairs(EntTable) do
for Key, Value in pairs(TypeTable) do
local Index = Ent
if ( type(Ent) != "string" ) then
Index = Ent:EntIndex()
end
--SendNetworkUpdate( Type, Index , Key, Value, ply )
AddExtraDelayedNetworkUpdate( Type, Index , Key, Value, ply )
end
end
end
end
local function DelayedFullUpdateEntityNetworkVars( ply )
--Msg("==starting timer for sending var data too "..tostring(ply).."\n")
timer.Simple(4, FullUpdateEntityNetworkVars, ply)
end
hook.Add( "PlayerInitialSpawn", "FullUpdateEntityNetworkBeamVars", DelayedFullUpdateEntityNetworkVars )
concommand.Add( "networkbeamvars_SendAll", DelayedFullUpdateEntityNetworkVars )
concommand.Add( "networkbeamvars_SendAllNow", FullUpdateEntityNetworkVars )
//
// Listen out for dead entities so we can remove their vars
//
local function NetworkVarsCleanup( ent )
NetworkVars[ ent ] = nil
end
hook.Add( "EntityRemoved", "NetworkBeamVarsCleanup", NetworkVarsCleanup )
end //end SERVER olny
Msg("======== Beam NetVars Lib v"..BeamNetVars.Version.." Installed ========\n")