A Long Long time ago, in a game company not so far away... Quake 3 was born. With it came a dedicated server and a log file for administrative purposes. The ingenious citizens of the galaxy took that log and mined it for all it was worth, bringing a variety of riches for all to share. The peoples hunger for more data was unbounded and the clever citizens dug deeper and deeper into that mine with ever more diminishing returns. Until today. The days of data mining from logs is over, instead data shall grow freely from the ground for all to enjoy....
Using the games log to see what's going on inside JKA and MB2 specifically has been going on for as long as the mod itself, but it is not without it's problems. Namely it is difficult to programmatically read, if you are not careful it is unsafe to read programmatically, and the performance can degrade as more data, and more types of data that are added unless care is taken about how the log is accessed, and lastly it is without extra steps both permanent and local. All these factors combine to make a replacement which avoids these problems desirable.
Today the games log is used to provide the data source for functionality such as RTV/RTM, integrations to discord, and other custom functionality. This presents us with a unique problem - any time we make any change to the log output there is a real chance we could be ruining someone's day by breaking their script. Maybe that person isn't around to support the script anymore and it will be broken forever.
Movie Battles II will introduce a new feature in the next patch, where all the current data that is currently written to the log file will optionally be sent out as UDP packets to the endpoint(s) of servers choice. The UDP packets are designed to be safe and easy to process, and fast to send. There are a few advantages here, people who run more than one server will no longer have to have multiple instances of multiple tools running against multiple log files. Game Server owners who's providers won't let external scripts run against the games.log will now be able to take advantage of scripting capabilities, and importantly, as multiple endpoints are supported, community wide efforts will be possible with server owners simply adding a destination for their data to contribute to. A few examples might be community wide efforts to share ban information, or even stats being shared across the whole community. The possibilities available by having this data freely and widely accessible are endless.
Furthermore, as the cost of sending UDP packets is much lower than writing to the disk, and then reading the same data again, we will be able to easily expand the new system to export much more granular data, and we will be open to requests for what people would like to see added - and unlike the current system, adding more data types won't break everyone's existing scripts.
To make adoption even easier, today we have made open source under the LGPL license, a crossplatform Library for receiving and processing the UDP packets into programmatically actionable data. At the moment, this is a barebones library which provides only the functionality to receive, parse packets and raise events. It is our hope that this Library can be a community wide effort to do much more than that and share the burden of such tools wildly across the community. The github for this library is here GitHub - MBII/MB2EventReceiver: Library for recieving and processing MB2 Event Notifications
Technical Details
The service must be enabled by setting the cvar sv_notificationservice to 1. A json document should then be created at GameData/MBII/rensConfig.json with the following format:
Optionally, the types of packet that are sent to an endpoint can be filtered by setting a TypeFlags field in the rensConfig.json file. If this value is omitted all packet types will be sent. A value of 0 will effectively disable an endpoint by not sending any packet types. Changes to the rensConfig.json file will take effect the next time the game module is loaded - for example, at map change.
Up to 16 different servers may be added as endpoints, IPv4, IPv6 and DNS may be used for the host.
Packet types are broken up into the categories in the table below. For clarity the exact packet types and their Bit Mask Value are provided later.
RENS Packet Types
MBII Packet Header (always 16 bytes)
ClientConnect (69 bytes)
ClientDisconnect (17 bytes)
ClientBegin (17 bytes)
SwitchTeams (18 bytes)
PlayerDeath (23 bytes)
ServerStart (89 bytes)
ServerShutdown (16 bytes)
Speech (169 bytes)
SmodLogin (26 bytes)
SmodCommand (19 bytes)
PrivateDuelEvent (19 bytes)
MapChange (80 bytes)
ModeChange (17 bytes)
NameChange (49 bytes)
Ban (21 bytes)
Intermission (16 bytes)
ObjectiveComplete (17 bytes)
Using the games log to see what's going on inside JKA and MB2 specifically has been going on for as long as the mod itself, but it is not without it's problems. Namely it is difficult to programmatically read, if you are not careful it is unsafe to read programmatically, and the performance can degrade as more data, and more types of data that are added unless care is taken about how the log is accessed, and lastly it is without extra steps both permanent and local. All these factors combine to make a replacement which avoids these problems desirable.
Today the games log is used to provide the data source for functionality such as RTV/RTM, integrations to discord, and other custom functionality. This presents us with a unique problem - any time we make any change to the log output there is a real chance we could be ruining someone's day by breaking their script. Maybe that person isn't around to support the script anymore and it will be broken forever.
Movie Battles II will introduce a new feature in the next patch, where all the current data that is currently written to the log file will optionally be sent out as UDP packets to the endpoint(s) of servers choice. The UDP packets are designed to be safe and easy to process, and fast to send. There are a few advantages here, people who run more than one server will no longer have to have multiple instances of multiple tools running against multiple log files. Game Server owners who's providers won't let external scripts run against the games.log will now be able to take advantage of scripting capabilities, and importantly, as multiple endpoints are supported, community wide efforts will be possible with server owners simply adding a destination for their data to contribute to. A few examples might be community wide efforts to share ban information, or even stats being shared across the whole community. The possibilities available by having this data freely and widely accessible are endless.
Furthermore, as the cost of sending UDP packets is much lower than writing to the disk, and then reading the same data again, we will be able to easily expand the new system to export much more granular data, and we will be open to requests for what people would like to see added - and unlike the current system, adding more data types won't break everyone's existing scripts.
To make adoption even easier, today we have made open source under the LGPL license, a crossplatform Library for receiving and processing the UDP packets into programmatically actionable data. At the moment, this is a barebones library which provides only the functionality to receive, parse packets and raise events. It is our hope that this Library can be a community wide effort to do much more than that and share the burden of such tools wildly across the community. The github for this library is here GitHub - MBII/MB2EventReceiver: Library for recieving and processing MB2 Event Notifications
Technical Details
The service must be enabled by setting the cvar sv_notificationservice to 1. A json document should then be created at GameData/MBII/rensConfig.json with the following format:
Code:
{
"Endpoints":[{
"Server":"127.0.0.1",
"Port":8080
}]
}
Optionally, the types of packet that are sent to an endpoint can be filtered by setting a TypeFlags field in the rensConfig.json file. If this value is omitted all packet types will be sent. A value of 0 will effectively disable an endpoint by not sending any packet types. Changes to the rensConfig.json file will take effect the next time the game module is loaded - for example, at map change.
Code:
{
"Endpoints":[{
"Server":"127.0.0.1",
"Port":8080,
"TypeFlags":1
}]
}
Up to 16 different servers may be added as endpoints, IPv4, IPv6 and DNS may be used for the host.
Packet types are broken up into the categories in the table below. For clarity the exact packet types and their Bit Mask Value are provided later.
| Grouping | Bit Mask Value |
|---|---|
| Server Infrastructure Events | 1 |
| Game Events | 2 |
| Speech Events | 4 |
| SMOD Events | 8 |
RENS Packet Types
| Enum Value | Name | Meaning | Bit Mask Value |
|---|---|---|---|
| 0 | MBII_RENS_CLIENTCONNECT | A client has connected to the server | 2 |
| 1 | MBII_RENS_CLIENTDISCONNECT | A client has disconnected from the server | 2 |
| 2 | MBII_RENS_CLIENTBEGIN | A client has fully entered the game (spawned/loaded) | 2 |
| 3 | MBII_RENS_TEAMCHANGE | A client has switched teams | 2 |
| 4 | MBII_RENS_SPEECH | A client has sent a chat message | 4 |
| 5 | MBII_RENS_KILL | A kill event occurred (death + killer + assist + MOD) | 2 |
| 6 | MBII_RENS_SERVERSTART | The server has started a new map/mode | 1 |
| 7 | MBII_RENS_SERVERSHUTDOWN | The server is shutting down | 1 |
| 8 | MBII_RENS_PRIVATEDUELEVENT | A private duel has started or ended | 2 |
| 9 | MBII_RENS_MAPCHANGE | The server has changed to a new map | 2 |
| 10 | MBII_RENS_MODECHANGE | The server has changed game mode | 2 |
| 11 | MBII_RENS_SMODCMD | An admin has executed an SMOD command | 8 |
| 12 | MBII_RENS_SMODLOGIN | An admin has logged in (success/fail) | 8 |
| 13 | MBII_RENS_NAMECHANGE | A client has changed their name | 2 |
| 14 | MBII_RENS_BAN | A client has been banned | 1 |
| 15 | MBII_RENS_INTERMISSION | Intermission has begun (round end) | 2 |
| 16 | MBII_RENS_OBJCOMPLETE | A client has completed an objective | 2 |
MBII Packet Header (always 16 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–3 | MBIIIdentifier | Literal "MBII" ASCII identifier | 4 |
| 4–7 | PacketBodyType | MBIINotificationType_t enum | 4 |
| 8–11 | LevelTime | Server time (ms) when event occurred | 4 |
| 12–13 | Port | Server port | 2 |
| 14 | Version | Protocol version | 1 |
| 15 | Flags | Protocol flags | 1 |
ClientConnect (69 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Connecting client's ID | 1 |
| 17–20 | IPAddress | Client IPv4 address | 4 |
| 21–36 | Guid[4] | Client GUID (4× uint32) | 16 |
| 37–68 | PlayerName | Player name (MAX_NAME_LENGTH = 32) | 32 |
ClientDisconnect (17 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Disconnecting client's ID | 1 |
ClientBegin (17 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Client who began playing | 1 |
SwitchTeams (18 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Client switching teams | 1 |
| 17 | NewTeam | New team ID | 1 |
PlayerDeath (23 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientKilledId | Victim client ID | 1 |
| 17 | ClientKilledById | Killer client ID | 1 |
| 18 | ClientAssistId | Assist client ID | 1 |
| 19–22 | MeansOfDeath | Damage type (enum as int) | 4 |
ServerStart (89 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | MBMode | Game mode | 1 |
| 17–20 | ruleset | Ruleset (int) | 4 |
| 21–24 | respawnMode | Respawn mode (qboolean) | 4 |
| 25–88 | Map | Map name (MAX_QPATH = 64) | 64 |
ServerShutdown (16 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
Speech (169 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Speaker client ID | 1 |
| 17 | MessageMode | Chat mode (team/global/etc.) | 1 |
| 18 | TargetClientId | Target client (if whisper) | 1 |
| 19–168 | Text | Chat text (MAX_SAY_TEXT = 150) | 150 |
SmodLogin (26 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Admin client ID | 1 |
| 17 | adminNum | Admin level | 1 |
| 18–21 | LoginSuccess | qboolean (int) | 4 |
| 22–25 | IPAddress | Admin IP address | 4 |
SmodCommand (19 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId | Admin issuing command | 1 |
| 17 | SmodCommandId | Command ID | 1 |
| 18 | ClientTargetId | Target client | 1 |
PrivateDuelEvent (19 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | ClientId1 | First dueling client | 1 |
| 17 | ClientId2 | Second dueling client | 1 |
| 18 | endDuel | 1 = duel ended | 1 |
MapChange (80 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16–79 | NewMap | Map name (MAX_QPATH = 64) | 64 |
ModeChange (17 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | NewMode | New game mode | 1 |
NameChange (49 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | clientId | Client changing name | 1 |
| 17–48 | NewName | New name (MAX_NAME_LENGTH = 32) | 32 |
Ban (21 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | clientId | Client being banned | 1 |
| 17–20 | IPAddress | Client IP address | 4 |
Intermission (16 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
ObjectiveComplete (17 bytes)
| Bytes | Field | Meaning | Size |
|---|---|---|---|
| 0–15 | Header | MBII packet header | 16 |
| 16 | clientId | Client completing objective | 1 |