• gm_sourcenet3 - Advanced Source Networking Library
    203 replies, posted
  • [release][B][U]Description:[/U][/B] This is a revamp of sourcenet, a module designed to expose Source's networking. [B][U]Notes:[/U][/B] - All allocated objects (sn3_bf_write, sn3_bf_read, UCHARPTR, dataFragments_t) must be freed, see examples. - Do not call :FinishReading/Writing on bit buffers passed as arguments, only free objects [I]you[/I] create. - If you're not using the hooking base, [B]always[/B] detach from functions before you change level. Not doing so will cause a crash. [B][U]SVN:[/U][/B] [url]http://christopherthorne.googlecode.com/svn/trunk/gm_sourcenet3/[/url] Includes Windows and Linux binaries, as well as the source code and examples. [B][U]Global Functions:[/B][/U] [code] -- Client: Retrieves server net channel -- Server: Retrieves specified player's net channel CNetChan( [number] entindex ) [CNetChan] -- Creates a new write bitbuf -- Always call FinishWriting after you've finished writing sn3_bf_write( [UCHARPTR] data, [number] bits ) [sn3_bf_write] -- Creates a new read bitbuf -- Always call FinishReading after you've finished reading sn3_bf_read( [UCHARPTR] data, [number] bits ) [sn3_bf_read] -- Allocates new fragments class -- Always call Delete when you've finished with the object dataFragments_t() [dataFragments_t] -- Allocates specified bytes -- Always call Delete when you've finished with the memory UCHARPTR( [number] bytes ) [UCHARPTR] -- Returns network string table container INetworkStringTableContainer() [INetworkStringTableContainer] -- Returns game event manager IGameEventManager2() [IGameEventManager2] -- Hooking functions (Always detach before unloading the module) -- PreProcessPacket( [CNetChan] netchan ) -- PostProcessPacket( [CNetChan] netchan ) Attach__CNetChan_ProcessPacket( [CNetChan] netchan ) Detach__CNetChan_ProcessPacket( [CNetChan] netchan ) -- PreSendDatagram( [CNetChan] netchan, [sn3_bf_write] extradata, [sn3_bf_write] reliabledata, [sn3_bf_write] unreliabledata, [sn3_bf_write] voicedata ) -- PostSendDatagram( [CNetChan] netchan ) Attach__CNetChan_SendDatagram( [CNetChan] netchan ) Detach__CNetChan_SendDatagram( [CNetChan] netchan ) -- PreNetChannelShutdown( [CNetChan] netchan, [string] reason ) -- PostNetChannelShutdown() Attach__CNetChan_Shutdown( [CNetChan] netchan ) Detach__CNetChan_Shutdown( [CNetChan] netchan ) -- INetChannelHandler::ConnectionStart( [INetChannelHandler] handler, [CNetChan] netchan ) Attach__INetChannelHandler_ConnectionStart( [INetChannelHandler] handler ) Detach__INetChannelHandler_ConnectionStart( [INetChannelHandler] handler ) -- INetChannelHandler::ConnectionClosing( [INetChannelHandler] handler, [string] reason ) Attach__INetChannelHandler_ConnectionClosing( [INetChannelHandler] handler ) Detach__INetChannelHandler_ConnectionClosing( [INetChannelHandler] handler ) -- INetChannelHandler::ConnectionCrashed( [INetChannelHandler] handler, [string] reason ) Attach__INetChannelHandler_ConnectionCrashed( [INetChannelHandler] handler ) Attach__INetChannelHandler_ConnectionCrashed( [INetChannelHandler] handler ) -- INetChannelHandler::PacketStart( [INetChannelHandler] handler, [number] incoming_sequence, [number] outgoing_sequence ) Attach__INetChannelHandler_PacketStart( [INetChannelHandler] handler ) Detach__INetChannelHandler_PacketStart( [INetChannelHandler] handler ) -- INetChannelHandler::PacketEnd( [INetChannelHandler] handler ) Attach__INetChannelHandler_PacketEnd( [INetChannelHandler] handler ) Detach__INetChannelHandler_PacketEnd( [INetChannelHandler] handler ) -- INetChannelHandler::FileRequested( [INetChannelHandler] handler, [string] filename, [number] transferID ) Attach__INetChannelHandler_FileRequested( [INetChannelHandler] handler ) Detach__INetChannelHandler_FileRequested( [INetChannelHandler] handler ) -- INetChannelHandler::FileReceived( [INetChannelHandler] handler, [string] filename, [number] transferID ) Attach__INetChannelHandler_FileReceived( [INetChannelHandler] handler ) Detach__INetChannelHandler_FileReceived( [INetChannelHandler] handler ) -- INetChannelHandler::FileDenied( [INetChannelHandler] handler, [string] filename, [number] transferID ) Attach__INetChannelHandler_FileDenied( [INetChannelHandler] handler ) Detach__INetChannelHandler_FileDenied( [INetChannelHandler] handler ) -- PreProcessMessages( [CNetChan] netchan, [sn3_bf_read] messages ) -- Optional return of new sn3_bf_read size in bits (incase you've tweaked the data) Attach__CNetChan_ProcessMessages() Detach__CNetChan_ProcessMessages() [/code] [B][U]Metatables:[/B][/U] [code] [U]sn3_bf_write[/U]: -- Data pointer GetBasePointer() [UCHARPTR] -- Max number of bits that can be written GetMaxNumBits() [number] -- Number of bits written GetNumBitsWritten() [number] -- Number of bytes written GetNumBytesWritten() [number] -- Number of bits remaining GetNumBitsLeft() [number] -- Number of bytes remaining GetNumBytesLeft() [number] -- Overflow status IsOverflowed() [boolean] -- Seeks to specified bit Seek( [number] bit ) -- Writes ang in specified bits WriteBitAngle( [number] ang, [number] bits ) -- Writes a UCHARPTR in specified bits, returns success WriteBits( [UCHARPTR] data, [number] bits ) [boolean] -- Writes a Vector coordinate WriteBitVec3Coord( [Vector] vec ) -- Writes a byte WriteByte( [number] val ) -- Writes a UCHARPTR in specified bytes WriteBytes( [UCHARPTR] data, [number] bytes ) -- Writes a character WriteChar( [number] val ) -- Writes a float WriteFloat( [number] val ) -- Writes a long WriteLong( [number] val ) -- Writes a single bit ( 1 or 0 ) WriteOneBit( [number] val ) -- Writes a short WriteShort( [number] val ) -- Writes a null-terminated string WriteString( [string] str ) -- Writes a signed long value in specified bits WriteSBitLong( [number] val, [number] bits ) -- Writes an unsigned long value in specified bits WriteUBitLong( [number] val, [number] bits ) -- Writes a word WriteWord( [number] val ) -- Deletes bitbuf (Only call this if you allocated the buffer) FinishWriting() [U]sn3_bf_read[/U]: -- Data pointer GetBasePointer() [UCHARPTR] -- Number of bits remaining GetNumBitsLeft() [number] -- Number of bytes remaining GetNumBytesLeft() [number] -- Number of bits read GetNumBitsRead() [number] -- Overflow status IsOverflowed() [boolean] -- Reads an angle ReadBitAngle( [number] bits ) [number] -- Reads angle object ReadBitAngles() [Angle] -- Reads bits (Always call :Delete when finished with the result) ReadBits( [number] bits ) [UCHARPTR] -- Reads a Vector coordinate ReadBitVec3Coord() [Vector] -- Reads a byte ReadByte() [number] -- Reads specified amount of bytes (Always call :Delete when finished with the result) ReadBytes( [number] bytes ) [UCHARPTR] -- Reads a character ReadChar() [number] -- Reads a float ReadFloat() [number] -- Reads a long ReadLong() [number] -- Reads a single bit ( 1 or 0 ) ReadOneBit() [number] -- Reads a short ReadShort() [number] -- Reads a string (max 1024) ReadString() [string] -- Reads a signed long value of length 'bits' ReadSBitLong( [number] bits ) [number] -- Reads an unsigned long value of length 'bits' ReadUBitLong( [number] bits ) [number] -- Reads a word ReadWord() [number] -- Seeks to specified bit Seek( [number] bit ) [boolean] -- Seeks to specified bit relative to current position SeekRelative( [number] bit ) [boolean] -- Total bytes available TotalBytesAvailable() [number] -- Deletes bitbuf (Only call this if you allocated the buffer) FinishReading() [U]CNetChan[/U]: -- Prints registered net messages to console (debugging) DumpMessages() -- Resets buffers and a few other member variables Reset() -- Appears to purge fragments, not documented Clear() -- Terminates the net channel with the specified reason Shutdown( [string] reason ) -- Adds data in buffers to send queue Transmit( [opt boolean] onlyreliable ) [boolean] -- Sends a local file SendFile( [string] filename, [number] transferid ) [boolean] -- Reports file denial DenyFile( [string] filename, [number] transferid ) -- Attempts
  • Avatar of Gbps
  • I'll be releasing Files on Demand [soon], it uses sourcenet3. I'll update this post when it's released
  • Avatar of yakahughes
  • Another freaking brilliant module. This probably means nothing coming from me, but well done.
  • Avatar of Kill coDer
  • Where can we find how the different messages are structured? Didn't valve have an online repository of the SDK code too? I can't find it..
  • [QUOTE=Kill coDer;26843103]Where can we find how the different messages are structured? Didn't valve have an online repository of the SDK code too? I can't find it..[/QUOTE] The messages aren't in the SDK. Take a look at sn3_base_netmessages.lua for structures.
  • Avatar of ColdFusion
  • [del][lua] include( "sn3_base_incoming.lua" ) local convar = CreateConVar("disconnect_msg", "Disconnect by user.") FilterOutgoingMessage( net_Disconnect, function( netchan, read, write ) write:WriteUBitLong( net_Disconnect, 6) read:ReadString() write:WriteString( convar:GetString() ) end )[/lua] Custom disconnect msg. aka change "SomeFaggot disconnected(Kicked by admin)" to "Somefaggot disconnected(Suck my donkey dick)" ( should probably say that you run this clientside, and that the people in the server see this when you disconnect.)[/del] Doesn't work. Because it detaches before the disconnect msg is send.
  • Avatar of ralle105
  • Am I just being stupid or could you not free the allocated objects in their __gc metamethod? Sweet module either way:smile:
  • [QUOTE=ralle105;26851596]Am I just being stupid or could you not free the allocated objects in their __gc metamethod? Sweet module either way:smile:[/QUOTE] That would cause objects passed as arguments to be deleted when they shouldn't be + there's not really any reason to use the garbage collector.
  • [QUOTE=ColdFusion;26851105][del][lua] include( "sn3_base_incoming.lua" ) local convar = CreateConVar("disconnect_msg", "Disconnect by user.") FilterOutgoingMessage( net_Disconnect, function( netchan, read, write ) write:WriteUBitLong( net_Disconnect, 6) read:ReadString() write:WriteString( convar:GetString() ) end )[/lua] Custom disconnect msg. aka change "SomeFaggot disconnected(Kicked by admin)" to "Somefaggot disconnected(Suck my donkey dick)" ( should probably say that you run this clientside, and that the people in the server see this when you disconnect.)[/del] Doesn't work. Because it detaches before the disconnect msg is send.[/QUOTE] [code] require( "sourcenet3" ) local buf = CNetChan():GetReliableBuffer() buf:WriteUBitLong( net_Disconnect, 6 ) buf:WriteString( "Bye!" ) CNetChan():Transmit() [/code]
  • I've fixed some problems in the base code for the next revision, however I'm having trouble with hooking since the last engine update. Currently looking into it.
  • Fixed. The problem was caused by GetData returning a pointer at a byte offset, which caused problems when the previous data (before the net messages) wasn't a set of complete bytes.
  • Avatar of mr.wolf
  • Quick question. As per Chris' code above, it is possible to detect the disconnect msg a player would normally transmit, and modify it as you want, however is it possible to modify the player's name as well? [quote]SomePerson disconnected (random reason)[/quote] Becomes [quote]SpecificPerson disconnected (reason to be determined)[/quote] Also, how would you read what a user's disconnect reason was and respond to it?
  • [QUOTE=mr.wolf;27259597]Quick question. As per Chris' code above, it is possible to detect the disconnect msg a player would normally transmit, and modify it as you want, however is it possible to modify the player's name as well? Becomes Also, how would you read what a user's disconnect reason was and respond to it?[/QUOTE] To modify the player name you would have to hook the svc_GameEvent message (outgoing), but I haven't added a wrapper for that yet. As for reading and responding, you can probably just add an incoming filter for the net_Disconnect message using the base code.
  • [QUOTE=mr.wolf;27259597]Quick question. As per Chris' code above, it is possible to detect the disconnect msg a player would normally transmit, and modify it as you want, however is it possible to modify the player's name as well? Becomes Also, how would you read what a user's disconnect reason was and respond to it?[/QUOTE] I've added the necessary functions to parse game events in revision 6. [lua]include( "sn3_base_gameevents.lua" ) hook.Add( "SendGameEvent", "ChangeReason", function( netchan, event ) if ( event:GetName() != "player_disconnect" ) then return end local reason = event:GetString( "reason" ) if ( reason == "Disconnect by user." ) then event:SetString( "reason", "Disconnected after " .. math.floor( netchan:GetTime() - netchan:GetConnectTime() ) .. " seconds" ) return event end end )[/lua] The name displayed is calculated using the "userid" key, so it won't be as easy to change.
  • Avatar of mr.wolf
  • Would it be possible to combine this with the normal user disconnect hook? Use sourcenet to find the reason for the disconnect, and pass the string off to the player.disconnect hook to display whatever you want? Does this take place prior to the player.disconnect hook?
  • Avatar of Nexus435
  • [QUOTE=mr.wolf;27392185]Would it be possible to combine this with the normal user disconnect hook? Use sourcenet to find the reason for the disconnect, and pass the string off to the player.disconnect hook to display whatever you want? Does this take place prior to the player.disconnect hook?[/QUOTE] [QUOTE=Chrisaster;26860742][code] require( "sourcenet3" ) local buf = CNetChan():GetReliableBuffer() buf:WriteUBitLong( net_Disconnect, 6 ) buf:WriteString( "Bye!" ) CNetChan():Transmit() [/code][/QUOTE]
  • Avatar of mr.wolf
  • Where are you reading the reason they disconnected in there? If the hook chris used above gets executed before the player.disconnect hook, then I can just assign the reason to a var and read it in the disconnect hook. Then I can print out whatever I want, in addition to the reason. What I am trying to do is alter the player's name, but keep the reason intact. Also, it would be cool to respond to reasons, but with chris's example above, I can do that. I only need to know which hook is executed first. I can experiment, but I don't have access to gmod at the moment.
  • [lua]include( "sn3_base_incoming.lua" ) FilterIncomingMessage( net_Disconnect, function( netchan, read, write ) local reason = read:ReadString() write:WriteUBitLong( net_Disconnect, 6 ) write:WriteString( string.reverse( reason ) ) end )[/lua] [quote]Client "Chrisaster" connected (192.168.1.9:27006). Dropped Chrisaster from server (.resu yb tcennocsiD)[/quote] This will change what the server sees the reason as too. Use the previous example if you just want to change what other clients are sent. [editline]13th January 2011[/editline] This won't work if you kick the user.
  • Avatar of PC Camp
  • im not sure if i understand what this does exactly, but it seems like its pretty useful. lol i think its used to transfer data from the client and server. anyone wanna give me an example on how to use this? lol
  • [QUOTE=PC Camp;27407307]im not sure if i understand what this does exactly, but it seems like its pretty useful. lol i think its used to transfer data from the client and server. anyone wanna give me an example on how to use this? lol[/QUOTE] There's a variety of examples included in the download.
  • Avatar of q3k
  • So I tried to use the module on my Linux srcds today... [code]error loading module 'sourcenet3' from file '/home/srcds/orangebox/garrysmod/lua/includes/modules/gm_sourcenet3_linux.dll': /home/srcds/orangebox/garrysmod/lua/includes/modules/gm_sourcenet3_linux.dll: undefined symbol: META_IGameEventManager2_name[/code]
  • [QUOTE=q3k;27432297]So I tried to use the module on my Linux srcds today... [code]error loading module 'sourcenet3' from file '/home/srcds/orangebox/garrysmod/lua/includes/modules/gm_sourcenet3_linux.dll': /home/srcds/orangebox/garrysmod/lua/includes/modules/gm_sourcenet3_linux.dll: undefined symbol: META_IGameEventManager2_name[/code][/QUOTE] My bad, I forgot to add the new obj files to the makefile. I'll fix it now. [editline]15th January 2011[/editline] Fixed.