Skip to content

Commit

Permalink
feat: strip Colors (#469)
Browse files Browse the repository at this point in the history
  • Loading branch information
CosminPerRam authored Jan 15, 2024
1 parent 0a33383 commit 5ae12dd
Show file tree
Hide file tree
Showing 11 changed files with 47 additions and 38 deletions.
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ see next point) and `tshock` (which is `terraria`).
* Minimum Supported Deno Version: `1.39.2`.
* `deno run --allow-net bin/gamedig.js --type tf2 127.0.0.1`
* Added code examples.
* New option: `stripColors` (defaults to `true`) for protocols that strips colors: unreal2, savage2, quake3, nadeo, gamespy2, doom3, armagetron.

#### Games
* Removed the players::setNum method, the library will no longer add empty players as
Expand Down
59 changes: 30 additions & 29 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -30,44 +30,45 @@ Confused on how this works, or you want to see more? Checkout the [examples](/ex

## Required Fields

| Field | Type | Description |
|:---|:---|:---|
| Field | Type | Description |
|:---------|:-------|:---------------------------------------------------------------|
| **type** | string | One of the game IDs listed in the [games list](GAMES_LIST.md). |
| **host** | string | Hostname or IP of the game server. |
| **host** | string | Hostname or IP of the game server. |

## Optional Fields

| Field | Type | Default | Description |
|:---|:---|:---|:---|
| **port** | number | Game port | Connection port or query port for the game server. Some games utilize a separate "query" port. If specifying the game port does not seem to work as expected, passing in this query port may work instead. |
| **maxAttempts** | number | 1 | Number of attempts to query server in case of failure. |
| **socketTimeout** | number | 2000 | Milliseconds to wait for a single packet. Beware that increasing this will cause many queries to take longer even if the server is online. |
| **attemptTimeout** | number | 10000 | Milliseconds allowed for an entire query attempt. This timeout is not commonly hit, as the socketTimeout typically fires first. |
| **givenPortOnly** | boolean | false | Only attempt to query server on given port. It will ignore the game's default port. |
| **ipFamily** | number | 0 | IP family/version returned when looking up hostnames via DNS, can be 0 (IPv4 and IPv6), 4 (IPv4 only) or 6 (IPv6 only). |
| **debug** | boolean | false | Enables massive amounts of debug logging to stdout. |
| **requestRules** | boolean | false | Valve games only. Additional 'rules' may be fetched into the `raw` key. |
| **requestRulesRequired** | boolean | false | Valve games only. `requestRules` is always required to have a response or the query will timeout. |
| **requestPlayersRequired** | boolean | false | Valve games only. Querying players is always required to have a response or the query will timeout. Some [games](GAMES_LIST.md) may not provide a players response. |
| Field | Type | Default | Description |
|:---------------------------|:--------|:----------|:-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **port** | number | Game port | Connection port or query port for the game server. Some games utilize a separate "query" port. If specifying the game port does not seem to work as expected, passing in this query port may work instead. |
| **maxAttempts** | number | 1 | Number of attempts to query server in case of failure. |
| **socketTimeout** | number | 2000 | Milliseconds to wait for a single packet. Beware that increasing this will cause many queries to take longer even if the server is online. |
| **attemptTimeout** | number | 10000 | Milliseconds allowed for an entire query attempt. This timeout is not commonly hit, as the socketTimeout typically fires first. |
| **givenPortOnly** | boolean | false | Only attempt to query server on given port. It will ignore the game's default port. |
| **ipFamily** | number | 0 | IP family/version returned when looking up hostnames via DNS, can be 0 (IPv4 and IPv6), 4 (IPv4 only) or 6 (IPv6 only). |
| **debug** | boolean | false | Enables massive amounts of debug logging to stdout. |
| **requestRules** | boolean | false | Valve games only. Additional 'rules' may be fetched into the `raw` key. |
| **requestRulesRequired** | boolean | false | Valve games only. `requestRules` is always required to have a response or the query will timeout. |
| **requestPlayersRequired** | boolean | false | Valve games only. Querying players is always required to have a response or the query will timeout. Some [games](GAMES_LIST.md) may not provide a players response. |
| **stripColors** | boolean | true | Enables stripping colors for protocols: unreal2, savage2, quake3, nadeo, gamespy2, doom3, armagetron. |

## Query Response

The returned state object will contain the following keys:

| Key | Type | Description |
|:---|:---|:---|
| **name** | string | Server name. |
| **map** | string | Server map. |
| **password** | boolean | If a password is required. |
| **numplayers** | number | Number of players connected. Data via [A2S_INFO](https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO). |
| **maxplayers** | number | Maximum number of connected players. |
| **players** | array of objects | Note that this could be of a different length compared to **numplayers**. Data via [A2S_PLAYER](https://developer.valvesoftware.com/wiki/Server_queries#A2S_PLAYER). |
| **players.name** | string | If the player's name is unknown, the string will be empty. |
| **players.raw** | object | Additional information about the player if available. |
| **bots** | array of objects | Same schema as `players`. |
| **connect** | string | This will typically include the game's `IP:PORT`. The port will reflect the server's game port, even if your request specified the game's query port in the request. For some games, this may be a server ID or connection URL if an IP:PORT is not appropriate for end-users. |
| **ping** | number | Round trip time to the server (in milliseconds). Note that this is not the RTT of an ICMP echo, as ICMP packets are often blocked by NATs and node has poor support for raw sockets. This value is derived from the RTT of one of the query packets, which is usually quite accurate, but may add a bit due to server lag. |
| **raw** | object | Contains all information received from the server in a disorganized format. |
| Key | Type | Description |
|:-----------------|:-----------------|:---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| **name** | string | Server name. |
| **map** | string | Server map. |
| **password** | boolean | If a password is required. |
| **numplayers** | number | Number of players connected. Data via [A2S_INFO](https://developer.valvesoftware.com/wiki/Server_queries#A2S_INFO). |
| **maxplayers** | number | Maximum number of connected players. |
| **players** | array of objects | Note that this could be of a different length compared to **numplayers**. Data via [A2S_PLAYER](https://developer.valvesoftware.com/wiki/Server_queries#A2S_PLAYER). |
| **players.name** | string | If the player's name is unknown, the string will be empty. |
| **players.raw** | object | Additional information about the player if available. |
| **bots** | array of objects | Same schema as `players`. |
| **connect** | string | This will typically include the game's `IP:PORT`. The port will reflect the server's game port, even if your request specified the game's query port in the request. For some games, this may be a server ID or connection URL if an IP:PORT is not appropriate for end-users. |
| **ping** | number | Round trip time to the server (in milliseconds). Note that this is not the RTT of an ICMP echo, as ICMP packets are often blocked by NATs and node has poor support for raw sockets. This value is derived from the RTT of one of the query packets, which is usually quite accurate, but may add a bit due to server lag. |
| **raw** | object | Contains all information received from the server in a disorganized format. |

Note that `raw` (or **unstable**) objects contents MAY change on a per-protocol basis between GameDig patch releases (although not typical).

Expand Down
7 changes: 5 additions & 2 deletions bin/gamedig.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,8 +6,11 @@ import Minimist from 'minimist'
import { GameDig } from './../lib/index.js'

const argv = Minimist(process.argv.slice(2), {
boolean: ['pretty', 'debug', 'givenPortOnly', 'requestRules', 'requestRulesRequired', 'requestPlayersRequired'],
string: ['guildId', 'listenUdpPort', 'ipFamily']
boolean: ['pretty', 'debug', 'givenPortOnly', 'requestRules', 'requestRulesRequired', 'requestPlayersRequired', 'stripColors'],
string: ['guildId', 'listenUdpPort', 'ipFamily'],
default: {
stripColors: true
}
})

const options = {}
Expand Down
1 change: 1 addition & 0 deletions lib/QueryRunner.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ const defaultOptions = {
socketTimeout: 2000,
attemptTimeout: 10000,
maxAttempts: 1,
stripColors: true,
ipFamily: 0
}

Expand Down
2 changes: 1 addition & 1 deletion protocols/armagetron.js
Original file line number Diff line number Diff line change
Expand Up @@ -60,6 +60,6 @@ export default class armagetron extends Core {
}

stripColorCodes (str) {
return str.replace(/0x[0-9a-f]{6}/g, '')
return this.options.stripColors ? str.replace(/0x[0-9a-f]{6}/g, '') : str
}
}
2 changes: 1 addition & 1 deletion protocols/doom3.js
Original file line number Diff line number Diff line change
Expand Up @@ -143,6 +143,6 @@ export default class doom3 extends Core {

stripColors (str) {
// uses quake 3 color codes
return str.replace(/\^(X.{6}|.)/g, '')
return this.options.stripColors ? str.replace(/\^(X.{6}|.)/g, '') : str
}
}
2 changes: 1 addition & 1 deletion protocols/gamespy2.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,7 +49,7 @@ export default class gamespy2 extends Core {
if (state.raw.gamename === 'armygame') {
const stripColor = (str) => {
// uses unreal 2 color codes
return str.replace(/\x1b...|[\x00-\x1a]/g, '')
return this.options.stripColors ? str.replace(/\x1b...|[\x00-\x1a]/g, '') : str
}
state.name = stripColor(state.name)
state.map = stripColor(state.map)
Expand Down
2 changes: 1 addition & 1 deletion protocols/nadeo.js
Original file line number Diff line number Diff line change
Expand Up @@ -81,6 +81,6 @@ export default class nadeo extends Core {
}

stripColors (str) {
return str.replace(/\$([0-9a-f]{3}|[a-z])/gi, '')
return this.options.stripColors ? str.replace(/\$([0-9a-f]{3}|[a-z])/gi, '') : str
}
}
5 changes: 4 additions & 1 deletion protocols/quake3.js
Original file line number Diff line number Diff line change
Expand Up @@ -16,9 +16,12 @@ export default class quake3 extends quake2 {
for (const player of state.players) {
player.name = this.stripColors(player.name)
}
for (const bot of state.bots) {
bot.name = this.stripColors(bot.name)
}
}

stripColors (str) {
return str.replace(/\^(X.{6}|.)/g, '')
return this.options.stripColors ? str.replace(/\^(X.{6}|.)/g, '') : str
}
}
2 changes: 1 addition & 1 deletion protocols/savage2.js
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,6 @@ export default class savage2 extends Core {
}

stripColorCodes (str) {
return str.replace(/\^./g, '')
return this.options.stripColors ? str.replace(/\^./g, '') : str
}
}
2 changes: 1 addition & 1 deletion protocols/unreal2.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,7 +125,7 @@ export default class unreal2 extends Core {
out = out.substring(0, out.length - 1)
}

if (stripColor) {
if (stripColor && this.options.stripColors) {
out = out.replace(/\x1b...|[\x00-\x1a]/gus, '')
}

Expand Down

0 comments on commit 5ae12dd

Please sign in to comment.