Read player data endpoints (#48)
* player info and pdata endpoints * add loadout and stats * ratelimit category + name
This commit is contained in:
parent
23f6cf87ce
commit
78942467a0
|
@ -26,7 +26,7 @@
|
|||
"error",
|
||||
"allman"
|
||||
],
|
||||
"no-mixed-spaces-and-tabs": "error",
|
||||
"no-mixed-spaces-and-tabs": ["error", "smart-tabs"],
|
||||
"eol-last": "error",
|
||||
"linebreak-style": [
|
||||
"error",
|
||||
|
|
|
@ -0,0 +1,175 @@
|
|||
const path = require( "path" )
|
||||
const { PLAYER_NOT_FOUND } = require( "../shared/errorcodes.js" )
|
||||
const { ParseDefinition, PdataToJsonUntyped } = require( "../shared/pjson.js" )
|
||||
const { getRatelimit } = require( "../shared/ratelimit.js" )
|
||||
const accounts = require( path.join( __dirname, "../shared/accounts.js" ) )
|
||||
const fs = require( "fs" )
|
||||
|
||||
const PLAYER_DATA_PDEF_231 = ParseDefinition( fs.readFileSync( "./persistent_player_data_version_231.pdef", "utf8" ) )
|
||||
|
||||
module.exports = ( fastify, opts, done ) =>
|
||||
{
|
||||
// exported routes
|
||||
|
||||
// GET /player/pdata
|
||||
// show pdata for a given player as json
|
||||
fastify.get( "/player/pdata",
|
||||
{
|
||||
config: { rateLimit: getRatelimit( "REQ_PER_MINUTE__PLAYER_DATA" ) }, // ratelimit
|
||||
schema: {
|
||||
querystring: {
|
||||
id: { type: "string" }, // the id of the player to get stats of
|
||||
}
|
||||
}
|
||||
},
|
||||
async ( request ) =>
|
||||
{
|
||||
let account = await accounts.AsyncGetPlayerByID( request.query.id )
|
||||
if( !account )
|
||||
{
|
||||
return { success: false, error: PLAYER_NOT_FOUND }
|
||||
}
|
||||
let pdata = PdataToJsonUntyped( account.persistentDataBaseline, PLAYER_DATA_PDEF_231 )
|
||||
return pdata
|
||||
} )
|
||||
|
||||
// GET /player/info
|
||||
// show info for a given player as json
|
||||
fastify.get( "/player/info",
|
||||
{
|
||||
config: { rateLimit: getRatelimit( "REQ_PER_MINUTE__PLAYER_DATA" ) }, // ratelimit
|
||||
schema: {
|
||||
querystring: {
|
||||
id: { type: "string" }, // the id of the player to get stats of
|
||||
}
|
||||
}
|
||||
},
|
||||
async ( request ) =>
|
||||
{
|
||||
let account = await accounts.AsyncGetPlayerByID( request.query.id )
|
||||
if( !account )
|
||||
{
|
||||
return { success: false, error: PLAYER_NOT_FOUND }
|
||||
}
|
||||
let pdata = PdataToJsonUntyped( account.persistentDataBaseline, PLAYER_DATA_PDEF_231 )
|
||||
|
||||
// define a filter for which properties are copied from the pdata
|
||||
let filter = ["gen", "xp", "activeCallingCardIndex", "activeCallsignIconIndex", "activeCallsignIconStyleIndex", "netWorth"]
|
||||
|
||||
let pdataFiltered = Object.fromEntries(
|
||||
filter
|
||||
.map( key => [key, pdata[key]] )
|
||||
)
|
||||
|
||||
let ret = {
|
||||
name: account.username,
|
||||
id: account.id
|
||||
}
|
||||
Object.assign( ret, pdataFiltered )
|
||||
|
||||
return ret
|
||||
} )
|
||||
|
||||
// GET /player/stats
|
||||
// show stats for a given player as json
|
||||
fastify.get( "/player/stats",
|
||||
{
|
||||
config: { rateLimit: getRatelimit( "REQ_PER_MINUTE__PLAYER_DATA" ) }, // ratelimit
|
||||
schema: {
|
||||
querystring: {
|
||||
id: { type: "string" }, // the id of the player to get stats of
|
||||
}
|
||||
}
|
||||
},
|
||||
async ( request ) =>
|
||||
{
|
||||
let account = await accounts.AsyncGetPlayerByID( request.query.id )
|
||||
if( !account )
|
||||
{
|
||||
return { success: false, error: PLAYER_NOT_FOUND }
|
||||
}
|
||||
|
||||
let pdata = PdataToJsonUntyped( account.persistentDataBaseline, PLAYER_DATA_PDEF_231 )
|
||||
|
||||
// define a filter for which properties are copied from the pdata
|
||||
let filter = ["gen", "xp", "credits", "netWorth", "factionXP", "titanXP", "fdTitanXP", "gameStats", "mapStats", "timeStats",
|
||||
"distanceStats", "weaponStats", "weaponKillStats", "killStats", "deathStats", "miscStats", "fdStats", "titanStats",
|
||||
"kdratio_lifetime", "kdratio_lifetime_pvp", "winStreak", "highestWinStreakEver", ]
|
||||
|
||||
let pdataFiltered = Object.fromEntries(
|
||||
filter
|
||||
.map( key => [key, pdata[key]] )
|
||||
)
|
||||
|
||||
let ret = {
|
||||
id: account.id
|
||||
}
|
||||
Object.assign( ret, pdataFiltered )
|
||||
|
||||
return ret
|
||||
} )
|
||||
|
||||
// GET /player/loadout
|
||||
// show louadout data for a given player as json
|
||||
fastify.get( "/player/loadout",
|
||||
{
|
||||
config: { rateLimit: getRatelimit( "REQ_PER_MINUTE__PLAYER_DATA" ) }, // ratelimit
|
||||
schema: {
|
||||
querystring: {
|
||||
id: { type: "string" }, // the id of the player to get stats of
|
||||
}
|
||||
}
|
||||
},
|
||||
async ( request ) =>
|
||||
{
|
||||
let account = await accounts.AsyncGetPlayerByID( request.query.id )
|
||||
if( !account )
|
||||
{
|
||||
return { success: false, error: PLAYER_NOT_FOUND }
|
||||
}
|
||||
let pdata = PdataToJsonUntyped( account.persistentDataBaseline, PLAYER_DATA_PDEF_231 )
|
||||
|
||||
// define a filter for which properties are copied from the pdata
|
||||
let filter = ["factionChoice", "activePilotLoadout", "activeTitanLoadout", "pilotLoadouts", "titanLoadouts"]
|
||||
|
||||
let pdataFiltered = Object.fromEntries(
|
||||
filter
|
||||
.map( key => [key, pdata[key]] )
|
||||
)
|
||||
|
||||
let ret = {
|
||||
id: account.id
|
||||
}
|
||||
Object.assign( ret, pdataFiltered )
|
||||
|
||||
return ret
|
||||
} )
|
||||
|
||||
done()
|
||||
}
|
||||
|
||||
// might be useful at some point
|
||||
// function StripPdataTypes( pdata )
|
||||
// {
|
||||
// if( typeof pdata != "object" ) return pdata
|
||||
// let stripped = {}
|
||||
// for( const [k, v] of Object.entries( pdata ) )
|
||||
// {
|
||||
// if( typeof v.value == "object" )
|
||||
// {
|
||||
// if( Array.isArray( v.value ) )
|
||||
// {
|
||||
// stripped[k] = v.value.map( val => StripPdataTypes( val ) )
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// stripped[k] = StripPdataTypes( v.value )
|
||||
// }
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// stripped[k] = v.value
|
||||
// }
|
||||
// }
|
||||
// return stripped
|
||||
// }
|
3
dev.env
3
dev.env
|
@ -28,9 +28,10 @@ REQ_PER_MINUTE__SERVER_HEARTBEAT=60
|
|||
REQ_PER_MINUTE__SERVER_UPDATEVALUES=20
|
||||
REQ_PER_MINUTE__SERVER_REMOVESERVER=5
|
||||
REQ_PER_MINUTE__ACCOUNT_WRITEPERSISTENCE=50
|
||||
REQ_PER_MINUTE__PLAYER_DATA=50
|
||||
|
||||
# origin
|
||||
ORIGIN_ENABLE=1
|
||||
ORIGIN_PERSIST_SID=1
|
||||
ORIGIN_EMAIL=
|
||||
ORIGIN_PASSWORD=
|
||||
ORIGIN_PASSWORD=
|
||||
|
|
|
@ -332,6 +332,46 @@ function PdataToJson( pdata, pdef )
|
|||
return ret
|
||||
}
|
||||
|
||||
function PdataToJsonUntyped( pdata, pdef )
|
||||
{
|
||||
let ret = {}
|
||||
let i = 0
|
||||
|
||||
function recursiveReadPdata( struct, base )
|
||||
{
|
||||
for ( let member of struct )
|
||||
{
|
||||
let arraySize = member.arraySize || 1
|
||||
if ( typeof( arraySize ) == "string" )
|
||||
arraySize = pdef.enums[ member.arraySize ].length
|
||||
|
||||
let retArray = []
|
||||
|
||||
for ( let j = 0; j < arraySize; j++ )
|
||||
{
|
||||
if ( member.type in NATIVE_TYPES )
|
||||
{
|
||||
retArray.push( NATIVE_TYPES[ member.type ].read( pdata, i, member.nativeArraySize ) )
|
||||
i += NATIVE_TYPES[ member.type ].size * ( member.nativeArraySize || 1 )
|
||||
}
|
||||
else if ( member.type in pdef.enums )
|
||||
retArray.push( pdef.enums[ member.type ][ pdata.readUInt8( i++ ) ] ) // enums are uint8s
|
||||
else if ( member.type in pdef.structs )
|
||||
{
|
||||
let newStruct = {}
|
||||
recursiveReadPdata( pdef.structs[ member.type ], newStruct )
|
||||
retArray.push( newStruct )
|
||||
}
|
||||
}
|
||||
|
||||
base[ member.name ] = member.arraySize ? retArray : retArray[ 0 ]
|
||||
}
|
||||
}
|
||||
|
||||
recursiveReadPdata( pdef.members, ret )
|
||||
|
||||
return ret
|
||||
}
|
||||
|
||||
//function PdataJsonToBuffer( json, pdef )
|
||||
//{
|
||||
|
@ -431,5 +471,6 @@ module.exports = {
|
|||
ParseDefinitionDiff: ParseDefinitionDiff,
|
||||
GetMemberSize: GetMemberSize,
|
||||
PdataToJson: PdataToJson,
|
||||
PdataToJsonUntyped: PdataToJsonUntyped,
|
||||
PdataJsonToBuffer: PdataJsonToBuffer,
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue