From d16312111f94075007890ac40a7bc1ab5e6e553e Mon Sep 17 00:00:00 2001 From: lotodore Date: Sun, 7 Oct 2007 18:46:40 +0000 Subject: [PATCH] Finally: User supplied avatars are transfered! They are stored on the server and clients request them if needed. Make sure the server has write access to the cache dir to make it work. --- src/net/clientthread.h | 7 ++++ src/net/common/clientstate.cpp | 30 ++++++++++++++++ src/net/common/clientthread.cpp | 51 ++++++++++++++++++++++++++++ src/net/common/servergamestate.cpp | 5 +++ src/net/common/serverlobbythread.cpp | 27 ++++++++++++++- src/net/serverlobbythread.h | 2 ++ src/net/socket_msg.h | 2 ++ 7 files changed, 123 insertions(+), 1 deletion(-) diff --git a/src/net/clientthread.h b/src/net/clientthread.h index e25734a9..c43fe903 100644 --- a/src/net/clientthread.h +++ b/src/net/clientthread.h @@ -76,6 +76,7 @@ protected: typedef std::map GameInfoMap; typedef std::list > NetPacketList; typedef std::map PlayerInfoMap; + typedef std::map > AvatarDataMap; // Main function of the thread. virtual void Main(); @@ -88,6 +89,10 @@ protected: void SetPlayerInfo(unsigned id, const PlayerInfo &info); void SetNewGameAdmin(unsigned id); + void AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type); + void StoreInTempAvatarData(unsigned playerId, const std::vector &data); + void CompleteTempAvatarData(unsigned playerId); + const ClientContext &GetContext() const; ClientContext &GetContext(); @@ -156,6 +161,8 @@ private: mutable boost::mutex m_playerInfoMapMutex; PlayerIdList m_playerInfoRequestList; + AvatarDataMap m_tempAvatarMap; + unsigned m_curGameId; unsigned m_guiPlayerId; bool m_sessionEstablished; diff --git a/src/net/common/clientstate.cpp b/src/net/common/clientstate.cpp index f04528a8..00241ce8 100644 --- a/src/net/common/clientstate.cpp +++ b/src/net/common/clientstate.cpp @@ -352,6 +352,7 @@ ClientStateStartSession::Process(ClientThread &client) initData.password = context.GetPassword(); initData.playerName = context.GetPlayerName(); string avatarFile = context.GetAvatarFile(); + initData.showAvatar = false; if (!avatarFile.empty()) { if (client.GetAvatarManager().GetHashForAvatar(avatarFile, initData.avatar)) @@ -394,6 +395,16 @@ AbstractClientStateReceiving::Process(ClientThread &client) NetPacketPlayerInfo::Data infoData; tmpPacket->ToNetPacketPlayerInfo()->GetData(infoData); client.SetPlayerInfo(infoData.playerId, infoData.playerInfo); + // Retrieve avatar if needed. + if (infoData.playerInfo.hasAvatar && !client.GetAvatarManager().HasAvatar(infoData.playerInfo.avatar)) + { + boost::shared_ptr retrieveAvatar(new NetPacketRetrieveAvatar); + NetPacketRetrieveAvatar::Data retrieveAvatarData; + retrieveAvatarData.requestId = infoData.playerId; + retrieveAvatarData.avatar = infoData.playerInfo.avatar; + static_cast(retrieveAvatar.get())->SetData(retrieveAvatarData); + client.GetSender().Send(client.GetContext().GetSocket(), retrieveAvatar); + } } else if (tmpPacket->ToNetPacketRemovedFromGame()) { @@ -481,6 +492,24 @@ AbstractClientStateReceiving::Process(ClientThread &client) tmpPacket->ToNetPacketGameListPlayerLeft()->GetData(playerLeftData); client.ModifyGameInfoRemovePlayer(playerLeftData.gameId, playerLeftData.playerId); } + else if (tmpPacket->ToNetPacketAvatarHeader()) + { + NetPacketAvatarHeader::Data headerData; + tmpPacket->ToNetPacketAvatarHeader()->GetData(headerData); + client.AddTempAvatarData(headerData.requestId, headerData.avatarFileSize, headerData.avatarFileType); + } + else if (tmpPacket->ToNetPacketAvatarFile()) + { + NetPacketAvatarFile::Data fileData; + tmpPacket->ToNetPacketAvatarFile()->GetData(fileData); + client.StoreInTempAvatarData(fileData.requestId, fileData.fileData); + } + else if (tmpPacket->ToNetPacketAvatarEnd()) + { + NetPacketAvatarEnd::Data endData; + tmpPacket->ToNetPacketAvatarEnd()->GetData(endData); + client.CompleteTempAvatarData(endData.requestId); + } else if (tmpPacket->ToNetPacketError()) { // Server reported an error. @@ -543,6 +572,7 @@ ClientStateWaitSession::InternalProcess(ClientThread &client, boost::shared_ptr< { client.GetSender().SendLowPrio(client.GetContext().GetSocket(), tmpList); } + // TODO handle error } return retVal; diff --git a/src/net/common/clientthread.cpp b/src/net/common/clientthread.cpp index ee887e75..7177d0b0 100644 --- a/src/net/common/clientthread.cpp +++ b/src/net/common/clientthread.cpp @@ -387,6 +387,7 @@ ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info) boost::mutex::scoped_lock lock(m_playerInfoMapMutex); m_playerInfoMap[id] = info; } + // Update player data for current game. boost::shared_ptr playerData = GetPlayerDataByUniqueId(id); if (playerData.get()) @@ -397,11 +398,15 @@ ClientThread::SetPlayerInfo(unsigned id, const PlayerInfo &info) { string avatarFile; if (GetAvatarManager().GetAvatarFileName(info.avatar, avatarFile)) + { playerData->SetAvatarFile(avatarFile); + } } } + // Notify GUI GetCallback().SignalNetClientPlayerChanged(id, info.playerName); + } void @@ -416,6 +421,52 @@ ClientThread::SetNewGameAdmin(unsigned id) } } +void +ClientThread::AddTempAvatarData(unsigned playerId, unsigned avatarSize, AvatarFileType type) +{ + boost::shared_ptr tmpAvatar(new AvatarData); + tmpAvatar->fileData.reserve(avatarSize); + tmpAvatar->fileType = type; + tmpAvatar->reportedSize = avatarSize; + + m_tempAvatarMap[playerId] = tmpAvatar; +} + +void +ClientThread::StoreInTempAvatarData(unsigned playerId, const vector &data) +{ + AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); + if (pos == m_tempAvatarMap.end()) + throw NetException(ERR_NET_INVALID_REQUEST_ID, 0); + // We trust the server (concerning size of the data). + std::copy(data.begin(), data.end(), back_inserter(pos->second->fileData)); +} + +void +ClientThread::CompleteTempAvatarData(unsigned playerId) +{ + AvatarDataMap::iterator pos = m_tempAvatarMap.find(playerId); + if (pos == m_tempAvatarMap.end()) + throw NetException(ERR_NET_INVALID_REQUEST_ID, 0); + + boost::shared_ptr tmpAvatar = pos->second; + unsigned avatarSize = (unsigned)tmpAvatar->fileData.size(); + if (avatarSize != tmpAvatar->reportedSize) + throw NetException(ERR_NET_WRONG_AVATAR_SIZE, 0); + + PlayerInfo tmpPlayerInfo; + if (!GetCachedPlayerInfo(playerId, tmpPlayerInfo)) + throw NetException(ERR_NET_UNKNOWN_PLAYER_ID, 0); + + GetAvatarManager().StoreAvatarInCache(tmpPlayerInfo.avatar, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize); + // TODO log error + // Free memory. + m_tempAvatarMap.erase(pos); + + // Update player info, but never re-request avatar. + SetPlayerInfo(playerId, tmpPlayerInfo); +} + const ClientContext & ClientThread::GetContext() const { diff --git a/src/net/common/servergamestate.cpp b/src/net/common/servergamestate.cpp index 9bb87b7a..71f80587 100644 --- a/src/net/common/servergamestate.cpp +++ b/src/net/common/servergamestate.cpp @@ -156,6 +156,11 @@ AbstractServerGameStateReceiving::Process(ServerGameThread &server) // Delegate to Lobby. server.GetLobbyThread().HandleGameRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); } + else if (packet->ToNetPacketRetrieveAvatar()) + { + // Delegate to Lobby. + server.GetLobbyThread().HandleGameRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); + } else if (packet->ToNetPacketLeaveCurrentGame()) { server.MoveSessionToLobby(session, NTF_NET_REMOVED_ON_REQUEST); diff --git a/src/net/common/serverlobbythread.cpp b/src/net/common/serverlobbythread.cpp index 113f33f1..fa6cba39 100644 --- a/src/net/common/serverlobbythread.cpp +++ b/src/net/common/serverlobbythread.cpp @@ -169,6 +169,13 @@ ServerLobbyThread::HandleGameRetrievePlayerInfo(SessionWrapper session, const Ne HandleNetPacketRetrievePlayerInfo(session, tmpPacket); } +void +ServerLobbyThread::HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) +{ + // Someone within a game requested an avatar. + HandleNetPacketRetrieveAvatar(session, tmpPacket); +} + void ServerLobbyThread::RemoveGame(unsigned id) { @@ -295,6 +302,8 @@ ServerLobbyThread::ProcessLoop() { if (packet->ToNetPacketRetrievePlayerInfo()) HandleNetPacketRetrievePlayerInfo(session, *packet->ToNetPacketRetrievePlayerInfo()); + else if (packet->ToNetPacketRetrieveAvatar()) + HandleNetPacketRetrieveAvatar(session, *packet->ToNetPacketRetrieveAvatar()); else if (packet->ToNetPacketCreateGame()) HandleNetPacketCreateGame(session, *packet->ToNetPacketCreateGame()); else if (packet->ToNetPacketJoinGame()) @@ -356,7 +365,7 @@ ServerLobbyThread::HandleNetPacketInit(SessionWrapper session, const NetPacketIn m_sessionManager.SetSessionPlayerData(session.sessionData->GetSocket(), tmpPlayerData); session.playerData = tmpPlayerData; - if (!GetAvatarManager().HasAvatar(initData.avatar)) + if (initData.showAvatar && !GetAvatarManager().HasAvatar(initData.avatar)) RequestPlayerAvatar(session); else EstablishSession(session); @@ -416,6 +425,7 @@ ServerLobbyThread::HandleNetPacketAvatarEnd(SessionWrapper session, const NetPac if (avatarSize == tmpAvatar->reportedSize) { GetAvatarManager().StoreAvatarInCache(avatarMD5, tmpAvatar->fileType, &tmpAvatar->fileData[0], avatarSize); + // TODO log error // Free memory. session.playerData->SetNetAvatarData(boost::shared_ptr()); // Init finished - start session. @@ -454,6 +464,21 @@ ServerLobbyThread::HandleNetPacketRetrievePlayerInfo(SessionWrapper session, con // TODO: handle error } +void +ServerLobbyThread::HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket) +{ + NetPacketRetrieveAvatar::Data request; + tmpPacket.GetData(request); + + string tmpFile; + if (GetAvatarManager().GetAvatarFileName(request.avatar, tmpFile)) + { + NetPacketList tmpPackets; + if (GetAvatarManager().AvatarFileToNetPackets(tmpFile, request.requestId, tmpPackets)) + GetSender().SendLowPrio(session.sessionData->GetSocket(), tmpPackets); + } +} + void ServerLobbyThread::HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket) { diff --git a/src/net/serverlobbythread.h b/src/net/serverlobbythread.h index 27015509..7221b943 100644 --- a/src/net/serverlobbythread.h +++ b/src/net/serverlobbythread.h @@ -61,6 +61,7 @@ public: void NotifyStartingGame(unsigned gameId); void HandleGameRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); + void HandleGameRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); void RemoveGame(unsigned id); @@ -88,6 +89,7 @@ protected: void HandleNetPacketAvatarFile(SessionWrapper session, const NetPacketAvatarFile &tmpPacket); void HandleNetPacketAvatarEnd(SessionWrapper session, const NetPacketAvatarEnd &tmpPacket); void HandleNetPacketRetrievePlayerInfo(SessionWrapper session, const NetPacketRetrievePlayerInfo &tmpPacket); + void HandleNetPacketRetrieveAvatar(SessionWrapper session, const NetPacketRetrieveAvatar &tmpPacket); void HandleNetPacketCreateGame(SessionWrapper session, const NetPacketCreateGame &tmpPacket); void HandleNetPacketJoinGame(SessionWrapper session, const NetPacketJoinGame &tmpPacket); void EstablishSession(SessionWrapper session); diff --git a/src/net/socket_msg.h b/src/net/socket_msg.h index 239c4bcd..8b8542e1 100644 --- a/src/net/socket_msg.h +++ b/src/net/socket_msg.h @@ -59,6 +59,8 @@ #define ERR_NET_INVALID_PLAYER_COUNT 115 #define ERR_NET_TOO_MANY_MANUAL_BLINDS 116 #define ERR_NET_BUF_INVALID_SIZE 117 +#define ERR_NET_INVALID_REQUEST_ID 118 +#define ERR_NET_WRONG_AVATAR_SIZE 119 #define ERR_IRC_INTERNAL 151 #define ERR_IRC_CONNECT_FAILED 152