// --------------------------------------------------------------------------------------------------------- // sh_beam.lua - Revision 1 // Shared // Controls beaming data from server to client // --------------------------------------------------------------------------------------------------------- // --------------------------------------------------------------------------------------------------------- // Define our library // --------------------------------------------------------------------------------------------------------- PCMod.Beam = {} PCMod.Beam.Version = "1.0" PCMod.Beam.StrSegs = {} PCMod.Beam.Hooks = {} PCMod.Beam.Range_SS = 1024 -- Range to beam ScreenSpaces to PCMod.PortData = {} PCMod.EntData = {} PCMod.Msg( "Beam Library Loaded (V" .. PCMod.Beam.Version .. ")", true ) if (SERVER) then // --------------------------------------------------------------------------------------------------------- // SendScreenSpace - Sends a screen space to the client // --------------------------------------------------------------------------------------------------------- function PCMod.Beam.SendScreenSpace( ply, ent ) PCMod.Msg( "Preparing to send SS...", true ) // If the entity is not on, send an empty ss if (!ent:Data().IsOn) then PCMod.Beam.BeamTable( ply, "ssdata", {} ) end // Get the SS data local ss = ent:ScreenSpace() if (!ss) then return end local dat = ss.Data // Ensure the player's beam data exists if (!ply.BeamData) then ply.BeamData = {} end if (!ply.BeamData[ ent:EntIndex() ]) then ply.BeamData[ ent:EntIndex() ] = {} end // Check the player's beam data for items that no longer exist local btbl = ply.BeamData[ ent:EntIndex() ] local newdat = {} for k, v in pairs( dat ) do if (type(v) == "table") then // For every device name and device in the screenspace; // k is the device name in the sspace, v is the actual device. // Check to see what version the player has // Cycle through player beam data for the right one // We're screwed if an entity needs multiple screenspaces - thomasfn local f = false for devname, rev in pairs( btbl ) do if (k == devname) then f = true -- We found the device, at least the player has recieved a version of this device -- Check the revisions if (rev != v.Rev) then -- Revision mismatch! Assume the server's version newdat[ k ] = v ply.BeamData[ ent:EntIndex() ][ devname ] = v.Rev PCMod.Msg( "Server has different revision! (" .. k .. ")", true ) end break end end if (f == false) then // We have not found this device, insert it right in PCMod.Msg( "Server has new device! (" .. k .. ")", true ) newdat[ k ] = v ply.BeamData[ ent:EntIndex() ][ k ] = v.Rev end else // We have a variable which isn't a table. Probably a 'sneaky' variable, let's send it anyway newdat[ k ] = v end end // Check if the player has a ss device that we don't for k, v in pairs( btbl ) do if (!table.HasKey( dat, k )) then // Tell the client the device no longer exists newdat[ k ] = 0 ply.BeamData[ ent:EntIndex() ][ k ] = nil end end // Send the data newdat.EntID = ent:EntIndex() PCMod.Beam.BeamTable( ply, "ssdata_update", newdat ) end // --------------------------------------------------------------------------------------------------------- // BeamTable - Sends a table to the client // --------------------------------------------------------------------------------------------------------- function PCMod.Beam.BeamTable( ply, tag, tbl ) if (type(tbl) != "table") then PCMod.Warning( "BeamTable recieved a non-table value!" ) return end PCMod.Beam.BeamString( ply, tag, PCMod.TableToString( tbl ) ) end // --------------------------------------------------------------------------------------------------------- // BeamString - Sends a string to the client (larger than 255 bytes) // --------------------------------------------------------------------------------------------------------- function PCMod.Beam.BeamString( ply, tag, str ) local rs = 230 - string.len( tag ) local chunks = PCMod.SplitString( str, rs ) umsg.Start( "pcmod_stringstart", ply ) umsg.String( tag ) umsg.Short( #chunks ) umsg.String( chunks[1] ) umsg.End() local i = 0 if (#chunks < 2) then return end for i = 2, #chunks do umsg.Start( "pcmod_stringseg", ply ) umsg.String( tag ) umsg.Short( i ) umsg.String( chunks[ i ] ) umsg.End() end end // --------------------------------------------------------------------------------------------------------- // BeamEntSS - Beam a screen space of an entity to all players in range // --------------------------------------------------------------------------------------------------------- function PCMod.Beam.BeamEntSS( ent, range ) if ((!ent) || (!ent:IsValid())) then return end for _, v in pairs( player.GetAll() ) do if (!v.SSBeam) then v.SSBeam = {} end if (!v.SSBeam[ ent:EntIndex() ]) then if ((v:GetPos()-ent:GetPos()):Length()