bool CGameClient::IsHearingClient( int index ) const { if ( IsHLTV() ) return true; if ( index == GetPlayerSlot() ) return m_bVoiceLoopback; CGameClient *pClient = sv.Client( index ); return pClient->m_VoiceStreams.Get( GetPlayerSlot() ) != 0; }
void ServerSession::ClientConnected(Network::Slot slot) { mClientTimeout[slot] = C_TIMEOUT; if (GetPlayerSlot(C_STATUS_OPEN) == C_PLAYER_NONE) { // Refuse the player, since we have too many players mServer->Send(slot, RefuseMessage(RefuseReason::TooManyPlayers)); mClientsToRemove.push_back(slot); } else { // Add client as pending client mPendingClients.push_back(slot); } }
void ServerSession::ClientDisconnected(Network::Slot slot) { PlayerID playerSlot = GetPlayerSlot(slot); if (playerSlot != C_PLAYER_NONE) { // TODO: Think about boot // TODO: Don't think about boot // TODO: Think about timeout? // TODO: Should we think about timeout? // TODO: Don't think about timeout. // TODO: Forget about boot. // TODO: Forget about timeout (keep it in mind, though) // REDO: Think about timeout. // TODO: Ponder meaning of life. // TODO: Give up. Network::RemovePlayerReason::RemovePlayerReason reason = Network::RemovePlayerReason::Left; for (unsigned int i = 0; i < mPlayers.size(); ++i) { if (mPlayers[i] != NULL && mPlayerClients[i] >= 0 && mServer->IsConnected(mPlayerClients[i])) { mServer->Send(mPlayerClients[i], Network::RemovePlayerMessage(playerSlot, reason)); } } if (mSessionNotifiee != NULL) mSessionNotifiee->PlayerDisconnected(playerSlot, mPlayers[playerSlot]->GetName(), reason); SafeDelete(mPlayers[playerSlot]); // Delete player? More proper to make it into an open slot? mPlayerClients[playerSlot] = C_STATUS_OPEN; } else { std::vector<ClientSlot>::iterator it; it = std::find(mPendingClients.begin(), mPendingClients.end(), slot); if (it != mPendingClients.end()) mPendingClients.erase(it); it = std::find(mClientsToRemove.begin(), mClientsToRemove.end(), slot); if (it != mClientsToRemove.end()) mClientsToRemove.erase(it); } }
void ServerSession::HandleJoinMessage(Network::Slot clientSlot, const std::string& name) { bool playerValid = true; RefuseReason::RefuseReason reason; // Find an open slot PlayerID openPlayerID = GetPlayerSlot(C_STATUS_OPEN); if (openPlayerID == C_PLAYER_NONE) { // There are no open slots playerValid = false; reason = RefuseReason::TooManyPlayers; } // If an open slot is found, check the player's name if (playerValid) { for (PlayerID i = 0; i < mPlayers.size(); ++i) { if (mPlayers[i] != NULL && mPlayers[i]->GetName() == name) { playerValid = false; reason = RefuseReason::InvalidName; break; } } } // If the player is valid, add them to the open slot if (playerValid) { mServer->Send(clientSlot, AcceptMessage(mPlayers.size(), openPlayerID)); AddPlayer(openPlayerID, clientSlot, name, 0); } else { // Refuse the player mClientsToRemove.push_back(clientSlot); mServer->Send(clientSlot, RefuseMessage(reason)); } std::vector<ClientSlot>::iterator it = std::find(mPendingClients.begin(), mPendingClients.end(), clientSlot); if (it != mPendingClients.end()) mPendingClients.erase(it); }
void ServerSession::Update(const GameTime& gameTime) { // Update the server mServer->Update(); // Handle all messages Network::SlotMessage message; while ((message = mServer->PopMessage()).mMessage != NULL) { // Get the player this message is about //PlayerID slot = GetPlayerID(message.mSlot); // If we've received a message, update timeout (unless they're marked to be removed) if (std::find(mClientsToRemove.begin(), mClientsToRemove.end(), message.mSlot) == mClientsToRemove.end()) { mClientTimeout[message.mSlot] = C_TIMEOUT; } // Parse the message content switch (message.mMessage->ID()) { case Network::C_MESSAGE_CHAT: { Network::ChatMessage* m = static_cast<Network::ChatMessage*>(message.mMessage); HandleChatMessage(m->mSourceID, m->mTargetID, m->mRecipient, m->mMessage); } break; case Network::C_MESSAGE_JOIN: { Network::JoinMessage* m = static_cast<Network::JoinMessage*>(message.mMessage); HandleJoinMessage(message.mSlot, m->mName); } break; case Network::C_MESSAGE_LEAVE_GAME: { Network::LeaveGameMessage* m = static_cast<Network::LeaveGameMessage*>(message.mMessage); // Do we need this? Notice this on timeout instead? } break; case Network::C_MESSAGE_PLACE_PIECE: { Network::PlacePieceMessage* m = static_cast<Network::PlacePieceMessage*>(message.mMessage); // If the move is valid, add the marker and move to the next player if (mGrid.GetMarkerInCell(m->mX, m->mY) == C_PLAYER_NONE) { if (mCurrentPlayer == m->mPlayerID) { mGrid.AddMarker(Logic::Cell(m->mX, m->mY), m->mPlayerID); if (mSessionNotifiee != NULL) mSessionNotifiee->PlacePiece(m->mPlayerID, Logic::Cell(m->mX, m->mY)); mServer->Send(Network::PlacePieceMessage(m->mPlayerID, m->mX, m->mY, -1)); if (!CheckAndHandleWin()) { mCurrentPlayer = mRuleset->GetNextPlayer(mCurrentPlayer); } } } mServer->Send(Network::TurnMessage(mCurrentPlayer)); } break; case Network::C_MESSAGE_SET_TEAM: { Network::SetTeamMessage* m = static_cast<Network::SetTeamMessage*>(message.mMessage); assert(mPlayers[m->mPlayerID] != NULL); assert(m->mTeam >= C_TEAM_NONE); assert(m->mTeam < 2); if (GetPlayerSlot(message.mSlot) == m->mPlayerID) { mPlayers[m->mPlayerID]->SetTeam(m->mTeam); if (mSessionNotifiee != NULL) mSessionNotifiee->SetTeam(m->mPlayerID, m->mTeam); mServer->Send(Network::SetTeamMessage(m->mPlayerID, m->mTeam)); } } break; case Network::C_MESSAGE_HIGHLIGHT: { Network::HighlightMessage* m = static_cast<Network::HighlightMessage*>(message.mMessage); PlayerID source = GetPlayerSlot(message.mSlot); for (PlayerID s = 0; s < mPlayers.size(); ++s) { if (mPlayers[s]->GetTeam() == mPlayers[source]->GetTeam() && s != source) { if (mPlayerClients[s] >= 0) { // Remote mServer->Send(Network::HighlightMessage(m->mX, m->mY, m->mType)); } else { // Local if (mSessionNotifiee != NULL) mSessionNotifiee->SetHighlightedCell(Logic::Cell(m->mX, m->mY), m->mType); } } } } break; } SafeDelete(message.mMessage); } // Decrease timeout float dt = gameTime.GetTimeSinceLastTick().Seconds; for (TimeoutMap::iterator it = mClientTimeout.begin(); it != mClientTimeout.end(); it++) { it->second -= dt; if (it->second <= 0.0f && mServer->IsConnected(it->first)) { // TODO: Enable timeout again mServer->DisconnectClient(it->first); } } }
bool CGameClient::IsProximityHearingClient( int index ) const { CGameClient *pClient = sv.Client( index ); return pClient->m_VoiceProximity.Get( GetPlayerSlot() ) != 0; }