Skip to content

Commit 1365535

Browse files
committed
Pass online settings into raw state, state compliant to standard query
1 parent 2ce6690 commit 1365535

File tree

2 files changed

+91
-39
lines changed

2 files changed

+91
-39
lines changed

protocols/unrealengine3.js

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -158,6 +158,35 @@ export default class unrealengine3 extends Core {
158158
if ('maxplayers' in state.raw) state.maxplayers = parseInt(state.raw.maxplayers)
159159
if ('hostport' in state.raw) state.gamePort = parseInt(state.raw.hostport)
160160
if ('gamever' in state.raw) state.version = state.raw.gamever
161+
162+
if (state.raw.playerTeamInfo && '' in state.raw.playerTeamInfo) {
163+
for (const playerInfo of state.raw.playerTeamInfo['']) {
164+
const player = {}
165+
for (const from of Object.keys(playerInfo)) {
166+
let key = from
167+
let value = playerInfo[from]
168+
169+
if (key === 'player') key = 'name'
170+
if (key === 'score' || key === 'ping' || key === 'team' || key === 'deaths' || key === 'pid') value = parseInt(value)
171+
player[key] = value
172+
}
173+
state.players.push(player)
174+
}
175+
}
176+
177+
if ('numplayers' in state.raw) state.numplayers = parseInt(state.raw.numplayers)
178+
else state.numplayers = state.players.length
179+
}
180+
181+
/**
182+
* Converts a UE3 unique id to a string
183+
* @param {UniqueNetId} reader the unique net idenitifer
184+
* @returns {string} a converted unique identifier
185+
*/
186+
static UniqueNetIdToString (uniqueNetId) {
187+
const bytes = ([...uniqueNetId]).reverse()
188+
const value = bytes[0] << 24 | bytes[1] << 16 | bytes[2] << 8 | bytes[3]
189+
return String(value)
161190
}
162191

163192
/**

protocols/unrealengine3lan.js

Lines changed: 62 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,13 @@ function parseNumber (str) {
66
return number
77
}
88

9+
function anyToString (obj) {
10+
if (typeof obj === 'boolean') {
11+
return obj ? 'True' : 'False'
12+
}
13+
return String(obj)
14+
}
15+
916
/**
1017
* Implements the LAN protocol for UnrealEngine3 based games (UE3)
1118
*/
@@ -72,7 +79,21 @@ export default class unrealengine3lan extends CoreLAN {
7279
if (outputAsArray && Array.isArray(state)) {
7380
state.push(...resultStates)
7481
} else {
75-
const firstPacket = resultStates.length ? { ...resultStates[0], $next: resultStates.slice(1).reduceRight((next, value) => ({ ...value, $next: next }), null) } : null
82+
// add linker as state root
83+
// const firstPacket = resultStates.length ? { ...resultStates[0], $next: resultStates.slice(1).reduceRight((next, value) => ({ ...value, $next: next }), null) } : null
84+
85+
// add linker into state.raw
86+
const firstPacket = resultStates?.[0]
87+
if (resultStates.length) {
88+
const nextPacket = resultStates.slice(1).reduceRight((next, value) => {
89+
// return { ...value, $next: next }
90+
Object.assign(value.raw, { $next: next })
91+
return value
92+
}, null)
93+
94+
Object.assign(firstPacket.raw, { $next: nextPacket })
95+
}
96+
7697
Object.assign(state, firstPacket)
7798
}
7899
}
@@ -120,7 +141,9 @@ export default class unrealengine3lan extends CoreLAN {
120141
parsePacket (buffer) {
121142
// create default empty state
122143
const state = this.createState()
123-
Object.assign(state, UE3.EmptyPayloadData)
144+
145+
// create empty game settings
146+
const OnlineGameSettings = { ...UE3.EmptyPayloadData }
124147

125148
const fullReader = this.reader(buffer)
126149
const packetVersion = fullReader.uint(1)
@@ -136,30 +159,31 @@ export default class unrealengine3lan extends CoreLAN {
136159
state.raw.hostaddress = ipStr
137160
state.raw.hostport = port
138161

139-
state.raw.NumOpenPublicConnections = reader.uint(4)
140-
state.raw.NumOpenPrivateConnections = reader.uint(4)
141-
state.raw.NumPublicConnections = reader.uint(4)
142-
state.raw.NumPrivateConnections = reader.uint(4)
162+
OnlineGameSettings.NumOpenPrivateConnections = 1
163+
OnlineGameSettings.NumOpenPublicConnections = reader.uint(4)
164+
OnlineGameSettings.NumOpenPrivateConnections = reader.uint(4)
165+
OnlineGameSettings.NumPublicConnections = reader.uint(4)
166+
OnlineGameSettings.NumPrivateConnections = reader.uint(4)
143167

144168
// new packets seem to have an additional bool/byte field,
145169
// flags generally consist of 8 1-byte/bool values
146-
state.raw.bShouldAdvertise = reader.uint(1) === 1
147-
state.raw.bIsLanMatch = reader.uint(1) === 1
148-
state.raw.bUsesStats = reader.uint(1) === 1
149-
state.raw.bAllowJoinInProgress = reader.uint(1) === 1
150-
state.raw.bAllowInvites = reader.uint(1) === 1
151-
state.raw.bUsesPresence = reader.uint(1) === 1
152-
state.raw.bAllowJoinViaPresence = reader.uint(1) === 1
153-
state.raw.bUsesArbitration = reader.uint(1) === 1
170+
OnlineGameSettings.bShouldAdvertise = reader.uint(1) === 1
171+
OnlineGameSettings.bIsLanMatch = reader.uint(1) === 1
172+
OnlineGameSettings.bUsesStats = reader.uint(1) === 1
173+
OnlineGameSettings.bAllowJoinInProgress = reader.uint(1) === 1
174+
OnlineGameSettings.bAllowInvites = reader.uint(1) === 1
175+
OnlineGameSettings.bUsesPresence = reader.uint(1) === 1
176+
OnlineGameSettings.bAllowJoinViaPresence = reader.uint(1) === 1
177+
OnlineGameSettings.bUsesArbitration = reader.uint(1) === 1
154178
if (packetVersion >= 5) {
155179
// read additional flag for newer packets
156-
state.raw.bAntiCheatProtected = reader.uint(1) === 1
180+
OnlineGameSettings.bAntiCheatProtected = reader.uint(1) === 1
157181
}
158182

159183
// Read the owning player id
160-
state.raw.OwningPlayerId = unrealengine3.readUniqueNetId(reader)
184+
OnlineGameSettings.OwningPlayerId = unrealengine3.readUniqueNetId(reader)
161185
// Read the owning player name
162-
state.raw.OwningPlayerName = unrealengine3.readString(reader)
186+
OnlineGameSettings.OwningPlayerName = unrealengine3.readString(reader)
163187

164188
// properties from the advertised settings
165189
const localizedProperties = []
@@ -194,8 +218,8 @@ export default class unrealengine3lan extends CoreLAN {
194218
}
195219

196220
// Turn all that raw state into something useful
221+
state.raw.session = OnlineGameSettings
197222
this.populateProperties(state)
198-
// DEBUG: delete state.raw
199223

200224
return state
201225
}
@@ -205,46 +229,45 @@ export default class unrealengine3lan extends CoreLAN {
205229
* @param {Object} state Parsed data
206230
*/
207231
populateProperties (state) {
232+
const { session } = state.raw
233+
208234
// pass raw data
209235
state.gameHost = state.raw.hostaddress
210236
state.gamePort = state.raw.hostport
211237

212-
state.name = state.raw.OwningPlayerName
213-
state.maxplayers = state.raw.NumOpenPublicConnections
238+
session.TotalOpenConnections = (session?.NumOpenPublicConnections || 0) + (session?.NumOpenPrivateConnections || 0)
239+
session.TotalConnections = (session?.NumPublicConnections || 0) + (session?.NumPrivateConnections || 0)
214240

215-
state.NumOpenPublicConnections = state.raw.NumOpenPublicConnections
216-
state.NumOpenPrivateConnections = state.raw.NumOpenPrivateConnections
217-
state.NumPublicConnections = state.raw.NumPublicConnections
218-
state.NumPrivateConnections = state.raw.NumPrivateConnections
241+
state.name = session?.OwningPlayerName
242+
state.raw.maxplayers = (session.TotalConnections).toString()
243+
state.raw.numplayers = (session.TotalConnections - session.TotalOpenConnections).toString()
219244

220-
state.bShouldAdvertise = state.raw.bShouldAdvertise
221-
state.bIsLanMatch = state.raw.bIsLanMatch
222-
state.bUsesStats = state.raw.bUsesStats
223-
state.bAllowJoinInProgress = state.raw.bAllowJoinInProgress
224-
state.bAllowInvites = state.raw.bAllowInvites
225-
state.bUsesPresence = state.raw.bUsesPresence
226-
state.bAllowJoinViaPresence = state.raw.bAllowJoinViaPresence
227-
state.bUsesArbitration = state.raw.bUsesArbitration
228-
state.bAntiCheatProtected = state.raw.bAntiCheatProtected
245+
// pass specific session fields
229246

230-
state.OwningPlayerId = Buffer.from(state.raw.OwningPlayerId).toString('hex')
231-
state.OwningPlayerName = state.raw.OwningPlayerName
247+
// replace uniqueid with stringified id
248+
session.OwningPlayerId = unrealengine3.UniqueNetIdToString(session?.OwningPlayerId)
249+
state.raw.OwningPlayerId = session.OwningPlayerId
250+
state.raw.OwningPlayerName = session.OwningPlayerName
251+
state.raw.bUsesStats = anyToString(session.bUsesStats || false)
252+
state.raw.bIsDedicated = anyToString(session.bIsDedicated || false)
253+
state.raw.NumPublicConnections = anyToString(session.NumPublicConnections)
232254

233255
// manually transform serialized properties into known structure
234256
const props = state.raw.Properties?.reduce((acc, prop) => {
235-
acc[`p${prop.PropertyId}`] = prop.Data.ValueRaw
257+
acc[`p${prop.PropertyId}`] = String(prop.Data.ValueRaw) // force string
236258
return acc
237259
}, {})
238260

239261
// manually transform serialized localized properties into known structure
240262
const propsLocalized = state.raw.LocalizedProperties?.reduce((acc, prop) => {
241-
acc[`s${prop.Id}`] = prop.ValueIndex // TOOD: find actual value
263+
acc[`s${prop.Id}`] = String(prop.ValueIndex) // force string
242264
return acc
243265
}, {})
244266

245267
// translate properties
246-
state.raw = { ...state.raw, ...props, ...propsLocalized }
247-
this.translate(state.raw, this.translateMap)
268+
const stateRaw = { ...state.raw, ...props, ...propsLocalized }
269+
Object.assign(state.raw, stateRaw)
270+
this.translate(state.raw, this.translateMap) // Note: Legacy handling of query values
248271

249272
// Turn all that raw state into something useful
250273
unrealengine3.staticPopulateProperties(state)

0 commit comments

Comments
 (0)