• [WIP] TableStream
    14 replies, posted
Ok I've began work on a new project. its a Lua module. This project is very similar to data-stream but will not use glon. The code so far is just a mock up. User-messages are restricted to 128 bytes so that's something i need to work on (not sure how yet). This is it ATM: [url]http://goluch.pastebin.org/437002[/url] (untested its a mock up) Though ATM it wil only have the ability to send tables very small in size, i hope to achieve something that will be able to send mass amounts of data with out the use of glon. If you have any feedback/suggestions please post. If you have nothing relevant and polite to say please don't post it here.
[QUOTE=goluch;23746795]User-messages are restricted to 128 bytes so that's something i need to work on (not sure how yet).[/QUOTE] User messages are limited to about 255 bytes, not 128. [QUOTE=goluch;23746795]Though ATM it wil only have the ability to send tables very small in size, i hope to achieve something that will be able to send mass amounts of data with out the use of glon.[/QUOTE] Could you tell us what exactly the advantage of not using GLON is?
Because Glon means all the data becomes a huge string and strings use up a lot of bytes, with datastream your end up sending way more then you need to.
[QUOTE=goluch;23748583]Because Glon means all the data becomes a huge string and strings use up a lot of bytes, with datastream your end up sending way more then you need to.[/QUOTE] It's like that so you can send from client to server. [editline]06:08AM[/editline] I'd suggest having a name for types. TABLESTREAM_COLOR = 10
[QUOTE=Overv;23748460]Could you tell us what exactly the advantage of not using GLON is?[/QUOTE] If you encode this table with GLON: [lua]{ "string one", "string two", Color(255, 255, 255, 255) }[/lua] It becomes: [lua]string onestring twoa255b255g255r255[/lua] Wasting up to 28 bytes (if I assume that one character takes up one byte), when you could just use umsg.String twice and umsg.Char thrice. It's nothing if you're working with small tables, but it's very noticeable if you want to send large tables (which is what datastream was originally intended to do).
[QUOTE=DarKSunrise;23754277]If you encode this table with GLON: [lua]{ "string one", "string two", Color(255, 255, 255, 255) }[/lua] It becomes: [lua]string onestring twoa255b255g255r255[/lua] Wasting up to 28 bytes (if I assume that one character takes up one byte), when you could just use umsg.String twice and umsg.Char thrice. It's nothing if you're working with small tables, but it's very noticeable if you want to send large tables (which is what datastream was originally intended to do).[/QUOTE] That's nice and all, but the client has no way of knowing it has to read two strings and a char from the user message.
That's why you need to try to read each thing. If it returns something else than the default value for that type, you'll know that it's the correct value. If it returns the default value, just call Reset on the bf_read object and try again. Here's something that I used in my gamemode to determine if it needs to read a char, a short or a long: [lua]local types = { {"Char", 0}, {"Short", 0}, {"Long", 0} }; usermessage.Hook("AddInventory", function(um) local id; -- Check all types. for _, v in ipairs(types) do local a = um["Read" .. v[1]](um); if(a ~= v[2]) then id = a; break; else um:Reset(); end end local slot = um:ReadChar(); LocalPlayer():GetInventory()[slot] = GAMEMODE.ItemIDs[id]; end);[/lua] Then you'll have to send a different usermessage if you want to set that value to it's default value though.
First off, Receive is spelled incorrectly. And your coding style changes every now and then.
That makes no sense. bf_read simply reads a stream of received bytes, it has no way of knowing which types are present. I don't understand why you think your system would work, but if you want a concrete example that shows how flawed it is, here you go: [lua]if ( SERVER ) then umsg.Start( "Test" ) umsg.Short( 2010 ) umsg.Char( 65 ) umsg.End() else local types = { { "Char", 0 }, { "Short", 0 } } usermessage.Hook( "Test", function( um ) for _, v in ipairs( types ) do local a = um[ "Read" .. v[1] ]( um ) if ( a != v[2] ) then print( "First value in user message is a \"" .. v[1] .. "\"" ) break else um:Reset() end end end ) end[/lua] [code]First value in user message is a "Char"[/code]
There must've been a flaw in my testing methods when I was trying that. Anyway, you can just send an extra char for the type. It will still be lighter than GLON.
Well, if you want to support everything, including sub-tables and keys of all types, you'll quickly get data that's as big as GLONs. But besides that, if you are going to send a substantial amount of data (take the level in GCraft as an example), you would use your own system anyway.
[QUOTE=Overv;23756051]bf_read simply reads a stream of received bytes, it has no way of knowing which types are present.[/QUOTE] What about this: [lua]if SERVER then //Mainly proof of concept, not at all perfect, might work in theory. //PRDMSG_ = PRDMSG_STR = 0 PRDMSG_NUM = 1 PRDMSG_BOL = 2 PRDMSG_ENT = 3 PRDMSG_VEC = 4 PRDMSG_ANG = 5 PRDMSG_COL = 6 function SendPredictedUsrMsg(ply, ...) local args = {...} umsg.Start("PredictedUsrMsg", ply) local str = "" local tbl = {} for _, v in pairs(args or {}) do //there are two loops, because the types need to be collected before anything is actually sent. if type(v) == "string" then str = str..PRDMSG_STR table.insert(tbl, v) elseif type(v) == "number" then str = str..PRDMSG_NUM table.insert(tbl, v) elseif type(v) == "boolean" then str = str..PRDMSG_BOL table.insert(tbl, v) elseif type(v) == "Entity" or type(v) == "Player" then str = str..PRDMSG_ENT table.insert(tbl, v) elseif type(v) == "Vector" then str = str..PRDMSG_VEC table.insert(tbl, v) elseif type(v) == "Angle" then str = str..PRDMSG_ANG table.insert(tbl, v) elseif type(v) == "Color" then str = str..PRDMSG_COL table.insert(tbl, v) end end umsg.Long(tonumber(str)) //HAHAHAHAH for _, v in pairs(tbl) do if type(v) == "string" then umsg.String(v) elseif type(v) == "number" then umsg.Long(v) elseif type(v) == "boolean" then umsg.Bool(v) elseif type(v) == "Entity" or type(v) == "Player" then umsg.Entity(v) elseif type(v) == "Vector" then umsg.Vector(v) elseif type(v) == "Angle" then umsg.Angle(v) elseif type(v) == "Color" then /*However this is done*/ end end umsg.End() end else PRDMSG_STR = 0 PRDMSG_NUM = 1 PRDMSG_BOL = 2 PRDMSG_ENT = 3 PRDMSG_VEC = 4 PRDMSG_ANG = 5 PRDMSG_COL = 6 usermessage.Hook("PredictedUsrMsg", function(um) local order = um:ReadLong() local tbl = {} for _, v in pairs(string.Explode(order, "")) do if v == PRDMSG_STR then table.insert(tbl, um:ReadString()) elseif v == PRDMSG_NUM then table.insert(tbl, um:ReadLong()) elseif v == PRDMSG_BOL then table.insert(tbl, um:ReadBool()) elseif v == PRDMSG_ENT then table.insert(tbl, um:ReadEntity()) elseif v == PRDMSG_VEC then table.insert(tbl, um:ReadVector()) elseif v == PRDMSG_ANG then table.insert(tbl, um:ReadAngle()) elseif v == PRDMSG_COL then table.insert(tbl, /*Something*/) end end //Do what you want with "tbl". end) end[/lua]
That's limited to about nine variables per usermessage, because the maximum value for an unsigned long is 4294967295. Then again, of course you could split it up to have multiple longs. Interesting concept, it might even be cheaper than sending a char for each variable.
[QUOTE=Overv;23756187]But besides that, if you are going to send a substantial amount of data (take the level in GCraft as an example), you would use your own system anyway.[/QUOTE] This exactly. Glon really is for when you have no idea what the table is and people too lazy to do their own networking, which is always the most efficient way.
[QUOTE=DarKSunrise;23774537]That's limited to about nine variables per usermessage, because the maximum value for an unsigned long is 4294967295. Then again, of course you could split it up to have multiple longs. Interesting concept, it might even be cheaper than sending a char for each variable.[/QUOTE] Yeah, this has lots of room for improvement.
Sorry, you need to Log In to post a reply to this thread.