Quake New Netcode of The Game + Data Types – Overview

Quake New Netcode of The Game + Data Types – Overview 1 - steamsplay.com
Quake New Netcode of The Game + Data Types – Overview 1 - steamsplay.com

Attempts to explain the new netcode of the game, new packets and how mods can use them.
 
 

Introduction

This guide is an attempt at document the netcode of Quake Enhanced for the purpose of modding and source ports adding compatibility.
 
 
There’s no guarantee about the information in this guide being 100% correct or complete.
 
 
The guide will be updated as new information comes in.
 
 
 

Overview

The 2021 Re-Release netcode is based off the existing Netquake netcode. It extends it further with more packets and functionality and adds a layer of encryption.
 
 
Quake netcode uses UDP for communication. The packets are wrapped around DTLS 1.2 for encryption and security. A PSK (Pre-Shared Key) is used for authentication between server and client. The game uses OpenSSL implementation of DTLS.
 
 
 

Data Types

Quake netcode uses a bunch of datatypes.
 
 

Function callTypeSize in bytesCallable from QCComments
WriteCharchar1Yes
WriteBytebyte1Yes
WriteShortshort2Yes
WriteLongint4Yes
WriteFloatfloat4No
WriteDoubledouble8No
WriteStringC-style string1+YesRepeats chars until the byte 0 is found
WriteCoordfloat4Yes
WriteAnglebyte1YesConverts a float using the following formula: ((int)f*256/360) & 255
WriteEntityshort2YesWrites out the entity index

 
 
 

Packets – Client to Server

PacketByte valueDescription
CLC_BAD0
CLC_NOP1
CLC_DISCONNECT2
CLC_MOVE3
CLC_STRINGCMD4
CLC_UNKNOWN15Appears to be sent every frame
CLC_UNKNOWN26

 
 
 

Packets – Server to Client

PacketByte valueDescription
SVC_BAD0
SVC_NOP1Used as a heartbeat
SVC_DISCONNECT2Sent when the server is closing the connection
SVC_UPDATESTAT3
SVC_VERSION4
SVC_SETVIEW5Tell the client to attach the camera to a specific entity
SVC_SOUND6
SVC_TIME7
SVC_PRINT8Print something
SVC_STUFFTEXT9Print on the top-left of the screen
SVC_SETANGLE10
SVC_SERVERINFO11Contains information about map, maxplayers, which files to precache, and so on
SVC_LIGHTSTYLE12
SVC_UPDATENAME13Sets a player name on the scoreboard
SVC_UPDATEFRAGS14Sets a player frags on the scoreboard
SVC_CLIENTDATA15
SVC_STOPSOUND16
SVC_UPDATECOLORS17
SVC_PARTICLE18Creates a particle emission effect
SVC_DAMAGE19
SVC_SPAWNSTATIC20
SVC_SPAWNBASELINE22
SVC_TEMPENTITY23
SVC_SETPAUSE24
SVC_SIGNONNUM25
SVC_CENTERPRINT26Prints something in the middle of the screen
SVC_KILLEDMONSTER27
SVC_FOUNDSECRET28
SVC_SPAWNSTATICSOUND29
SVC_INTERMISSION30
SVC_FINALE31
SVC_CDTRACK32
SVC_SELLSCREEN33
SVC_CUTSCENE34
SVC_SKYBOX37
SVC_BOTCHAT38Displays a text message in chat as coming from a player.
SVC_SPAWNEDMONSTER39
SVC_BONUSFLASH40
SVC_FOG41
SVC_SPAWNBASELINE242
SVC_SPAWNSTATIC243
SVC_SPAWNSTATICSOUND244
SVC_SETVIEWS45
SVC_UPDATEPING46
SVC_UPDATESOCIAL47
SVC_UPDATEPLINFO48
SVC_RAWPRINT49
SVC_SERVERVARS50
SVC_SEQ51
SVC_ACHIEVEMENT52
SVC_CHAT53Prints a message in the chat
SVC_LEVELCOMPLETED54Probably used for achievements
SVC_BACKTOLOBBY55Tells the client that they should go back to the lobby screen
SVC_LOCALSOUND56Plays a sound that is only heard by the client

 
 
 

SVC_*: A-Z

SVC_BOTCHAT

 
This packet tells the client to display a chat message as coming from a specific player id.
 
 

OffsetCallName
0WriteBytePacket Id
1WriteBytePlayer Id
2WriteShortString count
4WriteStringString 1
WriteStringString …

 
Example
 
 

WriteByte(MSG_ALL,SVC_BOTCHAT);
WriteByte(MSG_ALL,0); // Player 0, the host.
WriteShort(MSG_ALL,1); // How many strings are present
WriteString(MSG_ALL,"Someone is talking for me!");

 
 
With string replacement
 
 

WriteByte(MSG_ALL,SVC_BOTCHAT);
WriteByte(MSG_ALL,0); // Player 0, the host.
WriteShort(MSG_ALL,2); // How many strings are present
WriteString(MSG_ALL,"My name is {}");
WriteString(MSG_ALL,"JPiolho");

 
 
Quake New Netcode of The Game + Data Types - Overview - SVC_*: A-Z - EAF09AD
 
 

SVC_CENTERPRINT

 
This packet tells the client to print text in the middle of the screen. It supports string replacements.
 
 

OffsetCallName
0WriteBytePacket ID
1WriteShortString count
3WriteStringString 1
WriteStringString …

 
Default center print
 
 

WriteByte(MSG_ALL,SVC_CENTERPRINT);
WriteShort(MSG_ALL,1); // Number of strings that will follow
WriteString(MSG_ALL,"Hello world");

 
 
With string replacement
 
 

WriteByte(MSG_ALL,SVC_CENTERPRINT);
WriteShort(MSG_ALL,2); // Number of strings that will follow
WriteString(MSG_ALL,"Welcome to the game, {}");
WriteString(MSG_ALL,"JPiolho");

 
 
Quake New Netcode of The Game + Data Types - Overview - SVC_*: A-Z - EAF09AD
 
 

SVC_CHAT

 
This packet tells the client to print text in chat. It appears to only work in single player games.
 
Unlike SVC_BOTCHAT, you have full control over the name of the person plus you can specify some colors.
 
 
Available name colors: White (0), Red (1), Light Blue (2), Yellow (3)
 
Available message colors: White (0), Light blue (1)
 
 

OffsetCallName
0WriteBytePacket ID
1WriteByteName color (0-3)
2WriteByteMessage color (0-1)
3WriteStringName
WriteStringMessage

 
Default center print
 
 

WriteByte(MSG_ALL,53); // SVC_CHAT
WriteByte(MSG_ALL,0); // Name color (0-3)
WriteByte(MSG_ALL,0); // Message Color (0-1)
WriteString(MSG_ALL,"Name"); // Name
WriteString(MSG_ALL,"Color 0"); // Message

 
 
Quake New Netcode of The Game + Data Types - Overview - SVC_*: A-Z - EAF09AD
 
 

SVC_UPDATENAME

 
This packet tells the client to update a player’s name in the scoreboard
 
 

OffsetCallName
0WriteBytePacket Id
1WriteBytePlayer Id
2WriteStringPlayer name

 
Example
 
 

WriteByte(MSG_ALL,SVC_UPDATENAME);
WriteByte(MSG_ALL,0); // Player 0, the host.
WriteString(MSG_ALL,"Nobody"); // Set player name to 'Nobody'

 
 
 

Entity packet

This documentation is very incomplete
 
 
The entity packet is a bit special. It needs to be sent every frame to the players so that they know it exists. It also specifies all the attributes the client needs in order to display it on the client-side. Things like position, angles, model, solidness, etc…
 
 
Instead of having a regular numeric packet id, it relies on the bit 7 of the packet id being set. All the other bits in the byte are used as flags. The size of this packet is highly variable as it depends on the flags that are set.
 
 
Start by having a packet id of 128 and then adding different flags that you want.
 
 
The packet starts with a flag bitmap of 1 or more bytes. These indicate which entity properties are being sent. After the flag bitmap, the entity id is sent. After this, all the data that was specified in the flag bitmap is sent (in a specific order).
 
 
Byte Flagmap 1
 

BitName
0More flag bytes
1Origin X
2Origin Y
3Origin Z
4Angle Y
5No lerp
6Frame
7Entity packet signal (always set to 1)

 
If “More flag bytes” bit was set, then the following packet follows:
 
Byte flagmap 2
 

BitName
0Angle X
1Angle Z
2Model Index
3Color map
4Skin
5Effects
6Is it a long entity?
8More flag bytes

 
If “More flag bytes” bit was set, then the following packet follows:
 
Byte flagmap 3
 

BitName
0Alpha
1Unsure – Frame
2Unsure – Model Index
3Unsure – When the next think will happen
4
5Unsure – Origin Offset
6Solid
7More flag bytes

 
If “More flag bytes” bit was set, then the following packet follows:
 
Byte flagmap 4
 

BitName
0Unsure – Flags
1Unsure – Health
2Unsure – Model Index
3
4
5
6
7

 
The Entity Id follows. If “Long Entity” bit was set, the entity Id is sent as a Short (2 bytes). If not set then it’s sent as a byte (1 byte).
 
 
Now all the information that was specified in the flagmap is sent, in the following order:
 

CallIf bit is setNameComment
WriteByteByte 2, bit 2Model Index
WriteByteByte 1, bit 6Frame
WriteByteByte 2, bit 3Colormap
WriteByteByte 2, bit 4Skin
WriteByteByte 2, bit 5Effects
WriteFloatByte 1, bit 1Origin XIf byte 3 bit 5 is set, then the call is WriteShort
WriteByteByte 2, bit 0Angle X
WriteFloatByte 1, bit 2Origin YIf byte 3 bit 5 is set, then the call is WriteShort
WriteByteByte 1, bit 4Angle Y
WriteFloatByte 1, bit 3Origin ZIf byte 3 bit 5 is set, then the call is WriteShort
WriteByteByte 2, bit 1Angle Z
WriteByteByte 3, bit 0Alpha
WriteByteByte 3, bit 1Frame
WriteByteByte 3, bit 2Model Index
WriteByteByte 3, bit 3Next Think
WriteByteByte 3, bit 6Solid
UnknownByte 4, bit 0FlagsAppears to send multiple values
UnknownByte 4, bit 1HealthsAppears to send multiple values
UnknownByte 4, bit 2Model IndexesAppears to send multiple values

 
Example in QuakeC
 
 

 local float firstBits;
 local float secondBits;
 local float thirdBits;

 firstBits |= 1; // More bytes

 firstBits |= 1 << 1; // Origin 1
 firstBits |= 1 << 2; // Origin 2
 firstBits |= 1 << 3; // Origin 3
 firstBits |= 1 << 4; // Angle 2
 firstBits |= 1 << 6; // Frame

 secondBits |= (1 << 8) >> 8; // Angle 1
 secondBits |= (1 << 9) >> 8; // Angle 3
 secondBits |= (1 << 10) >> 8; // Model Index
 secondBits |= (1 << 11) >> 8; // Colormap
 secondBits |= (1 << 12) >> 8; // Skin
 secondBits |= (1 << 13) >> 8; // Effects
 secondBits |= (1 << 14) >> 8; // Long Entity
 secondBits |= (1 << 15) >> 8; // More bytes

 thirdBits |= (1 << 16) >> 16; // Alpha
 thirdBits |= (1 << 22) >> 16; // Solid

 msg_entity = self;
 WriteByte(MSG_ONE,firstBits | 128); // Packet Type

 // Send all the values
 if(firstBits & 1)
 WriteByte(MSG_ONE,secondBits);
 if(secondBits & 128)
 WriteByte(MSG_ONE,thirdBits);
 
 WriteShort(MSG_ONE,1500 + pNumber); // Entity ID

 WriteByte(MSG_ONE,modelindex_player);
 WriteByte(MSG_ONE,p.frame); 
 WriteByte(MSG_ONE,p.colormap);
 WriteByte(MSG_ONE,p.skin);
 WriteByte(MSG_ONE,p.effects);
 WriteCoord(MSG_ONE,p.origin_x);
 WriteAngle(MSG_ONE,p.angles_x);
 WriteCoord(MSG_ONE,p.origin_y);
 WriteAngle(MSG_ONE,p.angles_y);
 WriteCoord(MSG_ONE,p.origin_z);
 WriteAngle(MSG_ONE,p.angles_z);
 WriteByte(MSG_ONE,120);
 WriteByte(MSG_ONE,SOLID_NOT);

 
 

Written by JPiolho

 
 
Hope you enjoy the post for Quake New Netcode of The Game + Data Types – Overview, If you think we should update the post or something is wrong please let us know via comment and we will fix it how fast as possible! Thank you and have a great day!
 


Be the first to comment

Leave a Reply

Your email address will not be published.


*