openmohaa/code/gamespy/gstats/gstats.h
2023-02-04 21:00:01 +01:00

389 lines
13 KiB
C

/******
gstats.h
GameSpy Stats/Tracking SDK
Copyright 1999-2007 GameSpy Industries, Inc
******
Please see the GameSpy Stats and Tracking SDK documentation for more info
08-23-00 - DDW
Fixed a problem that prevented opening/closing/re-opening of the connection within
a single session.
*****/
#ifndef _GSTATS_H_
#define _GSTATS_H_
/********
INCLUDES
********/
#include "../common/gsCommon.h"
#include "gbucket.h"
#ifdef __cplusplus
extern "C" {
#endif
#if defined(_WIN32)
// Warnings are generated because we store function ptrs into a void* array
#pragma warning(disable: 4152) // function to data ptr
#pragma warning(disable: 4055) // data to function ptr
#endif
/********
TYPEDEFS
********/
/* The abstracted "game" structure */
typedef struct statsgame_s *statsgame_t;
/* All of the operations you can do on a bucket */
typedef enum {bo_set, bo_add, bo_sub, bo_mult, bo_div, bo_concat, bo_avg} bucketop_t;
#define NUMOPS 7
/* The types of buckets (server info, team info, or player info) */
typedef enum {bl_server, bl_team, bl_player} bucketlevel_t;
/* Init states for async initialization */
typedef enum {init_none, init_failed, init_connecting, init_awaitchallenge, init_awaitsessionkey, init_complete} initstate_t;
/* Used by the bucket operation macros */
typedef void *(*BucketFunc)(bucketset_t set, char *name,void *value);
typedef int (*SetIntFunc)(statsgame_t game,char *name, BucketFunc func, int value, int index);
typedef double (*SetFloatFunc)(statsgame_t game,char *name, BucketFunc func, double value, int index);
typedef char *(*SetStringFunc)(statsgame_t game,char *name, BucketFunc func, char *value, int index);
extern BucketFunc bucketfuncs[NUMOPS];
extern void * bopfuncs[][3];
/********
DEFINES
********/
/* Error codes */
#define GE_NOERROR 0
#define GE_NOSOCKET 1 /* Unable to create a socket */
#define GE_NODNS 2 /* Unable to resolve a DNS name */
#define GE_NOCONNECT 3 /* Unable to connect to stats server, or connection lost */
#define GE_BUSY 4 /* Not used */
#define GE_DATAERROR 5 /* Bad data from the stats server */
#define GE_CONNECTING 6 /* Connect did no immediately complete. Call InitStatsThink() */
#define GE_TIMEDOUT 7 /* Connect attempt timed out */
/* Types of snapshots, update (any snapshot that is not final) or final */
#define SNAP_UPDATE 0
#define SNAP_FINAL 1
/* If you want to allow disk logging in case the stats server isn't available.
This has SERIOUS security repercussions, so please read the docs before turning this on */
#define ALLOW_DISK
#if defined(NOFILE)
#undef ALLOW_DISK
#endif /* make sure it's never defined on platforms with no disk! */
/********
VARS
********/
/* You need to fill these in with your game-specific info */
extern char gcd_secret_key[256];
extern char gcd_gamename[256];
/* The hostname of the stats server.
If the app resolves the hostname, an
IP can be stored here before calling
InitStatsConnection */
extern char StatsServerHostname[64];
/********
PROTOTYPES
********/
#ifndef GSI_UNICODE
#define GenerateAuth GenerateAuthA
#define SendGameSnapShot SendGameSnapShotA
#define NewPlayer NewPlayerA
#define NewTeam NewTeamA
#else
#define GenerateAuth GenerateAuthW
#define SendGameSnapShot SendGameSnapShotW
#define NewPlayer NewPlayerW
#define NewTeam NewTeamW
#endif
/********
InitStatsConnection
DESCRIPTION
Opens a connection to the stats server. Should be done before calling
NewGame or any of the bucket/snapshot functions. May block for 1-2 secs
while the connection is established so you will want to do this before
gameplay starts or in another thread.
PARAMETERS
gameport: integer port associated with your server (may be the same as
your developer spec query port). Used only to help players differentiate
between servers on the same machine (no queries are done on it). If not
appropriate for your game, pass in 0.
RETURNS
GE_NODNS: Unable to resolve stats server DNS
GE_NOSOCKET: Unable to create data socket
GE_NOCONNECT: Unable to connect to stats server
GE_DATAERROR: Unable to receive challenge from stats server, or bad challenge
GE_NOERROR: Connected to stats server and ready to send data
Note: You can still call ANY of the other Stats SDK functions, even if the
connection fails. If you have disk logging enabled, these calls will be logged
for future sending, otherwise they will be discarded.
*********/
int InitStatsConnection(int gameport);
int InitStatsAsync(int gameport, gsi_time theInitTimeout);
int InitStatsThink();
/********
StatsThink
DESCRIPTION
Eats up any incoming keep-alive messages that are sent by the stats server.
Returns any errors occur because of a socket problem or if the SDK was
not completely initialized.
RETURNS
1 if no errors occured during read, 0 on all other errors
********/
int StatsThink();
/********
IsStatsConnected
DESCRIPTION
Returns whether or not you are currently connected to the stats server. Even
if your initial connection was successful, you may lose connection later and
want to try to reconnnect
RETURNS
1 if connected, 0 otherwise
*********/
int IsStatsConnected();
/********
CloseStatsConnection
DESCRIPTION
Closes the connection to the stats server. You should do this when done
with the connection.
*********/
void CloseStatsConnection(void);
/********
GetChallenge
DESCRIPTION
Returns a string that should be sent to clients for authentication
(using GenerateAuth). You do not have to free the string when done.
This string will be constant for the entire length of the game and is
generated during the call to NewGame.
PARAMETERS
game: Game to return the challenge string for. If game is NULL, the last
game created with NewGame will be used.
RETURNS
A string to send to clients so they can authorize. If you game is NULL and
you haven't created a game with NewGame, it returns "NULLGAME".
*********/
char *GetChallenge(statsgame_t game);
/********
GenerateAuth
DESCRIPTION
Should be used on the CLIENT SIDE to generate an authentication reply
(auth_N) for a given challenge and password (CD Key or Profile password)
PARAMETERS
challenge: The challenge string sent by the server. On the server this
should be generated with GetChallenge
password: The CD Key (un-hashed) or profile password
response: The output authentication string
RETURNS
A pointer to response
*********/
char *GenerateAuth(const char *challenge, const gsi_char *password,/*[out]*/char response[33]);
/********
NewGame
DESCRIPTION
Creates a new game for logging and registers it with the stats server.
Creates all the game structures, including buckets if needed.
PARAMETERS
usebuckets: Set to 1 for bucket based logging, 0 if you are going to create
the snapshots yourself. See the SDK for more info.
RETURNS
A pointer to the new game. If you are not connected, and disk logging is
disabled, this will be NULL. You can still pass NULL to any function without
causing any errors.
Note: The last game created by NewGame is stored internally.
If you only create / use one game at a time, you can simply discard
the return value and pass NULL for game into all of the bucket and snapshot functions.
*********/
statsgame_t NewGame(int usebuckets);
/********
FreeGame
DESCRIPTION
Frees a game and its associated structures (including buckets). You should
send a final snapshot for the game (using SendGameSnapShot with SNAP_FINAL)
before freeing the game.
PARAMETERS
game: The game you want to free. If set to NULL, it will free the last
game created with NewGame.
*********/
void FreeGame(statsgame_t game);
/********
SendGameSnapShot
DESCRIPTION
Sends a snapshot of information about the current game. If bucket based
logging is enabled the snapshot will be generated from the buckets, otherwise
you should provide it in "snapshot".
PARAMETERS
game: The game to send a snapshot for. If set to NULL, the last game
created with NewGame will be used.
snapshot: The snapshot to send. If you are using buckets, this will not be
used, so you can pass in NULL
final: If this is SNAP_UPDATE, the game is marked as in progress, if it
is SNAP_FINAL, the game is marked as complete.
RETURNS
GE_DATAERROR: If game is NULL and the last game created by NewGame failed
(because the connection was lost and disk logging is disabled)
GE_NOCONNECT: If the connection is lost and disk logging is disabled
GE_NOERROR: The update was sent, or disk logging is enabled and the game was logged
*********/
int SendGameSnapShot(statsgame_t game, const gsi_char *snapshot, int final);
/******************************
BUCKET FUNCTION PROTOTYPES
These functions are only used for bucket-based logging
*******************************/
/********
Bucket_____Op
DESCRIPTION
Performs an operation on a bucket for a game. If the bucket doesn't exist already,
the call will set the bucket to whatever "value" is.
You can always create each bucket explicitly by using bo_set with whatever initial
value you want the bucket to have.
Valid operations include set, add, subtract, multiply, divide, concat, and average.
Each bucket type (int, float, or string) has its own operation function, always call
the same one for each bucket (i.e. don't create a bucket with BucketIntOp then try to
add a float with BucketFloatOp).
PARAMETERS
game: The game to send containing the bucket you want to operate on.
If set to NULL, the last game created with NewGame will be used.
name: The name of the bucket to update. Note that for player or team buckets, this name
does NOT include the "_" or "_t" (e.g. "score" for player score, not "score_N"). The underscore
and number will be added automatically.
operation: One of the bucketop_t enums defined above
value: Argument for the operation (bucket OP= value, e.g. bucket += value, bucket *= value)
bucketlevel: One of the bucketlevel_t enums defined above. Determines whether you are
referring to a server, player, or team bucket. Note that you can have seperate buckets of
each type with the same name (e.g. "score" player bucket for each player and "score" team
bucket for each team)
index: For player or team buckets, the game index of the player or team (as passed to NewPlayer or
NewTeam). This will be translated to the actual index internally.
Not used for server buckets (bl_server).
*********/
#define BucketIntOp(game, name, operation, value, bucketlevel, index) (((SetIntFunc)bopfuncs[bucketlevel][bt_int])(game,name,bucketfuncs[operation],value,index) )
#define BucketFloatOp(game, name, operation, value, bucketlevel, index) (((SetFloatFunc)bopfuncs[bucketlevel][bt_float])(game,name,bucketfuncs[operation],value,index) )
#define BucketStringOp(game, name, operation, value, bucketlevel, index) (((SetStringFunc)bopfuncs[bucketlevel][bt_string])(game,name,bucketfuncs[operation],value,index) )
/********
NewPlayer
DESCRIPTION
Adds a "player" to the game and assigns them an internal player number. Sets
their connect time to the number of seconds since NewGame was called.
PARAMETERS
game: The game to add the player to. If set to NULL, the last game created
with NewGame will be used.
pnum: Your internal reference for this player, use this value in any calls
to the Bucket___Op functions.
name: The name for this player. If you don't have one yet, set it to empty ("")
then call: BucketStringOp(game,"player",bo_set,realplayername, bl_player, pnum)
when you get a realplayername.
**********/
void NewPlayer(statsgame_t game,int pnum, gsi_char *name);
/********
RemovePlayer
DESCRIPTION
Removes a "player" from the game and sets their disconnect time to the
number of seconds since NewGame was called.
PARAMETERS
game: The game to remove the player from. If set to NULL, the last game created
with NewGame will be used.
pnum: Your internal reference for this player, use this value in any calls
to the Bucket___Op functions.
**********/
void RemovePlayer(statsgame_t game,int pnum);
/*********
NewTeam
RemoveTeam
DESCRIPTION
See the player functions above. These function the same, except for teams
**********/
void NewTeam(statsgame_t game,int tnum, gsi_char *name);
void RemoveTeam(statsgame_t game,int tnum);
/*********
GetPlayerIndex
GetTeamIndex
DESCRIPTION
Gets the gstats reference number for that player or team. For
example, if you start the game and players 0, 1, and 2 join, then player 1
leaves, and another player 1 joins, the new player 1 will be referenced
by gstats as 3. If player 3 joins, it will be referenced as player 4, and so on.
Normally this doesn't matter to you, but if you want to do a key name or key value
that references a player or team number (for example, setting a player's team number),
you need to use the translated values.
PARAMETERS
game: The game to retrieve the translated value for. If set to NULL,the last game created
with NewGame will be used.
pnum/tnum: Your internal player or team number (as sent to NewTeam/NewPlayer)
**********/
int GetPlayerIndex(statsgame_t game, int pnum);
int GetTeamIndex(statsgame_t game, int tnum);
#ifdef __cplusplus
}
#endif
#endif