mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2024-12-25 06:53:35 +00:00
Merge branch 'main' into PetFixes
This commit is contained in:
commit
20d682066c
@ -314,6 +314,7 @@ add_subdirectory(dGame)
|
|||||||
add_subdirectory(dZoneManager)
|
add_subdirectory(dZoneManager)
|
||||||
add_subdirectory(dNavigation)
|
add_subdirectory(dNavigation)
|
||||||
add_subdirectory(dPhysics)
|
add_subdirectory(dPhysics)
|
||||||
|
add_subdirectory(dServer)
|
||||||
|
|
||||||
# Create a list of common libraries shared between all binaries
|
# Create a list of common libraries shared between all binaries
|
||||||
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum")
|
set(COMMON_LIBRARIES "dCommon" "dDatabase" "dNet" "raknet" "mariadbConnCpp" "magic_enum")
|
||||||
|
@ -25,6 +25,9 @@
|
|||||||
#include "eAuthMessageType.h"
|
#include "eAuthMessageType.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
#include "Server.h"
|
||||||
|
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
dServer* server = nullptr;
|
dServer* server = nullptr;
|
||||||
@ -33,7 +36,6 @@ namespace Game {
|
|||||||
std::mt19937 randomEngine;
|
std::mt19937 randomEngine;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger();
|
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -46,14 +48,11 @@ int main(int argc, char** argv) {
|
|||||||
std::signal(SIGINT, Game::OnSignal);
|
std::signal(SIGINT, Game::OnSignal);
|
||||||
std::signal(SIGTERM, Game::OnSignal);
|
std::signal(SIGTERM, Game::OnSignal);
|
||||||
|
|
||||||
//Create all the objects we need to run our service:
|
|
||||||
Game::logger = SetupLogger();
|
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
|
||||||
|
|
||||||
//Read our config:
|
|
||||||
Game::config = new dConfig("authconfig.ini");
|
Game::config = new dConfig("authconfig.ini");
|
||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
//Create all the objects we need to run our service:
|
||||||
|
Server::SetupLogger("AuthServer");
|
||||||
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
|
||||||
LOG("Starting Auth server...");
|
LOG("Starting Auth server...");
|
||||||
LOG("Version: %s", PROJECT_VERSION);
|
LOG("Version: %s", PROJECT_VERSION);
|
||||||
@ -162,18 +161,6 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger() {
|
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/AuthServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
|
||||||
bool logToConsole = false;
|
|
||||||
bool logDebugStatements = false;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
logToConsole = true;
|
|
||||||
logDebugStatements = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return new Logger(logPath, logToConsole, logDebugStatements);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->length < 4) return;
|
if (packet->length < 4) return;
|
||||||
|
|
||||||
|
@ -1,3 +1,7 @@
|
|||||||
add_executable(AuthServer "AuthServer.cpp")
|
add_executable(AuthServer "AuthServer.cpp")
|
||||||
target_link_libraries(AuthServer ${COMMON_LIBRARIES})
|
|
||||||
|
target_link_libraries(AuthServer ${COMMON_LIBRARIES} dServer)
|
||||||
|
|
||||||
|
target_include_directories(AuthServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||||
|
|
||||||
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
add_compile_definitions(AuthServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||||
|
@ -6,7 +6,9 @@ set(DCHATSERVER_SOURCES
|
|||||||
|
|
||||||
add_executable(ChatServer "ChatServer.cpp")
|
add_executable(ChatServer "ChatServer.cpp")
|
||||||
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
add_library(dChatServer ${DCHATSERVER_SOURCES})
|
||||||
|
target_include_directories(dChatServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||||
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
add_compile_definitions(ChatServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||||
|
|
||||||
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
target_link_libraries(dChatServer ${COMMON_LIBRARIES} dChatFilter)
|
||||||
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer)
|
target_link_libraries(ChatServer ${COMMON_LIBRARIES} dChatFilter dChatServer dServer)
|
||||||
|
|
||||||
|
@ -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);
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
};
|
};
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
#include "ChatIgnoreList.h"
|
#include "ChatIgnoreList.h"
|
||||||
|
|
||||||
#include "Game.h"
|
#include "Game.h"
|
||||||
|
#include "Server.h"
|
||||||
|
|
||||||
//RakNet includes:
|
//RakNet includes:
|
||||||
#include "RakNetDefines.h"
|
#include "RakNetDefines.h"
|
||||||
@ -38,7 +39,6 @@ namespace Game {
|
|||||||
PlayerContainer playerContainer;
|
PlayerContainer playerContainer;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger();
|
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
int main(int argc, char** argv) {
|
int main(int argc, char** argv) {
|
||||||
@ -51,14 +51,13 @@ int main(int argc, char** argv) {
|
|||||||
std::signal(SIGINT, Game::OnSignal);
|
std::signal(SIGINT, Game::OnSignal);
|
||||||
std::signal(SIGTERM, Game::OnSignal);
|
std::signal(SIGTERM, Game::OnSignal);
|
||||||
|
|
||||||
|
Game::config = new dConfig("chatconfig.ini");
|
||||||
|
|
||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Game::logger = SetupLogger();
|
Server::SetupLogger("ChatServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
|
||||||
//Read our config:
|
//Read our config:
|
||||||
Game::config = new dConfig("chatconfig.ini");
|
|
||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
|
||||||
|
|
||||||
LOG("Starting Chat server...");
|
LOG("Starting Chat server...");
|
||||||
LOG("Version: %s", PROJECT_VERSION);
|
LOG("Version: %s", PROJECT_VERSION);
|
||||||
@ -182,18 +181,6 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger() {
|
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/ChatServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
|
||||||
bool logToConsole = false;
|
|
||||||
bool logDebugStatements = false;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
logToConsole = true;
|
|
||||||
logDebugStatements = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return new Logger(logPath, logToConsole, logDebugStatements);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
LOG("A server has disconnected, erasing their connected players from the list.");
|
LOG("A server has disconnected, erasing their connected players from the list.");
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
|
@ -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);
|
||||||
|
@ -348,17 +348,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chatCommand == "resetmission") {
|
|
||||||
uint32_t missionId;
|
|
||||||
if (!GeneralUtils::TryParse(args[0], missionId)) {
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission ID.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
auto* missionComponent = entity->GetComponent<MissionComponent>();
|
|
||||||
if (!missionComponent) return;
|
|
||||||
missionComponent->ResetMission(missionId);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (user->GetMaxGMLevel() == eGameMasterLevel::CIVILIAN || entity->GetGMLevel() >= eGameMasterLevel::CIVILIAN) {
|
if (user->GetMaxGMLevel() == eGameMasterLevel::CIVILIAN || entity->GetGMLevel() >= eGameMasterLevel::CIVILIAN) {
|
||||||
if (chatCommand == "die") {
|
if (chatCommand == "die") {
|
||||||
entity->Smash(entity->GetObjectID());
|
entity->Smash(entity->GetObjectID());
|
||||||
@ -388,6 +377,18 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
|||||||
if (entity->GetGMLevel() == eGameMasterLevel::CIVILIAN) return;
|
if (entity->GetGMLevel() == eGameMasterLevel::CIVILIAN) return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (chatCommand == "resetmission" && args.size() >= 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||||
|
uint32_t missionId;
|
||||||
|
if (!GeneralUtils::TryParse(args[0], missionId)) {
|
||||||
|
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission ID.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto* missionComponent = entity->GetComponent<MissionComponent>();
|
||||||
|
if (!missionComponent) return;
|
||||||
|
missionComponent->ResetMission(missionId);
|
||||||
|
}
|
||||||
|
|
||||||
// Log command to database
|
// Log command to database
|
||||||
Database::Get()->InsertSlashCommandUsage(entity->GetObjectID(), chatCommand);
|
Database::Get()->InsertSlashCommandUsage(entity->GetObjectID(), chatCommand);
|
||||||
|
|
||||||
@ -704,33 +705,6 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
|
|||||||
entity->GetCharacter()->SetPlayerFlag(flagId, false);
|
entity->GetCharacter()->SetPlayerFlag(flagId, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (chatCommand == "resetmission" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
|
||||||
if (args.size() == 0) return;
|
|
||||||
|
|
||||||
uint32_t missionID;
|
|
||||||
|
|
||||||
if (!GeneralUtils::TryParse(args[0], missionID)) {
|
|
||||||
ChatPackets::SendSystemMessage(sysAddr, u"Invalid mission id.");
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* comp = static_cast<MissionComponent*>(entity->GetComponent(eReplicaComponentType::MISSION));
|
|
||||||
|
|
||||||
if (comp == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto* mission = comp->GetMission(missionID);
|
|
||||||
|
|
||||||
if (mission == nullptr) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
mission->SetMissionState(eMissionState::ACTIVE);
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Pet status utility
|
// Pet status utility
|
||||||
if (chatCommand == "setpetstatus" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
if (chatCommand == "setpetstatus" && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
|
||||||
if (args.size() == 0) {
|
if (args.size() == 0) {
|
||||||
|
@ -9,7 +9,8 @@ add_executable(MasterServer "MasterServer.cpp")
|
|||||||
add_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
add_compile_definitions(MasterServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||||
|
|
||||||
target_link_libraries(dMasterServer ${COMMON_LIBRARIES})
|
target_link_libraries(dMasterServer ${COMMON_LIBRARIES})
|
||||||
target_link_libraries(MasterServer ${COMMON_LIBRARIES} dMasterServer)
|
target_link_libraries(MasterServer ${COMMON_LIBRARIES} dMasterServer dServer)
|
||||||
|
target_include_directories(dMasterServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||||
|
|
||||||
if(WIN32)
|
if(WIN32)
|
||||||
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
add_dependencies(MasterServer WorldServer AuthServer ChatServer)
|
||||||
|
@ -40,6 +40,7 @@
|
|||||||
#include "FdbToSqlite.h"
|
#include "FdbToSqlite.h"
|
||||||
#include "BitStreamUtils.h"
|
#include "BitStreamUtils.h"
|
||||||
#include "Start.h"
|
#include "Start.h"
|
||||||
|
#include "Server.h"
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
@ -55,7 +56,6 @@ namespace Game {
|
|||||||
bool shutdownSequenceStarted = false;
|
bool shutdownSequenceStarted = false;
|
||||||
int ShutdownSequence(int32_t signal = -1);
|
int ShutdownSequence(int32_t signal = -1);
|
||||||
int32_t FinalizeShutdown(int32_t signal = -1);
|
int32_t FinalizeShutdown(int32_t signal = -1);
|
||||||
Logger* SetupLogger();
|
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
std::map<uint32_t, std::string> activeSessions;
|
std::map<uint32_t, std::string> activeSessions;
|
||||||
SystemAddress authServerMasterPeerSysAddr;
|
SystemAddress authServerMasterPeerSysAddr;
|
||||||
@ -77,8 +77,10 @@ int main(int argc, char** argv) {
|
|||||||
std::signal(SIGINT, Game::OnSignal);
|
std::signal(SIGINT, Game::OnSignal);
|
||||||
std::signal(SIGTERM, Game::OnSignal);
|
std::signal(SIGTERM, Game::OnSignal);
|
||||||
|
|
||||||
|
Game::config = new dConfig("masterconfig.ini");
|
||||||
|
|
||||||
//Create all the objects we need to run our service:
|
//Create all the objects we need to run our service:
|
||||||
Game::logger = SetupLogger();
|
Server::SetupLogger("MasterServer");
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
|
||||||
if (!dConfig::Exists("authconfig.ini")) LOG("Could not find authconfig.ini, using default settings");
|
if (!dConfig::Exists("authconfig.ini")) LOG("Could not find authconfig.ini, using default settings");
|
||||||
@ -87,9 +89,6 @@ int main(int argc, char** argv) {
|
|||||||
if (!dConfig::Exists("sharedconfig.ini")) LOG("Could not find sharedconfig.ini, using default settings");
|
if (!dConfig::Exists("sharedconfig.ini")) LOG("Could not find sharedconfig.ini, using default settings");
|
||||||
if (!dConfig::Exists("worldconfig.ini")) LOG("Could not find worldconfig.ini, using default settings");
|
if (!dConfig::Exists("worldconfig.ini")) LOG("Could not find worldconfig.ini, using default settings");
|
||||||
|
|
||||||
Game::config = new dConfig("masterconfig.ini");
|
|
||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
|
||||||
|
|
||||||
uint32_t clientNetVersion = 171022;
|
uint32_t clientNetVersion = 171022;
|
||||||
const auto clientNetVersionString = Game::config->GetValue("client_net_version");
|
const auto clientNetVersionString = Game::config->GetValue("client_net_version");
|
||||||
@ -395,19 +394,6 @@ int main(int argc, char** argv) {
|
|||||||
return ShutdownSequence(EXIT_SUCCESS);
|
return ShutdownSequence(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger() {
|
|
||||||
std::string logPath =
|
|
||||||
(BinaryPathFinder::GetBinaryDir() / ("logs/MasterServer_" + std::to_string(time(nullptr)) + ".log")).string();
|
|
||||||
bool logToConsole = false;
|
|
||||||
bool logDebugStatements = false;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
logToConsole = true;
|
|
||||||
logDebugStatements = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return new Logger(logPath, logToConsole, logDebugStatements);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION) {
|
||||||
LOG("A server has disconnected");
|
LOG("A server has disconnected");
|
||||||
|
6
dServer/CMakeLists.txt
Normal file
6
dServer/CMakeLists.txt
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
set(DSERVER_SOURCES
|
||||||
|
"Server.cpp")
|
||||||
|
|
||||||
|
add_library(dServer STATIC ${DSERVER_SOURCES})
|
||||||
|
|
||||||
|
target_include_directories(dServer PUBLIC ".")
|
29
dServer/Server.cpp
Normal file
29
dServer/Server.cpp
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
#include "Server.h"
|
||||||
|
|
||||||
|
#include "BinaryPathFinder.h"
|
||||||
|
#include "Game.h"
|
||||||
|
#include "Logger.h"
|
||||||
|
#include "dConfig.h"
|
||||||
|
|
||||||
|
void Server::SetupLogger(const std::string_view serviceName) {
|
||||||
|
if (Game::logger) {
|
||||||
|
LOG("A logger has already been setup, skipping.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto logsDir = BinaryPathFinder::GetBinaryDir() / "logs";
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(logsDir)) std::filesystem::create_directory(logsDir);
|
||||||
|
|
||||||
|
std::string logPath = (logsDir / serviceName).string() + "_" + std::to_string(time(nullptr)) + ".log";
|
||||||
|
bool logToConsole = false;
|
||||||
|
bool logDebugStatements = false;
|
||||||
|
#ifdef _DEBUG
|
||||||
|
logToConsole = true;
|
||||||
|
logDebugStatements = true;
|
||||||
|
#endif
|
||||||
|
Game::logger = new Logger(logPath, logToConsole, logDebugStatements);
|
||||||
|
|
||||||
|
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
||||||
|
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
||||||
|
}
|
10
dServer/Server.h
Normal file
10
dServer/Server.h
Normal file
@ -0,0 +1,10 @@
|
|||||||
|
#ifndef __SERVER__H__
|
||||||
|
#define __SERVER__H__
|
||||||
|
|
||||||
|
#include <string_view>
|
||||||
|
|
||||||
|
namespace Server {
|
||||||
|
void SetupLogger(const std::string_view serviceName);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif //!__SERVER__H__
|
@ -7,5 +7,6 @@ add_executable(WorldServer "WorldServer.cpp")
|
|||||||
add_compile_definitions(WorldServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
add_compile_definitions(WorldServer PRIVATE PROJECT_VERSION="\"${PROJECT_VERSION}\"")
|
||||||
|
|
||||||
target_link_libraries(dWorldServer ${COMMON_LIBRARIES})
|
target_link_libraries(dWorldServer ${COMMON_LIBRARIES})
|
||||||
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics Detour Recast tinyxml2 dWorldServer dNavigation)
|
target_link_libraries(WorldServer ${COMMON_LIBRARIES} dChatFilter dGame dZoneManager dPhysics Detour Recast tinyxml2 dWorldServer dNavigation dServer)
|
||||||
|
target_include_directories(WorldServer PRIVATE ${PROJECT_SOURCE_DIR}/dServer)
|
||||||
|
|
||||||
|
@ -77,6 +77,7 @@
|
|||||||
#include "CheatDetection.h"
|
#include "CheatDetection.h"
|
||||||
#include "eGameMasterLevel.h"
|
#include "eGameMasterLevel.h"
|
||||||
#include "StringifiedEnum.h"
|
#include "StringifiedEnum.h"
|
||||||
|
#include "Server.h"
|
||||||
|
|
||||||
namespace Game {
|
namespace Game {
|
||||||
Logger* logger = nullptr;
|
Logger* logger = nullptr;
|
||||||
@ -102,8 +103,8 @@ void WorldShutdownProcess(uint32_t zoneId);
|
|||||||
void FinalizeShutdown();
|
void FinalizeShutdown();
|
||||||
void SendShutdownMessageToMaster();
|
void SendShutdownMessageToMaster();
|
||||||
|
|
||||||
Logger* SetupLogger(uint32_t zoneID, uint32_t instanceID);
|
|
||||||
void HandlePacketChat(Packet* packet);
|
void HandlePacketChat(Packet* packet);
|
||||||
|
void HandleMasterPacket(Packet* packet);
|
||||||
void HandlePacket(Packet* packet);
|
void HandlePacket(Packet* packet);
|
||||||
|
|
||||||
struct tempSessionInfo {
|
struct tempSessionInfo {
|
||||||
@ -143,14 +144,11 @@ int main(int argc, char** argv) {
|
|||||||
if (argument == "-port") ourPort = atoi(argv[i + 1]);
|
if (argument == "-port") ourPort = atoi(argv[i + 1]);
|
||||||
}
|
}
|
||||||
|
|
||||||
//Create all the objects we need to run our service:
|
|
||||||
Game::logger = SetupLogger(zoneID, instanceID);
|
|
||||||
if (!Game::logger) return EXIT_FAILURE;
|
|
||||||
|
|
||||||
//Read our config:
|
|
||||||
Game::config = new dConfig("worldconfig.ini");
|
Game::config = new dConfig("worldconfig.ini");
|
||||||
Game::logger->SetLogToConsole(Game::config->GetValue("log_to_console") != "0");
|
|
||||||
Game::logger->SetLogDebugStatements(Game::config->GetValue("log_debug_statements") == "1");
|
//Create all the objects we need to run our service:
|
||||||
|
Server::SetupLogger("WorldServer_" + std::to_string(zoneID) + "_" + std::to_string(instanceID));
|
||||||
|
if (!Game::logger) return EXIT_FAILURE;
|
||||||
|
|
||||||
LOG("Starting World server...");
|
LOG("Starting World server...");
|
||||||
LOG("Version: %s", Game::projectVersion.c_str());
|
LOG("Version: %s", Game::projectVersion.c_str());
|
||||||
@ -412,7 +410,7 @@ int main(int argc, char** argv) {
|
|||||||
//Check for packets here:
|
//Check for packets here:
|
||||||
packet = Game::server->ReceiveFromMaster();
|
packet = Game::server->ReceiveFromMaster();
|
||||||
if (packet) { //We can get messages not handle-able by the dServer class, so handle them if we returned anything.
|
if (packet) { //We can get messages not handle-able by the dServer class, so handle them if we returned anything.
|
||||||
HandlePacket(packet);
|
HandleMasterPacket(packet);
|
||||||
Game::server->DeallocateMasterPacket(packet);
|
Game::server->DeallocateMasterPacket(packet);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -529,18 +527,6 @@ int main(int argc, char** argv) {
|
|||||||
return EXIT_SUCCESS;
|
return EXIT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger* SetupLogger(uint32_t zoneID, uint32_t instanceID) {
|
|
||||||
std::string logPath = (BinaryPathFinder::GetBinaryDir() / ("logs/WorldServer_" + std::to_string(zoneID) + "_" + std::to_string(instanceID) + "_" + std::to_string(time(nullptr)) + ".log")).string();
|
|
||||||
bool logToConsole = false;
|
|
||||||
bool logDebugStatements = false;
|
|
||||||
#ifdef _DEBUG
|
|
||||||
logToConsole = true;
|
|
||||||
logDebugStatements = true;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
return new Logger(logPath, logToConsole, logDebugStatements);
|
|
||||||
}
|
|
||||||
|
|
||||||
void HandlePacketChat(Packet* packet) {
|
void HandlePacketChat(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
LOG("Lost our connection to chat, zone(%i), instance(%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
LOG("Lost our connection to chat, zone(%i), instance(%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
||||||
@ -672,6 +658,138 @@ void HandlePacketChat(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void HandleMasterPacket(Packet* packet) {
|
||||||
|
|
||||||
|
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::MASTER || packet->length < 4) return;
|
||||||
|
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
||||||
|
case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
||||||
|
uint64_t requestID = PacketUtils::ReadU64(8, packet);
|
||||||
|
uint32_t objectID = PacketUtils::ReadU32(16, packet);
|
||||||
|
ObjectIDManager::HandleRequestPersistentIDResponse(requestID, objectID);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eMasterMessageType::SESSION_KEY_RESPONSE: {
|
||||||
|
//Read our session key and to which user it belongs:
|
||||||
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
|
uint64_t header = inStream.Read(header);
|
||||||
|
uint32_t sessionKey = 0;
|
||||||
|
std::string username;
|
||||||
|
|
||||||
|
inStream.Read(sessionKey);
|
||||||
|
username = PacketUtils::ReadString(12, packet, false);
|
||||||
|
|
||||||
|
//Find them:
|
||||||
|
auto it = m_PendingUsers.find(username);
|
||||||
|
if (it == m_PendingUsers.end()) return;
|
||||||
|
|
||||||
|
//Convert our key:
|
||||||
|
std::string userHash = std::to_string(sessionKey);
|
||||||
|
userHash = md5(userHash);
|
||||||
|
|
||||||
|
//Verify it:
|
||||||
|
if (userHash != it->second.hash) {
|
||||||
|
LOG("SOMEONE IS TRYING TO HACK? SESSION KEY MISMATCH: ours: %s != master: %s", userHash.c_str(), it->second.hash.c_str());
|
||||||
|
Game::server->Disconnect(it->second.sysAddr, eServerDisconnectIdentifiers::INVALID_SESSION_KEY);
|
||||||
|
return;
|
||||||
|
} else {
|
||||||
|
LOG("User %s authenticated with correct key.", username.c_str());
|
||||||
|
|
||||||
|
UserManager::Instance()->DeleteUser(packet->systemAddress);
|
||||||
|
|
||||||
|
//Create our user and send them in:
|
||||||
|
UserManager::Instance()->CreateUser(it->second.sysAddr, username, userHash);
|
||||||
|
|
||||||
|
auto zone = Game::zoneManager->GetZone();
|
||||||
|
if (zone) {
|
||||||
|
float x = 0.0f;
|
||||||
|
float y = 0.0f;
|
||||||
|
float z = 0.0f;
|
||||||
|
|
||||||
|
if (zone->GetZoneID().GetMapID() == 1100) {
|
||||||
|
auto pos = zone->GetSpawnPos();
|
||||||
|
x = pos.x;
|
||||||
|
y = pos.y;
|
||||||
|
z = pos.z;
|
||||||
|
}
|
||||||
|
|
||||||
|
WorldPackets::SendLoadStaticZone(it->second.sysAddr, x, y, z, zone->GetChecksum());
|
||||||
|
}
|
||||||
|
|
||||||
|
if (Game::server->GetZoneID() == 0) {
|
||||||
|
//Since doing this reroute breaks the client's request, we have to call this manually.
|
||||||
|
UserManager::Instance()->RequestCharacterList(it->second.sysAddr);
|
||||||
|
}
|
||||||
|
|
||||||
|
m_PendingUsers.erase(username);
|
||||||
|
|
||||||
|
//Notify master:
|
||||||
|
{
|
||||||
|
CBITSTREAM;
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_ADDED);
|
||||||
|
bitStream.Write((LWOMAPID)Game::server->GetZoneID());
|
||||||
|
bitStream.Write((LWOINSTANCEID)instanceID);
|
||||||
|
Game::server->SendToMaster(&bitStream);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case eMasterMessageType::AFFIRM_TRANSFER_REQUEST: {
|
||||||
|
const uint64_t requestID = PacketUtils::ReadU64(8, packet);
|
||||||
|
|
||||||
|
LOG("Got affirmation request of transfer %llu", requestID);
|
||||||
|
|
||||||
|
CBITSTREAM;
|
||||||
|
|
||||||
|
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE);
|
||||||
|
bitStream.Write(requestID);
|
||||||
|
Game::server->SendToMaster(&bitStream);
|
||||||
|
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eMasterMessageType::SHUTDOWN: {
|
||||||
|
Game::lastSignal = -1;
|
||||||
|
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
case eMasterMessageType::NEW_SESSION_ALERT: {
|
||||||
|
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||||
|
uint64_t header = inStream.Read(header);
|
||||||
|
uint32_t sessionKey = inStream.Read(sessionKey);
|
||||||
|
|
||||||
|
std::string username;
|
||||||
|
|
||||||
|
uint32_t len;
|
||||||
|
inStream.Read(len);
|
||||||
|
|
||||||
|
for (uint32_t i = 0; i < len; i++) {
|
||||||
|
char character; inStream.Read<char>(character);
|
||||||
|
username += character;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Find them:
|
||||||
|
User* user = UserManager::Instance()->GetUser(username.c_str());
|
||||||
|
if (!user) {
|
||||||
|
LOG("Got new session alert for user %s, but they're not logged in.", username.c_str());
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
//Check the key:
|
||||||
|
if (sessionKey != std::atoi(user->GetSessionKey().c_str())) {
|
||||||
|
LOG("Got new session alert for user %s, but the session key is invalid.", username.c_str());
|
||||||
|
Game::server->Disconnect(user->GetSystemAddress(), eServerDisconnectIdentifiers::INVALID_SESSION_KEY);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
LOG("Unknown packet ID from master %i", int(packet->data[3]));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void HandlePacket(Packet* packet) {
|
void HandlePacket(Packet* packet) {
|
||||||
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
if (packet->data[0] == ID_DISCONNECTION_NOTIFICATION || packet->data[0] == ID_CONNECTION_LOST) {
|
||||||
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
|
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||||
@ -730,145 +848,6 @@ void HandlePacket(Packet* packet) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::MASTER) {
|
|
||||||
switch (static_cast<eMasterMessageType>(packet->data[3])) {
|
|
||||||
case eMasterMessageType::REQUEST_PERSISTENT_ID_RESPONSE: {
|
|
||||||
uint64_t requestID = PacketUtils::ReadU64(8, packet);
|
|
||||||
uint32_t objectID = PacketUtils::ReadU32(16, packet);
|
|
||||||
ObjectIDManager::HandleRequestPersistentIDResponse(requestID, objectID);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case eMasterMessageType::REQUEST_ZONE_TRANSFER_RESPONSE: {
|
|
||||||
uint64_t requestID = PacketUtils::ReadU64(8, packet);
|
|
||||||
ZoneInstanceManager::Instance()->HandleRequestZoneTransferResponse(requestID, packet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case eMasterMessageType::SESSION_KEY_RESPONSE: {
|
|
||||||
//Read our session key and to which user it belongs:
|
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
|
||||||
uint64_t header = inStream.Read(header);
|
|
||||||
uint32_t sessionKey = 0;
|
|
||||||
std::string username;
|
|
||||||
|
|
||||||
inStream.Read(sessionKey);
|
|
||||||
username = PacketUtils::ReadString(12, packet, false);
|
|
||||||
|
|
||||||
//Find them:
|
|
||||||
auto it = m_PendingUsers.find(username);
|
|
||||||
if (it == m_PendingUsers.end()) return;
|
|
||||||
|
|
||||||
//Convert our key:
|
|
||||||
std::string userHash = std::to_string(sessionKey);
|
|
||||||
userHash = md5(userHash);
|
|
||||||
|
|
||||||
//Verify it:
|
|
||||||
if (userHash != it->second.hash) {
|
|
||||||
LOG("SOMEONE IS TRYING TO HACK? SESSION KEY MISMATCH: ours: %s != master: %s", userHash.c_str(), it->second.hash.c_str());
|
|
||||||
Game::server->Disconnect(it->second.sysAddr, eServerDisconnectIdentifiers::INVALID_SESSION_KEY);
|
|
||||||
return;
|
|
||||||
} else {
|
|
||||||
LOG("User %s authenticated with correct key.", username.c_str());
|
|
||||||
|
|
||||||
UserManager::Instance()->DeleteUser(packet->systemAddress);
|
|
||||||
|
|
||||||
//Create our user and send them in:
|
|
||||||
UserManager::Instance()->CreateUser(it->second.sysAddr, username, userHash);
|
|
||||||
|
|
||||||
auto zone = Game::zoneManager->GetZone();
|
|
||||||
if (zone) {
|
|
||||||
float x = 0.0f;
|
|
||||||
float y = 0.0f;
|
|
||||||
float z = 0.0f;
|
|
||||||
|
|
||||||
if (zone->GetZoneID().GetMapID() == 1100) {
|
|
||||||
auto pos = zone->GetSpawnPos();
|
|
||||||
x = pos.x;
|
|
||||||
y = pos.y;
|
|
||||||
z = pos.z;
|
|
||||||
}
|
|
||||||
|
|
||||||
WorldPackets::SendLoadStaticZone(it->second.sysAddr, x, y, z, zone->GetChecksum());
|
|
||||||
}
|
|
||||||
|
|
||||||
if (Game::server->GetZoneID() == 0) {
|
|
||||||
//Since doing this reroute breaks the client's request, we have to call this manually.
|
|
||||||
UserManager::Instance()->RequestCharacterList(it->second.sysAddr);
|
|
||||||
}
|
|
||||||
|
|
||||||
m_PendingUsers.erase(username);
|
|
||||||
|
|
||||||
//Notify master:
|
|
||||||
{
|
|
||||||
CBITSTREAM;
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::PLAYER_ADDED);
|
|
||||||
bitStream.Write((LWOMAPID)Game::server->GetZoneID());
|
|
||||||
bitStream.Write((LWOINSTANCEID)instanceID);
|
|
||||||
Game::server->SendToMaster(&bitStream);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case eMasterMessageType::AFFIRM_TRANSFER_REQUEST: {
|
|
||||||
const uint64_t requestID = PacketUtils::ReadU64(8, packet);
|
|
||||||
|
|
||||||
LOG("Got affirmation request of transfer %llu", requestID);
|
|
||||||
|
|
||||||
CBITSTREAM;
|
|
||||||
|
|
||||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::MASTER, eMasterMessageType::AFFIRM_TRANSFER_RESPONSE);
|
|
||||||
bitStream.Write(requestID);
|
|
||||||
Game::server->SendToMaster(&bitStream);
|
|
||||||
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case eMasterMessageType::SHUTDOWN: {
|
|
||||||
Game::lastSignal = -1;
|
|
||||||
LOG("Got shutdown request from master, zone (%i), instance (%i)", Game::server->GetZoneID(), Game::server->GetInstanceID());
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
case eMasterMessageType::NEW_SESSION_ALERT: {
|
|
||||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
|
||||||
uint64_t header = inStream.Read(header);
|
|
||||||
uint32_t sessionKey = inStream.Read(sessionKey);
|
|
||||||
|
|
||||||
std::string username;
|
|
||||||
|
|
||||||
uint32_t len;
|
|
||||||
inStream.Read(len);
|
|
||||||
|
|
||||||
for (uint32_t i = 0; i < len; i++) {
|
|
||||||
char character; inStream.Read<char>(character);
|
|
||||||
username += character;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Find them:
|
|
||||||
User* user = UserManager::Instance()->GetUser(username.c_str());
|
|
||||||
if (!user) {
|
|
||||||
LOG("Got new session alert for user %s, but they're not logged in.", username.c_str());
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
//Check the key:
|
|
||||||
if (sessionKey != std::atoi(user->GetSessionKey().c_str())) {
|
|
||||||
LOG("Got new session alert for user %s, but the session key is invalid.", username.c_str());
|
|
||||||
Game::server->Disconnect(user->GetSystemAddress(), eServerDisconnectIdentifiers::INVALID_SESSION_KEY);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
default:
|
|
||||||
LOG("Unknown packet ID from master %i", int(packet->data[3]));
|
|
||||||
}
|
|
||||||
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::WORLD) return;
|
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::WORLD) return;
|
||||||
|
|
||||||
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
switch (static_cast<eWorldMessageType>(packet->data[3])) {
|
||||||
|
@ -1,3 +1,4 @@
|
|||||||
|
|
||||||
# In-game commands
|
# In-game commands
|
||||||
* All commands are prefixed by `/` and typed in the in-game chat window. Some commands require elevated gmlevel privileges. Operands within `<>` are required, operands within `()` are not.
|
* All commands are prefixed by `/` and typed in the in-game chat window. Some commands require elevated gmlevel privileges. Operands within `<>` are required, operands within `()` are not.
|
||||||
|
|
||||||
@ -5,34 +6,34 @@
|
|||||||
|
|
||||||
|Command|Usage|Description|Admin Level Requirement|
|
|Command|Usage|Description|Admin Level Requirement|
|
||||||
|--- |--- |--- |--- |
|
|--- |--- |--- |--- |
|
||||||
|credits|`/credits`|Displays the names of the people behind Darkflame Universe.||
|
|credits|`/credits`|Displays the names of the people behind Darkflame Universe.|0|
|
||||||
|die|`/die`|Smashes the player.||
|
|die|`/die`|Smashes the player.|0|
|
||||||
|info|`/info`|Displays server info to the user, including where to find the server's source code.||
|
|info|`/info`|Displays server info to the user, including where to find the server's source code.|0|
|
||||||
|instanceinfo|`/instanceinfo`|Displays in the chat the current zone, clone, and instance id.||
|
|instanceinfo|`/instanceinfo`|Displays in the chat the current zone, clone, and instance id.|0|
|
||||||
|ping|`/ping (-l)`|Displays in chat your average ping. If the `-l` flag is used, the latest ping is displayed.||
|
|ping|`/ping (-l)`|Displays in chat your average ping. If the `-l` flag is used, the latest ping is displayed.||
|
||||||
|pvp|`/pvp`|Toggle your PVP flag.||
|
|pvp|`/pvp`|Toggle your PVP flag.|0|
|
||||||
|resurrect|`/resurrect`|Resurrects the player.||
|
|resurrect|`/resurrect`|Resurrects the player.|0|
|
||||||
|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox.||
|
|requestmailcount|`/requestmailcount`|Sends notification with number of unread messages in the player's mailbox.|0|
|
||||||
|who|`/who`|Displays in chat all players on the instance.||
|
|who|`/who`|Displays in chat all players on the instance.|0|
|
||||||
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on.|8 or if `allow_nameplate_off` is set to exactly `1` in the settings|
|
|togglenameplate|`/togglenameplate`|Turns the nameplate above your head that is visible to other players off and on.|8 unless `allow_nameplate_off` is set to exactly `1` in the settings then admin level requirement is 0|
|
||||||
|toggleskipcinematics|`/toggleskipcinematics`|Skips mission and world load related cinematics.|8 or if `allow_players_to_skip_cinematics` is set to exactly `1` in the settings then 0|
|
|toggleskipcinematics|`/toggleskipcinematics`|Skips mission and world load related cinematics.|8 unless `allow_players_to_skip_cinematics` is set to exactly `1` in the settings then admin level requirement is 0|
|
||||||
|
|
||||||
## Moderation Commands
|
## Moderation Commands
|
||||||
|
|
||||||
|Command|Usage|Description|Admin Level Requirement|
|
|Command|Usage|Description|Admin Level Requirement|
|
||||||
|--- |--- |--- |--- |
|
|--- |--- |--- |--- |
|
||||||
|gmlevel|`/gmlevel <level>`|Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands. Aliases: `/setgmlevel`, `/makegm`.||
|
|gmlevel|`/gmlevel <level>`|Within the authorized range of levels for the current account, changes the character's game master level to the specified value. This is required to use certain commands. Aliases: `/setgmlevel`, `/makegm`.|Account GM level greater than 0|
|
||||||
|kick|`/kick <username>`|Kicks the player off the server.|2|
|
|kick|`/kick <username>`|Kicks the player off the server.|2|
|
||||||
|mailitem|`/mailitem <player name> <item id>`|Mails an item to the given player. The mailed item has predetermined content. The sender name is set to "Darkflame Universe." The title of the message is "Lost item." The body of the message is "This is a replacement item for one you lost."|3|
|
|mailitem|`/mailitem <player name> <item id>`|Mails an item to the given player. The mailed item has predetermined content. The sender name is set to "Darkflame Universe." The title of the message is "Lost item." The body of the message is "This is a replacement item for one you lost."|3|
|
||||||
|ban|`/ban <username>`|Bans a user from the server.|4|
|
|ban|`/ban <username>`|Bans a user from the server.|4|
|
||||||
|approveproperty|`/approveproperty`|Approves the property the player is currently visiting.|5|
|
|approveproperty|`/approveproperty`|Approves the property the player is currently visiting.|5|
|
||||||
|mute|`/mute <username> (days) (hours)`|Mute player for the given amount of time. If no time is given, the mute is indefinite.|6|
|
|mute|`/mute <username> (days) (hours)`|Mute player for the given amount of time. If no time is given, the mute is indefinite.|6|
|
||||||
|
|fly|`/fly <speed>`|This toggles your flying state with an optional parameter for the speed scale.|6|
|
||||||
|attackimmune|`/attackimmune <value>`|Sets the character's immunity to basic attacks state, where value can be one of "1", to make yourself immune to basic attack damage, or "0" to undo.|8|
|
|attackimmune|`/attackimmune <value>`|Sets the character's immunity to basic attacks state, where value can be one of "1", to make yourself immune to basic attack damage, or "0" to undo.|8|
|
||||||
|gmimmune|`/gmimmunve <value>`|Sets the character's GMImmune state, where value can be one of "1", to make yourself immune to damage, or "0" to undo.|8|
|
|gmimmune|`/gmimmunve <value>`|Sets the character's GMImmune state, where value can be one of "1", to make yourself immune to damage, or "0" to undo.|8|
|
||||||
|gminvis|`/gminvis`|Toggles invisibility for the character, though it's currently a bit buggy. Requires nonzero GM Level for the character, but the account must have a GM level of 8.|8|
|
|gminvis|`/gminvis`|Toggles invisibility for the character, though it's currently a bit buggy. Requires nonzero GM Level for the character, but the account must have a GM level of 8.|8|
|
||||||
|setname|`/setname <name>`|Sets a temporary name for your player. The name resets when you log out.|8|
|
|setname|`/setname <name>`|Sets a temporary name for your player. The name resets when you log out.|8|
|
||||||
|title|`/title <title>`|Temporarily appends your player's name with " - <title>". This resets when you log out.|8|
|
|title|`/title <title>`|Temporarily appends your player's name with " - <title>". This resets when you log out.|8|
|
||||||
|fly|`/fly <speed>`|This toggles your flying state with an optional parameter for the speed scale.|4|
|
|
||||||
|
|
||||||
## Server Operation Commands
|
## Server Operation Commands
|
||||||
|
|
||||||
@ -51,14 +52,14 @@ These commands are primarily for development and testing. The usage of many of t
|
|||||||
|
|
||||||
|Command|Usage|Description|Admin Level Requirement|
|
|Command|Usage|Description|Admin Level Requirement|
|
||||||
|--- |--- |--- |--- |
|
|--- |--- |--- |--- |
|
||||||
|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables.||
|
|fix-stats|`/fix-stats`|Resets skills, buffs, and destroyables.|0|
|
||||||
|join|`/join <password>`|Joins a private zone with given password.||
|
|join|`/join <password>`|Joins a private zone with given password.|0|
|
||||||
|leave-zone|`/leave-zone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station.||
|
|leave-zone|`/leave-zone` or <br> `/leavezone`|If you are in an instanced zone, transfers you to the closest main world. For example, if you are in an instance of Avant Gardens Survival or the Spider Queen Battle, you are sent to Avant Gardens. If you are in the Battle of Nimbus Station, you are sent to Nimbus Station.|0|
|
||||||
|setminifig|`/setminifig <body part> <minifig item id>`|Alters your player's minifig. Body part can be one of "Eyebrows", "Eyes", "HairColor", "HairStyle", "Pants", "LeftHand", "Mouth", "RightHand", "Shirt", or "Hands". Changing minifig parts could break the character so this command is limited to GMs.|1|
|
|setminifig|`/setminifig <body part> <minifig item id>`|Alters your player's minifig. Body part can be one of "Eyebrows", "Eyes", "HairColor", "HairStyle", "Pants", "LeftHand", "Mouth", "RightHand", "Shirt", or "Hands". Changing minifig parts could break the character so this command is limited to GMs.|1|
|
||||||
|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh).|1|
|
|testmap|`/testmap <zone> (force) (clone-id)`|Transfers you to the given zone by id and clone id. Add "force" to skip checking if the zone is accessible (this can softlock your character, though, if you e.g. try to teleport to Frostburgh).|1|
|
||||||
|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|6|
|
|reportproxphys|`/reportproxphys`|Prints to console the position and radius of proximity sensors.|6|
|
||||||
|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects.|6|
|
|spawnphysicsverts|`/spawnphysicsverts`|Spawns a 1x1 brick at all vertices of phantom physics objects.|6|
|
||||||
|teleport|`/teleport <x> (y) <z>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Alias: `/tele`.|6|
|
|teleport|`/teleport <x> (y) <z>` or <br> `/tele <x> (y) <z>`|Teleports you. If no Y is given, you are teleported to the height of the terrain or physics object at (x, z). Alias: `/tele`.|6|
|
||||||
|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name.|8|
|
|activatespawner|`/activatespawner <spawner name>`|Activates spawner by name.|8|
|
||||||
|addmission|`/addmission <mission id>`|Accepts the mission, adding it to your journal.|8|
|
|addmission|`/addmission <mission id>`|Accepts the mission, adding it to your journal.|8|
|
||||||
|boost|`/boost (time)`|Adds a passive boost action if you are in a vehicle. If time is given it will end after that amount of time|8|
|
|boost|`/boost (time)`|Adds a passive boost action if you are in a vehicle. If time is given it will end after that amount of time|8|
|
||||||
@ -96,9 +97,10 @@ These commands are primarily for development and testing. The usage of many of t
|
|||||||
|setcontrolscheme|`/setcontrolscheme <scheme number>`|Sets the character control scheme to the specified number.|8|
|
|setcontrolscheme|`/setcontrolscheme <scheme number>`|Sets the character control scheme to the specified number.|8|
|
||||||
|setcurrency|`/setcurrency <coins>`|Sets your coins.|8|
|
|setcurrency|`/setcurrency <coins>`|Sets your coins.|8|
|
||||||
|setflag|`/setflag (value) <flag id>`|Sets the given inventory or health flag to the given value, where value can be one of "on" or "off". If no value is given, by default this adds the flag to your character (equivalent of calling `/setflag on <flag id>`).|8|
|
|setflag|`/setflag (value) <flag id>`|Sets the given inventory or health flag to the given value, where value can be one of "on" or "off". If no value is given, by default this adds the flag to your character (equivalent of calling `/setflag on <flag id>`).|8|
|
||||||
|setinventorysize|`/setinventorysize <size> (inventory)`|Sets your inventory size to the given size. If `inventory` is provided, the number or string will be used to set that inventory to the requested size. Alias: `/setinvsize`|8|
|
|setinventorysize|`/setinventorysize <size> (inventory)` or <br> `/setinvsize <size> (inventory)`|Sets your inventory size to the given size. If `inventory` is provided, the number or string will be used to set that inventory to the requested size. Alias: `/setinvsize`|8|
|
||||||
|setuistate|`/setuistate <ui state>`|Changes UI state.|8|
|
|setuistate|`/setuistate <ui state>`|Changes UI state.|8|
|
||||||
|spawn|`/spawn <id>`|Spawns an object at your location by id.|8|
|
|spawn|`/spawn <id>`|Spawns an object at your location by id.|8|
|
||||||
|
|spawngroup|`/spawngroup <id> <amount> <radius>`|Spawns `<amount>` of object `<id>` within the given `<radius>` from your location|8|
|
||||||
|speedboost|`/speedboost <amount>`|Sets the speed multiplier to the given amount. `/speedboost 1.5` will set the speed multiplier to 1.5x the normal speed.|8|
|
|speedboost|`/speedboost <amount>`|Sets the speed multiplier to the given amount. `/speedboost 1.5` will set the speed multiplier to 1.5x the normal speed.|8|
|
||||||
|startcelebration|`/startcelebration <id>`|Starts a celebration effect on your character.|8|
|
|startcelebration|`/startcelebration <id>`|Starts a celebration effect on your character.|8|
|
||||||
|stopeffect|`/stopeffect <effect id>`|Stops the given effect.|8|
|
|stopeffect|`/stopeffect <effect id>`|Stops the given effect.|8|
|
||||||
@ -107,14 +109,15 @@ These commands are primarily for development and testing. The usage of many of t
|
|||||||
|triggerspawner|`/triggerspawner <spawner name>`|Triggers spawner by name.|8|
|
|triggerspawner|`/triggerspawner <spawner name>`|Triggers spawner by name.|8|
|
||||||
|unlock-emote|`/unlock-emote <emote id>`|Unlocks for your character the emote of the given id.|8|
|
|unlock-emote|`/unlock-emote <emote id>`|Unlocks for your character the emote of the given id.|8|
|
||||||
|Set Level|`/setlevel <requested_level> (username)`|Sets the using entities level to the requested level. Takes an optional parameter of an in-game players username to set the level of.|8|
|
|Set Level|`/setlevel <requested_level> (username)`|Sets the using entities level to the requested level. Takes an optional parameter of an in-game players username to set the level of.|8|
|
||||||
|crash|`/crash`|Crashes the server.|9|
|
|
||||||
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|
|
||||||
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|
|
||||||
|setskillslot|`/setskillslot <slot> <skill id>`||8|
|
|setskillslot|`/setskillslot <slot> <skill id>`||8|
|
||||||
|setfaction|`/setfaction <faction id>`|Clears the users current factions and sets it|8|
|
|setfaction|`/setfaction <faction id>`|Clears the users current factions and sets it|8|
|
||||||
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
|addfaction|`/addfaction <faction id>`|Add the faction to the users list of factions|8|
|
||||||
|getfactions|`/getfactions`|Shows the player's factions|8|
|
|getfactions|`/getfactions`|Shows the player's factions|8|
|
||||||
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
|setrewardcode|`/setrewardcode <code>`|Sets the rewardcode for the account you are logged into if it's a valid rewardcode, See cdclient table `RewardCodes`|8|
|
||||||
|
|crash|`/crash`|Crashes the server.|9|
|
||||||
|
|rollloot|`/rollloot <loot matrix index> <item id> <amount>`|Given a `loot matrix index`, look for `item id` in that matrix `amount` times and print to the chat box statistics of rolling that loot matrix.|9|
|
||||||
|
|castskill|`/castskill <skill id>`|Casts the skill as the player|9|
|
||||||
|
|
||||||
## Detailed `/inspect` Usage
|
## Detailed `/inspect` Usage
|
||||||
|
|
||||||
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
`/inspect <component> (-m <waypoint> | -a <animation> | -s | -p | -f (faction) | -t)`
|
||||||
|
@ -116,27 +116,30 @@ TEST(MagicEnumTest, eGameMessageTypeTest) {
|
|||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ASSERT_EARRAY_SORTED(EARRAY_VAR)\
|
#define LOG_EARRAY(EARRAY_VAR, INDICE, ENTRY) LOG(#EARRAY_VAR"[%i] = %i, %s", INDICE, ENTRY, magic_enum::enum_name(ENTRY).data());
|
||||||
for (int i = 0; i < EARRAY_VAR->size(); i++) {\
|
|
||||||
const auto entryCurr = EARRAY_VAR->at(i).first;\
|
|
||||||
LOG_EARRAY(EARRAY_VAR, i, entryCurr);\
|
|
||||||
const auto entryNext = EARRAY_VAR->at(++i).first;\
|
|
||||||
LOG_EARRAY(EARRAY_VAR, i, entryNext);\
|
|
||||||
ASSERT_TRUE(entryCurr < entryNext);\
|
|
||||||
};\
|
|
||||||
|
|
||||||
#define LOG_EARRAY(EARRAY_VAR, INDICE, ENTRY)\
|
namespace {
|
||||||
LOG(#EARRAY_VAR"[%i] = %i, %s", INDICE, ENTRY, magic_enum::enum_name(ENTRY).data());
|
template <typename T>
|
||||||
|
void AssertEnumArraySorted(const T& eArray) {
|
||||||
|
for (int i = 0; i < eArray->size(); ++i) {
|
||||||
|
const auto entryCurr = eArray->at(i).first;
|
||||||
|
LOG_EARRAY(eArray, i, entryCurr);
|
||||||
|
const auto entryNext = eArray->at(++i).first;
|
||||||
|
LOG_EARRAY(eArray, i, entryNext);
|
||||||
|
ASSERT_TRUE(entryCurr < entryNext);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Test that the magic enum arrays are pre-sorted
|
// Test that the magic enum arrays are pre-sorted
|
||||||
TEST(MagicEnumTest, ArraysAreSorted) {
|
TEST(MagicEnumTest, ArraysAreSorted) {
|
||||||
Game::logger = new Logger("./MagicEnumTest_ArraysAreSorted.log", true, true);
|
Game::logger = new Logger("./MagicEnumTest_ArraysAreSorted.log", true, true);
|
||||||
|
|
||||||
constexpr auto wmArray = &magic_enum::enum_entries<eWorldMessageType>();
|
constexpr auto wmArray = &magic_enum::enum_entries<eWorldMessageType>();
|
||||||
ASSERT_EARRAY_SORTED(wmArray);
|
AssertEnumArraySorted(wmArray);
|
||||||
|
|
||||||
constexpr auto gmArray = &magic_enum::enum_entries<eGameMessageType>();
|
constexpr auto gmArray = &magic_enum::enum_entries<eGameMessageType>();
|
||||||
ASSERT_EARRAY_SORTED(gmArray);
|
AssertEnumArraySorted(gmArray);
|
||||||
|
|
||||||
delete Game::logger;
|
delete Game::logger;
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user