404 lines
12 KiB
Lua
404 lines
12 KiB
Lua
///////////////////////////////////////////////
|
|
// ===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")
|