Usermessage with string of size 254 is too large?

Hi everyone,

I’m having a very strange issue with usermessages. I’m trying to send a table of strings (each value has been split so that it is a maximum of 254 bytes), although complaints are raised when I try to send the values - “Error sending usermessage - too large (usermessage)”.

[lua]
timer.Simple(1, function ( )
if (Player && IsValid(Player)) then
local totalBytes = string.len(PlayerInfo[1][13])
local its, leftover = math.modf(totalBytes/255)
–Find how many iterations we can perform,then if there is anything leftover.

			MsgN("Preparing to send vehicle info to "..Player:GetName()..", size "..totalBytes.." byte(s), "..its.." iterations.")
			if (its > 0) then
				local tab = {}
				for i = 1,its do
					tab["s"..i] = string.sub(PlayerInfo[1][13],(i * 254) - 253, (i * 254))
				end
				
				tab["s"..its + 1] = string.sub(PlayerInfo[1][13], (its * 254) + 1, totalBytes)
			
				for k,v in pairs(tab) do
					MsgN("On "..k.." iteration, size is "..string.len(v))
					umsg.Start("usermessage",Player)
						--umsg.String(tab["s"..k])
						umsg.Short(totalBytes)
						umsg.String(v)
					umsg.End()
				end
			
			else //255 bytes or less than to send, it can fit in one umsg.
				MsgN("Running else.")
				umsg.Start("usermessage",Player)
					umsg.Short(totalBytes)
					umsg.String(PlayerInfo[1][13])
				umsg.End()
			end
		end
	end);

[/lua]

The MsgN prints out the following in a test case:
“Perparing to send vehicle info to (username), size 280 byte(s), 1 iterations.”
“On s1 iteration, size is 254”
“On s2 iteration, size is 26”

Directly after that is when I see the too large error.

Aside from potentially unoptimized coding, can anyone see what’s wrong?

Is it possible that the short you’re sending is pushing the message over the size cap?

A short is 2 bytes, if your string takes 254 bytes, and the short takes 2 bytes, that’s 256 bytes for a usermessage. Bear in mind that usermessages’ maximum size is 255 bytes, not 256.

EDIT: Also, a string’s size is actually it’s total length + 1 byte, since they seem to be null-terminated.

EDIT2: Why don’t you use datastream? It’s essentially the wrapper for what you are trying to do.

Sorry, I forgot to mention, I had actually tried sending the usermessage without anything other than the string (with the string still sized at 254 bytes), and I was still getting that too large error.

I was looking on the wiki about using datastreams; how much efficiency would I be losing by switching to datastreams? Does it really make sense, when I already have usermessages almost completely implemented, save for a weird glitch?

You’d lose alot of efficiency. Datastream essentially sends a usermessage for every value AND index, so that’s 2x the work. To fix your problem, you need to add in the name of your usermessage to the number of bytes as well.

Ohhh. Do I then treat the name just like I would another string being sent then? I was wondering why it was getting cutoff.

[editline]21st June 2012[/editline]

Alright, I just did a little math and figured in the new limitations. All working now, thank you very much everyone!

Yeah, I was going to say, the name of the usermessage is included in the size limit.

I see someone beat me to it though. :v:

Also, I believe you can use this

if your usermessage name takes too much space.

Hm… Worth a try, thank you.

Use umsg.PoolString for the message name too. Also you do know that the message name is added to the size, right?

I told him.

You are going to completely fuck yourself over in the longrun. datastreams are gone in GM13. So as soon as GM13 becomes live, you will have to recode the entire thing.

IIRC the message name only takes up 2 bytes since it’s pooled.

Yeah, I had a feeling. If the current wiki wasn’t down right now I’d read into the net library to a depth greater than reading a facepunch thread about it, but from what I was reading, it looks really cool. I may have to recode this thing, but if the net library is as nice as people are saying it is, then recoding this will be a lot easier.

Does it, even when I don’t run the function for explicitly pooling the name?