440 lines
12 KiB
C++
440 lines
12 KiB
C++
//-----------------------------------------------------------------------------
|
|
//
|
|
// Xbox Matchmaking Definitions for Title: Jedi Academy [0x4C41000B]
|
|
// Generated by MatchSim
|
|
//
|
|
//-----------------------------------------------------------------------------
|
|
#pragma once
|
|
|
|
|
|
#include <xtl.h>
|
|
#include <xonline.h>
|
|
#include <assert.h>
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Constants
|
|
//-----------------------------------------------------------------------------
|
|
|
|
//
|
|
// Attribute IDs ID num Data Type
|
|
// ------ ----------------------------
|
|
const DWORD XATTRIB_GAME_TYPE = 0x0001 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_CURRENT_MAP = 0x0002 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_SESSION_NAME = 0x0003 | X_ATTRIBUTE_DATATYPE_STRING;
|
|
const DWORD XATTRIB_FRIENDLY_FIRE = 0x0004 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_JEDI_MASTERY = 0x0005 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_TOTAL_PLAYERS = 0x0007 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_SABER_ONLY = 0x0008 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
const DWORD XATTRIB_DEDICATED = 0x0009 | X_ATTRIBUTE_DATATYPE_INTEGER;
|
|
|
|
|
|
//
|
|
// Attribute Maximum Lengths
|
|
// (for strings, this doesn't include the terminating NULL)
|
|
//
|
|
const DWORD XATTRIB_SESSION_NAME_MAX_LEN = 16; // SessionName attribute
|
|
|
|
|
|
// Specify X_MATCH_NULL_INTEGER for optional integer query arguments
|
|
const ULONGLONG X_MATCH_NULL_INTEGER = 0x7FFFFFFFFFFFFFFFui64;
|
|
|
|
// Maximum number of sessions returned by OptiMatch query
|
|
const DWORD MAX_OPTI_MATCH_RESULTS = 25;
|
|
|
|
// Maximum number of sessions returned by JoinSessionByID query
|
|
const DWORD MAX_JOIN_SESSION_BY_ID_RESULTS = 1;
|
|
|
|
// Number of QoS probes
|
|
const DWORD NUM_QOS_PROBES = 8;
|
|
|
|
// Maximum bandwidth to consume for QoS probes
|
|
const DWORD QOS_BITS_PER_SEC = 16000;
|
|
|
|
|
|
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// Types
|
|
//-----------------------------------------------------------------------------
|
|
|
|
// Helper class for getting/setting blob attributes
|
|
class CBlob
|
|
{
|
|
public:
|
|
CBlob() : m_wLength( 0 ), m_pvData( NULL ) {}
|
|
CBlob( WORD wLength, const PVOID pvData ) : m_wLength( wLength), m_pvData( pvData) {}
|
|
CBlob( const CBlob & b ) { *this = b; }
|
|
CBlob & operator=( const CBlob & b )
|
|
{ m_wLength = b.Length; m_pvData = b.Data; return *this; }
|
|
BOOL operator==( const CBlob & b ) const
|
|
{ return m_wLength == b.Length && memcmp( m_pvData, b.Data, b.Length ) == 0; }
|
|
BOOL IsNull() { return m_pvData == NULL; }
|
|
__declspec( property( put = SetData, get=GetData ) ) const PVOID Data;
|
|
const PVOID GetData() const { return m_pvData; }
|
|
VOID SetData( const PVOID pvData ) { m_pvData = pvData; }
|
|
__declspec( property( put = SetLength, get=GetLength ) ) WORD Length;
|
|
WORD GetLength() const { return m_wLength; }
|
|
VOID SetLength( WORD wLength ) { m_wLength = wLength; }
|
|
private:
|
|
WORD m_wLength;
|
|
PVOID m_pvData;
|
|
};
|
|
|
|
// A null blob is defined as having a NULL pointer
|
|
#define NULL_BLOB CBlob( 0, NULL )
|
|
|
|
// Macro for declaring "blob literals" (much like the _T() macro does for strings)
|
|
#define B( length, ptr ) CBlob( length, (const PVOID) ptr )
|
|
|
|
class CSession
|
|
{
|
|
public:
|
|
CSession();
|
|
~CSession();
|
|
|
|
HRESULT Create();
|
|
HRESULT Update();
|
|
HRESULT Delete();
|
|
HRESULT Process();
|
|
|
|
VOID Reset();
|
|
|
|
DWORD PublicFilled;
|
|
DWORD PublicOpen;
|
|
DWORD PrivateFilled;
|
|
DWORD PrivateOpen;
|
|
XNKEY KeyExchangeKey;
|
|
XNKID SessionID;
|
|
|
|
BOOL IsUpdating() const { return m_State == STATE_UPDATING; }
|
|
BOOL IsDeleting() const { return m_State == STATE_DELETING; }
|
|
BOOL IsCreating() const { return m_State == STATE_CREATING; }
|
|
BOOL Exists() const { return m_State == STATE_ACTIVE || IsUpdating(); }
|
|
|
|
// Attribute Accessors
|
|
|
|
BOOL IsListening() const { return m_bListening; }
|
|
__declspec( property( put = SetQosResponse, get = GetQosResponse ) ) CBlob QosResponse;
|
|
CBlob GetQosResponse();
|
|
VOID SetQosResponse( CBlob Value );
|
|
VOID Listen( BOOL bEnable = TRUE, DWORD dwBitsPerSec = 0 );
|
|
static const DWORD NO_WAIT = 1;
|
|
|
|
__declspec( property( put = SetGameType, get=GetGameType ) ) ULONGLONG GameType;
|
|
ULONGLONG GetGameType();
|
|
VOID SetGameType( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetCurrentMap, get=GetCurrentMap ) ) ULONGLONG CurrentMap;
|
|
ULONGLONG GetCurrentMap();
|
|
VOID SetCurrentMap( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetSessionName, get=GetSessionName ) ) const WCHAR * SessionName;
|
|
const WCHAR * GetSessionName();
|
|
VOID SetSessionName( const WCHAR * Value );
|
|
|
|
__declspec( property( put = SetFriendlyFire, get=GetFriendlyFire ) ) ULONGLONG FriendlyFire;
|
|
ULONGLONG GetFriendlyFire();
|
|
VOID SetFriendlyFire( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetJediMastery, get=GetJediMastery ) ) ULONGLONG JediMastery;
|
|
ULONGLONG GetJediMastery();
|
|
VOID SetJediMastery( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetTotalPlayers, get=GetTotalPlayers ) ) ULONGLONG TotalPlayers;
|
|
ULONGLONG GetTotalPlayers();
|
|
VOID SetTotalPlayers( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetSaberOnly, get=GetSaberOnly ) ) ULONGLONG SaberOnly;
|
|
ULONGLONG GetSaberOnly();
|
|
VOID SetSaberOnly( ULONGLONG Value );
|
|
|
|
__declspec( property( put = SetDedicated, get=GetDedicated ) ) ULONGLONG Dedicated;
|
|
ULONGLONG GetDedicated();
|
|
VOID SetDedicated( ULONGLONG Value );
|
|
|
|
private:
|
|
|
|
// The m_Attributes array is accessed using predefined constants:
|
|
enum
|
|
{
|
|
GAME_TYPE_INDEX,
|
|
CURRENT_MAP_INDEX,
|
|
SESSION_NAME_INDEX,
|
|
FRIENDLY_FIRE_INDEX,
|
|
JEDI_MASTERY_INDEX,
|
|
TOTAL_PLAYERS_INDEX,
|
|
SABER_ONLY_INDEX,
|
|
DEDICATED_INDEX,
|
|
NUM_ATTRIBUTES
|
|
};
|
|
|
|
XONLINE_ATTRIBUTE m_Attributes[NUM_ATTRIBUTES];
|
|
|
|
// Storage for the SessionName string attribute
|
|
WCHAR m_strSessionName[XATTRIB_SESSION_NAME_MAX_LEN+1];
|
|
|
|
|
|
// Qos listening
|
|
struct QosQEntry
|
|
{
|
|
XNKID SessionID; // Session to unregister
|
|
DWORD dwStartTick; // Time entry was added
|
|
struct QosQEntry *pNext; // Next item in the queue
|
|
};
|
|
class CSessionQosQ
|
|
{
|
|
public:
|
|
CSessionQosQ();
|
|
VOID Add( XNKID & SessionID, DWORD dwStartTick );
|
|
VOID Remove( XNKID &SessionID );
|
|
VOID Dequeue();
|
|
const QosQEntry *Head() const { return m_pHead; }
|
|
const QosQEntry *Tail() const { return m_pTail; }
|
|
private:
|
|
|
|
QosQEntry *m_pHead;
|
|
QosQEntry *m_pTail;
|
|
};
|
|
|
|
CSessionQosQ m_SessionQosQ;
|
|
BOOL m_bListening; // Listening for Qos probes
|
|
CBlob m_QosResponse;
|
|
VOID PurgeSessionQ( BOOL fRemoveAll = FALSE );
|
|
VOID PurgeSessionQHead();
|
|
|
|
|
|
|
|
HRESULT ProcessStateCreateSession();
|
|
HRESULT ProcessStateUpdateSession();
|
|
HRESULT ProcessStateDeleteSession();
|
|
HRESULT ProcessStateActiveSession();
|
|
|
|
VOID Close();
|
|
VOID SetupAttributes();
|
|
|
|
XONLINETASK_HANDLE m_hSessionTask;
|
|
|
|
enum STATE
|
|
{
|
|
STATE_IDLE,
|
|
STATE_CREATING,
|
|
STATE_UPDATING,
|
|
STATE_DELETING,
|
|
STATE_ACTIVE
|
|
};
|
|
|
|
STATE m_State;
|
|
BOOL m_bKeyRegistered;
|
|
BOOL m_bUpdate;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// COptiMatchResult represents a single return result from the
|
|
// OptiMatch query
|
|
//
|
|
#pragma pack(push, 1)
|
|
class COptiMatchResult
|
|
{
|
|
public:
|
|
// The query return attributes must come first, and in the order
|
|
// returned by the query
|
|
ULONGLONG GameType;
|
|
ULONGLONG CurrentMap;
|
|
WCHAR SessionName[XATTRIB_SESSION_NAME_MAX_LEN+1];
|
|
ULONGLONG FriendlyFire;
|
|
ULONGLONG JediMastery;
|
|
ULONGLONG SaberOnly;
|
|
ULONGLONG Dedicated;
|
|
|
|
|
|
XNKID SessionID;
|
|
XNKEY KeyExchangeKey;
|
|
XNADDR HostAddress;
|
|
DWORD PublicOpen;
|
|
DWORD PrivateOpen;
|
|
DWORD PublicFilled;
|
|
DWORD PrivateFilled;
|
|
XNQOSINFO* pQosInfo;
|
|
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
// Collection of results for the OptiMatch query
|
|
class COptiMatchQueryResults
|
|
{
|
|
public:
|
|
COptiMatchQueryResults() { m_dwSize = 0; }
|
|
DWORD Size() { return m_dwSize; }
|
|
COptiMatchResult &operator[]( DWORD i ) { return v[i]; }
|
|
private:
|
|
void Clear() { m_dwSize = 0; }
|
|
void Remove( DWORD i )
|
|
{
|
|
assert( i < m_dwSize );
|
|
if( i < m_dwSize )
|
|
{
|
|
m_dwSize--;
|
|
memcpy( &v[i], &v[i+1], sizeof( v[0] ) * ( m_dwSize - i ) );
|
|
}
|
|
}
|
|
void SetSize( DWORD dwSize ) { m_dwSize = dwSize; }
|
|
friend class COptiMatchQuery;
|
|
COptiMatchResult v[MAX_OPTI_MATCH_RESULTS];
|
|
DWORD m_dwSize;
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// Query object for OptiMatch query (id 0x1)
|
|
//
|
|
class COptiMatchQuery
|
|
{
|
|
public:
|
|
COptiMatchQuery();
|
|
~COptiMatchQuery();
|
|
COptiMatchQueryResults Results;
|
|
|
|
HRESULT Process();
|
|
void Cancel();
|
|
void Clear();
|
|
BOOL Done() const { return m_State == STATE_DONE; }
|
|
BOOL Succeeded() const { return SUCCEEDED( m_hrQuery ); }
|
|
HRESULT Query(
|
|
ULONGLONG GameType, // Optional: X_MATCH_NULL_INTEGER to omit
|
|
ULONGLONG CurrentMap, // Optional: X_MATCH_NULL_INTEGER to omit
|
|
ULONGLONG MinimumPlayers,
|
|
ULONGLONG MaximumPlayers,
|
|
ULONGLONG FriendlyFire, // Optional: X_MATCH_NULL_INTEGER to omit
|
|
ULONGLONG JediMastery, // Optional: X_MATCH_NULL_INTEGER to omit
|
|
ULONGLONG SaberOnly, // Optional: X_MATCH_NULL_INTEGER to omit
|
|
ULONGLONG Dedicated // Optional: X_MATCH_NULL_INTEGER to omit
|
|
);
|
|
BOOL IsRunning() const { return m_State == STATE_RUNNING || m_State == STATE_PROBING_CONNECTIVITY; }
|
|
BOOL IsProbing() const { return m_State == STATE_PROBING_BANDWIDTH; }
|
|
HRESULT Probe();
|
|
private:
|
|
|
|
// Quality of Service
|
|
const XNADDR *m_rgpXnAddr[ MAX_OPTI_MATCH_RESULTS ];
|
|
const XNKID *m_rgpXnKid [ MAX_OPTI_MATCH_RESULTS ];
|
|
const XNKEY *m_rgpXnKey [ MAX_OPTI_MATCH_RESULTS ];
|
|
XNQOS *m_pXnQos;
|
|
enum STATE
|
|
{
|
|
STATE_IDLE,
|
|
STATE_RUNNING,
|
|
STATE_PROBING_CONNECTIVITY,
|
|
STATE_PROBING_BANDWIDTH,
|
|
STATE_DONE
|
|
};
|
|
|
|
STATE m_State;
|
|
HRESULT m_hrQuery;
|
|
XONLINETASK_HANDLE m_hSearchTask;
|
|
};
|
|
|
|
|
|
|
|
|
|
//
|
|
// CJoinSessionByIDResult represents a single return result from the
|
|
// JoinSessionByID query
|
|
//
|
|
#pragma pack(push, 1)
|
|
class CJoinSessionByIDResult
|
|
{
|
|
public:
|
|
|
|
XNKID SessionID;
|
|
XNKEY KeyExchangeKey;
|
|
XNADDR HostAddress;
|
|
DWORD PublicOpen;
|
|
DWORD PrivateOpen;
|
|
DWORD PublicFilled;
|
|
DWORD PrivateFilled;
|
|
XNQOSINFO* pQosInfo;
|
|
|
|
};
|
|
#pragma pack(pop)
|
|
|
|
|
|
|
|
// Collection of results for the JoinSessionByID query
|
|
class CJoinSessionByIDQueryResults
|
|
{
|
|
public:
|
|
CJoinSessionByIDQueryResults() { m_dwSize = 0; }
|
|
DWORD Size() { return m_dwSize; }
|
|
CJoinSessionByIDResult &operator[]( DWORD i ) { return v[i]; }
|
|
private:
|
|
void Clear() { m_dwSize = 0; }
|
|
void Remove( DWORD i )
|
|
{
|
|
assert( i < m_dwSize );
|
|
if( i < m_dwSize )
|
|
{
|
|
m_dwSize--;
|
|
memcpy( &v[i], &v[i+1], sizeof( v[0] ) * ( m_dwSize - i ) );
|
|
}
|
|
}
|
|
void SetSize( DWORD dwSize ) { m_dwSize = dwSize; }
|
|
friend class CJoinSessionByIDQuery;
|
|
CJoinSessionByIDResult v[MAX_JOIN_SESSION_BY_ID_RESULTS];
|
|
DWORD m_dwSize;
|
|
};
|
|
|
|
|
|
|
|
//
|
|
// Query object for JoinSessionByID query (id 0x2)
|
|
//
|
|
class CJoinSessionByIDQuery
|
|
{
|
|
public:
|
|
CJoinSessionByIDQuery();
|
|
~CJoinSessionByIDQuery();
|
|
CJoinSessionByIDQueryResults Results;
|
|
|
|
HRESULT Process();
|
|
void Cancel();
|
|
void Clear();
|
|
BOOL Done() const { return m_State == STATE_DONE; }
|
|
BOOL Succeeded() const { return SUCCEEDED( m_hrQuery ); }
|
|
HRESULT Query(
|
|
ULONGLONG SessionID
|
|
);
|
|
BOOL IsRunning() const { return m_State == STATE_RUNNING || m_State == STATE_PROBING_CONNECTIVITY; }
|
|
BOOL IsProbing() const { return m_State == STATE_PROBING_BANDWIDTH; }
|
|
HRESULT Probe();
|
|
private:
|
|
|
|
// Quality of Service
|
|
const XNADDR *m_rgpXnAddr[ MAX_JOIN_SESSION_BY_ID_RESULTS ];
|
|
const XNKID *m_rgpXnKid [ MAX_JOIN_SESSION_BY_ID_RESULTS ];
|
|
const XNKEY *m_rgpXnKey [ MAX_JOIN_SESSION_BY_ID_RESULTS ];
|
|
XNQOS *m_pXnQos;
|
|
enum STATE
|
|
{
|
|
STATE_IDLE,
|
|
STATE_RUNNING,
|
|
STATE_PROBING_CONNECTIVITY,
|
|
STATE_PROBING_BANDWIDTH,
|
|
STATE_DONE
|
|
};
|
|
|
|
STATE m_State;
|
|
HRESULT m_hrQuery;
|
|
XONLINETASK_HANDLE m_hSearchTask;
|
|
};
|