-
Notifications
You must be signed in to change notification settings - Fork 144
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
chore: extract dayz from valve (#448)
- Loading branch information
1 parent
6bfbc88
commit 90b3c60
Showing
4 changed files
with
187 additions
and
155 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,182 @@ | ||
import valve from './valve.js' | ||
import { Buffer } from 'node:buffer' | ||
|
||
export default class dayz extends valve { | ||
async run (state) { | ||
if (!this.options.port) this.options.port = 27016 | ||
await super.queryInfo(state) | ||
await super.queryChallenge() | ||
await super.queryPlayers(state) | ||
await this.queryRules(state) | ||
|
||
this.processQueryInfo(state) | ||
await super.cleanup(state) | ||
} | ||
|
||
async queryRules (state) { | ||
if (!this.options.requestRules) { | ||
return | ||
} | ||
|
||
const rules = {} | ||
state.raw.rules = rules | ||
const dayZPayload = [] | ||
|
||
this.logger.debug('Requesting rules ...') | ||
|
||
const b = await this.sendPacket(0x56, null, 0x45, true) | ||
if (b === null) return // timed out - the server probably has rules disabled | ||
|
||
let dayZPayloadEnded = false | ||
|
||
const reader = this.reader(b) | ||
const num = reader.uint(2) | ||
for (let i = 0; i < num; i++) { | ||
if (!dayZPayloadEnded) { | ||
const one = reader.uint(1) | ||
const two = reader.uint(1) | ||
const three = reader.uint(1) | ||
if (one !== 0 && two !== 0 && three === 0) { | ||
while (true) { | ||
const byte = reader.uint(1) | ||
if (byte === 0) break | ||
dayZPayload.push(byte) | ||
} | ||
continue | ||
} else { | ||
reader.skip(-3) | ||
dayZPayloadEnded = true | ||
} | ||
} | ||
|
||
const key = reader.string() | ||
rules[key] = reader.string() | ||
} | ||
|
||
state.raw.dayzMods = this.readDayzMods(Buffer.from(dayZPayload)) | ||
} | ||
|
||
processQueryInfo (state) { | ||
// DayZ embeds some of the server information inside the tags attribute | ||
if (!state.raw.tags) { return } | ||
|
||
state.raw.dlcEnabled = false | ||
state.raw.firstPerson = false | ||
for (const tag of state.raw.tags) { | ||
if (tag.startsWith('lqs')) { | ||
const value = parseInt(tag.replace('lqs', '')) | ||
if (!isNaN(value)) { | ||
state.raw.queue = value | ||
} | ||
} | ||
if (tag.includes('no3rd')) { | ||
state.raw.firstPerson = true | ||
} | ||
if (tag.includes('isDLC')) { | ||
state.raw.dlcEnabled = true | ||
} | ||
if (tag.includes(':')) { | ||
state.raw.time = tag | ||
} | ||
if (tag.startsWith('etm')) { | ||
const value = parseInt(tag.replace('etm', '')) | ||
if (!isNaN(value)) { | ||
state.raw.dayAcceleration = value | ||
} | ||
} | ||
if (tag.startsWith('entm')) { | ||
const value = parseInt(tag.replace('entm', '')) | ||
if (!isNaN(value)) { | ||
state.raw.nightAcceleration = value | ||
} | ||
} | ||
} | ||
} | ||
|
||
readDayzMods (/** Buffer */ buffer) { | ||
if (!buffer.length) { | ||
return {} | ||
} | ||
|
||
this.logger.debug('DAYZ BUFFER') | ||
this.logger.debug(buffer) | ||
|
||
const reader = this.reader(buffer) | ||
const version = this.readDayzByte(reader) | ||
const overflow = this.readDayzByte(reader) | ||
const dlc1 = this.readDayzByte(reader) | ||
const dlc2 = this.readDayzByte(reader) | ||
this.logger.debug('version ' + version) | ||
this.logger.debug('overflow ' + overflow) | ||
this.logger.debug('dlc1 ' + dlc1) | ||
this.logger.debug('dlc2 ' + dlc2) | ||
if (dlc1) { | ||
const unknown = this.readDayzUint(reader, 4) // ? | ||
this.logger.debug('unknown ' + unknown) | ||
} | ||
if (dlc2) { | ||
const unknown = this.readDayzUint(reader, 4) // ? | ||
this.logger.debug('unknown ' + unknown) | ||
} | ||
const mods = [] | ||
mods.push(...this.readDayzModsSection(reader, true)) | ||
mods.push(...this.readDayzModsSection(reader, false)) | ||
this.logger.debug('dayz buffer rest:', reader.rest()) | ||
return mods | ||
} | ||
|
||
readDayzModsSection (/** Reader */ reader, withHeader) { | ||
const out = [] | ||
const count = this.readDayzByte(reader) | ||
this.logger.debug('dayz mod section withHeader:' + withHeader + ' count:' + count) | ||
for (let i = 0; i < count; i++) { | ||
if (reader.done()) break | ||
const mod = {} | ||
if (withHeader) { | ||
mod.unknown = this.readDayzUint(reader, 4) // ? | ||
|
||
// For some reason this is 4 on all of them, but doesn't exist on the last one? but only sometimes? | ||
const offset = reader.offset() | ||
const flag = this.readDayzByte(reader) | ||
if (flag !== 4) reader.setOffset(offset) | ||
|
||
mod.workshopId = this.readDayzUint(reader, 4) | ||
} | ||
mod.title = this.readDayzString(reader) | ||
this.logger.debug(mod) | ||
out.push(mod) | ||
} | ||
return out | ||
} | ||
|
||
readDayzUint (reader, bytes) { | ||
const out = [] | ||
for (let i = 0; i < bytes; i++) { | ||
out.push(this.readDayzByte(reader)) | ||
} | ||
const buf = Buffer.from(out) | ||
const r2 = this.reader(buf) | ||
return r2.uint(bytes) | ||
} | ||
|
||
readDayzByte (reader) { | ||
const byte = reader.uint(1) | ||
if (byte === 1) { | ||
const byte2 = reader.uint(1) | ||
if (byte2 === 1) return 1 | ||
if (byte2 === 2) return 0 | ||
if (byte2 === 3) return 0xff | ||
return 0 // ? | ||
} | ||
return byte | ||
} | ||
|
||
readDayzString (reader) { | ||
const length = this.readDayzByte(reader) | ||
const out = [] | ||
for (let i = 0; i < length; i++) { | ||
out.push(this.readDayzByte(reader)) | ||
} | ||
return Buffer.from(out).toString('utf8') | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.