2012-11-26 18:58:24 +00:00
/*
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
Doom 3 BFG Edition GPL Source Code
2012-11-28 15:47:07 +00:00
Copyright ( C ) 1993 - 2012 id Software LLC , a ZeniMax Media company .
2012-11-26 18:58:24 +00:00
2012-11-28 15:47:07 +00:00
This file is part of the Doom 3 BFG Edition GPL Source Code ( " Doom 3 BFG Edition Source Code " ) .
2012-11-26 18:58:24 +00:00
Doom 3 BFG Edition Source Code is free software : you can redistribute it and / or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation , either version 3 of the License , or
( at your option ) any later version .
Doom 3 BFG Edition Source Code is distributed in the hope that it will be useful ,
but WITHOUT ANY WARRANTY ; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
GNU General Public License for more details .
You should have received a copy of the GNU General Public License
along with Doom 3 BFG Edition Source Code . If not , see < http : //www.gnu.org/licenses/>.
In addition , the Doom 3 BFG Edition Source Code is also subject to certain additional terms . You should have received a copy of these additional terms immediately following the terms and conditions of the GNU General Public License which accompanied the Doom 3 BFG Edition Source Code . If not , please request a copy in writing from id Software at the address below .
If you have questions concerning this license or the applicable additional terms , you may contact in writing id Software LLC , c / o ZeniMax Media Inc . , Suite 120 , Rockville , Maryland 20850 USA .
= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =
*/
# include "sys_lobby_backend.h"
# define INVALID_LOBBY_USER_NAME " " // Used to be "INVALID" but Sony might not like that.
class idSessionCallbacks ;
class idDebugGraph ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idLobby
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
class idLobby : public idLobbyBase
{
2012-11-26 18:58:24 +00:00
public :
idLobby ( ) ;
2012-11-28 15:47:07 +00:00
enum lobbyType_t
{
2012-11-26 18:58:24 +00:00
TYPE_PARTY = 0 ,
TYPE_GAME = 1 ,
TYPE_GAME_STATE = 2 ,
TYPE_INVALID = 0xff
} ;
2012-11-28 15:47:07 +00:00
enum lobbyState_t
{
2012-11-26 18:58:24 +00:00
STATE_IDLE ,
STATE_CREATE_LOBBY_BACKEND ,
STATE_SEARCHING ,
STATE_OBTAINING_ADDRESS ,
STATE_CONNECT_HELLO_WAIT ,
STATE_FINALIZE_CONNECT ,
STATE_FAILED ,
NUM_STATES
} ;
2012-11-28 15:47:07 +00:00
enum failedReason_t
{
2012-11-26 18:58:24 +00:00
FAILED_UNKNOWN ,
FAILED_CONNECT_FAILED ,
FAILED_MIGRATION_CONNECT_FAILED ,
} ;
2012-11-28 15:47:07 +00:00
void Initialize ( lobbyType_t sessionType_ , class idSessionCallbacks * callbacks ) ;
void StartHosting ( const idMatchParameters & parms ) ;
void StartFinding ( const idMatchParameters & parms_ ) ;
2012-11-26 18:58:24 +00:00
void Pump ( ) ;
void ProcessSnapAckQueue ( ) ;
void Shutdown ( bool retainMigrationInfo = false , bool skipGoodbye = false ) ; // Goto idle state
2012-11-28 15:47:07 +00:00
void HandlePacket ( lobbyAddress_t & remoteAddress , idBitMsg fragMsg , idPacketProcessor : : sessionId_t sessionID ) ;
lobbyState_t GetState ( )
{
return state ;
}
2012-11-26 18:58:24 +00:00
virtual bool HasActivePeers ( ) const ;
2012-11-28 15:47:07 +00:00
virtual bool IsLobbyFull ( ) const
{
return NumFreeSlots ( ) = = 0 ;
}
2012-11-26 18:58:24 +00:00
int NumFreeSlots ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
enum reliablePlayerToPlayer_t
{
2012-11-26 18:58:24 +00:00
//RELIABLE_PLAYER_TO_PLAYER_VOICE_EVENT,
RELIABLE_PLAYER_TO_PLAYER_GAME_DATA ,
// Game messages would be reserved here in the same way that RELIABLE_GAME_DATA is.
// I'm worried about using up the 0xff values we have for reliable type, so I'm not
// going to reserve anything here just yet.
NUM_RELIABLE_PLAYER_TO_PLAYER ,
} ;
2012-11-28 15:47:07 +00:00
enum reliableType_t
{
2012-11-26 18:58:24 +00:00
RELIABLE_HELLO , // host to peer : connection established
RELIABLE_USER_CONNECTED , // host to peer : a new session user connected
RELIABLE_USER_DISCONNECTED , // host to peer : a session user disconnected
RELIABLE_START_LOADING , // host to peer : peer should begin loading the map
RELIABLE_LOADING_DONE , // peer to host : finished loading map
RELIABLE_IN_GAME , // peer to host : first full snap received, in game now
RELIABLE_SNAPSHOT_ACK , // peer to host : got a snapshot
RELIABLE_RESOURCE_ACK , // peer to host : got some new resources
2012-11-28 15:47:07 +00:00
RELIABLE_CONNECT_AND_MOVE_TO_LOBBY , // host to peer : connect to this server
2012-11-26 18:58:24 +00:00
RELIABLE_PARTY_CONNECT_OK , // host to peer
RELIABLE_PARTY_LEAVE_GAME_LOBBY , // host to peer : leave game lobby
RELIABLE_MATCH_PARMS , // host to peer : update in match parms
RELIABLE_UPDATE_MATCH_PARMS , // peer to host : peer updating match parms
// User join in progress msg's (join in progress for the party/game lobby, not inside a match)
RELIABLE_USER_CONNECT_REQUEST , // peer to host: local user wants to join session in progress
RELIABLE_USER_CONNECT_DENIED , // host to peer: user join session in progress denied (not enough slots)
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// User leave in progress msg's (leave in progress for the party/game lobby, not inside a match)
RELIABLE_USER_DISCONNECT_REQUEST , // peer to host: request host to remove user from session
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_KICK_PLAYER , // host to peer : kick a player
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_MATCHFINISHED , // host to peer - Match is in post looking at score board
RELIABLE_ENDMATCH , // host to peer - End match, and go to game lobby
RELIABLE_ENDMATCH_PREMATURE , // host to peer - End match prematurely, and go to game lobby (onl possible in unrated/custom games)
RELIABLE_SESSION_USER_MODIFIED , // peer to host : user changed something (emblem, name, etc)
RELIABLE_UPDATE_SESSION_USER , // host to peers : inform all peers of the change
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_HEADSET_STATE , // * to * : headset state change for user
RELIABLE_VOICE_STATE , // * to * : voice state changed for user pair (mute, unmute, etc)
RELIABLE_PING , // * to * : send host->peer, then reflected
RELIABLE_PING_VALUES , // host to peers : ping data from lobbyUser_t for everyone
RELIABLE_BANDWIDTH_VALUES , // peer to host: data back about bandwidth test
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_ARBITRATE , // host to peer : start arbitration
RELIABLE_ARBITRATE_OK , // peer to host : ack arbitration request
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_POST_STATS , // host to peer : here, write these stats now (hacky)
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_MIGRATION_GAME_DATA , // host to peers: game data to use incase of a migration
RELIABLE_START_MATCH_GAME_LOBBY_HOST , // game lobby host to game state lobby host: start the match, since all players are in
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_DUMMY_MSG , // used as a placeholder for old removed msg's
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
RELIABLE_PLAYER_TO_PLAYER_BEGIN ,
// use reliablePlayerToPlayer_t
RELIABLE_PLAYER_TO_PLAYER_END = RELIABLE_PLAYER_TO_PLAYER_BEGIN + NUM_RELIABLE_PLAYER_TO_PLAYER ,
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// * to * : misc reliable game data above this
2012-11-28 15:47:07 +00:00
RELIABLE_GAME_DATA = RELIABLE_PLAYER_TO_PLAYER_END
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// JGM: Reliable type in packet is a byte and there are a lot of reliable game messages.
// Feel free to bump this up since it's arbitrary anyway, but take a look at gameReliable_t.
// At the moment, both Doom and Rage have around 32 gameReliable_t values.
compile_time_assert ( RELIABLE_GAME_DATA < 64 ) ;
2012-11-28 15:47:07 +00:00
static const char * stateToString [ NUM_STATES ] ;
2012-11-26 18:58:24 +00:00
// Consts
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int PEER_HEARTBEAT_IN_SECONDS = 5 ; // Make sure something was sent every 5 seconds, so we don't time out
static const int CONNECT_REQUEST_FREQUENCY_IN_SECONDS = 5 ; // Frequency at which we resend a request to connect to a server (will increase in frequency over time down to MIN_CONNECT_FREQUENCY_IN_SECONDS)
static const int MIN_CONNECT_FREQUENCY_IN_SECONDS = 1 ; // Min frequency of connection attempts
static const int MAX_CONNECT_ATTEMPTS = 5 ;
static const int BANDWIDTH_REPORTING_MAX = 10240 ; // make bps to report receiving (clamp if higher). For quantizing
static const int BANDWIDTH_REPORTING_BITS = 16 ; // number of bits to use for bandwidth reporting
static const int MAX_BPS_HISTORY = 32 ; // size of outgoing bps history to maintain for each client
static const int MAX_SNAP_SIZE = idPacketProcessor : : MAX_MSG_SIZE ;
static const int MAX_SNAPSHOT_QUEUE = 64 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int OOB_HELLO = 0 ;
static const int OOB_GOODBYE = 1 ;
static const int OOB_GOODBYE_W_PARTY = 2 ;
static const int OOB_GOODBYE_FULL = 3 ;
static const int OOB_RESOURCE_LIST = 4 ;
static const int OOB_VOICE_AUDIO = 5 ;
static const int OOB_MATCH_QUERY = 6 ;
static const int OOB_MATCH_QUERY_ACK = 7 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int OOB_SYSTEMLINK_QUERY = 8 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int OOB_MIGRATE_INVITE = 9 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int OOB_BANDWIDTH_TEST = 10 ;
2012-11-28 15:47:07 +00:00
enum connectionState_t
{
2012-11-26 18:58:24 +00:00
CONNECTION_FREE = 0 , // Free peer slot
CONNECTION_CONNECTING = 1 , // Waiting for response from host for initial connection
CONNECTION_ESTABLISHED = 2 , // Connection is established and active
} ;
2012-11-28 15:47:07 +00:00
struct peer_t
{
peer_t ( )
{
2012-11-26 18:58:24 +00:00
loaded = false ;
inGame = false ;
networkChecksum = 0 ;
lastSnapTime = 0 ;
snapHz = 0.0f ;
numResources = 0 ;
lastHeartBeat = 0 ;
connectionState = CONNECTION_FREE ;
packetProc = NULL ;
snapProc = NULL ;
nextPing = 0 ; // do it asap
lastPingRtt = 0 ;
sessionID = idPacketProcessor : : SESSION_ID_INVALID ;
startResourceLoadTime = 0 ;
nextThrottleCheck = 0 ;
maxSnapQueueSize = 0 ;
throttledSnapRate = 0 ;
pauseSnapshots = false ;
receivedBps = - 1.0f ;
maxSnapBps = - 1.0f ;
receivedThrottle = 0 ;
receivedThrottleTime = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
throttleSnapsForXSeconds = 0 ;
recoverPing = 0 ;
failedPingRecoveries = 0 ;
rightBeforeSnapsPing = 0 ;
bandwidthTestLastSendTime = 0 ;
bandwidthSequenceNum = 0 ;
bandwidthTestBytes = 0 ;
bandwidthChallengeStartSendTime = 0 ;
bandwidthChallengeResults = false ;
bandwidthChallengeSendComplete = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
numSnapsSent = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
ResetConnectState ( ) ;
} ;
2012-11-28 15:47:07 +00:00
void ResetConnectState ( )
{
2012-11-26 18:58:24 +00:00
lastResourceTime = 0 ;
lastSnapTime = 0 ;
snapHz =
2012-11-28 15:47:07 +00:00
lastProcTime = 0 ;
2012-11-26 18:58:24 +00:00
lastInBandProcTime = 0 ;
lastFragmentSendTime = 0 ;
needToSubmitPendingSnap = false ;
lastSnapJobTime = true ;
startResourceLoadTime = 0 ;
receivedBps = - 1.0 ;
maxSnapBps = - 1.0f ;
receivedThrottle = 0 ;
receivedThrottleTime = 0 ;
throttleSnapsForXSeconds = 0 ;
recoverPing = 0 ;
failedPingRecoveries = 0 ;
rightBeforeSnapsPing = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bandwidthTestLastSendTime = 0 ;
bandwidthSequenceNum = 0 ;
bandwidthTestBytes = 0 ;
bandwidthChallengeStartSendTime = 0 ;
bandwidthChallengeResults = false ;
bandwidthChallengeSendComplete = false ;
memset ( sentBpsHistory , 0 , sizeof ( sentBpsHistory ) ) ;
receivedBpsIndex = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
debugGraphs . Clear ( ) ;
}
2012-11-28 15:47:07 +00:00
void ResetAllData ( )
{
2012-11-26 18:58:24 +00:00
ResetConnectState ( ) ;
ResetMatchData ( ) ;
}
2012-11-28 15:47:07 +00:00
void ResetMatchData ( )
{
2012-11-26 18:58:24 +00:00
loaded = false ;
networkChecksum = 0 ;
inGame = false ;
numResources = 0 ;
needToSubmitPendingSnap = false ;
throttledSnapRate = 0 ;
maxSnapQueueSize = 0 ;
receivedBpsIndex = - 1 ;
numSnapsSent = 0 ;
pauseSnapshots = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Reset the snapshot processor
2012-11-28 15:47:07 +00:00
if ( snapProc ! = NULL )
{
2012-11-26 18:58:24 +00:00
snapProc - > Reset ( false ) ;
}
}
2012-11-28 15:47:07 +00:00
void Print ( )
{
idLib : : Printf ( " lastResourceTime: %d \n " , lastResourceTime ) ;
idLib : : Printf ( " lastSnapTime: %d \n " , lastSnapTime ) ;
idLib : : Printf ( " lastProcTime: %d \n " , lastProcTime ) ;
idLib : : Printf ( " lastInBandProcTime: %d \n " , lastInBandProcTime ) ;
idLib : : Printf ( " lastFragmentSendTime: %d \n " , lastFragmentSendTime ) ;
idLib : : Printf ( " needToSubmitPendingSnap: %d \n " , needToSubmitPendingSnap ) ;
idLib : : Printf ( " lastSnapJobTime: %d \n " , lastSnapJobTime ) ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
bool IsActive ( ) const
{
return connectionState ! = CONNECTION_FREE ;
}
bool IsConnected ( ) const
{
return connectionState = = CONNECTION_ESTABLISHED ;
}
2012-11-26 18:58:24 +00:00
connectionState_t GetConnectionState ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
connectionState_t connectionState ;
bool loaded ; // true if this peer has finished loading the map
2012-11-28 15:47:07 +00:00
bool inGame ; // true if this peer received the first snapshot, and is in-game
2012-11-26 18:58:24 +00:00
int lastSnapTime ; // Last time a snapshot was sent on the network to this peer
float snapHz ;
int lastProcTime ; // Used to determine when a packet was processed for sending to this peer
int lastInBandProcTime ; // Last time a in-band packet was processed for sending
int lastFragmentSendTime ; // Last time a fragment was sent out (fragments are processed msg's, waiting to be fully sent)
unsigned long networkChecksum ; // Checksum used to determine if a peer loaded the network resources the EXACT same as the server did
int pauseSnapshots ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lobbyAddress_t address ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numResources ; // number of network resources we know the peer has
2012-11-28 15:47:07 +00:00
idPacketProcessor * packetProc ; // Processes packets for this peer
idSnapshotProcessor * snapProc ; // Processes snapshots for this peer
idStaticList < idDebugGraph * , 4 > debugGraphs ; //
2012-11-26 18:58:24 +00:00
int lastResourceTime ; // Used to throttle the sending of resources
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int lastHeartBeat ;
int nextPing ; // next Sys_Milliseconds when I'll send this peer a RELIABLE_PING
int lastPingRtt ;
bool needToSubmitPendingSnap ;
int lastSnapJobTime ; // Last time a snapshot was sent to the joblist for this peer
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int startResourceLoadTime ; // Used to determine how long a peer has been loading resources
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int maxSnapQueueSize ; // how big has the snap queue gotten?
int throttledSnapRate ; // effective snap rate for this peer
int nextThrottleCheck ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int numSnapsSent ;
float sentBpsHistory [ MAX_BPS_HISTORY ] ;
int receivedBpsIndex ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
float receivedBps ; // peer's reported bps (they tell us their effective downstream)
float maxSnapBps ;
2012-11-28 15:47:07 +00:00
float receivedThrottle ; // amount of accumlated time this client has been lagging behind
2012-11-26 18:58:24 +00:00
int receivedThrottleTime ; // last time we did received based throttle calculations
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int throttleSnapsForXSeconds ;
int recoverPing ;
int failedPingRecoveries ;
int rightBeforeSnapsPing ;
int bandwidthChallengeStartSendTime ; // time we sent first packet of bw challenge to this peer
int bandwidthTestLastSendTime ; // last time in MS we sent them a bw challenge packet
int bandwidthTestBytes ; // used to measure number of bytes we sent them
int bandwidthSequenceNum ; // number of challenge sequences we sent them
bool bandwidthChallengeResults ; // we got results back
bool bandwidthChallengeSendComplete ; // we finished sending everything
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idPacketProcessor : : sessionId_t sessionID ;
} ;
2012-11-28 15:47:07 +00:00
const char * GetLobbyName ( )
{
switch ( lobbyType )
{
case TYPE_PARTY :
return " TYPE_PARTY " ;
case TYPE_GAME :
return " TYPE_GAME " ;
case TYPE_GAME_STATE :
return " TYPE_GAME_STATE " ;
2012-11-26 18:58:24 +00:00
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
return " LOBBY_INVALID " ;
}
2012-11-28 15:47:07 +00:00
virtual lobbyUserID_t AllocLobbyUserSlotForBot ( const char * botName ) ; // find a open user slot for the bot, and return the userID.
2012-11-26 18:58:24 +00:00
virtual void RemoveBotFromLobbyUserList ( lobbyUserID_t lobbyUserID ) ; // release the session user slot, so that it can be claimed by a player, etc.
virtual bool GetLobbyUserIsBot ( lobbyUserID_t lobbyUserID ) const ; // check to see if the lobby user is a bot or not
2012-11-28 15:47:07 +00:00
virtual int GetNumLobbyUsers ( ) const
{
return userList . Num ( ) ;
}
2012-11-26 18:58:24 +00:00
virtual int GetNumActiveLobbyUsers ( ) const ;
virtual bool AllPeersInGame ( ) const ;
2012-11-28 15:47:07 +00:00
lobbyUser_t * GetLobbyUser ( int index )
{
return ( index > = 0 & & index < GetNumLobbyUsers ( ) ) ? userList [ index ] : NULL ;
}
const lobbyUser_t * GetLobbyUser ( int index ) const
{
return ( index > = 0 & & index < GetNumLobbyUsers ( ) ) ? userList [ index ] : NULL ;
}
virtual bool IsLobbyUserConnected ( int index ) const
{
return ! IsLobbyUserDisconnected ( index ) ;
}
2012-11-26 18:58:24 +00:00
virtual int PeerIndexFromLobbyUser ( lobbyUserID_t lobbyUserID ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
virtual int GetPeerTimeSinceLastPacket ( int peerIndex ) const ;
2012-11-28 15:47:07 +00:00
virtual int PeerIndexForHost ( ) const
{
return host ;
}
virtual int PeerIndexOnHost ( ) const
{
return peerIndexOnHost ; // Returns -1 if we are the host
}
virtual const idMatchParameters & GetMatchParms ( ) const
{
return parms ;
}
2012-11-26 18:58:24 +00:00
lobbyType_t GetActingGameStateLobbyType ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// If IsHost is true, we are a host accepting connections from peers
2012-11-28 15:47:07 +00:00
bool IsHost ( ) const
{
return isHost ;
}
2012-11-26 18:58:24 +00:00
// If IsPeer is true, we are a peer, with an active connection to a host
2012-11-28 15:47:07 +00:00
bool IsPeer ( ) const
{
if ( host = = - 1 )
{
2012-11-26 18:58:24 +00:00
return false ; // Can't possibly be a peer if we haven't setup a host
}
assert ( ! IsHost ( ) ) ;
return peers [ host ] . IsConnected ( ) ;
}
2012-11-28 15:47:07 +00:00
bool IsConnectingPeer ( ) const
{
if ( host = = - 1 )
{
2012-11-26 18:58:24 +00:00
return false ; // Can't possibly be a peer if we haven't setup a host
}
assert ( ! IsHost ( ) ) ;
return peers [ host ] . connectionState = = CONNECTION_CONNECTING ;
}
// IsRunningAsHostOrPeer means we are either an active host, and can accept connections from peers, or we are a peer with an active connection to a host
2012-11-28 15:47:07 +00:00
bool IsRunningAsHostOrPeer ( ) const
{
return IsHost ( ) | | IsPeer ( ) ;
}
bool IsLobbyActive ( ) const
{
return IsRunningAsHostOrPeer ( ) ;
}
struct reliablePlayerToPlayerHeader_t
{
2012-11-26 18:58:24 +00:00
int fromSessionUserIndex ;
int toSessionUserIndex ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
reliablePlayerToPlayerHeader_t ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Both read and write return false if the data is invalid.
// The state of the msg and object are undefined if false is returned.
2012-11-28 15:47:07 +00:00
// The network packets contain userIds, and Read/Write will translate from userId to a
// sessionUserIndex. The sessionUserIndex should be the same on all peers, but the
2012-11-26 18:58:24 +00:00
// userId has to be used in case the target player quits while the message is on the
// wire from the originating peer to the server.
2012-11-28 15:47:07 +00:00
bool Read ( idLobby * lobby , idBitMsg & msg ) ;
bool Write ( idLobby * lobby , idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int GetTotalOutgoingRate ( ) ; // returns total instant outgoing bandwidth in B/s
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//private:
public : // Turning this on for now, for the sake of getting this up and running to see where things are
// State functions
void State_Idle ( ) ;
void State_Create_Lobby_Backend ( ) ;
void State_Searching ( ) ;
void State_Obtaining_Address ( ) ;
void State_Finalize_Connect ( ) ;
void State_Connect_Hello_Wait ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void SetState ( lobbyState_t newState ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void StartCreating ( ) ;
2012-11-28 15:47:07 +00:00
int FindPeer ( const lobbyAddress_t & remoteAddress , idPacketProcessor : : sessionId_t sessionID , bool ignoreSessionID = false ) ;
int FindAnyPeer ( const lobbyAddress_t & remoteAddress ) const ;
2012-11-26 18:58:24 +00:00
int FindFreePeer ( ) const ;
2012-11-28 15:47:07 +00:00
int AddPeer ( const lobbyAddress_t & remoteAddress , idPacketProcessor : : sessionId_t sessionID ) ;
2012-11-26 18:58:24 +00:00
void DisconnectPeerFromSession ( int p ) ;
void SetPeerConnectionState ( int p , connectionState_t newState , bool skipGoodbye = false ) ;
void DisconnectAllPeers ( ) ;
2012-11-28 15:47:07 +00:00
virtual void SendReliable ( int type , idBitMsg & msg , bool callReceiveReliable = true , peerMask_t sessionUserMask = MAX_UNSIGNED_TYPE ( peerMask_t ) ) ;
virtual void SendReliableToLobbyUser ( lobbyUserID_t lobbyUserID , int type , idBitMsg & msg ) ;
virtual void SendReliableToHost ( int type , idBitMsg & msg ) ;
void SendGoodbye ( const lobbyAddress_t & remoteAddress , bool wasFull = false ) ;
void QueueReliableMessage ( int peerNum , byte type )
{
QueueReliableMessage ( peerNum , type , NULL , 0 ) ;
}
void QueueReliableMessage ( int p , byte type , const byte * data , int dataLen ) ;
2012-11-26 18:58:24 +00:00
virtual int GetNumConnectedPeers ( ) const ;
virtual int GetNumConnectedPeersInGame ( ) const ;
void SendMatchParmsToPeers ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static bool IsReliablePlayerToPlayerType ( byte type ) ;
2012-11-28 15:47:07 +00:00
void HandleReliablePlayerToPlayerMsg ( int peerNum , idBitMsg & msg , int type ) ;
void HandleReliablePlayerToPlayerMsg ( const reliablePlayerToPlayerHeader_t & info , idBitMsg & msg , int reliableType ) ;
void SendConnectionLess ( const lobbyAddress_t & remoteAddress , byte type )
{
SendConnectionLess ( remoteAddress , type , NULL , 0 ) ;
}
void SendConnectionLess ( const lobbyAddress_t & remoteAddress , byte type , const byte * data , int dataLen ) ;
2012-11-26 18:58:24 +00:00
void SendConnectionRequest ( ) ;
2012-11-28 15:47:07 +00:00
void ConnectTo ( const lobbyConnectInfo_t & connectInfo , bool fromInvite ) ;
void HandleGoodbyeFromPeer ( int peerNum , lobbyAddress_t & remoteAddress , int msgType ) ;
2012-11-26 18:58:24 +00:00
void HandleConnectionAttemptFailed ( ) ;
bool ConnectToNextSearchResult ( ) ;
2012-11-28 15:47:07 +00:00
bool CheckVersion ( idBitMsg & msg , lobbyAddress_t peerAddress ) ;
bool VerifyNumConnectingUsers ( idBitMsg & msg ) ;
bool VerifyLobbyUserIDs ( idBitMsg & msg ) ;
int HandleInitialPeerConnection ( idBitMsg & msg , const lobbyAddress_t & peerAddress , int peerNum ) ;
2012-11-26 18:58:24 +00:00
void InitStateLobbyHost ( ) ;
2012-11-28 15:47:07 +00:00
void SendMembersToLobby ( lobbyType_t destLobbyType , const lobbyConnectInfo_t & connectInfo , bool waitForOtherMembers ) ;
void SendMembersToLobby ( idLobby & destLobby , bool waitForOtherMembers ) ;
void SendPeerMembersToLobby ( int peerIndex , lobbyType_t destLobbyType , const lobbyConnectInfo_t & connectInfo , bool waitForOtherMembers ) ;
2012-11-26 18:58:24 +00:00
void SendPeerMembersToLobby ( int peerIndex , lobbyType_t destLobbyType , bool waitForOtherMembers ) ;
void NotifyPartyOfLeavingGameLobby ( ) ;
uint32 GetPartyTokenAsHost ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
virtual void DrawDebugNetworkHUD ( ) const ;
virtual void DrawDebugNetworkHUD2 ( ) const ;
virtual void DrawDebugNetworkHUD_ServerSnapshotMetrics ( bool draw ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void CheckHeartBeats ( ) ;
bool IsLosingConnectionToHost ( ) const ;
bool IsMigratedStatsGame ( ) const ;
bool ShouldRelaunchMigrationGame ( ) const ;
bool ShouldShowMigratingDialog ( ) const ;
bool IsMigrating ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Pings
2012-11-28 15:47:07 +00:00
struct pktPing_t
{
2012-11-26 18:58:24 +00:00
int timestamp ;
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void PingPeers ( ) ;
void SendPingValues ( ) ;
void PumpPings ( ) ;
2012-11-28 15:47:07 +00:00
void HandleReliablePing ( int p , idBitMsg & msg ) ;
void HandlePingReply ( int p , const pktPing_t & ping ) ;
void HandlePingValues ( idBitMsg & msg ) ;
void HandleBandwidhTestValue ( int p , idBitMsg & msg ) ;
void HandleMigrationGameData ( idBitMsg & msg ) ;
void HandleHeadsetStateChange ( int fromPeer , idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
bool SendAnotherFragment ( int p ) ;
bool CanSendMoreData ( int p ) ;
2012-11-28 15:47:07 +00:00
void ProcessOutgoingMsg ( int p , const void * data , int size , bool isOOB , int userData ) ;
2012-11-26 18:58:24 +00:00
void ResendReliables ( int p ) ;
void PumpPackets ( ) ;
2012-11-28 15:47:07 +00:00
void UpdateMatchParms ( const idMatchParameters & p ) ;
2012-11-26 18:58:24 +00:00
// SessionID helpers
idPacketProcessor : : sessionId_t EncodeSessionID ( uint32 key ) const ;
2012-11-28 15:47:07 +00:00
void DecodeSessionID ( idPacketProcessor : : sessionId_t sessionID , uint32 & key ) const ;
2012-11-26 18:58:24 +00:00
idPacketProcessor : : sessionId_t GenerateSessionID ( ) const ;
bool SessionIDCanBeUsedForInBand ( idPacketProcessor : : sessionId_t sessionID ) const ;
idPacketProcessor : : sessionId_t IncrementSessionID ( idPacketProcessor : : sessionId_t sessionID ) const ;
2012-11-28 15:47:07 +00:00
void HandleHelloAck ( int p , idBitMsg & msg ) ;
virtual const char * GetLobbyUserName ( lobbyUserID_t lobbyUserID ) const ;
2012-11-26 18:58:24 +00:00
virtual bool GetLobbyUserWeaponAutoReload ( lobbyUserID_t lobbyUserID ) const ;
virtual bool GetLobbyUserWeaponAutoSwitch ( lobbyUserID_t lobbyUserID ) const ;
virtual int GetLobbyUserSkinIndex ( lobbyUserID_t lobbyUserID ) const ;
virtual int GetLobbyUserLevel ( lobbyUserID_t lobbyUserID ) const ;
virtual int GetLobbyUserQoS ( lobbyUserID_t lobbyUserID ) const ;
virtual int GetLobbyUserTeam ( lobbyUserID_t lobbyUserID ) const ;
virtual bool SetLobbyUserTeam ( lobbyUserID_t lobbyUserID , int teamNumber ) ;
virtual int GetLobbyUserPartyToken ( lobbyUserID_t lobbyUserID ) const ;
2012-11-28 15:47:07 +00:00
virtual idPlayerProfile * GetProfileFromLobbyUser ( lobbyUserID_t lobbyUserID ) ;
virtual idLocalUser * GetLocalUserFromLobbyUser ( lobbyUserID_t lobbyUserID ) ;
2012-11-26 18:58:24 +00:00
virtual int GetNumLobbyUsersOnTeam ( int teamNumber ) const ;
2012-11-28 15:47:07 +00:00
const char * GetPeerName ( int peerNum ) const ;
virtual const char * GetHostUserName ( ) const ;
void HandleReliableMsg ( int p , idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
// Bandwidth / Qos / Throttling
void BeginBandwidthTest ( ) ;
bool BandwidthTestStarted ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void ServerUpdateBandwidthTest ( ) ;
void ClientUpdateBandwidthTest ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void ThrottlePeerSnapRate ( int peerNum ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// sys_session_instance_users.cpp
//
2012-11-28 15:47:07 +00:00
lobbyUser_t * AllocUser ( const lobbyUser_t & defaults ) ;
void FreeUser ( lobbyUser_t * user ) ;
bool VerifyUser ( const lobbyUser_t * lobbyUser ) const ;
2012-11-26 18:58:24 +00:00
void FreeAllUsers ( ) ;
2012-11-28 15:47:07 +00:00
void RegisterUser ( lobbyUser_t * lobbyUser ) ;
void UnregisterUser ( lobbyUser_t * lobbyUser ) ;
bool IsSessionUserLocal ( const lobbyUser_t * lobbyUser ) const ;
2012-11-26 18:58:24 +00:00
bool IsSessionUserIndexLocal ( int i ) const ;
int GetLobbyUserIndexByID ( lobbyUserID_t lobbyUserId , bool ignoreLobbyType = false ) const ;
2012-11-28 15:47:07 +00:00
lobbyUser_t * GetLobbyUserByID ( lobbyUserID_t lobbyUserId , bool ignoreLobbyType = false ) ;
2012-11-26 18:58:24 +00:00
// Helper function to create a lobby user from a local user
2012-11-28 15:47:07 +00:00
lobbyUser_t CreateLobbyUserFromLocalUser ( const idLocalUser * localUser ) ;
2012-11-26 18:58:24 +00:00
// This function is designed to initialize the session users of type lobbyType (TYPE_GAME or TYPE_PARTY)
// to the current list of local users that are being tracked by the sign-in manager
void InitSessionUsersFromLocalUsers ( bool onlineMatch ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Convert an local userhandle to a session user (-1 if there is no session user with this handle)
int GetLobbyUserIndexByLocalUserHandle ( const localUserHandle_t localUserHandle ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// This takes a session user, and converts to a controller user
2012-11-28 15:47:07 +00:00
idLocalUser * GetLocalUserFromLobbyUserIndex ( int lobbyUserIndex ) ;
2012-11-26 18:58:24 +00:00
// Takes a controller user, and converts to a session user (will return NULL if there is no session user for this controller user)
2012-11-28 15:47:07 +00:00
lobbyUser_t * GetSessionUserFromLocalUser ( const idLocalUser * controller ) ;
2012-11-26 18:58:24 +00:00
void RemoveUsersWithDisconnectedPeers ( ) ;
2012-11-28 15:47:07 +00:00
void RemoveSessionUsersByIDList ( idList < lobbyUserID_t > & usersToRemoveByID ) ;
2012-11-26 18:58:24 +00:00
void SendNewUsersToPeers ( int skipPeer , int userStart , int numUsers ) ;
void SendPeersMicStatusToNewUsers ( int peerNumber ) ;
2012-11-28 15:47:07 +00:00
void AddUsersFromMsg ( idBitMsg & msg , int fromPeer ) ;
void UpdateSessionUserOnPeers ( idBitMsg & msg ) ;
void HandleUpdateSessionUser ( idBitMsg & msg ) ;
void CreateUserUpdateMessage ( int userIndex , idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
void UpdateLocalSessionUsers ( ) ;
int PeerIndexForSessionUserIndex ( int sessionUserIndex ) const ;
2012-11-28 15:47:07 +00:00
void HandleUserConnectFailure ( int p , idBitMsg & inMsg , int reliableType ) ;
void ProcessUserDisconnectMsg ( idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
void CompactDisconnectedUsers ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Sends a request to the host to join a local user to a session
2012-11-28 15:47:07 +00:00
void RequestLocalUserJoin ( idLocalUser * localUser ) ;
2012-11-26 18:58:24 +00:00
// Sends a request to the host to remove a session user from the session
void RequestSessionUserDisconnect ( int sessionUserIndex ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// This function sycs the session users with the current list of of local users on the signin manager.
// It will remove the session users that are either no longer on the signin manager, or it
// will remove them if they are no longer allowed to be in the session.
// If it finds a local users that are not in a particular session, it will add that user if allowed.
void SyncLobbyUsersWithLocalUsers ( bool allowJoin , bool onlineMatch ) ;
2012-11-28 15:47:07 +00:00
bool ValidateConnectedUser ( const lobbyUser_t * user ) const ;
2012-11-26 18:58:24 +00:00
virtual bool IsLobbyUserDisconnected ( int userIndex ) const ;
virtual bool IsLobbyUserValid ( lobbyUserID_t lobbyUserID ) const ;
virtual bool IsLobbyUserLoaded ( lobbyUserID_t lobbyUserID ) const ;
virtual bool LobbyUserHasFirstFullSnap ( lobbyUserID_t lobbyUserID ) const ;
virtual lobbyUserID_t GetLobbyUserIdByOrdinal ( int userIndex ) const ;
virtual int GetLobbyUserIndexFromLobbyUserID ( lobbyUserID_t lobbyUserID ) const ;
virtual void EnableSnapshotsForLobbyUser ( lobbyUserID_t lobbyUserID ) ;
2012-11-28 15:47:07 +00:00
virtual bool IsPeerDisconnected ( int peerIndex ) const
{
return ! peers [ peerIndex ] . IsConnected ( ) ;
}
2012-11-26 18:58:24 +00:00
float GetAverageSessionLevel ( ) ;
float GetAverageLocalUserLevel ( bool onlineOnly ) ;
2012-11-28 15:47:07 +00:00
void QueueReliablePlayerToPlayerMessage ( int fromSessionUserIndex , int toSessionUserIndex , reliablePlayerToPlayer_t type , const byte * data , int dataLen ) ;
2012-11-26 18:58:24 +00:00
virtual void KickLobbyUser ( lobbyUserID_t lobbyUserID ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int GetNumConnectedUsers ( ) const ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//
// sys_session_instance_migrate.cpp
//
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool IsBetterHost ( int ping1 , lobbyUserID_t userId1 , int ping2 , lobbyUserID_t userId2 ) ;
2012-11-28 15:47:07 +00:00
int FindMigrationInviteIndex ( lobbyAddress_t & address ) ;
2012-11-26 18:58:24 +00:00
void UpdateHostMigration ( ) ;
void BuildMigrationInviteList ( bool inviteOldHost ) ;
void PickNewHost ( bool forceMe = false , bool inviteOldHost = false ) ;
void PickNewHostInternal ( bool forceMe , bool inviteOldHost ) ;
void BecomeHost ( ) ;
void EndMigration ( ) ;
void ResetAllMigrationState ( ) ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
void SendMigrationGameData ( ) ;
2012-11-28 15:47:07 +00:00
bool GetMigrationGameData ( idBitMsg & msg , bool reading ) ;
bool GetMigrationGameDataUser ( lobbyUserID_t lobbyUserID , idBitMsg & msg , bool reading ) ;
2012-11-26 18:58:24 +00:00
//
// Snapshots
// sys_session_instance_snapshot.cpp
//
void UpdateSnaps ( ) ;
bool SendCompletedSnaps ( ) ;
bool SendResources ( int p ) ;
bool SubmitPendingSnap ( int p ) ;
void SendCompletedPendingSnap ( int p ) ;
void CheckPeerThrottle ( int p ) ;
void ApplySnapshotDelta ( int p , int snapshotNumber ) ;
bool ApplySnapshotDeltaInternal ( int p , int snapshotNumber ) ;
2012-11-28 15:47:07 +00:00
void SendSnapshotToPeer ( idSnapShot & ss , int p ) ;
2012-11-26 18:58:24 +00:00
bool AllPeersHaveBaseState ( ) ;
void ThrottleSnapsForXSeconds ( int p , int seconds , bool recoverPing ) ;
bool FirstSnapHasBeenSent ( int p ) ;
virtual bool EnsureAllPeersHaveBaseState ( ) ;
virtual bool AllPeersHaveStaleSnapObj ( int objId ) ;
virtual bool AllPeersHaveExpectedSnapObj ( int objId ) ;
virtual void MarkSnapObjDeleted ( int objId ) ;
virtual void RefreshSnapObj ( int objId ) ;
void ResetBandwidthStats ( ) ;
void DetectSaturation ( int p ) ;
2012-11-28 15:47:07 +00:00
virtual void AddSnapObjTemplate ( int objID , idBitMsg & msg ) ;
2012-11-26 18:58:24 +00:00
static const int MAX_PEERS = MAX_PLAYERS ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------
// Pings
//------------------------
2012-11-28 15:47:07 +00:00
struct pktPingValues_t
{
2012-11-26 18:58:24 +00:00
idArray < short , MAX_PEERS > pings ;
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int PING_INTERVAL_MS = 3000 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int lastPingValuesRecvTime ; // so clients can display something when server stops pinging
int nextSendPingValuesTime ; // the next time to send RELIABLE_PING_VALUES
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int MIGRATION_GAME_DATA_INTERVAL_MS = 1000 ;
int nextSendMigrationGameTime ; // when to send next migration game data
int nextSendMigrationGamePeer ; // who to send next migration game data to
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lobbyType_t lobbyType ;
lobbyState_t state ; // State of this lobby
failedReason_t failedReason ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int host ; // which peer is the host of this type of session (-1 if we are the host)
int peerIndexOnHost ; // -1 if we are the host
lobbyAddress_t hostAddress ; // address of the host for this type of session
bool isHost ; // true if we are the host
2012-11-28 15:47:07 +00:00
idLobbyBackend * lobbyBackend ;
2012-11-26 18:58:24 +00:00
int helloStartTime ; // Used to determine when the first hello was sent
int lastConnectRequest ; // Used to determine when the last hello was sent
int connectionAttempts ; // Number of connection attempts
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool needToDisplayMigrateMsg ; // If true, we migrated as host, so we need to display the msg as soon as the lobby is active
gameDialogMessages_t migrationDlg ; // current migration dialog we should be showing
2012-11-28 15:47:07 +00:00
uint8 migrateMsgFlags ; // cached match flags from the old game we migrated from, so we know what type of msg to display
2012-11-26 18:58:24 +00:00
bool joiningMigratedGame ; // we are joining a migrated game and need to tell the session mgr if we succeed or fail
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// ------------------------
// Bandwidth challenge
// ------------------------
int bandwidthChallengeEndTime ; // When the challenge will end/timeout
int bandwidthChallengeStartTime ; // time in MS the challenge started
bool bandwidthChallengeFinished ; // (HOST) test is finished and we received results back from all peers (or timed out)
int bandwidthChallengeNumGoodSeq ; // (PEER) num of good, in order packets we recevieved
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
int lastSnapBspHistoryUpdateSequence ;
2012-11-28 15:47:07 +00:00
void SaveDisconnectedUser ( const lobbyUser_t & user ) ; // This is needed to get the a user's gamertag after disconnection.
idSessionCallbacks * sessionCB ;
enum migrationState_t
{
2012-11-26 18:58:24 +00:00
MIGRATE_NONE ,
MIGRATE_PICKING_HOST ,
MIGRATE_BECOMING_HOST ,
} ;
2012-11-28 15:47:07 +00:00
struct migrationInvite_t
{
migrationInvite_t ( )
{
2012-11-26 18:58:24 +00:00
lastInviteTime = - 1 ;
pingMs = 0 ;
migrationGameData = - 1 ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
lobbyAddress_t address ;
int pingMs ;
lobbyUserID_t userId ;
int lastInviteTime ;
int migrationGameData ;
} ;
2012-11-28 15:47:07 +00:00
struct migrationInfo_t
{
migrationInfo_t ( )
{
2012-11-26 18:58:24 +00:00
state = MIGRATE_NONE ;
ourPingMs = 0 ;
ourUserId = lobbyUserID_t ( ) ;
}
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
migrationState_t state ;
idStaticList < migrationInvite_t , MAX_PEERS > invites ;
int migrationStartTime ;
int ourPingMs ;
lobbyUserID_t ourUserId ;
2012-11-28 15:47:07 +00:00
struct persistUntilGameEnds_t
{
persistUntilGameEnds_t ( )
{
2012-11-26 18:58:24 +00:00
Clear ( ) ;
}
2012-11-28 15:47:07 +00:00
void Clear ( )
{
2012-11-26 18:58:24 +00:00
wasMigratedHost = false ;
wasMigratedJoin = false ;
wasMigratedGame = false ;
ourGameData = - 1 ;
hasGameData = false ;
hasRelaunchedMigratedGame = false ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
memset ( gameData , 0 , sizeof ( gameData ) ) ;
memset ( gameDataUser , 0 , sizeof ( gameDataUser ) ) ;
}
2012-11-28 15:47:07 +00:00
int ourGameData ;
2012-11-26 18:58:24 +00:00
bool wasMigratedHost ; // we are hosting a migrated session
bool wasMigratedJoin ; // we joined a migrated session
bool wasMigratedGame ; // If true, we migrated from a game
bool hasRelaunchedMigratedGame ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// A generic blob of data that the gamechallenge (or anything else) can read and write to for host migration
static const int MIGRATION_GAME_DATA_SIZE = 32 ;
byte gameData [ MIGRATION_GAME_DATA_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
static const int MIGRATION_GAME_DATA_USER_SIZE = 64 ;
byte gameDataUser [ MAX_PLAYERS ] [ MIGRATION_GAME_DATA_USER_SIZE ] ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool hasGameData ;
} persistUntilGameEndsData ;
} ;
2012-11-28 15:47:07 +00:00
struct disconnectedUser_t
{
2012-11-26 18:58:24 +00:00
lobbyUserID_t lobbyUserID ; // Locally generated to be unique, and internally keeps the local user handle
char gamertag [ lobbyUser_t : : MAX_GAMERTAG ] ;
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
migrationInfo_t migrationInfo ;
bool showHostLeftTheSession ;
bool connectIsFromInvite ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idList < lobbyConnectInfo_t > searchResults ;
2012-11-28 15:47:07 +00:00
typedef idStaticList < lobbyUser_t * , MAX_PLAYERS > idLobbyUserList ;
2012-11-26 18:58:24 +00:00
typedef idStaticList < lobbyUser_t , MAX_PLAYERS > idLobbyUserPool ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idLobbyUserList userList ; // list of currently connected users to this lobby
idLobbyUserList freeUsers ; // list of free users
idLobbyUserPool userPool ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idList < disconnectedUser_t > disconnectedUsers ; // List of users which were connected, but aren't anymore, for printing their name on the hud
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStaticList < peer_t , MAX_PEERS > peers ; // Unique machines connected to this lobby
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
uint32 partyToken ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idMatchParameters parms ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
bool loaded ; // Used for game sessions, whether this machine is loaded or not
bool respondToArbitrate ; // true when the host has requested us to arbitrate our session (for TYPE_GAME only)
bool everyoneArbitrated ;
bool waitForPartyOk ;
bool startLoadingFromHost ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
//------------------------
// Snapshot jobs
//------------------------
static const int SNAP_OBJ_JOB_MEMORY = 1024 * 128 ; // 128k of obj memory
2012-11-28 15:47:07 +00:00
lzwCompressionData_t * lzwData ; // Shared across all snapshot jobs
uint8 * objMemory ; // Shared across all snapshot jobs
2012-11-26 18:58:24 +00:00
bool haveSubmittedSnaps ; // True if we previously submitted snaps to jobs
2012-11-28 15:47:07 +00:00
idSnapShot * localReadSS ;
struct snapDeltaAck_t
{
2012-11-26 18:58:24 +00:00
int p ;
int snapshotNumber ;
} ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
idStaticList < snapDeltaAck_t , 16 > snapDeltaAckQueue ;
} ;
/*
= = = = = = = = = = = = = = = = = = = = = = = =
idSessionCallbacks
= = = = = = = = = = = = = = = = = = = = = = = =
*/
2012-11-28 15:47:07 +00:00
class idSessionCallbacks
{
2012-11-26 18:58:24 +00:00
public :
2012-11-28 15:47:07 +00:00
virtual idLobby & GetPartyLobby ( ) = 0 ;
virtual idLobby & GetGameLobby ( ) = 0 ;
virtual idLobby & GetActingGameStateLobby ( ) = 0 ;
virtual idLobby * GetLobbyFromType ( idLobby : : lobbyType_t lobbyType ) = 0 ;
2012-11-26 18:58:24 +00:00
virtual int GetUniquePlayerId ( ) const = 0 ;
2012-11-28 15:47:07 +00:00
virtual idSignInManagerBase & GetSignInManager ( ) = 0 ;
virtual void SendRawPacket ( const lobbyAddress_t & to , const void * data , int size , bool useDirectPort ) = 0 ;
virtual bool BecomingHost ( idLobby & lobby ) = 0 ; // Called when a lobby is about to become host
virtual void BecameHost ( idLobby & lobby ) = 0 ; // Called when a lobby becomes a host
virtual bool BecomingPeer ( idLobby & lobby ) = 0 ; // Called when a lobby is about to become peer
virtual void BecamePeer ( idLobby & lobby ) = 0 ; // Called when a lobby becomes a peer
virtual void FailedGameMigration ( idLobby & lobby ) = 0 ;
virtual void MigrationEnded ( idLobby & lobby ) = 0 ;
virtual void GoodbyeFromHost ( idLobby & lobby , int peerNum , const lobbyAddress_t & remoteAddress , int msgType ) = 0 ;
2012-11-26 18:58:24 +00:00
virtual uint32 GetSessionOptions ( ) = 0 ;
2012-11-28 15:47:07 +00:00
virtual bool AnyPeerHasAddress ( const lobbyAddress_t & remoteAddress ) const = 0 ;
2012-11-26 18:58:24 +00:00
virtual idSession : : sessionState_t GetState ( ) const = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
virtual void ClearMigrationState ( ) = 0 ;
// Called when the lobby receives a RELIABLE_ENDMATCH msg
2012-11-28 15:47:07 +00:00
virtual void EndMatchInternal ( bool premature = false ) = 0 ;
2012-11-26 18:58:24 +00:00
// Called when the game lobby receives leaderboard stats
2012-11-28 15:47:07 +00:00
virtual void RecvLeaderboardStats ( idBitMsg & msg ) = 0 ;
2012-11-26 18:58:24 +00:00
// Called once the lobby received its first full snap (used to advance from LOADING to INGAME state)
virtual void ReceivedFullSnap ( ) = 0 ;
2012-11-28 15:47:07 +00:00
2012-11-26 18:58:24 +00:00
// Called when lobby received RELIABLE_PARTY_LEAVE_GAME_LOBBY msg
virtual void LeaveGameLobby ( ) = 0 ;
2012-11-28 15:47:07 +00:00
virtual void PrePickNewHost ( idLobby & lobby , bool forceMe , bool inviteOldHost ) = 0 ;
virtual bool PreMigrateInvite ( idLobby & lobby ) = 0 ;
virtual void HandleOobVoiceAudio ( const lobbyAddress_t & from , const idBitMsg & msg ) = 0 ;
2012-11-26 18:58:24 +00:00
// ConnectAndMoveToLobby is called when the lobby receives a RELIABLE_CONNECT_AND_MOVE_TO_LOBBY
2012-11-28 15:47:07 +00:00
virtual void ConnectAndMoveToLobby ( idLobby : : lobbyType_t destLobbyType , const lobbyConnectInfo_t & connectInfo , bool waitForPartyOk ) = 0 ;
virtual class idVoiceChatMgr * GetVoiceChat ( ) = 0 ;
virtual void HandleServerQueryRequest ( lobbyAddress_t & remoteAddr , idBitMsg & msg , int msgType ) = 0 ;
virtual void HandleServerQueryAck ( lobbyAddress_t & remoteAddr , idBitMsg & msg ) = 0 ;
2012-11-26 18:58:24 +00:00
virtual void HandlePeerMatchParamUpdate ( int peer , int msg ) = 0 ;
2012-11-28 15:47:07 +00:00
virtual idLobbyBackend * CreateLobbyBackend ( const idMatchParameters & p , float skillLevel , idLobbyBackend : : lobbyBackendType_t lobbyType ) = 0 ;
virtual idLobbyBackend * FindLobbyBackend ( const idMatchParameters & p , int numPartyUsers , float skillLevel , idLobbyBackend : : lobbyBackendType_t lobbyType ) = 0 ;
virtual idLobbyBackend * JoinFromConnectInfo ( const lobbyConnectInfo_t & connectInfo , idLobbyBackend : : lobbyBackendType_t lobbyType ) = 0 ;
virtual void DestroyLobbyBackend ( idLobbyBackend * lobbyBackend ) = 0 ;
2012-11-26 18:58:24 +00:00
} ;