I've been mucking around with the new net library in gmod beta, figured i'd share some findings with you all. There are some things i still haven't quite figured out, such as sending tables that have strings as indices (sending tables with strings in them requires hacky workarounds right now, but it may just be a feature garry hasn't coded yet). All in all this looks very promising though.
The cool thing about the net library is that the same code works both ways (client to server OR server to client) with very little modification. Here's my test script:
[lua]local receiving_side = CLIENT // which side is receiving?
if receiving_side then
MsgN( "Loaded test script..." )
// TEST #1
// Reading tables.
net.Receive( "Test1", function( len )
MsgN( "TEST 1: Received message of ", len, " bits..." )
MsgN( "Printing the random arbitrary table..." )
PrintTable( net.ReadTable() )
end )
// TEST #2
// Read specific values.
net.Receive( "Test2", function( len )
MsgN( "TEST 2: Received message of ", len, " bits..." )
MsgN( "ReadFloat:" )
MsgN( net.ReadFloat() )
MsgN( "ReadLong:" )
MsgN( net.ReadLong() )
MsgN( "ReadEntity:" )
MsgN( net.ReadEntity() )
MsgN( "ReadByte:" )
MsgN( net.ReadByte() )
MsgN( "ReadString:" )
MsgN( net.ReadString() )
MsgN( "ReadVector:" )
MsgN( net.ReadVector() )
MsgN( "ReadAngle:" )
MsgN( net.ReadAngle() )
end )
else
MsgN( "Loaded test script..." )
// TEST #1
// Send tables.
local test_table = { "eggs", "cheese", "apple", 100200, 3.4567, Vector(1.2345,800,-900), Entity(1) }
net.Start( "Test1" )
net.WriteTable( test_table )
if receiving_side == SERVER then
net.SendToServer()
else
net.Broadcast() // Send it to all players.
// net.Send( Entity(1) ) // alternatively you could send it to only yourself!
end
// TEST #2
// Send specific things.
local fl = 2.3456
local long = 100200
local ent = Entity(1)
local byte = 10
local str = "John Lua"
local vec = Vector( 900, 3.4567, -500 )
local ang = Angle( 4.5678, -90, 45 )
net.Start( "Test2" )
net.WriteFloat( fl )
net.WriteLong( long )
net.WriteEntity( ent )
net.WriteByte( byte )
net.WriteString( str )
net.WriteVector( vec )
net.WriteAngles( ang )
if receiving_side == SERVER then
net.SendToServer()
else
net.Broadcast() // Send it to all players.
// net.Send( Entity(1) ) // alternatively you could send it to only yourself!
end
end[/lua]
Here's the output if anyone is wondering:
[code]TEST 1: Received message of 659 bits...
Printing the random arbitrary table...
1 = eggs
2 = cheese
3 = apple
4 = 100200
5 = 3
6 = 1.2188 800.0000 -900.0000
7 = Player [1][nüke]
TEST 2: Received message of 310 bits...
ReadFloat:
2.3455998897552
ReadLong:
100200
ReadEntity:
Player [1][nüke]
ReadByte:
10
ReadString:
John Lua
ReadVector:
900.0000 3.4375 -500.0000
ReadAngle:
4.563 -90.000 45.000[/code]
[b]Some more useful links:[/b]
[url=http://www.facepunch.com/showthread.php?p=33345668#post33345668]#1[/url]
[url=http://www.facepunch.com/showthread.php?p=32974347#post32974347]#2[/url]
Share your findings here and also feel free to post code if you want it tested.
- snip -
Last I checked the net library just crashed the entire game
Works fine for me...
[QUOTE=twoski;33401851]Works fine for me...[/QUOTE]
You're not calling net.Send(ply ). Don't worry though, the crashing will be fixed next Beta update.
Look: [url]http://www.facepunch.com/threads/1142025[/url]
Yes for the time being we can only use net.Broadcast(), which is fine since everything being written in the beta is for testing purposes only.
I hope that net.WriteTable supports more than just longs, entities and vectors next update.
In a twitter reply Garry implied that they will be supported.
[QUOTE=FPtje;33404241]In a twitter reply Garry implied that they will be supported.[/QUOTE]
As in strings, and other tables? I hope so.
Curious, but if you need to send a complex table to the client, why not just send the table encoded with glon to the client and have them reconstruct it?
[QUOTE=Kogitsune;33407468]Curious, but if you need to send a complex table to the client, why not just send the table encoded with glon to the client and have them reconstruct it?[/QUOTE]
Efficience, speed and data size.
[QUOTE=Wizard of Ass;33407694]Efficience, speed and data size.[/QUOTE]
You could use the AD2 like a module and use Donovan's encoding/decoding once it's shared on server and client I think. It's fast and compresses data nicely into a string.
[QUOTE=Kogitsune;33407468]Curious, but if you need to send a complex table to the client, why not just send the table encoded with glon to the client and have them reconstruct it?[/QUOTE]
That's what datastream did to my knowledge so i assume that method wouldn't be any less optimal. I'll see if it works.
[QUOTE=Kogitsune;33407468]Curious, but if you need to send a complex table to the client, why not just send the table encoded with glon to the client and have them reconstruct it?[/QUOTE]
Glon sends it as a string, which has more overhead than sending as bits and bytes.. which is what we're doing.
Plus my code is readable.
[lua]--
-- Write a whole table to the stream
-- This is less optimal than writing each
-- item indivdually and in a specific order
-- because it adds type information before each var
--
function net.WriteTable( tab )
for k, v in pairs( tab ) do
net.WriteType( k )
net.WriteType( v )
end
-- End of table
net.WriteByte( 0 )
end
function net.ReadTable()
local tab = {}
while true do
local t = net.ReadByte()
if ( t == 0 ) then return tab end
local k = net.ReadType( t )
local t = net.ReadByte()
if ( t == 0 ) then return tab end
local v = net.ReadType( t )
tab[ k ] = v
end
end
net.WriteVars =
{
[TYPE_NUMBER] = function ( t, v ) net.WriteByte( t ) net.WriteLong( v ) end,
[TYPE_ENTITY] = function ( t, v ) net.WriteByte( t ) net.WriteEntity( v ) end,
[TYPE_VECTOR] = function ( t, v ) net.WriteByte( t ) net.WriteVector( v ) end,
}
function net.WriteType( v )
local typeid = TypeID( v )
local wv = net.WriteVars[ typeid ]
if ( wv ) then return wv( typeid, v ) end
Error( "Couldn't write type " .. typeid )
end
net.ReadVars =
{
[TYPE_NUMBER] = function () return net.ReadLong() end,
[TYPE_ENTITY] = function () return net.ReadEntity() end,
[TYPE_VECTOR] = function () return net.ReadVector() end,
}
function net.ReadType( typeid )
local rv = net.ReadVars[ typeid ]
if ( rv ) then return rv( v ) end
Error( "Couldn't read type " .. typeid )
end[/lua]
Yeah, and here's hoping that net.WriteTable will support angles and more complex tables (ie. tables with strings, nested tables, etc).
Angles would be easy i think.
e: Boobs
You could just .WriteAngle
Oh, i missed that. Well then, all that we really need is support for tables containing strings and nested tables.
[QUOTE=twoski;33421845]Oh, i missed that. Well then, all that we really need is support for tables containing strings and nested tables.[/QUOTE]You also were using semi-expensive math functions (matrix multiplication/trig) to convert the angle into a normalized direction vector then back into an angle. It was not the best method to send the data packed in an angle object, three floats.
[QUOTE]Oh, i missed that. Well then, all that we really need is support for tables containing strings and nested tables.[/QUOTE]
Agree.
It can be very useful to send over tables full of random stuff. Even though I expect garry to say something along the lines of: "If you would have coded it in a less inefficient and chaotic way then you wouldn't be needing it." I think it can still be useful.
Even if the direct need for it is not there as it can also be done manually, it would add so much ease of use. Sending over the table as is just makes the code faster to work with. Looping through it and reconstructing it on the client is simply annoying to do, and nested tables quickly become looping hell.
Do we get this package of awesomeness or are we expected to get our datastructures in line and do it manually? (or with GLON...)
[QUOTE=psycix;33425795]Agree.
It can be very useful to send over tables full of random stuff. Even though I expect garry to say something along the lines of: "If you would have coded it in a less inefficient and chaotic way then you wouldn't be needing it." I think it can still be useful.
Even if the direct need for it is not there as it can also be done manually, it would add so much ease of use. Sending over the table as is just makes the code faster to work with. Looping through it and reconstructing it on the client is simply annoying to do, and nested tables quickly become looping hell.
Do we get this package of awesomeness or are we expected to get our datastructures in line and do it manually? (or with GLON...)[/QUOTE]
I had fun turning {[1]={1,2},[2]={1,2}} into "1;1:2/2;1:2". And then back.
Reminded me of code breaking.
[QUOTE=skullorz;33430720]I had fun turning {[1]={1,2},[2]={1,2}} into "1;1:2/2;1:2". And then back.
Reminded me of code breaking.[/QUOTE] Yeah, writing your own data structures is always fun and a good idea. If you do it specific to the data you are sending, its almost always far more efficient than glon and other "one size fits all" data structures.
There are some situations where it'd be nice to have support for tables containing arbitrary things.
An example would be my notification system. Some examples of its use:
[lua]ply:Notify( { "You were killed by ", attacker, "." } )
ply:Notify( {"You took ", num, " damage from ", attacker, "." } )
ply:Notify( {"You found a ", Color(255,0,0), "red thing." } ) [/lua]
As you can see the table can contain any number of elements (the elements can be players, colors, numbers and text) and there's no specific order to it. I figure Garry will implement code that handles something like this since there's no point in making people jump through hoops making their own WriteTable clones.
Wait, so with the replacement of datastream we don't send tables through networking any more?
You still can, the types you can have in tables being sent is fairly limited at the moment though. I imagine it's still a work in progress.
I'm just having fun theorycrafting and coming up with ways to send stuff that isn't supported yet.
[QUOTE=Ylsid;33433444]Wait, so with the replacement of datastream we don't send tables through networking any more?[/QUOTE]
You will have to deconstruct your table(s) most of the time or use glon. Oh to joy I love glon.
[QUOTE=Aide;33433588]You will have to deconstruct your table(s) most of the time or use glon. Oh to joy I love glon.[/QUOTE]
Well WriteTable is still under construction so you likely won't need to. GLON is also a bad choice.
I did get my variable length table code to work! It's really hacky in some areas (colors need to be converted to tables without string indices) but otherwise it works perfectly.
[img]http://i.imgur.com/05cPf.jpg[/img]
[lua]
net.Start( "LogEvent" )
local tbl = {}
for k,v in pairs( msg ) do
table.insert( tbl, TypeID( v ) )
end
net.WriteTable( tbl )
for k,v in pairs( msg ) do
if type( v ) == "string" then
net.WriteString( v )
elseif type( v ) == "table" then
net.WriteTable( { v.r, v.g, v.b } )
else
net.WriteLong( v )
end
end
net.Broadcast() [/lua]
There's the serverside code, where msg is a table full of strings, numbers and colors.
Client code:
[lua]
net.Receive( "LogEvent", function( len )
MsgN( "Received message of ", len, " bits..." )
local tbl = net.ReadTable()
local notice = {}
for k,v in pairs( tbl ) do
if v == TypeID( "a" ) then
table.insert( notice, net.ReadString() )
elseif v == TypeID( 1 ) then
table.insert( notice, net.ReadLong() )
else
local col = net.ReadTable()
table.insert( notice, Color( col[1], col[2], col[3] ) )
end
end
end )[/lua]
Of course this is hacky as hell and we're better off waiting for garry to just finish the net library. But it's fun to muck around.
My new way would just be taking the WriteTable function, and then overwriting it with a function that supports strings and other tables. Either that, or just overwrite WriteVar, because that's what makes WriteTable write different data types.
Why don't you just wait till it's finsihed? What would be the point of a WriteTable function that didn't write a table properly? You think I decided that I would have a WriteTable function but only allow you to send strings, floats and vectors in them?
[QUOTE=garry;33434257]Why don't you just wait till it's finsihed? What would be the point of a WriteTable function that didn't write a table properly? You think I decided that I would have a WriteTable function but only allow you to send strings, floats and vectors in them?[/QUOTE]
Meh, okay.
Table size: 6.
1 = eggs
2 = cheese
3 = shovel
4 = apple
5 = orange
6 = hitler
2 and 6
cheese hitler
someone should hit us up with some rough docd on the net library, like.. how to omit players? not all of us got beta keys...
Sorry, you need to Log In to post a reply to this thread.