Next Update v2

Then you were probably setting NWVars clientside without knowing, possibly because you were doing it in shared code. Either way that should be fixed now.

This gets printed whenever I start up my game and could probably use some line breaks at the end of it. No big deal

It’s Garry’s Mod

We’re still releasing this week, right?

I’m only using it in one place in my current code, sending a table from the server to the client to be directly added in chat.AddText since the table can contain any number of Colors, Players, and strings. I could rewrite my own function for sending it but it would probably just be exactly the same as net.WriteTable but only for those 3 data types.

And no writing keys and types of keys (since it’s a sequential table) which saves resources

What about something like this:
local function WriteChat(…)
local args = {…}
local sends = {}
for i = 1, #args do – flatten players into team col and nick; can’t think of way to get correct len without this
local o = args*
if type(o) == “Player” then
sends[#sends + 1] = team.GetColor(o:Team())
sends[#sends + 1] = o:Nick()
sends[#sends + 1] = o
net.WriteUInt(#sends, 4)
for i = 1, #sends do
local o = sends*
local typ = type(o)
if typ == “string” or typ == “number” then
net.WriteUInt(0, 1)
elseif IsColor(o) then
net.WriteUInt(1, 1)

local function ReadChat()
local len = net.ReadUInt(4)
local ret = {}
for i = 1, len do
local typ = net.ReadUInt(1)
local func = (typ == 0) and net.ReadString or net.ReadColor
ret[#ret + 1] = func()
return ret
Two bad points on this: 1) Extra for loop to flatten players 2) Couldn’t get WriteBit/ReadBit to work so I used WriteUInt with size of 1

Edit: Just tested with this code vs writetable:
if SERVER then
function temporary()
WriteChat(color_white, "Hello there, ", player.GetHumans()[1], “!”)
net.Receive(“Testerino”, function(len)
local tbl = ReadChat()
The len argument of the receiver was 241 with WriteChat and 504 with WriteTable. I’d say that’s pretty good.

Actually, for that it would be less because it would only be 1 player, 1 color and 1 string ( although, if you want to allow unlimited you can simply alternate ReadColor / ReadString until the value doesn’t exist in a do while loop [ which runs a minimum of 1 time ] ).

The values would be a few extra bytes total. Not exactly the worst overhead but I am agreeing that it can be better.

Stuff can really add up when you get in that mindset.

That’s why it is a calculable “risk” and why it shouldn’t be the end-all-be-all function to use… For a simple chat table that can grow, I don’t see an issue with using it even though the function below wouldn’t network as much:

if ( SERVER ) then
	util.AddNetworkString( "ChatMessage" );
	concommand.Add( "dev_chattest", function( _p, _cmd, _args )
		net.Start( "ChatMessage" );
			net.WriteEntity( _p );

			net.WriteColor( color_white );
			net.WriteString( "Testing" );

			net.WriteColor( color_black );
			net.WriteString( "gingtseT" );

			net.WriteColor( color_white );
			net.WriteString( "Testing" );

			net.WriteColor( color_black );
			net.WriteString( "gingtseT" );

			net.WriteColor( color_white );
			net.WriteString( "Testing" );

			net.WriteColor( color_black );
			net.WriteString( "gingtseT" );

			net.WriteColor( color_white );
			net.WriteString( "Testing" );

			net.WriteColor( color_black );
			net.WriteString( "gingtseT" );

		net.Broadcast( );
	end );
	net.Receive( "ChatMessage", function( _len )
		local _p = net.ReadEntity( );

		local _chat = {
			color_white, _p:Nick( ) .. ": ";

		// Same as do-while which runs at the minimum of 1 time...
		while ( true ) do
			// Always returns a color...
			local _color = net.ReadColor( );

			local _text = net.ReadString( );

			if ( !_text || _text == "" ) then break; end

			table.insert( _chat, _color );
			table.insert( _chat, _text );

		chat.AddText( unpack( _chat ) );
		chat.PlaySound( );
	end );

I’ve always been worried about calling net.Read* when I’m not expecting there to be data , is it ok? I thought it might have return some unexpected values or something.

next update v battle of the writetable replacements

[lua]nchat = {
writetype = {
[TYPE_NIL] = function() return 0 end,
–[[ [TYPE_BOOL] = function(val)
return 1, {val and “true” or “false”}
end, ]]
[TYPE_NUMBER] = function(val)
return 1, {val}
[TYPE_STRING] = function(val)
return 1, {val}
[TYPE_TABLE] = function(val)
assert(nchat.iscolor(val), string.format(“unsupported object type ‘%s’ (%s)”, type(arg), tostring(arg)))

		return 1, {val}
	[TYPE_ENTITY] = function(val, vals)
		if(val:GetClass() == "player") then
			return 3, {team.GetColor(val:Team()), val:Nick(), nchat.lastcol}
			return 1, {val:GetClass()}
	--[[ [TYPE_VECTOR] = function(val)
		return 1, {tostring(val)}
	[TYPE_ANGLE] = function(val)
		return 1, {tostring(val)}
	end ]]
iscolor = function(val)
	return TypeID(val) == TYPE_TABLE and val.r and val.g and val.b and val.a
pack = function(col)
	local num = col.b

	num = bit.bor(num, bit.lshift(col.g, 8))
	num = bit.bor(num, bit.lshift(col.r, 16))

	return num
unpack = function(num)
	local b =, 255)
	local g =, 8), 255)
	local r =, 16), 255)

	return Color(r, g, b)


if(SERVER) then

nchat.writechat = function(...)
	local args = {...}
	local len = 0
	local vals = {}

	nchat.lastcol = Color(255, 255, 255)

	for k, arg in pairs(args) do
		local func = nchat.writetype[TypeID(arg)]

		--assert(func, string.format("unsupported object type '%s' (%s)", type(arg), tostring(arg)))

		if(func) then
			local num, sep = func(arg)

			len = len + num

			for k, val in pairs(sep) do
				vals[#vals + 1] = val

	if(len < 1) then return end

	net.WriteUInt(len - 1, 5) --32 things

	for k, val in pairs(vals) do
		local color = TypeID(val) == TYPE_TABLE --it's either a string or a color

		if not(color and nchat.lastcol == color) then

			if(color) then
				net.WriteUInt(nchat.pack(val), 24) --packed colors are 24 bits

				nchat.lastcol = val

nchat.readchat = function()
local tab = {}

	local len = net.ReadUInt(5) + 1

	for i = 1, len do
		local kind = net.ReadBit() == 1

		if(kind) then
			tab[#tab + 1] = nchat.unpack(net.ReadUInt(24))
			tab[#tab + 1] = net.ReadString()



I had support for bools, vectors and angles before I realized chat.AddText doesn’t support them by default
results from sending a player, string, color, vector, string, angle, string, and a bool:

mine’s 1/3 the size of using writetable, but this is a pretty biased test

sending a player, color, string, color, string:

47% size

Any chances that we could see DarkRP gamemodes like “MilitaryRP” “MethRP” “SlaveRP” being forced to change their gamemode name back to DarkRP, or face blacklist?
I just remember Garry mentioning it being something that would be done sometime ago, and I was wondering if it’s still out there.

That would take constant monitoring and policing

Expanding on this, what about all those twoscore servers?

Fake servers are not added to the list anymore. You can test this in Dev.

So the update is pretty much ready. We should be able to push it on Monday if nothing goes wrong, after that we should be able to work on requests again.

Oh also more frequent updates. I think that’d be a good thing. :v:

I still dont think I was since no code change between it breaking and working again, and the code that changed when it broke in the first place shouldnt have caused any problem like this. Regardless, the problem seems to have vanished but I’ll keep and eye out for it just in case.

If there’s no data to be read, then there should be no issue however net.ReadColor will always return a color because of how it works, and how the Color function works.

When reading files in other languages, you continue until EOF ( End of file ) or until there is no more data. There should be no issue with it with net-messages, and I just tested the code I posted and it worked fine. It didn’t work for testing Color, but it did for string so…

In true GMod fashion, it should be released over the weekend, with no fixes until the Monday after :v:

I hate to make a fool of myself but it’s late night and I’m hoping I’m just helping out.

But does the next update fix the sv_cheats 0 0 1 shit? People can use commands like that to run client side scripts ie. lua cheats if there isn’t an anti cheat that checks for variable manipulation. No dll injection needed.