Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat: update Soldat protocol #642

Merged
merged 8 commits into from
Sep 25, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
## 5.X.Y
* Feat: Replaced `punycode` package usage with `url.domainToASCII` (#630).
* Feat: World of Padman (2007) - Added support (#636)
* Feat: Update Soldat protocol (#642)

## 5.1.3
* Fix: `Deus Ex` using the wrong protocol (#621)
Expand Down
5 changes: 4 additions & 1 deletion GAMES_LIST.md
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,7 @@
| sinepisodes | SiN Episodes | [Valve Protocol](#valve) |
| sof | Soldier of Fortune | |
| sof2 | Soldier of Fortune 2 | |
| soldat | Soldat | |
| soldat | Soldat | [Notes](#soldat) |
| sotf | Sons Of The Forest | [Valve Protocol](#valve) |
| soulmask | Soulmask | [Valve Protocol](#valve) |
| spaceengineers | Space Engineers | [Valve Protocol](#valve) |
Expand Down Expand Up @@ -490,3 +490,6 @@ EOS does not provide players data.
### <a name="palworld"></a>Palworld
Palworld support can be unstable, the devs mention the api is currently experimental.
To query Palworld servers, the `RESTAPIEnabled` setting must be `True` in the configuration file, and you need to pass the `username` (currently always `admin`) and the `adminpassword` (from the server config) as the `password` parameter.

### <a name="soldat"></a>Soldat
Requires `Allow_Download` and `Logging` to be `1` in the server config.
9 changes: 6 additions & 3 deletions lib/games.js
Original file line number Diff line number Diff line change
Expand Up @@ -2648,9 +2648,12 @@ export const games = {
name: 'Soldat',
release_year: 2002,
options: {
port: 13073,
port_query_offset: 123,
protocol: 'ase'
port: 23073,
port_query_offset: 10,
protocol: 'soldat'
},
extra: {
doc_notes: 'soldat'
}
},
sof: {
Expand Down
3 changes: 2 additions & 1 deletion protocols/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -62,12 +62,13 @@ import xonotic from './xonotic.js'
import altvmp from './altvmp.js'
import vintagestorymaster from './vintagestorymaster.js'
import vintagestory from './vintagestory.js'
import soldat from './soldat.js'

export {
armagetron, ase, asa, assettocorsa, battlefield, buildandshoot, cs2d, discord, doom3, eco, epic, factorio, farmingsimulator, ffow,
fivem, gamespy1, gamespy2, gamespy3, geneshift, goldsrc, gtasao, hexen2, jc2mp, kspdmp, mafia2mp, mafia2online, minecraft,
minecraftbedrock, minecraftvanilla, minetest, mumble, mumbleping, nadeo, openttd, palworld, quake1, quake2, quake3, rfactor, ragemp, samp,
savage2, starmade, starsiege, teamspeak2, teamspeak3, terraria, tribes1, tribes1master, unreal2, ut3, valve,
vcmp, ventrilo, warsow, eldewrito, beammpmaster, beammp, dayz, theisleevrima, xonotic, altvmp, vintagestorymaster,
vintagestory
vintagestory, soldat
}
45 changes: 45 additions & 0 deletions protocols/soldat.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
import Core from './core.js'

const extractValue = (text, regex, defaultValue, parser = (val) => val) => {
const match = text.match(regex)
return match ? parser(match[1] || defaultValue) : defaultValue
}

export default class soldat extends Core {
async run (state) {
const data = await this.withTcp(async socket => {
return await this.tcpSend(socket, 'STARTFILES\r\nlogs/gamestat.txt\r\nENDFILES\r\n', (data) => {
const asString = data.toString()
if (asString.endsWith('\r\n') && !asString.endsWith('ENDFILES\r\n')) {
return undefined
}
return data
})
})

const string = data.toString()

state.numplayers = extractValue(string, /Players:\s*(\d+)/, 0, Number)
state.map = extractValue(string, /Map:\s*(.+)/, '')

const lines = string.trim().split('\n')
const playersIndex = lines.findIndex(line => line.startsWith('Players list'))

if (playersIndex > -1) {
for (let i = playersIndex + 1; i < lines.length - 1; i += 5) {
state.players.push({
name: lines[i].trim(),
raw: {
kills: parseInt(lines[i + 1].trim()),
deaths: parseInt(lines[i + 2].trim()),
team: parseInt(lines[i + 3].trim()),
ping: parseInt(lines[i + 4].trim())
}
})
}
}

state.raw.response = string
state.raw.gamemode = extractValue(string, /Gamemode:\s*(.+)/, '')
}
}
Loading