chore: Remove pointer management in PlayerContainer (#1397)

* const

use cbegin, remove null checks

they are references now, they cant be null themselves

Change to reference instead of ptr

Remove getter

const

* allow duplicate request

without the reply you apparently need to re-log for some reason.

Update PlayerContainer.cpp
This commit is contained in:
David Markowitz 2024-01-05 20:42:30 -08:00 committed by GitHub
parent 440dc8b88f
commit 0dc6763a3c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 328 additions and 328 deletions

View File

@ -26,37 +26,36 @@ void ChatIgnoreList::GetIgnoreList(Packet* packet) {
LWOOBJID playerId; LWOOBJID playerId;
inStream.Read(playerId); inStream.Read(playerId);
auto* receiver = Game::playerContainer.GetPlayerData(playerId); auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) { if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId); LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return; return;
} }
if (!receiver->ignoredPlayers.empty()) { if (!receiver.ignoredPlayers.empty()) {
LOG_DEBUG("Player %llu already has an ignore list", playerId); LOG_DEBUG("Player %llu already has an ignore list, but is requesting it again.", playerId);
return; } else {
} auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId));
if (ignoreList.empty()) {
LOG_DEBUG("Player %llu has no ignores", playerId);
return;
}
auto ignoreList = Database::Get()->GetIgnoreList(static_cast<uint32_t>(playerId)); for (auto& ignoredPlayer : ignoreList) {
if (ignoreList.empty()) { receiver.ignoredPlayers.emplace_back(ignoredPlayer.name, ignoredPlayer.id);
LOG_DEBUG("Player %llu has no ignores", playerId); GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
return; GeneralUtils::SetBit(receiver.ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
} }
for (auto& ignoredPlayer : ignoreList) {
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayer.id, ignoredPlayer.name });
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::CHARACTER);
GeneralUtils::SetBit(receiver->ignoredPlayers.back().playerId, eObjectBits::PERSISTENT);
} }
CBITSTREAM; CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::GET_IGNORE); WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::GET_IGNORE);
bitStream.Write<uint8_t>(false); // Probably is Is Free Trial, but we don't care about that bitStream.Write<uint8_t>(false); // Probably is Is Free Trial, but we don't care about that
bitStream.Write<uint16_t>(0); // literally spacing due to struct alignment bitStream.Write<uint16_t>(0); // literally spacing due to struct alignment
bitStream.Write<uint16_t>(receiver->ignoredPlayers.size()); bitStream.Write<uint16_t>(receiver.ignoredPlayers.size());
for (const auto& ignoredPlayer : receiver->ignoredPlayers) { for (const auto& ignoredPlayer : receiver.ignoredPlayers) {
bitStream.Write(ignoredPlayer.playerId); bitStream.Write(ignoredPlayer.playerId);
bitStream.Write(LUWString(ignoredPlayer.playerName, 36)); bitStream.Write(LUWString(ignoredPlayer.playerName, 36));
} }
@ -69,14 +68,14 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
LWOOBJID playerId; LWOOBJID playerId;
inStream.Read(playerId); inStream.Read(playerId);
auto* receiver = Game::playerContainer.GetPlayerData(playerId); auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) { if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId); LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return; return;
} }
constexpr int32_t MAX_IGNORES = 32; constexpr int32_t MAX_IGNORES = 32;
if (receiver->ignoredPlayers.size() > MAX_IGNORES) { if (receiver.ignoredPlayers.size() > MAX_IGNORES) {
LOG_DEBUG("Player %llu has too many ignores", playerId); LOG_DEBUG("Player %llu has too many ignores", playerId);
return; return;
} }
@ -88,21 +87,21 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
std::string toIgnoreStr = toIgnoreName.GetAsString(); std::string toIgnoreStr = toIgnoreName.GetAsString();
CBITSTREAM; CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::ADD_IGNORE); WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::ADD_IGNORE);
// Check if the player exists // Check if the player exists
LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY; LWOOBJID ignoredPlayerId = LWOOBJID_EMPTY;
if (toIgnoreStr == receiver->playerName || toIgnoreStr.find("[GM]") == 0) { if (toIgnoreStr == receiver.playerName || toIgnoreStr.find("[GM]") == 0) {
LOG_DEBUG("Player %llu tried to ignore themselves", playerId); LOG_DEBUG("Player %llu tried to ignore themselves", playerId);
bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR); bitStream.Write(ChatIgnoreList::AddResponse::GENERAL_ERROR);
} else if (std::count(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), toIgnoreStr) > 0) { } else if (std::count(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), toIgnoreStr) > 0) {
LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str()); LOG_DEBUG("Player %llu is already ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED); bitStream.Write(ChatIgnoreList::AddResponse::ALREADY_IGNORED);
} else { } else {
// Get the playerId falling back to query if not online // Get the playerId falling back to query if not online
auto* playerData = Game::playerContainer.GetPlayerData(toIgnoreStr); const auto& playerData = Game::playerContainer.GetPlayerData(toIgnoreStr);
if (!playerData) { if (!playerData) {
// Fall back to query // Fall back to query
auto player = Database::Get()->GetCharacterInfo(toIgnoreStr); auto player = Database::Get()->GetCharacterInfo(toIgnoreStr);
@ -112,7 +111,7 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
ignoredPlayerId = player->id; ignoredPlayerId = player->id;
} }
} else { } else {
ignoredPlayerId = playerData->playerID; ignoredPlayerId = playerData.playerID;
} }
if (ignoredPlayerId != LWOOBJID_EMPTY) { if (ignoredPlayerId != LWOOBJID_EMPTY) {
@ -120,7 +119,7 @@ void ChatIgnoreList::AddIgnore(Packet* packet) {
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER); GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::CHARACTER);
GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT); GeneralUtils::SetBit(ignoredPlayerId, eObjectBits::PERSISTENT);
receiver->ignoredPlayers.push_back(IgnoreData{ ignoredPlayerId, toIgnoreStr }); receiver.ignoredPlayers.emplace_back(toIgnoreStr, ignoredPlayerId);
LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str()); LOG_DEBUG("Player %llu is ignoring %s", playerId, toIgnoreStr.c_str());
bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS); bitStream.Write(ChatIgnoreList::AddResponse::SUCCESS);
@ -141,7 +140,7 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
LWOOBJID playerId; LWOOBJID playerId;
inStream.Read(playerId); inStream.Read(playerId);
auto* receiver = Game::playerContainer.GetPlayerData(playerId); auto& receiver = Game::playerContainer.GetPlayerDataMutable(playerId);
if (!receiver) { if (!receiver) {
LOG("Tried to get ignore list, but player %llu not found in container", playerId); LOG("Tried to get ignore list, but player %llu not found in container", playerId);
return; return;
@ -153,17 +152,17 @@ void ChatIgnoreList::RemoveIgnore(Packet* packet) {
inStream.Read(removedIgnoreName); inStream.Read(removedIgnoreName);
std::string removedIgnoreStr = removedIgnoreName.GetAsString(); std::string removedIgnoreStr = removedIgnoreName.GetAsString();
auto toRemove = std::remove(receiver->ignoredPlayers.begin(), receiver->ignoredPlayers.end(), removedIgnoreStr); auto toRemove = std::remove(receiver.ignoredPlayers.begin(), receiver.ignoredPlayers.end(), removedIgnoreStr);
if (toRemove == receiver->ignoredPlayers.end()) { if (toRemove == receiver.ignoredPlayers.end()) {
LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str()); LOG_DEBUG("Player %llu is not ignoring %s", playerId, removedIgnoreStr.c_str());
return; return;
} }
Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId)); Database::Get()->RemoveIgnore(static_cast<uint32_t>(playerId), static_cast<uint32_t>(toRemove->playerId));
receiver->ignoredPlayers.erase(toRemove, receiver->ignoredPlayers.end()); receiver.ignoredPlayers.erase(toRemove, receiver.ignoredPlayers.end());
CBITSTREAM; CBITSTREAM;
WriteOutgoingReplyHeader(bitStream, receiver->playerID, ChatIgnoreList::Response::REMOVE_IGNORE); WriteOutgoingReplyHeader(bitStream, receiver.playerID, ChatIgnoreList::Response::REMOVE_IGNORE);
bitStream.Write<int8_t>(0); bitStream.Write<int8_t>(0);
LUWString playerNameSend(removedIgnoreStr, 33); LUWString playerNameSend(removedIgnoreStr, 33);

View File

@ -25,7 +25,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
LWOOBJID playerID = 0; LWOOBJID playerID = 0;
inStream.Read(playerID); inStream.Read(playerID);
auto player = Game::playerContainer.GetPlayerData(playerID); auto& player = Game::playerContainer.GetPlayerDataMutable(playerID);
if (!player) return; if (!player) return;
auto friendsList = Database::Get()->GetFriendsList(playerID); auto friendsList = Database::Get()->GetFriendsList(playerID);
@ -37,15 +37,15 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER); GeneralUtils::SetBit(fd.friendID, eObjectBits::CHARACTER);
fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs fd.isBestFriend = friendData.isBestFriend; //0 = friends, 1 = left_requested, 2 = right_requested, 3 = both_accepted - are now bffs
if (fd.isBestFriend) player->countOfBestFriends += 1; if (fd.isBestFriend) player.countOfBestFriends += 1;
fd.friendName = friendData.friendName; fd.friendName = friendData.friendName;
//Now check if they're online: //Now check if they're online:
auto fr = Game::playerContainer.GetPlayerData(fd.friendID); const auto& fr = Game::playerContainer.GetPlayerData(fd.friendID);
if (fr) { if (fr) {
fd.isOnline = true; fd.isOnline = true;
fd.zoneID = fr->zoneID; fd.zoneID = fr.zoneID;
//Since this friend is online, we need to update them on the fact that we've just logged in: //Since this friend is online, we need to update them on the fact that we've just logged in:
SendFriendUpdate(fr, player, 1, fd.isBestFriend); SendFriendUpdate(fr, player, 1, fd.isBestFriend);
@ -54,7 +54,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
fd.zoneID = LWOZONEID(); fd.zoneID = LWOZONEID();
} }
player->friends.push_back(fd); player.friends.push_back(fd);
} }
//Now, we need to send the friendlist to the server they came from: //Now, we need to send the friendlist to the server they came from:
@ -66,13 +66,13 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GET_FRIENDS_LIST_RESPONSE);
bitStream.Write<uint8_t>(0); bitStream.Write<uint8_t>(0);
bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it. bitStream.Write<uint16_t>(1); //Length of packet -- just writing one as it doesn't matter, client skips it.
bitStream.Write<uint16_t>(player->friends.size()); bitStream.Write<uint16_t>(player.friends.size());
for (auto& data : player->friends) { for (const auto& data : player.friends) {
data.Serialize(bitStream); data.Serialize(bitStream);
} }
SystemAddress sysAddr = player->sysAddr; SystemAddress sysAddr = player.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
@ -95,51 +95,49 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
char isBestFriendRequest{}; char isBestFriendRequest{};
inStream.Read(isBestFriendRequest); inStream.Read(isBestFriendRequest);
auto requestor = Game::playerContainer.GetPlayerData(requestorPlayerID); auto& requestor = Game::playerContainer.GetPlayerDataMutable(requestorPlayerID);
if (!requestor) { if (!requestor) {
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str()); LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
return; return;
} }
if (requestor->playerName == playerName) { if (requestor.playerName == playerName) {
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN); SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
return; return;
}; };
std::unique_ptr<PlayerData> requestee(Game::playerContainer.GetPlayerData(playerName));
auto& requestee = Game::playerContainer.GetPlayerDataMutable(playerName);
// Check if player is online first // Check if player is online first
if (isBestFriendRequest && !requestee) { if (isBestFriendRequest && !requestee) {
for (auto friendDataCandidate : requestor->friends) { for (auto& friendDataCandidate : requestor.friends) {
if (friendDataCandidate.friendName == playerName) { if (friendDataCandidate.friendName != playerName) continue;
requestee.reset(new PlayerData()); // Setup the needed info since you can add a best friend offline.
// Setup the needed info since you can add a best friend offline. requestee.playerID = friendDataCandidate.friendID;
requestee->playerID = friendDataCandidate.friendID; requestee.playerName = friendDataCandidate.friendName;
requestee->playerName = friendDataCandidate.friendName; requestee.zoneID = LWOZONEID();
requestee->zoneID = LWOZONEID();
FriendData requesteeFriendData{}; FriendData requesteeFriendData{};
requesteeFriendData.friendID = requestor->playerID; requesteeFriendData.friendID = requestor.playerID;
requesteeFriendData.friendName = requestor->playerName; requesteeFriendData.friendName = requestor.playerName;
requesteeFriendData.isFTP = false; requesteeFriendData.isFTP = false;
requesteeFriendData.isOnline = false; requesteeFriendData.isOnline = false;
requesteeFriendData.zoneID = requestor->zoneID; requesteeFriendData.zoneID = requestor.zoneID;
requestee->friends.push_back(requesteeFriendData); requestee.friends.push_back(requesteeFriendData);
requestee->sysAddr = UNASSIGNED_SYSTEM_ADDRESS; requestee.sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
break; break;
}
} }
} }
// If at this point we dont have a target, then they arent online and we cant send the request. // If at this point we dont have a target, then they arent online and we cant send the request.
// Send the response code that corresponds to what the error is. // Send the response code that corresponds to what the error is.
if (!requestee) { if (!requestee) {
requestee.reset(new PlayerData()); requestee.playerName = playerName;
requestee->playerName = playerName;
auto responseType = Database::Get()->GetCharacterInfo(playerName) auto responseType = Database::Get()->GetCharacterInfo(playerName)
? eAddFriendResponseType::NOTONLINE ? eAddFriendResponseType::NOTONLINE
: eAddFriendResponseType::INVALIDCHARACTER; : eAddFriendResponseType::INVALIDCHARACTER;
SendFriendResponse(requestor, requestee.get(), responseType); SendFriendResponse(requestor, requestee, responseType);
return; return;
} }
@ -147,7 +145,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
uint8_t oldBestFriendStatus{}; uint8_t oldBestFriendStatus{};
uint8_t bestFriendStatus{}; uint8_t bestFriendStatus{};
auto bestFriendInfo = Database::Get()->GetBestFriendStatus(requestorPlayerID, requestee->playerID); auto bestFriendInfo = Database::Get()->GetBestFriendStatus(requestorPlayerID, requestee.playerID);
if (bestFriendInfo) { if (bestFriendInfo) {
// Get the IDs // Get the IDs
LWOOBJID queryPlayerID = bestFriendInfo->playerCharacterId; LWOOBJID queryPlayerID = bestFriendInfo->playerCharacterId;
@ -174,51 +172,48 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
// Only do updates if there was a change in the bff status. // Only do updates if there was a change in the bff status.
if (oldBestFriendStatus != bestFriendStatus) { if (oldBestFriendStatus != bestFriendStatus) {
auto maxBestFriends = Game::playerContainer.GetMaxNumberOfBestFriends(); auto maxBestFriends = Game::playerContainer.GetMaxNumberOfBestFriends();
if (requestee->countOfBestFriends >= maxBestFriends || requestor->countOfBestFriends >= maxBestFriends) { if (requestee.countOfBestFriends >= maxBestFriends || requestor.countOfBestFriends >= maxBestFriends) {
if (requestee->countOfBestFriends >= maxBestFriends) { if (requestee.countOfBestFriends >= maxBestFriends) {
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false); SendFriendResponse(requestor, requestee, eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
} }
if (requestor->countOfBestFriends >= maxBestFriends) { if (requestor.countOfBestFriends >= maxBestFriends) {
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::YOURFRIENDSLISTFULL, false); SendFriendResponse(requestor, requestee, eAddFriendResponseType::YOURFRIENDSLISTFULL, false);
} }
} else { } else {
// Then update the database with this new info. // Then update the database with this new info.
Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee->playerID, bestFriendStatus); Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee.playerID, bestFriendStatus);
// Sent the best friend update here if the value is 3 // Sent the best friend update here if the value is 3
if (bestFriendStatus == 3U) { if (bestFriendStatus == 3U) {
requestee->countOfBestFriends += 1; requestee.countOfBestFriends += 1;
requestor->countOfBestFriends += 1; requestor.countOfBestFriends += 1;
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee.get(), requestor, eAddFriendResponseType::ACCEPTED, false, true); if (requestee.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee, requestor, eAddFriendResponseType::ACCEPTED, false, true);
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::ACCEPTED, false, true); if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::ACCEPTED, false, true);
for (auto& friendData : requestor->friends) { for (auto& friendData : requestor.friends) {
if (friendData.friendID == requestee->playerID) { if (friendData.friendID == requestee.playerID) {
friendData.isBestFriend = true; friendData.isBestFriend = true;
} }
} }
for (auto& friendData : requestee->friends) { for (auto& friendData : requestee.friends) {
if (friendData.friendID == requestor->playerID) { if (friendData.friendID == requestor.playerID) {
friendData.isBestFriend = true; friendData.isBestFriend = true;
} }
} }
} }
} }
} else { } else {
if (requestor->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::WAITINGAPPROVAL, true, true); if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::WAITINGAPPROVAL, true, true);
} }
} else { } else {
auto maxFriends = Game::playerContainer.GetMaxNumberOfFriends(); auto maxFriends = Game::playerContainer.GetMaxNumberOfFriends();
if (requestee->friends.size() >= maxFriends) { if (requestee.friends.size() >= maxFriends) {
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::THEIRFRIENDLISTFULL, false); SendFriendResponse(requestor, requestee, eAddFriendResponseType::THEIRFRIENDLISTFULL, false);
} else if (requestor->friends.size() >= maxFriends) { } else if (requestor.friends.size() >= maxFriends) {
SendFriendResponse(requestor, requestee.get(), eAddFriendResponseType::YOURFRIENDSLISTFULL, false); SendFriendResponse(requestor, requestee, eAddFriendResponseType::YOURFRIENDSLISTFULL, false);
} else { } else {
// Do not send this if we are requesting to be a best friend. // Do not send this if we are requesting to be a best friend.
SendFriendRequest(requestee.get(), requestor); SendFriendRequest(requestee, requestor);
} }
} }
// If the player is actually a player and not a ghost one defined above, release it from being deleted.
if (requestee->sysAddr != UNASSIGNED_SYSTEM_ADDRESS) requestee.release();
} }
void ChatPacketHandler::HandleFriendResponse(Packet* packet) { void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
@ -230,8 +225,8 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
std::string friendName = PacketUtils::ReadString(0x15, packet, true); std::string friendName = PacketUtils::ReadString(0x15, packet, true);
//Now to try and find both of these: //Now to try and find both of these:
auto requestor = Game::playerContainer.GetPlayerData(playerID); auto& requestor = Game::playerContainer.GetPlayerDataMutable(playerID);
auto requestee = Game::playerContainer.GetPlayerData(friendName); auto& requestee = Game::playerContainer.GetPlayerDataMutable(friendName);
if (!requestor || !requestee) return; if (!requestor || !requestee) return;
eAddFriendResponseType serverResponseCode{}; eAddFriendResponseType serverResponseCode{};
@ -254,8 +249,8 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
// Now that we have handled the base cases, we need to check the other cases. // Now that we have handled the base cases, we need to check the other cases.
if (serverResponseCode == eAddFriendResponseType::ACCEPTED) { if (serverResponseCode == eAddFriendResponseType::ACCEPTED) {
for (auto friendData : requestor->friends) { for (const auto& friendData : requestor.friends) {
if (friendData.friendID == requestee->playerID) { if (friendData.friendID == requestee.playerID) {
serverResponseCode = eAddFriendResponseType::ALREADYFRIEND; serverResponseCode = eAddFriendResponseType::ALREADYFRIEND;
if (friendData.isBestFriend) { if (friendData.isBestFriend) {
isAlreadyBestFriends = 1U; isAlreadyBestFriends = 1U;
@ -267,25 +262,23 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
// This message is NOT sent for best friends and is handled differently for those requests. // This message is NOT sent for best friends and is handled differently for those requests.
if (serverResponseCode == eAddFriendResponseType::ACCEPTED) { if (serverResponseCode == eAddFriendResponseType::ACCEPTED) {
// Add the each player to the others friend list. // Add the each player to the others friend list.
FriendData requestorData; auto& requestorData = requestee.friends.emplace_back();
requestorData.zoneID = requestor->zoneID; requestorData.zoneID = requestor.zoneID;
requestorData.friendID = requestor->playerID; requestorData.friendID = requestor.playerID;
requestorData.friendName = requestor->playerName; requestorData.friendName = requestor.playerName;
requestorData.isBestFriend = false; requestorData.isBestFriend = false;
requestorData.isFTP = false; requestorData.isFTP = false;
requestorData.isOnline = true; requestorData.isOnline = true;
requestee->friends.push_back(requestorData);
FriendData requesteeData; auto& requesteeData = requestor.friends.emplace_back();
requesteeData.zoneID = requestee->zoneID; requesteeData.zoneID = requestee.zoneID;
requesteeData.friendID = requestee->playerID; requesteeData.friendID = requestee.playerID;
requesteeData.friendName = requestee->playerName; requesteeData.friendName = requestee.playerName;
requesteeData.isBestFriend = false; requesteeData.isBestFriend = false;
requesteeData.isFTP = false; requesteeData.isFTP = false;
requesteeData.isOnline = true; requesteeData.isOnline = true;
requestor->friends.push_back(requesteeData);
Database::Get()->AddFriend(requestor->playerID, requestee->playerID); Database::Get()->AddFriend(requestor.playerID, requestee.playerID);
} }
if (serverResponseCode != eAddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends); if (serverResponseCode != eAddFriendResponseType::DECLINED) SendFriendResponse(requestor, requestee, serverResponseCode, isAlreadyBestFriends);
@ -313,26 +306,27 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
Database::Get()->RemoveFriend(playerID, friendID); Database::Get()->RemoveFriend(playerID, friendID);
//Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended: //Now, we need to send an update to notify the sender (and possibly, receiver) that their friendship has been ended:
auto goonA = Game::playerContainer.GetPlayerData(playerID); auto& goonA = Game::playerContainer.GetPlayerDataMutable(playerID);
if (goonA) { if (goonA) {
// Remove the friend from our list of friends // Remove the friend from our list of friends
for (auto friendData = goonA->friends.begin(); friendData != goonA->friends.end(); friendData++) { for (auto friendData = goonA.friends.cbegin(); friendData != goonA.friends.cend(); friendData++) {
if ((*friendData).friendID == friendID) { if (friendData->friendID == friendID) {
if ((*friendData).isBestFriend) --goonA->countOfBestFriends; if (friendData->isBestFriend) --goonA.countOfBestFriends;
goonA->friends.erase(friendData); goonA.friends.erase(friendData);
break; break;
} }
} }
SendRemoveFriend(goonA, friendName, true); SendRemoveFriend(goonA, friendName, true);
} }
auto goonB = Game::playerContainer.GetPlayerData(friendID); auto& goonB = Game::playerContainer.GetPlayerDataMutable(friendID);
if (!goonB) return; if (!goonB) return;
// Do it again for other person // Do it again for other person
for (auto friendData = goonB->friends.begin(); friendData != goonB->friends.end(); friendData++) { for (auto friendData = goonB.friends.cbegin(); friendData != goonB.friends.cend(); friendData++) {
if ((*friendData).friendID == playerID) { if (friendData->friendID == playerID) {
if ((*friendData).isBestFriend) --goonB->countOfBestFriends; if (friendData->isBestFriend) --goonB.countOfBestFriends;
goonB->friends.erase(friendData); goonB.friends.erase(friendData);
break; break;
} }
} }
@ -346,13 +340,11 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
LWOOBJID playerID = LWOOBJID_EMPTY; LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID); inStream.Read(playerID);
auto* sender = Game::playerContainer.GetPlayerData(playerID); const auto& sender = Game::playerContainer.GetPlayerData(playerID);
if (sender == nullptr) return; if (!sender) return;
if (Game::playerContainer.GetIsMuted(sender)) return; if (sender.GetIsMuted()) return;
const auto senderName = std::string(sender->playerName.c_str());
inStream.SetReadOffset(0x14 * 8); inStream.SetReadOffset(0x14 * 8);
@ -361,7 +353,7 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
std::string message = PacketUtils::ReadString(0x66, packet, true, 512); std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
LOG("Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str()); LOG("Got a message from (%s) [%d]: %s", sender.playerName.c_str(), channel, message.c_str());
if (channel != 8) return; if (channel != 8) return;
@ -370,30 +362,28 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
if (team == nullptr) return; if (team == nullptr) return;
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = Game::playerContainer.GetPlayerData(memberId); const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
if (otherMember == nullptr) return; if (!otherMember) return;
const auto otherName = std::string(otherMember->playerName.c_str());
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(otherMember->playerID); bitStream.Write(otherMember.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(otherMember->playerID); bitStream.Write(otherMember.playerID);
bitStream.Write<uint8_t>(8); bitStream.Write<uint8_t>(8);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(senderName)); bitStream.Write(LUWString(sender.playerName));
bitStream.Write(sender->playerID); bitStream.Write(sender.playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(otherName)); bitStream.Write(LUWString(otherMember.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //teams? bitStream.Write<uint8_t>(0); //teams?
bitStream.Write(LUWString(message, 512)); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = otherMember->sysAddr; SystemAddress sysAddr = otherMember.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
} }
@ -404,35 +394,32 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512); std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
//Get the bois: //Get the bois:
auto goonA = Game::playerContainer.GetPlayerData(senderID); const auto& goonA = Game::playerContainer.GetPlayerData(senderID);
auto goonB = Game::playerContainer.GetPlayerData(receiverName); const auto& goonB = Game::playerContainer.GetPlayerData(receiverName);
if (!goonA || !goonB) return; if (!goonA || !goonB) return;
if (Game::playerContainer.GetIsMuted(goonA)) return; if (goonA.GetIsMuted()) return;
std::string goonAName = goonA->playerName.c_str();
std::string goonBName = goonB->playerName.c_str();
//To the sender: //To the sender:
{ {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonA->playerID); bitStream.Write(goonA.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA->playerID); bitStream.Write(goonA.playerID);
bitStream.Write<uint8_t>(7); bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(goonAName)); bitStream.Write(LUWString(goonA.playerName));
bitStream.Write(goonA->playerID); bitStream.Write(goonA.playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(goonBName)); bitStream.Write(LUWString(goonB.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //success bitStream.Write<uint8_t>(0); //success
bitStream.Write(LUWString(message, 512)); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonA->sysAddr; SystemAddress sysAddr = goonA.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
@ -440,22 +427,22 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
{ {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonB->playerID); bitStream.Write(goonB.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA->playerID); bitStream.Write(goonA.playerID);
bitStream.Write<uint8_t>(7); bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69); bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(goonAName)); bitStream.Write(LUWString(goonA.playerName));
bitStream.Write(goonA->playerID); bitStream.Write(goonA.playerID);
bitStream.Write<uint16_t>(0); bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(goonBName)); bitStream.Write(LUWString(goonB.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(3); //new whisper bitStream.Write<uint8_t>(3); //new whisper
bitStream.Write(LUWString(message, 512)); bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonB->sysAddr; SystemAddress sysAddr = goonB.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
} }
@ -466,11 +453,9 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
inStream.Read(playerID); inStream.Read(playerID);
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true); std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
auto* player = Game::playerContainer.GetPlayerData(playerID); const auto& player = Game::playerContainer.GetPlayerData(playerID);
if (player == nullptr) { if (!player) return;
return;
}
auto* team = Game::playerContainer.GetTeam(playerID); auto* team = Game::playerContainer.GetTeam(playerID);
@ -478,13 +463,11 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
team = Game::playerContainer.CreateTeam(playerID); team = Game::playerContainer.CreateTeam(playerID);
} }
auto* other = Game::playerContainer.GetPlayerData(invitedPlayer); const auto& other = Game::playerContainer.GetPlayerData(invitedPlayer);
if (other == nullptr) { if (!other) return;
return;
}
if (Game::playerContainer.GetTeam(other->playerID) != nullptr) { if (Game::playerContainer.GetTeam(other.playerID) != nullptr) {
return; return;
} }
@ -558,12 +541,12 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str()); LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
auto* kicked = Game::playerContainer.GetPlayerData(kickedPlayer); const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer);
LWOOBJID kickedId = LWOOBJID_EMPTY; LWOOBJID kickedId = LWOOBJID_EMPTY;
if (kicked != nullptr) { if (kicked) {
kickedId = kicked->playerID; kickedId = kicked.playerID;
} else { } else {
kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer)); kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
} }
@ -588,16 +571,16 @@ void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str()); LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
auto* promoted = Game::playerContainer.GetPlayerData(promotedPlayer); const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer);
if (promoted == nullptr) return; if (!promoted) return;
auto* team = Game::playerContainer.GetTeam(playerID); auto* team = Game::playerContainer.GetTeam(playerID);
if (team != nullptr) { if (team != nullptr) {
if (team->leaderID != playerID) return; if (team->leaderID != playerID) return;
Game::playerContainer.PromoteMember(team, promoted->playerID); Game::playerContainer.PromoteMember(team, promoted.playerID);
} }
} }
@ -630,10 +613,10 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
inStream.Read(playerID); inStream.Read(playerID);
auto* team = Game::playerContainer.GetTeam(playerID); auto* team = Game::playerContainer.GetTeam(playerID);
auto* data = Game::playerContainer.GetPlayerData(playerID); const auto& data = Game::playerContainer.GetPlayerData(playerID);
if (team != nullptr && data != nullptr) { if (team != nullptr && data) {
if (team->local && data->zoneID.GetMapID() != team->zoneId.GetMapID() && data->zoneID.GetCloneID() != team->zoneId.GetCloneID()) { if (team->local && data.zoneID.GetMapID() != team->zoneId.GetMapID() && data.zoneID.GetCloneID() != team->zoneId.GetCloneID()) {
Game::playerContainer.RemoveMember(team, playerID, false, false, true, true); Game::playerContainer.RemoveMember(team, playerID, false, false, true, true);
return; return;
@ -653,49 +636,49 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
Game::playerContainer.TeamStatusUpdate(team); Game::playerContainer.TeamStatusUpdate(team);
const auto leaderName = GeneralUtils::UTF8ToUTF16(data->playerName); const auto leaderName = GeneralUtils::UTF8ToUTF16(data.playerName);
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = Game::playerContainer.GetPlayerData(memberId); const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
if (memberId == playerID) continue; if (memberId == playerID) continue;
const auto memberName = Game::playerContainer.GetName(memberId); const auto memberName = Game::playerContainer.GetName(memberId);
if (otherMember != nullptr) { if (otherMember) {
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data->playerID, data->zoneID); ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, data.playerID, data.zoneID);
} }
ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0)); ChatPacketHandler::SendTeamAddPlayer(data, false, team->local, false, memberId, memberName, otherMember ? otherMember.zoneID : LWOZONEID(0, 0, 0));
} }
Game::playerContainer.UpdateTeamsOnWorld(team, false); Game::playerContainer.UpdateTeamsOnWorld(team, false);
} }
} }
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) { void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerData& sender) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::TEAM_INVITE);
bitStream.Write(LUWString(sender->playerName.c_str())); bitStream.Write(LUWString(sender.playerName.c_str()));
bitStream.Write(sender->playerID); bitStream.Write(sender.playerID);
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_INVITE_CONFIRM); bitStream.Write(eGameMessageType::TEAM_INVITE_CONFIRM);
bitStream.Write(bLeaderIsFreeTrial); bitStream.Write(bLeaderIsFreeTrial);
@ -710,19 +693,19 @@ void ChatPacketHandler::SendTeamInviteConfirm(PlayerData* receiver, bool bLeader
bitStream.Write(character); bitStream.Write(character);
} }
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) { void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_GET_STATUS_RESPONSE); bitStream.Write(eGameMessageType::TEAM_GET_STATUS_RESPONSE);
bitStream.Write(i64LeaderID); bitStream.Write(i64LeaderID);
@ -735,36 +718,36 @@ void ChatPacketHandler::SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderI
bitStream.Write(character); bitStream.Write(character);
} }
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID) { void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_SET_LEADER); bitStream.Write(eGameMessageType::TEAM_SET_LEADER);
bitStream.Write(i64PlayerID); bitStream.Write(i64PlayerID);
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_ADD_PLAYER); bitStream.Write(eGameMessageType::TEAM_ADD_PLAYER);
bitStream.Write(bIsFreeTrial); bitStream.Write(bIsFreeTrial);
@ -776,24 +759,24 @@ void ChatPacketHandler::SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTria
bitStream.Write(character); bitStream.Write(character);
} }
bitStream.Write1(); bitStream.Write1();
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) { if (receiver.zoneID.GetCloneID() == zoneID.GetCloneID()) {
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0); zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
} }
bitStream.Write(zoneID); bitStream.Write(zoneID);
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) { void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_REMOVE_PLAYER); bitStream.Write(eGameMessageType::TEAM_REMOVE_PLAYER);
bitStream.Write(bDisband); bitStream.Write(bDisband);
@ -807,32 +790,32 @@ void ChatPacketHandler::SendTeamRemovePlayer(PlayerData* receiver, bool bDisband
bitStream.Write(character); bitStream.Write(character);
} }
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) { void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID) {
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
CMSGHEADER; CMSGHEADER;
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
bitStream.Write(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG); bitStream.Write(eGameMessageType::TEAM_SET_OFF_WORLD_FLAG);
bitStream.Write(i64PlayerID); bitStream.Write(i64PlayerID);
if (receiver->zoneID.GetCloneID() == zoneID.GetCloneID()) { if (receiver.zoneID.GetCloneID() == zoneID.GetCloneID()) {
zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0); zoneID = LWOZONEID(zoneID.GetMapID(), zoneID.GetInstanceID(), 0);
} }
bitStream.Write(zoneID); bitStream.Write(zoneID);
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend) { void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const PlayerData& playerData, uint8_t notifyType, uint8_t isBestFriend) {
/*chat notification is displayed if log in / out and friend is updated in friends list /*chat notification is displayed if log in / out and friend is updated in friends list
[u8] - update type [u8] - update type
Update types Update types
@ -848,38 +831,36 @@ void ChatPacketHandler::SendFriendUpdate(PlayerData* friendData, PlayerData* pla
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(friendData->playerID); bitStream.Write(friendData.playerID);
//portion that will get routed: //portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::UPDATE_FRIEND_NOTIFY);
bitStream.Write<uint8_t>(notifyType); bitStream.Write<uint8_t>(notifyType);
std::string playerName = playerData->playerName.c_str(); std::string playerName = playerData.playerName.c_str();
bitStream.Write(LUWString(playerName)); bitStream.Write(LUWString(playerName));
bitStream.Write(playerData->zoneID.GetMapID()); bitStream.Write(playerData.zoneID.GetMapID());
bitStream.Write(playerData->zoneID.GetInstanceID()); bitStream.Write(playerData.zoneID.GetInstanceID());
if (playerData->zoneID.GetCloneID() == friendData->zoneID.GetCloneID()) { if (playerData.zoneID.GetCloneID() == friendData.zoneID.GetCloneID()) {
bitStream.Write(0); bitStream.Write(0);
} else { } else {
bitStream.Write(playerData->zoneID.GetCloneID()); bitStream.Write(playerData.zoneID.GetCloneID());
} }
bitStream.Write<uint8_t>(isBestFriend); //isBFF bitStream.Write<uint8_t>(isBestFriend); //isBFF
bitStream.Write<uint8_t>(0); //isFTP bitStream.Write<uint8_t>(0); //isFTP
SystemAddress sysAddr = friendData->sysAddr; SystemAddress sysAddr = friendData.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* sender) { void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const PlayerData& sender) {
if (!receiver || !sender) return;
//Make sure people aren't requesting people that they're already friends with: //Make sure people aren't requesting people that they're already friends with:
for (auto fr : receiver->friends) { for (const auto& fr : receiver.friends) {
if (fr.friendID == sender->playerID) { if (fr.friendID == sender.playerID) {
SendFriendResponse(sender, receiver, eAddFriendResponseType::ALREADYFRIEND, fr.isBestFriend); SendFriendResponse(sender, receiver, eAddFriendResponseType::ALREADYFRIEND, fr.isBestFriend);
return; //we have this player as a friend, yeet this function so it doesn't send another request. return; //we have this player as a friend, yeet this function so it doesn't send another request.
} }
@ -887,54 +868,50 @@ void ChatPacketHandler::SendFriendRequest(PlayerData* receiver, PlayerData* send
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_REQUEST);
bitStream.Write(LUWString(sender->playerName.c_str())); bitStream.Write(LUWString(sender.playerName));
bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side. bitStream.Write<uint8_t>(0); // This is a BFF flag however this is unused in live and does not have an implementation client side.
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendFriendResponse(PlayerData* receiver, PlayerData* sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) { void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready, uint8_t isBestFriendRequest) {
if (!receiver || !sender) return;
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
// Portion that will get routed: // Portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::ADD_FRIEND_RESPONSE);
bitStream.Write(responseCode); bitStream.Write(responseCode);
// For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver. // For all requests besides accepted, write a flag that says whether or not we are already best friends with the receiver.
bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender->sysAddr != UNASSIGNED_SYSTEM_ADDRESS); bitStream.Write<uint8_t>(responseCode != eAddFriendResponseType::ACCEPTED ? isBestFriendsAlready : sender.sysAddr != UNASSIGNED_SYSTEM_ADDRESS);
// Then write the player name // Then write the player name
bitStream.Write(LUWString(sender->playerName.c_str())); bitStream.Write(LUWString(sender.playerName));
// Then if this is an acceptance code, write the following extra info. // Then if this is an acceptance code, write the following extra info.
if (responseCode == eAddFriendResponseType::ACCEPTED) { if (responseCode == eAddFriendResponseType::ACCEPTED) {
bitStream.Write(sender->playerID); bitStream.Write(sender.playerID);
bitStream.Write(sender->zoneID); bitStream.Write(sender.zoneID);
bitStream.Write(isBestFriendRequest); //isBFF bitStream.Write(isBestFriendRequest); //isBFF
bitStream.Write<uint8_t>(0); //isFTP bitStream.Write<uint8_t>(0); //isFTP
} }
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }
void ChatPacketHandler::SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful) { void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful) {
if (!receiver) return;
CBITSTREAM; CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(receiver->playerID); bitStream.Write(receiver.playerID);
//portion that will get routed: //portion that will get routed:
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE); BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::REMOVE_FRIEND_RESPONSE);
bitStream.Write<uint8_t>(isSuccessful); //isOnline bitStream.Write<uint8_t>(isSuccessful); //isOnline
bitStream.Write(LUWString(personToRemove)); bitStream.Write(LUWString(personToRemove));
SystemAddress sysAddr = receiver->sysAddr; SystemAddress sysAddr = receiver.sysAddr;
SEND_PACKET; SEND_PACKET;
} }

View File

@ -4,6 +4,7 @@
#include "BitStream.h" #include "BitStream.h"
struct PlayerData; struct PlayerData;
enum class eAddFriendResponseType : uint8_t; enum class eAddFriendResponseType : uint8_t;
namespace ChatPacketHandler { namespace ChatPacketHandler {
@ -23,18 +24,18 @@ namespace ChatPacketHandler {
void HandleTeamLootOption(Packet* packet); void HandleTeamLootOption(Packet* packet);
void HandleTeamStatusRequest(Packet* packet); void HandleTeamStatusRequest(Packet* packet);
void SendTeamInvite(PlayerData* receiver, PlayerData* sender); void SendTeamInvite(const PlayerData& receiver, const PlayerData& sender);
void SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName); void SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
void SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName); void SendTeamStatus(const PlayerData& receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName);
void SendTeamSetLeader(PlayerData* receiver, LWOOBJID i64PlayerID); void SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i64PlayerID);
void SendTeamAddPlayer(PlayerData* receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID); void SendTeamAddPlayer(const PlayerData& receiver, bool bIsFreeTrial, bool bLocal, bool bNoLootOnDeath, LWOOBJID i64PlayerID, std::u16string wsPlayerName, LWOZONEID zoneID);
void SendTeamRemovePlayer(PlayerData* receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName); void SendTeamRemovePlayer(const PlayerData& receiver, bool bDisband, bool bIsKicked, bool bIsLeaving, bool bLocal, LWOOBJID i64LeaderID, LWOOBJID i64PlayerID, std::u16string wsPlayerName);
void SendTeamSetOffWorldFlag(PlayerData* receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID); void SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOOBJID i64PlayerID, LWOZONEID zoneID);
//FriendData is the player we're SENDING this stuff to. Player is the friend that changed state. //FriendData is the player we're SENDING this stuff to. Player is the friend that changed state.
void SendFriendUpdate(PlayerData* friendData, PlayerData* playerData, uint8_t notifyType, uint8_t isBestFriend); void SendFriendUpdate(const PlayerData& friendData, const PlayerData& playerData, uint8_t notifyType, uint8_t isBestFriend);
void SendFriendRequest(PlayerData* receiver, PlayerData* sender); void SendFriendRequest(const PlayerData& receiver, const PlayerData& sender);
void SendFriendResponse(PlayerData* receiver, PlayerData* sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready = 0U, uint8_t isBestFriendRequest = 0U); void SendFriendResponse(const PlayerData& receiver, const PlayerData& sender, eAddFriendResponseType responseCode, uint8_t isBestFriendsAlready = 0U, uint8_t isBestFriendRequest = 0U);
void SendRemoveFriend(PlayerData* receiver, std::string& personToRemove, bool isSuccessful); void SendRemoveFriend(const PlayerData& receiver, std::string& personToRemove, bool isSuccessful);
}; };

View File

@ -28,27 +28,32 @@ TeamData::TeamData() {
void PlayerContainer::InsertPlayer(Packet* packet) { void PlayerContainer::InsertPlayer(Packet* packet) {
CINSTREAM_SKIP_HEADER; CINSTREAM_SKIP_HEADER;
PlayerData* data = new PlayerData(); LWOOBJID playerId;
inStream.Read(data->playerID); if (!inStream.Read(playerId)) {
LOG("Failed to read player ID");
return;
}
auto& data = m_Players[playerId];
data.playerID = playerId;
uint32_t len; uint32_t len;
inStream.Read<uint32_t>(len); inStream.Read<uint32_t>(len);
for (int i = 0; i < len; i++) { for (int i = 0; i < len; i++) {
char character; inStream.Read<char>(character); char character; inStream.Read<char>(character);
data->playerName += character; data.playerName += character;
} }
inStream.Read(data->zoneID); inStream.Read(data.zoneID);
inStream.Read(data->muteExpire); inStream.Read(data.muteExpire);
data->sysAddr = packet->systemAddress; data.sysAddr = packet->systemAddress;
m_Names[data->playerID] = GeneralUtils::UTF8ToUTF16(data->playerName); m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
m_Players.insert(std::make_pair(data->playerID, data)); LOG("Added user: %s (%llu), zone: %i", data.playerName.c_str(), data.playerID, data.zoneID.GetMapID());
LOG("Added user: %s (%llu), zone: %i", data->playerName.c_str(), data->playerID, data->zoneID.GetMapID());
Database::Get()->UpdateActivityLog(data->playerID, eActivityType::PlayerLoggedIn, data->zoneID.GetMapID()); Database::Get()->UpdateActivityLog(data.playerID, eActivityType::PlayerLoggedIn, data.zoneID.GetMapID());
} }
void PlayerContainer::RemovePlayer(Packet* packet) { void PlayerContainer::RemovePlayer(Packet* packet) {
@ -57,26 +62,27 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
inStream.Read(playerID); inStream.Read(playerID);
//Before they get kicked, we need to also send a message to their friends saying that they disconnected. //Before they get kicked, we need to also send a message to their friends saying that they disconnected.
std::unique_ptr<PlayerData> player(this->GetPlayerData(playerID)); const auto& player = GetPlayerData(playerID);
if (player == nullptr) { if (!player) {
LOG("Failed to find user: %llu", playerID);
return; return;
} }
for (auto& fr : player->friends) { for (const auto& fr : player.friends) {
auto fd = this->GetPlayerData(fr.friendID); const auto& fd = this->GetPlayerData(fr.friendID);
if (fd) ChatPacketHandler::SendFriendUpdate(fd, player.get(), 0, fr.isBestFriend); if (fd) ChatPacketHandler::SendFriendUpdate(fd, player, 0, fr.isBestFriend);
} }
auto* team = GetTeam(playerID); auto* team = GetTeam(playerID);
if (team != nullptr) { if (team != nullptr) {
const auto memberName = GeneralUtils::UTF8ToUTF16(std::string(player->playerName.c_str())); const auto memberName = GeneralUtils::UTF8ToUTF16(player.playerName);
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (!otherMember) continue;
ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, { 0, 0, 0 }); ChatPacketHandler::SendTeamSetOffWorldFlag(otherMember, playerID, { 0, 0, 0 });
} }
@ -85,7 +91,7 @@ void PlayerContainer::RemovePlayer(Packet* packet) {
LOG("Removed user: %llu", playerID); LOG("Removed user: %llu", playerID);
m_Players.erase(playerID); m_Players.erase(playerID);
Database::Get()->UpdateActivityLog(playerID, eActivityType::PlayerLoggedOut, player->zoneID.GetMapID()); Database::Get()->UpdateActivityLog(playerID, eActivityType::PlayerLoggedOut, player.zoneID.GetMapID());
} }
void PlayerContainer::MuteUpdate(Packet* packet) { void PlayerContainer::MuteUpdate(Packet* packet) {
@ -95,15 +101,15 @@ void PlayerContainer::MuteUpdate(Packet* packet) {
time_t expire = 0; time_t expire = 0;
inStream.Read(expire); inStream.Read(expire);
auto* player = this->GetPlayerData(playerID); auto& player = this->GetPlayerDataMutable(playerID);
if (player == nullptr) { if (!player) {
LOG("Failed to find user: %llu", playerID); LOG("Failed to find user: %llu", playerID);
return; return;
} }
player->muteExpire = expire; player.muteExpire = expire;
BroadcastMuteUpdate(playerID, expire); BroadcastMuteUpdate(playerID, expire);
} }
@ -201,11 +207,11 @@ TeamData* PlayerContainer::GetTeam(LWOOBJID playerID) {
} }
void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) { void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
if (team->memberIDs.size() >= 4){ if (team->memberIDs.size() >= 4) {
LOG("Tried to add player to team that already had 4 players"); LOG("Tried to add player to team that already had 4 players");
auto* player = GetPlayerData(playerID); const auto& player = GetPlayerData(playerID);
if (!player) return; if (!player) return;
ChatPackets::SendSystemMessage(player->sysAddr, u"The teams is full! You have not been added to a team!"); ChatPackets::SendSystemMessage(player.sysAddr, u"The teams is full! You have not been added to a team!");
return; return;
} }
@ -215,18 +221,18 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
team->memberIDs.push_back(playerID); team->memberIDs.push_back(playerID);
auto* leader = GetPlayerData(team->leaderID); const auto& leader = GetPlayerData(team->leaderID);
auto* member = GetPlayerData(playerID); const auto& member = GetPlayerData(playerID);
if (leader == nullptr || member == nullptr) return; if (!leader || !member) return;
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName); const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
const auto memberName = GeneralUtils::UTF8ToUTF16(member->playerName); const auto memberName = GeneralUtils::UTF8ToUTF16(member.playerName);
ChatPacketHandler::SendTeamInviteConfirm(member, false, leader->playerID, leader->zoneID, team->lootFlag, 0, 0, leaderName); ChatPacketHandler::SendTeamInviteConfirm(member, false, leader.playerID, leader.zoneID, team->lootFlag, 0, 0, leaderName);
if (!team->local) { if (!team->local) {
ChatPacketHandler::SendTeamSetLeader(member, leader->playerID); ChatPacketHandler::SendTeamSetLeader(member, leader.playerID);
} else { } else {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
} }
@ -234,16 +240,16 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
UpdateTeamsOnWorld(team, false); UpdateTeamsOnWorld(team, false);
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == member) continue; if (otherMember == member) continue;
const auto otherMemberName = GetName(memberId); const auto otherMemberName = GetName(memberId);
ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember != nullptr ? otherMember->zoneID : LWOZONEID(0, 0, 0)); ChatPacketHandler::SendTeamAddPlayer(member, false, team->local, false, memberId, otherMemberName, otherMember ? otherMember.zoneID : LWOZONEID(0, 0, 0));
if (otherMember != nullptr) { if (otherMember) {
ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member->playerID, memberName, member->zoneID); ChatPacketHandler::SendTeamAddPlayer(otherMember, false, team->local, false, member.playerID, memberName, member.zoneID);
} }
} }
} }
@ -253,9 +259,9 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
if (index == team->memberIDs.end()) return; if (index == team->memberIDs.end()) return;
auto* member = GetPlayerData(playerID); const auto& member = GetPlayerData(playerID);
if (member != nullptr && !silent) { if (member && !silent) {
ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(member, LWOOBJID_EMPTY);
} }
@ -266,9 +272,9 @@ void PlayerContainer::RemoveMember(TeamData* team, LWOOBJID playerID, bool disba
continue; continue;
} }
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (!otherMember) continue;
ChatPacketHandler::SendTeamRemovePlayer(otherMember, disband, kicked, leaving, false, team->leaderID, playerID, memberName); ChatPacketHandler::SendTeamRemovePlayer(otherMember, disband, kicked, leaving, false, team->leaderID, playerID, memberName);
} }
@ -290,9 +296,9 @@ void PlayerContainer::PromoteMember(TeamData* team, LWOOBJID newLeader) {
team->leaderID = newLeader; team->leaderID = newLeader;
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (!otherMember) continue;
ChatPacketHandler::SendTeamSetLeader(otherMember, newLeader); ChatPacketHandler::SendTeamSetLeader(otherMember, newLeader);
} }
@ -304,14 +310,14 @@ void PlayerContainer::DisbandTeam(TeamData* team) {
if (index == mTeams.end()) return; if (index == mTeams.end()) return;
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (!otherMember) continue;
const auto memberName = GeneralUtils::UTF8ToUTF16(otherMember->playerName); const auto memberName = GeneralUtils::UTF8ToUTF16(otherMember.playerName);
ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY); ChatPacketHandler::SendTeamSetLeader(otherMember, LWOOBJID_EMPTY);
ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember->playerID, memberName); ChatPacketHandler::SendTeamRemovePlayer(otherMember, true, false, false, team->local, team->leaderID, otherMember.playerID, memberName);
} }
UpdateTeamsOnWorld(team, true); UpdateTeamsOnWorld(team, true);
@ -326,19 +332,19 @@ void PlayerContainer::TeamStatusUpdate(TeamData* team) {
if (index == mTeams.end()) return; if (index == mTeams.end()) return;
auto* leader = GetPlayerData(team->leaderID); const auto& leader = GetPlayerData(team->leaderID);
if (leader == nullptr) return; if (!leader) return;
const auto leaderName = GeneralUtils::UTF8ToUTF16(leader->playerName); const auto leaderName = GeneralUtils::UTF8ToUTF16(leader.playerName);
for (const auto memberId : team->memberIDs) { for (const auto memberId : team->memberIDs) {
auto* otherMember = GetPlayerData(memberId); const auto& otherMember = GetPlayerData(memberId);
if (otherMember == nullptr) continue; if (!otherMember) continue;
if (!team->local) { if (!team->local) {
ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader->zoneID, team->lootFlag, 0, leaderName); ChatPacketHandler::SendTeamStatus(otherMember, team->leaderID, leader.zoneID, team->lootFlag, 0, leaderName);
} }
} }
@ -364,23 +370,42 @@ void PlayerContainer::UpdateTeamsOnWorld(TeamData* team, bool deleteTeam) {
} }
std::u16string PlayerContainer::GetName(LWOOBJID playerID) { std::u16string PlayerContainer::GetName(LWOOBJID playerID) {
const auto& pair = m_Names.find(playerID); const auto iter = m_Names.find(playerID);
if (pair == m_Names.end()) return u""; if (iter == m_Names.end()) return u"";
return pair->second; return iter->second;
} }
LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) { LWOOBJID PlayerContainer::GetId(const std::u16string& playerName) {
for (const auto& pair : m_Names) { LWOOBJID toReturn = LWOOBJID_EMPTY;
if (pair.second == playerName) {
return pair.first; for (const auto& [id, name] : m_Names) {
if (name == playerName) {
toReturn = id;
break;
} }
} }
return LWOOBJID_EMPTY; return toReturn;
} }
bool PlayerContainer::GetIsMuted(PlayerData* data) { PlayerData& PlayerContainer::GetPlayerDataMutable(const LWOOBJID& playerID) {
return data->muteExpire == 1 || data->muteExpire > time(NULL); return m_Players[playerID];
}
PlayerData& PlayerContainer::GetPlayerDataMutable(const std::string& playerName) {
for (auto& [id, player] : m_Players) {
if (!player) continue;
if (player.playerName == playerName) return player;
}
return m_Players[LWOOBJID_EMPTY];
}
const PlayerData& PlayerContainer::GetPlayerData(const LWOOBJID& playerID) {
return GetPlayerDataMutable(playerID);
}
const PlayerData& PlayerContainer::GetPlayerData(const std::string& playerName) {
return GetPlayerDataMutable(playerName);
} }

View File

@ -8,6 +8,7 @@
#include <unordered_map> #include <unordered_map>
struct IgnoreData { struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {}
inline bool operator==(const std::string& other) const noexcept { inline bool operator==(const std::string& other) const noexcept {
return playerName == other; return playerName == other;
} }
@ -16,19 +17,31 @@ struct IgnoreData {
return playerId == other; return playerId == other;
} }
LWOOBJID playerId; LWOOBJID playerId = LWOOBJID_EMPTY;
std::string playerName; std::string playerName;
}; };
struct PlayerData { struct PlayerData {
LWOOBJID playerID; operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY;
}
bool operator==(const PlayerData& other) const noexcept {
return playerID == other.playerID;
}
bool GetIsMuted() const {
return muteExpire == 1 || muteExpire > time(NULL);
}
SystemAddress sysAddr{};
LWOZONEID zoneID{};
LWOOBJID playerID = LWOOBJID_EMPTY;
time_t muteExpire = 0;
uint8_t countOfBestFriends = 0;
std::string playerName; std::string playerName;
SystemAddress sysAddr;
LWOZONEID zoneID;
std::vector<FriendData> friends; std::vector<FriendData> friends;
std::vector<IgnoreData> ignoredPlayers; std::vector<IgnoreData> ignoredPlayers;
time_t muteExpire;
uint8_t countOfBestFriends = 0;
}; };
struct TeamData { struct TeamData {
@ -52,22 +65,10 @@ public:
void CreateTeamServer(Packet* packet); void CreateTeamServer(Packet* packet);
void BroadcastMuteUpdate(LWOOBJID player, time_t time); void BroadcastMuteUpdate(LWOOBJID player, time_t time);
PlayerData* GetPlayerData(const LWOOBJID& playerID) { const PlayerData& GetPlayerData(const LWOOBJID& playerID);
auto it = m_Players.find(playerID); const PlayerData& GetPlayerData(const std::string& playerName);
if (it != m_Players.end()) return it->second; PlayerData& GetPlayerDataMutable(const LWOOBJID& playerID);
return nullptr; PlayerData& GetPlayerDataMutable(const std::string& playerName);
}
PlayerData* GetPlayerData(const std::string& playerName) {
for (auto player : m_Players) {
if (player.second) {
std::string pn = player.second->playerName.c_str();
if (pn == playerName) return player.second;
}
}
return nullptr;
}
TeamData* CreateLocalTeam(std::vector<LWOOBJID> members); TeamData* CreateLocalTeam(std::vector<LWOOBJID> members);
TeamData* CreateTeam(LWOOBJID leader, bool local = false); TeamData* CreateTeam(LWOOBJID leader, bool local = false);
@ -80,15 +81,12 @@ public:
void UpdateTeamsOnWorld(TeamData* team, bool deleteTeam); void UpdateTeamsOnWorld(TeamData* team, bool deleteTeam);
std::u16string GetName(LWOOBJID playerID); std::u16string GetName(LWOOBJID playerID);
LWOOBJID GetId(const std::u16string& playerName); LWOOBJID GetId(const std::u16string& playerName);
bool GetIsMuted(PlayerData* data);
uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; } uint32_t GetMaxNumberOfBestFriends() { return m_MaxNumberOfBestFriends; }
uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; } uint32_t GetMaxNumberOfFriends() { return m_MaxNumberOfFriends; }
std::map<LWOOBJID, PlayerData*>& GetAllPlayerData() { return m_Players; }
private: private:
LWOOBJID m_TeamIDCounter = 0; LWOOBJID m_TeamIDCounter = 0;
std::map<LWOOBJID, PlayerData*> m_Players; std::map<LWOOBJID, PlayerData> m_Players;
std::vector<TeamData*> mTeams; std::vector<TeamData*> mTeams;
std::unordered_map<LWOOBJID, std::u16string> m_Names; std::unordered_map<LWOOBJID, std::u16string> m_Names;
uint32_t m_MaxNumberOfBestFriends = 5; uint32_t m_MaxNumberOfBestFriends = 5;

View File

@ -130,7 +130,7 @@ public:
LWOOBJID friendID; LWOOBJID friendID;
std::string friendName; std::string friendName;
void Serialize(RakNet::BitStream& bitStream) { void Serialize(RakNet::BitStream& bitStream) const {
bitStream.Write<uint8_t>(isOnline); bitStream.Write<uint8_t>(isOnline);
bitStream.Write<uint8_t>(isBestFriend); bitStream.Write<uint8_t>(isBestFriend);
bitStream.Write<uint8_t>(isFTP); bitStream.Write<uint8_t>(isFTP);