{"action":"created","issue":{"url":"https://api.github.com/repos/garrynewman/garrysmod/issues/1106","repository_url":"https://api.github.com/repos/garrynewman/garrysmod","labels_url":"https://api.github.com/repos/garrynewman/garrysmod/issues/1106/labels{/name}","comments_url":"https://api.github.com/repos/garrynewman/garrysmod/issues/1106/comments","events_url":"https://api.github.com/repos/garrynewman/garrysmod/issues/1106/events","html_url":"https://github.com/garrynewman/garrysmod/pull/1106","id":124557269,"number":1106,"title":"Update net.lua","user":{"login":"Python1320","id":207340,"avatar_url":"https://avatars.githubusercontent.com/u/207340?v=3","gravatar_id":"","url":"https://api.github.com/users/Python1320","html_url":"https://github.com/Python1320","followers_url":"https://api.github.com/users/Python1320/followers","following_url":"https://api.github.com/users/Python1320/following{/other_user}","gists_url":"https://api.github.com/users/Python1320/gists{/gist_id}","starred_url":"https://api.github.com/users/Python1320/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Python1320/subscriptions","organizations_url":"https://api.github.com/users/Python1320/orgs","repos_url":"https://api.github.com/users/Python1320/repos","events_url":"https://api.github.com/users/Python1320/events{/privacy}","received_events_url":"https://api.github.com/users/Python1320/received_events","type":"User","site_admin":false},"labels":[],"state":"open","locked":false,"assignee":null,"milestone":null,"comments":14,"created_at":"2016-01-01T18:55:34Z","updated_at":"2016-04-17T05:49:26Z","closed_at":null,"pull_request":{"url":"https://api.github.com/repos/garrynewman/garrysmod/pulls/1106","html_url":"https://github.com/garrynewman/garrysmod/pull/1106","diff_url":"https://github.com/garrynewman/garrysmod/pull/1106.diff","patch_url":"https://github.com/garrynewman/garrysmod/pull/1106.patch"},"body":"Add net.ReadPlayer/WritePlayer, saving GMod from network bloat one byte at a time."},"comment":{"url":"https://api.github.com/repos/garrynewman/garrysmod/issues/comments/210960873","html_url":"https://github.com/garrynewman/garrysmod/pull/1106#issuecomment-210960873","issue_url":"https://api.github.com/repos/garrynewman/garrysmod/issues/1106","id":210960873,"user":{"login":"Acecool","id":4174280,"avatar_url":"https://avatars.githubusercontent.com/u/4174280?v=3","gravatar_id":"","url":"https://api.github.com/users/Acecool","html_url":"https://github.com/Acecool","followers_url":"https://api.github.com/users/Acecool/followers","following_url":"https://api.github.com/users/Acecool/following{/other_user}","gists_url":"https://api.github.com/users/Acecool/gists{/gist_id}","starred_url":"https://api.github.com/users/Acecool/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/Acecool/subscriptions","organizations_url":"https://api.github.com/users/Acecool/orgs","repos_url":"https://api.github.com/users/Acecool/repos","events_url":"https://api.github.com/users/Acecool/events{/privacy}","received_events_url":"https://api.github.com/users/Acecool/received_events","type":"User","site_admin":false},"created_at":"2016-04-17T05:49:26Z","updated_at":"2016-04-17T05:49:26Z","body":"Here is an explanation why I both support this, and don't; more so towards supporting this helper-function though... \r\n\r\nIf you want to read/write Player, you need to know a few things... You don't need 8 bits for the amount of data because the max number of players is 128... You can further reduce it depending on max players, basically you use the max player value to choose the number of bits and because both client and server can read it, you can always use the max bit value for the amount of players on the server... Basically, if the max player count is 8, you don't need 7 bits, you can use 3 bits... Now, I see you want to support 0 being sent, but then why check for ! value incoming since net messages are verified unless you force it not to be... You can ignore sending the data and the read value will get nothing, ie sending is optional in some cases, since you're not reading any other data you don't have to worry about putting the optional data last either...\r\n\r\nNow, the way I understand networking to work, you use the SUM to know the max value able to be sent... Bit counting details here: https://dl.dropboxusercontent.com/u/26074909/tutoring/networking/bit_counting.lua.html\r\n\r\nSo with 2^8 you can send a value up to 255 ( 256 if you exclude 0 and shift, which is what we'll need to do for 128 player count to save 1 more bit )... So, for 128 max-players to send 1-128 we can use WriteUInt( EntIndex - 1, 7 ) to send, and Entity( ReadUInt + 1 ) to read... UInt reduces the bit value by 1 because we don't need to know if it is positive or negative, we already know...\r\n\r\nIf you want to discuss saving a bit each time, why not save a little bit more which the above revisions?\r\n\r\nWith this said, I agree that micro-optimizations do make sense in video games.... so I'll support this, as long as you save at least 1 more bit; if you want to add in the max player bit-slider in as an additional way to optimize, then I'd support that too....\r\n\r\nI am still around and I'm still involved in GMod...\r\n\r\nHere...\r\n```lua\r\n--\r\n-- Better, or best... For this we'll simply inverse, ie subtract, based on division... ie default bits is 7 so 128 / 128 is 1 therefore bits - 1 is 7... 128 / 64 is 2, so we get 6, etc...\r\n--\r\nfunction net.GetPlayerCountInBits( )\r\n\r\n\tlocal max = game.MaxPlayers( );\r\n\r\n\t-- Max players should never be 0, but I've never tried... Prevent sending 0 bits and division by 0...\r\n\t-- max = ( max > 0 ) && max || 1;\r\n\r\n\tlocal bits = 7;\r\n\r\n\t-- Ceiling because we need to go to the next step with decimals... +1 because we're using we want bits to be at the max, otherwise we'd need to use 8 or shift the value to allow > 64 be 0....\r\n\treturn bits - math.ceil( 128 / max ) + 1;\r\n\r\nend\r\n\r\n\r\n--\r\n-- Write a player to the stream\r\n--\r\nfunction net.WritePlayer( ply )\r\n\r\n\tif ( IsValid( ply ) && ply:IsPlayer() ) then\r\n\t\tnet.WriteUInt( ply:EntIndex() - 1, net.GetPlayerCountInBits( ) )\r\n\tend\r\n\r\nend\r\n\r\n\r\n--\r\n-- Read a player from the stream\r\n--\r\nfunction net.ReadPlayer( )\r\n\r\n\tlocal i = net.ReadUInt( net.GetPlayerCountInBits( ) ) + 1\r\n\tif ( !i ) then return end\r\n\r\n\tlocal ply = Entity( i )\r\n\treturn ply\r\n\r\nend\r\n```\r\n\r\nYou could a different method for getting the bits to send but it is longer and not as clean in my opinion...\r\n```lua\r\n--\r\n-- Not exactly slow, but not the best either... You could return in each of the if / else and remove the bits var; some hate 1 way in multiple ways out though...\r\n--\r\nfunction net.GetPlayerCountInBits( )\r\n\r\n\tlocal max = game.MaxPlayers( );\r\n\tlocal bits = 7;\r\n\tif ( max > 64 ) then\r\n\t\tbits = 7;\r\n\telseif ( max > 32 ) then\r\n\t\tbits = 6;\r\n\telseif ( max > 16 ) then\r\n\t\tbits = 5;\r\n\telseif ( max > 8 ) then\r\n\t\tbits = 4;\r\n\telseif ( max > 4 ) then\r\n\t\tbits = 3;\r\n\telseif ( max > 2 ) then\r\n\t\tbits = 2;\r\n\telse\r\n\t\tbits = 1;\r\n\tend\r\n\r\n\treturn bits;\r\n\r\nend\r\n```"}}