Omg You send that information 20 times per sec? Well of course that doesn’t work. All that state that a player has doesn’t need to be send every frame. You should have dedicated messages when some of that state changes. Does the player name, headid, legid, etc change every frame? Most of that does probably never change at all. So there’s no point of sending it over 20 times a sec. You usually have things like the position that would probably change the most and some other things. However those should be communicated seperately when its necessary. The same is with your map information. A map with 1369 cells, even when send as 1 byte per cell, requires 1.4kB. Again, you usually should send cell information when there’s actually a change. So you would have a dedicated message that indicates the row and column as well as the new value. This is essentially a 3 byte payload message to transmit a single cell change. Of course messages need to have some sort of message type. So a 4 byte message would be enough. Though since the server could accumulate several changes between two network frames, it may make sense to actually combine several cell changes into a single packet.
So a packet may contain a byte for the packet type, a byte for the number of cell information in the packet followed by the row, column and value of the cell. Depending on the type of game, if map changes can involve cell changes over an area, this may have a seperate message to just encode the start and end cell and then fill those cells with a given value. That way you have small individual packets.
While it’s a good idea to use GUIDs to identify players in general, it’s not a good idea to use it in network packets. You usually have a list of connected clients and the server can hand out short single digit IDs Of course those IDs should not change during a sesstion. So you would usually manage them in a dictionary. So the first playet may get id 1, the second the id 2 and so on. In most cases you don’t have to worry about reusing ids if a player left and another joins, though it’s of course possible.
Of course you still need “keyframe” packets which you send initially to sync the whole state of a player and the whole state of the grid. This may be repeated every now and then in case something went wrong. Though websockets run over TCP. So you can’t really miss or drop any packets as they are automatically re-transmitted.
As I said, the exact message types you want to use, what data they should contain completely depends on your type of game, which data changes how often an in which cases. On top of that certain data, if there’s a lot, can be compressed. For example you said the values are in the range 0 - 7. If you think about possible additions if the value can stay below 16 (0-15) you can actually store two cells in a single byte / char since a value up to 15 can be stored in just 4 bits. Though if there’s a lot repetition one can use simply run-length encoding to drastically reduce the transmitted data.
Those are the most fundamental basics about network communication. As I said, it depends on your game mechanics what the best approach is. Though it’s certainly not necessary to send all this information 20 times a second. Things like the player name is probably send once at the start and never again (unless you have the option to change the name un the fly in which case you can send a single “player name changed message” when it actually got changed).