// decrement the player count advertised on this session // DWORD XBL_MM_RemovePlayer( bool usePrivateSlot ) { if(!logged_on || !session.Exists()) return -1; // The value we're given only tells us if they were eligble for a private slot when // they joined, but they may have actually ended up in a public slot. As such, this // can get pretty wacky. Oh well. if ( usePrivateSlot && session.PrivateFilled ) { session.PrivateFilled--; session.PrivateOpen++; session.TotalPlayers--; } else { if ( session.PublicFilled ) { session.PublicFilled--; session.PublicOpen++; session.TotalPlayers--; } else { assert( 0 ); } } session.Update(); return 0; }
// increment the player count advertised on this session // DWORD XBL_MM_AddPlayer( bool usePrivateSlot ) { if (!logged_on || !session.Exists()) return -1; // SOF2 had a really bad system that checked for server's friends. We do what // MS says is good - all invites/joins go into private, everyone else goes public. if( usePrivateSlot && session.PrivateOpen ) { session.PrivateFilled++; session.PrivateOpen--; session.TotalPlayers++; } else { // Either joined via matchmaking, or we don't have any more private slots // Give them a public slot. if ( session.PublicOpen ) { session.PublicFilled++; session.PublicOpen--; session.TotalPlayers++; } else { assert( 0 ); } } session.Update(); return 0; }
// Ensure that our session is being advertised correctly // Will update map name after a level change, etc... void XBL_MM_Advertise() { // If not on xboxlive dont post server if(!logged_on) return; if ( session.Exists() ) { // Our session is already being advertised, update it XBL_MM_Update_Session(); } else { // Brand new session XBL_MM_Init_Session(); } }
// SOF2 had some silly two-stage thing. They stored off the session parms here, then used // a couple globals to delay advertisement until later. I'm going to try and avoid that void XBL_MM_Init_Session() { // Fill in # of slots. OpenPublic is total slots, minus one for server, minus # reserved for private session.PrivateFilled = 0; session.PrivateOpen = sv_privateClients->integer; session.PublicFilled = (com_dedicated->integer ? 0 : 1); // Non-dedicated server fills a slot session.PublicOpen = sv_maxclients->integer - (session.PrivateOpen + session.PublicFilled); session.TotalPlayers = session.PublicFilled; // Get current map index, and gametype int index = mapNameToIndex( sv_mapname->string ); if (index == MAP_ARRAY_SIZE) { Com_Error( ERR_FATAL, "Bad map name: %s\n", sv_mapname->string ); } session.CurrentMap = index; session.GameType = sv_gametype->integer; // Copy the host's gamertag to the session name XONLINE_USER* pHostAccount = XBL_GetUserInfo( XBL_GetSelectedAccountIndex() ); WCHAR sessionName[XONLINE_GAMERTAG_SIZE] = { 0 }; if ( pHostAccount ) { charToWchar( sessionName, pHostAccount->szGamertag ); } else { charToWchar( sessionName, "unknown" ); } session.SetSessionName( sessionName ); // All other game options: session.FriendlyFire = g_friendlyFire.integer; session.JediMastery = g_maxForceRank.integer; session.SaberOnly = HasSetSaberOnly(); session.Dedicated = com_dedicated->integer; // Actually create the session. If we don't call Process immediately, it explodes HRESULT hr = session.Create(); if (hr != S_OK) { Com_Error( ERR_DROP, "Failed to create session: 0x%x\n", hr ); } do { if( !XBL_PumpLogon() ) return; hr = session.Process(); } while ( session.IsCreating() ); // VVFIXME - Better error handling if ( !session.Exists() ) { Com_Error( ERR_DROP, "Failed to create session #2: 0x%x\n", hr ); } // Fix for a bug. Server was using Notification API before advertising, so for // the first few seconds, had the wrong sessionID, and thus couldn't invite. // Force an update now: XBL_F_CheckJoinableStatus( true ); }