Compare commits

...

13 Commits

Author SHA1 Message Date
David Markowitz
48d37d00ab Merge branch 'player-stuff-3' into I-love-players 2024-01-14 01:49:10 -08:00
6592bbea46 chore: remove all raw packet reading from chat packet handler (#1415)
* chore: default size to 33 on LU(W)Strings since that's the most common lenght
Was doing this on other places, but not the main one

* chore: remove all raw packet reading from chat packet handler

and general chat packet cleanup

* fix team invite/promote/kick

* Address feedback

* fix friends check

* update comments

* Address feedback
Add GM level handeling

* Address feedback
2024-01-14 01:03:01 -06:00
David Markowitz
52ed34de48 Merge branch 'main' into player-stuff-3 2024-01-13 17:37:18 -08:00
David Markowitz
a62f6d63c6 chore: Move static Player functions and internal linkage to manager class (#1412)
* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.

* Moving and organizing Player code

- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.
- Remove static storage container (static containers can be destroyed before exit/terminate handler executes)

* remove player cast

* Remove extra includes

* Add a player manager

Used for the static Player functions.  Further removes stuff from the Player class/file.
2024-01-13 03:40:56 -06:00
David Markowitz
d77c0cd409 move to unordered_set 2024-01-13 01:30:47 -08:00
David Markowitz
d3eb5a56d9 chore: Move ghosting functionality to component
Tested that ghosting still works and players are still firing off the OnPlayerLeave and relevant handlers.
2024-01-12 22:56:03 -08:00
David Markowitz
1c5b8cc265 Merge branch 'main' into player-stuff-2 2024-01-12 21:47:46 -08:00
David Markowitz
ee01d13969 Add a player manager
Used for the static Player functions.  Further removes stuff from the Player class/file.
2024-01-12 04:33:36 -08:00
David Markowitz
0dd3cce8ed Remove extra includes 2024-01-12 03:26:33 -08:00
David Markowitz
87d5bd0229 remove player cast 2024-01-12 03:17:01 -08:00
David Markowitz
f4a6086e4c Merge branch 'player-stuff' of https://github.com/DarkflameUniverse/DarkflameServer into player-stuff 2024-01-11 04:35:00 -08:00
David Markowitz
eccd6f691f Moving and organizing Player code
- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.
- Remove static storage container (static containers can be destroyed before exit/terminate handler executes)
2024-01-11 04:34:55 -08:00
David Markowitz
a54085945f Moving and organizing Player code
- Move code to CharacterComponent
- Remove extraneous interfaces
- Simplify some code greatly
- Change some types to return and take in const ref (only structs larger than 8 bytes benefit from this change.)
- Update code to use CharacterComponent for sending to zone instead of Player*.
2024-01-11 04:33:53 -08:00
23 changed files with 567 additions and 435 deletions

View File

@@ -2,7 +2,6 @@
#include "PlayerContainer.h"
#include "Database.h"
#include <vector>
#include "PacketUtils.h"
#include "BitStreamUtils.h"
#include "Game.h"
#include "dServer.h"
@@ -18,6 +17,8 @@
#include "eChatInternalMessageType.h"
#include "eClientMessageType.h"
#include "eGameMessageType.h"
#include "StringifiedEnum.h"
#include "eGameMasterLevel.h"
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
//Get from the packet which player we want to do something with:
@@ -78,31 +79,27 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID requestorPlayerID;
inStream.Read(requestorPlayerID);
uint32_t spacing{};
inStream.Read(spacing);
std::string playerName = "";
uint16_t character;
bool noMoreLettersInName = false;
for (uint32_t j = 0; j < 33; j++) {
inStream.Read(character);
if (character == '\0') noMoreLettersInName = true;
if (!noMoreLettersInName) playerName.push_back(static_cast<char>(character));
}
LUWString LUplayerName;
char isBestFriendRequest{};
inStream.Read(requestorPlayerID);
inStream.IgnoreBytes(4);
inStream.Read(LUplayerName);
inStream.Read(isBestFriendRequest);
auto playerName = LUplayerName.GetAsString();
auto& requestor = Game::playerContainer.GetPlayerDataMutable(requestorPlayerID);
if (!requestor) {
LOG("No requestor player %llu sent to %s found.", requestorPlayerID, playerName.c_str());
return;
}
// you cannot friend yourself
if (requestor.playerName == playerName) {
SendFriendResponse(requestor, requestor, eAddFriendResponseType::MYTHRAN);
SendFriendResponse(requestor, requestor, eAddFriendResponseType::GENERALERROR);
return;
};
@@ -141,6 +138,13 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
return;
}
// Prevent GM friend spam
// If the player we are trying to be friends with is not a civilian and we are a civilian, abort the process
if (requestee.gmLevel > eGameMasterLevel::CIVILIAN && requestor.gmLevel == eGameMasterLevel::CIVILIAN ) {
SendFriendResponse(requestor, requestee, eAddFriendResponseType::MYTHRAN);
return;
}
if (isBestFriendRequest) {
uint8_t oldBestFriendStatus{};
@@ -218,15 +222,19 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
eAddFriendResponseCode clientResponseCode = static_cast<eAddFriendResponseCode>(packet->data[0x14]);
std::string friendName = PacketUtils::ReadString(0x15, packet, true);
LWOOBJID playerID;
eAddFriendResponseCode clientResponseCode;
LUWString friendName;
inStream.Read(playerID);
inStream.IgnoreBytes(4);
inStream.Read(clientResponseCode);
inStream.Read(friendName);
//Now to try and find both of these:
auto& requestor = Game::playerContainer.GetPlayerDataMutable(playerID);
auto& requestee = Game::playerContainer.GetPlayerDataMutable(friendName);
auto& requestee = Game::playerContainer.GetPlayerDataMutable(friendName.GetAsString());
if (!requestor || !requestee) return;
eAddFriendResponseType serverResponseCode{};
@@ -288,8 +296,11 @@ void ChatPacketHandler::HandleFriendResponse(Packet* packet) {
void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
LUWString LUFriendName;
inStream.Read(playerID);
std::string friendName = PacketUtils::ReadString(0x14, packet, true);
inStream.IgnoreBytes(4);
inStream.Read(LUFriendName);
auto friendName = LUFriendName.GetAsString();
//we'll have to query the db here to find the user, since you can delete them while they're offline.
//First, we need to find their ID:
@@ -335,123 +346,144 @@ void ChatPacketHandler::HandleRemoveFriend(Packet* packet) {
SendRemoveFriend(goonB, goonAName, true);
}
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
if (!sender) return;
if (sender.GetIsMuted()) return;
inStream.SetReadOffset(0x14 * 8);
uint8_t channel = 0;
inStream.Read(channel);
std::string message = PacketUtils::ReadString(0x66, packet, true, 512);
LOG("Got a message from (%s) [%d]: %s", sender.playerName.c_str(), channel, message.c_str());
if (channel != 8) return;
auto* team = Game::playerContainer.GetTeam(playerID);
if (team == nullptr) return;
for (const auto memberId : team->memberIDs) {
const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
if (!otherMember) return;
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(otherMember.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(otherMember.playerID);
bitStream.Write<uint8_t>(8);
bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(sender.playerName));
bitStream.Write(sender.playerID);
bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(otherMember.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //teams?
bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = otherMember.sysAddr;
SEND_PACKET;
}
}
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
LWOOBJID senderID = PacketUtils::ReadS64(0x08, packet);
std::string receiverName = PacketUtils::ReadString(0x66, packet, true);
std::string message = PacketUtils::ReadString(0xAA, packet, true, 512);
//Get the bois:
const auto& goonA = Game::playerContainer.GetPlayerData(senderID);
const auto& goonB = Game::playerContainer.GetPlayerData(receiverName);
if (!goonA || !goonB) return;
if (goonA.GetIsMuted()) return;
//To the sender:
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonA.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA.playerID);
bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(goonA.playerName));
bitStream.Write(goonA.playerID);
bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(goonB.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(0); //success
bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonA.sysAddr;
SEND_PACKET;
}
//To the receiver:
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(goonB.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(goonA.playerID);
bitStream.Write<uint8_t>(7);
bitStream.Write<unsigned int>(69);
bitStream.Write(LUWString(goonA.playerName));
bitStream.Write(goonA.playerID);
bitStream.Write<uint16_t>(0);
bitStream.Write<uint8_t>(0); //not mythran nametag
bitStream.Write(LUWString(goonB.playerName));
bitStream.Write<uint8_t>(0); //not mythran for receiver
bitStream.Write<uint8_t>(3); //new whisper
bitStream.Write(LUWString(message, 512));
SystemAddress sysAddr = goonB.sysAddr;
SEND_PACKET;
}
}
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
void ChatPacketHandler::HandleGMLevelUpdate(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
std::string invitedPlayer = PacketUtils::ReadString(0x14, packet, true);
auto& player = Game::playerContainer.GetPlayerData(playerID);
if (!player) return;
inStream.Read(player.gmLevel);
}
// the structure the client uses to send this packet is shared in many chat messages
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
void ChatPacketHandler::HandleChatMessage(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
if (!sender || sender.GetIsMuted()) return;
eChatChannel channel;
uint32_t size;
inStream.IgnoreBytes(4);
inStream.Read(channel);
inStream.Read(size);
inStream.IgnoreBytes(77);
LUWString message(size);
inStream.Read(message);
LOG("Got a message from (%s) via [%s]: %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str());
switch (channel) {
case eChatChannel::TEAM: {
auto* team = Game::playerContainer.GetTeam(playerID);
if (team == nullptr) return;
for (const auto memberId : team->memberIDs) {
const auto& otherMember = Game::playerContainer.GetPlayerData(memberId);
if (!otherMember) return;
SendPrivateChatMessage(sender, otherMember, otherMember, message, eChatChannel::TEAM, eChatMessageResponseCode::SENT);
}
break;
}
default:
LOG("Unhandled Chat channel [%s]", StringifiedEnum::ToString(channel).data());
break;
}
}
// the structure the client uses to send this packet is shared in many chat messages
// that are sent to the server. Because of this, there are large gaps of unused data in chat messages
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
inStream.Read(playerID);
const auto& sender = Game::playerContainer.GetPlayerData(playerID);
if (!sender || sender.GetIsMuted()) return;
eChatChannel channel;
uint32_t size;
LUWString LUReceiverName;
inStream.IgnoreBytes(4);
inStream.Read(channel);
if (channel != eChatChannel::PRIVATE_CHAT) LOG("WARNING: Received Private chat with the wrong channel!");
inStream.Read(size);
inStream.IgnoreBytes(77);
inStream.Read(LUReceiverName);
auto receiverName = LUReceiverName.GetAsString();
inStream.IgnoreBytes(2);
LUWString message(size);
inStream.Read(message);
LOG("Got a message from (%s) via [%s]: %s to %s", sender.playerName.c_str(), StringifiedEnum::ToString(channel).data(), message.GetAsString().c_str(), receiverName.c_str());
const auto& receiver = Game::playerContainer.GetPlayerData(receiverName);
if (!receiver) {
PlayerData otherPlayer;
otherPlayer.playerName = receiverName;
auto responseType = Database::Get()->GetCharacterInfo(receiverName)
? eChatMessageResponseCode::NOTONLINE
: eChatMessageResponseCode::GENERALERROR;
SendPrivateChatMessage(sender, otherPlayer, sender, message, eChatChannel::GENERAL, responseType);
return;
}
// Check to see if they are friends
// only freinds can whispr each other
for (const auto& fr : receiver.friends) {
if (fr.friendID == sender.playerID) {
//To the sender:
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::SENT);
//To the receiver:
SendPrivateChatMessage(sender, receiver, receiver, message, eChatChannel::PRIVATE_CHAT, eChatMessageResponseCode::RECEIVEDNEWWHISPER);
return;
}
}
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::GENERAL, eChatMessageResponseCode::NOTFRIENDS);
}
void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode) {
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
bitStream.Write(routeTo.playerID);
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
bitStream.Write(sender.playerID);
bitStream.Write(channel);
bitStream.Write<uint32_t>(0); // not used
bitStream.Write(LUWString(sender.playerName));
bitStream.Write(sender.playerID);
bitStream.Write<uint16_t>(0); // sourceID
bitStream.Write(sender.gmLevel);
bitStream.Write(LUWString(receiver.playerName));
bitStream.Write(receiver.gmLevel);
bitStream.Write(responseCode);
bitStream.Write(message);
SystemAddress sysAddr = routeTo.sysAddr;
SEND_PACKET;
}
void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID;
LUWString invitedPlayer;
inStream.Read(playerID);
inStream.IgnoreBytes(4);
inStream.Read(invitedPlayer);
const auto& player = Game::playerContainer.GetPlayerData(playerID);
@@ -463,7 +495,7 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
team = Game::playerContainer.CreateTeam(playerID);
}
const auto& other = Game::playerContainer.GetPlayerData(invitedPlayer);
const auto& other = Game::playerContainer.GetPlayerData(invitedPlayer.GetAsString());
if (!other) return;
@@ -480,7 +512,7 @@ void ChatPacketHandler::HandleTeamInvite(Packet* packet) {
SendTeamInvite(other, player);
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.c_str());
LOG("Got team invite: %llu -> %s", playerID, invitedPlayer.GetAsString().c_str());
}
void ChatPacketHandler::HandleTeamInviteResponse(Packet* packet) {
@@ -534,21 +566,25 @@ void ChatPacketHandler::HandleTeamLeave(Packet* packet) {
void ChatPacketHandler::HandleTeamKick(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
LUWString kickedPlayer;
inStream.Read(playerID);
inStream.IgnoreBytes(4);
inStream.Read(kickedPlayer);
std::string kickedPlayer = PacketUtils::ReadString(0x14, packet, true);
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.c_str());
LOG("(%llu) kicking (%s) from team", playerID, kickedPlayer.GetAsString().c_str());
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer);
const auto& kicked = Game::playerContainer.GetPlayerData(kickedPlayer.GetAsString());
LWOOBJID kickedId = LWOOBJID_EMPTY;
if (kicked) {
kickedId = kicked.playerID;
} else {
kickedId = Game::playerContainer.GetId(GeneralUtils::UTF8ToUTF16(kickedPlayer));
kickedId = Game::playerContainer.GetId(kickedPlayer.string);
}
if (kickedId == LWOOBJID_EMPTY) return;
@@ -564,14 +600,17 @@ void ChatPacketHandler::HandleTeamKick(Packet* packet) {
void ChatPacketHandler::HandleTeamPromote(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
LUWString promotedPlayer;
inStream.Read(playerID);
inStream.IgnoreBytes(4);
inStream.Read(promotedPlayer);
std::string promotedPlayer = PacketUtils::ReadString(0x14, packet, true);
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.GetAsString().c_str());
LOG("(%llu) promoting (%s) to team leader", playerID, promotedPlayer.c_str());
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer);
const auto& promoted = Game::playerContainer.GetPlayerData(promotedPlayer.GetAsString());
if (!promoted) return;

View File

@@ -7,14 +7,53 @@ struct PlayerData;
enum class eAddFriendResponseType : uint8_t;
enum class eChatChannel : uint8_t {
SYSTEMNOTIFY = 0,
SYSTEMWARNING,
SYSTEMERROR,
BROADCAST,
LOCAL,
LOCALNOANIM,
EMOTE,
PRIVATE_CHAT,
TEAM,
TEAMLOCAL,
GUILD,
GUILDNOTIFY,
PROPERTY,
ADMIN,
COMBATDAMAGE,
COMBATHEALING,
COMBATLOOT,
COMBATEXP,
COMBATDEATH,
GENERAL,
TRADE,
LFG,
USER
};
enum class eChatMessageResponseCode : uint8_t {
SENT = 0,
NOTONLINE,
GENERALERROR,
RECEIVEDNEWWHISPER,
NOTFRIENDS,
SENDERFREETRIAL,
RECEIVERFREETRIAL,
};
namespace ChatPacketHandler {
void HandleFriendlistRequest(Packet* packet);
void HandleFriendRequest(Packet* packet);
void HandleFriendResponse(Packet* packet);
void HandleRemoveFriend(Packet* packet);
void HandleGMLevelUpdate(Packet* packet);
void HandleChatMessage(Packet* packet);
void HandlePrivateChatMessage(Packet* packet);
void SendPrivateChatMessage(const PlayerData& sender, const PlayerData& receiver, const PlayerData& routeTo, const LUWString& message, const eChatChannel channel, const eChatMessageResponseCode responseCode);
void HandleTeamInvite(Packet* packet);
void HandleTeamInviteResponse(Packet* packet);

View File

@@ -20,6 +20,7 @@
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "ChatIgnoreList.h"
#include "StringifiedEnum.h"
#include "Game.h"
#include "Server.h"
@@ -223,7 +224,8 @@ void HandlePacket(Packet* packet) {
}
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::CHAT) {
switch (static_cast<eChatMessageType>(packet->data[3])) {
eChatMessageType chat_message_type = static_cast<eChatMessageType>(packet->data[3]);
switch (chat_message_type) {
case eChatMessageType::GET_FRIENDS_LIST:
ChatPacketHandler::HandleFriendlistRequest(packet);
break;
@@ -293,9 +295,61 @@ void HandlePacket(Packet* packet) {
case eChatMessageType::TEAM_SET_LOOT:
ChatPacketHandler::HandleTeamLootOption(packet);
break;
case eChatMessageType::GMLEVEL_UPDATE:
ChatPacketHandler::HandleGMLevelUpdate(packet);
break;
case eChatMessageType::LOGIN_SESSION_NOTIFY:
case eChatMessageType::USER_CHANNEL_CHAT_MESSAGE:
case eChatMessageType::WORLD_DISCONNECT_REQUEST:
case eChatMessageType::WORLD_PROXIMITY_RESPONSE:
case eChatMessageType::WORLD_PARCEL_RESPONSE:
case eChatMessageType::TEAM_MISSED_INVITE_CHECK:
case eChatMessageType::GUILD_CREATE:
case eChatMessageType::GUILD_INVITE:
case eChatMessageType::GUILD_INVITE_RESPONSE:
case eChatMessageType::GUILD_LEAVE:
case eChatMessageType::GUILD_KICK:
case eChatMessageType::GUILD_GET_STATUS:
case eChatMessageType::GUILD_GET_ALL:
case eChatMessageType::SHOW_ALL:
case eChatMessageType::BLUEPRINT_MODERATED:
case eChatMessageType::BLUEPRINT_MODEL_READY:
case eChatMessageType::PROPERTY_READY_FOR_APPROVAL:
case eChatMessageType::PROPERTY_MODERATION_CHANGED:
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED:
case eChatMessageType::PROPERTY_BUILDMODE_CHANGED_REPORT:
case eChatMessageType::MAIL:
case eChatMessageType::WORLD_INSTANCE_LOCATION_REQUEST:
case eChatMessageType::REPUTATION_UPDATE:
case eChatMessageType::SEND_CANNED_TEXT:
case eChatMessageType::CHARACTER_NAME_CHANGE_REQUEST:
case eChatMessageType::CSR_REQUEST:
case eChatMessageType::CSR_REPLY:
case eChatMessageType::GM_KICK:
case eChatMessageType::GM_ANNOUNCE:
case eChatMessageType::WORLD_ROUTE_PACKET:
case eChatMessageType::GET_ZONE_POPULATIONS:
case eChatMessageType::REQUEST_MINIMUM_CHAT_MODE:
case eChatMessageType::MATCH_REQUEST:
case eChatMessageType::UGCMANIFEST_REPORT_MISSING_FILE:
case eChatMessageType::UGCMANIFEST_REPORT_DONE_FILE:
case eChatMessageType::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
case eChatMessageType::UGCC_REQUEST:
case eChatMessageType::WHO:
case eChatMessageType::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
case eChatMessageType::ACHIEVEMENT_NOTIFY:
case eChatMessageType::GM_CLOSE_PRIVATE_CHAT_WINDOW:
case eChatMessageType::UNEXPECTED_DISCONNECT:
case eChatMessageType::PLAYER_READY:
case eChatMessageType::GET_DONATION_TOTAL:
case eChatMessageType::UPDATE_DONATION:
case eChatMessageType::PRG_CSR_COMMAND:
case eChatMessageType::HEARTBEAT_REQUEST_FROM_WORLD:
case eChatMessageType::UPDATE_FREE_TRIAL_STATUS:
LOG("Unhandled CHAT Message id: %s (%i)", StringifiedEnum::ToString(chat_message_type).data(), chat_message_type);
break;
default:
LOG("Unknown CHAT id: %i", int(packet->data[3]));
LOG("Unknown CHAT Message id: %i", chat_message_type);
}
}

View File

@@ -10,6 +10,7 @@
#include "Database.h"
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "eGameMasterLevel.h"
#include "ChatPackets.h"
#include "dConfig.h"
@@ -22,6 +23,10 @@ PlayerContainer::~PlayerContainer() {
m_Players.clear();
}
PlayerData::PlayerData() {
gmLevel == eGameMasterLevel::CIVILIAN;
}
TeamData::TeamData() {
lootFlag = Game::config->GetValue("default_team_loot") == "0" ? 0 : 1;
}
@@ -47,6 +52,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
inStream.Read(data.zoneID);
inStream.Read(data.muteExpire);
inStream.Read(data.gmLevel);
data.sysAddr = packet->systemAddress;
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);

View File

@@ -7,6 +7,8 @@
#include "dServer.h"
#include <unordered_map>
enum class eGameMasterLevel : uint8_t;
struct IgnoreData {
IgnoreData(const std::string& name, const LWOOBJID& id) : playerName(name), playerId(id) {}
inline bool operator==(const std::string& other) const noexcept {
@@ -22,6 +24,7 @@ struct IgnoreData {
};
struct PlayerData {
PlayerData();
operator bool() const noexcept {
return playerID != LWOOBJID_EMPTY;
}
@@ -42,6 +45,8 @@ struct PlayerData {
std::string playerName;
std::vector<FriendData> friends;
std::vector<IgnoreData> ignoredPlayers;
eGameMasterLevel gmLevel;
bool isFTP = false;
};
struct TeamData {

View File

@@ -3,6 +3,7 @@ set(DGAME_SOURCES "Character.cpp"
"EntityManager.cpp"
"LeaderboardManager.cpp"
"Player.cpp"
"PlayerManager.cpp"
"TeamManager.cpp"
"TradingManager.cpp"
"User.cpp"

View File

@@ -25,6 +25,7 @@
#include "eTriggerEventType.h"
#include "eObjectBits.h"
#include "PositionUpdate.h"
#include "eChatMessageType.h"
//Component includes:
#include "Component.h"
@@ -858,9 +859,20 @@ void Entity::SetGMLevel(eGameMasterLevel value) {
}
CharacterComponent* character = GetComponent<CharacterComponent>();
if (character) character->SetGMLevel(value);
if (!character) return;
character->SetGMLevel(value);
GameMessages::SendGMLevelBroadcast(m_ObjectID, value);
// Update the chat server of our GM Level
{
CBITSTREAM;
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::GMLEVEL_UPDATE);
bitStream.Write(m_ObjectID);
bitStream.Write(m_GMLevel);
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
}
}
void Entity::WriteBaseReplicaData(RakNet::BitStream* outBitStream, eReplicaPacketType packetType) {
@@ -2125,9 +2137,9 @@ void Entity::ProcessPositionUpdate(PositionUpdate& update) {
controllablePhysicsComponent->SetAngularVelocity(update.angularVelocity);
controllablePhysicsComponent->SetDirtyAngularVelocity(update.angularVelocity != NiPoint3::ZERO);
auto* player = static_cast<Player*>(this);
player->SetGhostReferencePoint(update.position);
Game::entityManager->QueueGhostUpdate(player->GetObjectID());
auto* ghostComponent = GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->SetGhostReferencePoint(update.position);
Game::entityManager->QueueGhostUpdate(GetObjectID());
if (updateChar) Game::entityManager->SerializeEntity(this);
}

View File

@@ -23,6 +23,8 @@
#include "eGameMasterLevel.h"
#include "eReplicaComponentType.h"
#include "eReplicaPacketType.h"
#include "PlayerManager.h"
#include "GhostComponent.h"
// Configure which zones have ghosting disabled, mostly small worlds.
std::vector<LWOMAPID> EntityManager::m_GhostingExcludedZones = {
@@ -187,8 +189,9 @@ void EntityManager::SerializeEntities() {
entity->WriteComponents(&stream, eReplicaPacketType::SERIALIZATION);
if (entity->GetIsGhostingCandidate()) {
for (auto* player : Player::GetAllPlayers()) {
if (player->IsObserved(toSerialize)) {
for (auto* player : PlayerManager::GetAllPlayers()) {
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (ghostComponent && ghostComponent->IsObserved(toSerialize)) {
Game::server->Send(&stream, player->GetSystemAddress(), false);
}
}
@@ -376,11 +379,12 @@ void EntityManager::ConstructEntity(Entity* entity, const SystemAddress& sysAddr
if (skipChecks) {
Game::server->Send(&stream, UNASSIGNED_SYSTEM_ADDRESS, true);
} else {
for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
if (player->GetPlayerReadyForUpdates()) {
Game::server->Send(&stream, player->GetSystemAddress(), false);
} else {
player->AddLimboConstruction(entity->GetObjectID());
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->AddLimboConstruction(entity->GetObjectID());
}
}
}
@@ -405,7 +409,7 @@ void EntityManager::ConstructAllEntities(const SystemAddress& sysAddr) {
}
}
UpdateGhosting(Player::GetPlayer(sysAddr));
UpdateGhosting(PlayerManager::GetPlayer(sysAddr));
}
void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr) {
@@ -418,9 +422,10 @@ void EntityManager::DestructEntity(Entity* entity, const SystemAddress& sysAddr)
Game::server->Send(&stream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
if (!player->GetPlayerReadyForUpdates()) {
player->RemoveLimboConstruction(entity->GetObjectID());
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->RemoveLimboConstruction(entity->GetObjectID());
}
}
}
@@ -465,7 +470,7 @@ void EntityManager::QueueGhostUpdate(LWOOBJID playerID) {
void EntityManager::UpdateGhosting() {
for (const auto playerID : m_PlayersToUpdateGhosting) {
auto* player = Player::GetPlayer(playerID);
auto* player = PlayerManager::GetPlayer(playerID);
if (player == nullptr) {
continue;
@@ -483,13 +488,14 @@ void EntityManager::UpdateGhosting(Player* player) {
}
auto* missionComponent = player->GetComponent<MissionComponent>();
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (missionComponent == nullptr) {
if (missionComponent == nullptr || !ghostComponent) {
return;
}
const auto& referencePoint = player->GetGhostReferencePoint();
const auto isOverride = player->GetGhostOverride();
const auto& referencePoint = ghostComponent->GetGhostReferencePoint();
const auto isOverride = ghostComponent->GetGhostOverride();
for (auto* entity : m_EntitiesToGhost) {
const auto isAudioEmitter = entity->GetLOT() == 6368;
@@ -498,7 +504,7 @@ void EntityManager::UpdateGhosting(Player* player) {
const int32_t id = entity->GetObjectID();
const auto observed = player->IsObserved(id);
const auto observed = ghostComponent->IsObserved(id);
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
@@ -510,7 +516,7 @@ void EntityManager::UpdateGhosting(Player* player) {
}
if (observed && distance > ghostingDistanceMax && !isOverride) {
player->GhostEntity(id);
ghostComponent->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress());
@@ -527,7 +533,7 @@ void EntityManager::UpdateGhosting(Player* player) {
}
}
player->ObserveEntity(id);
ghostComponent->ObserveEntity(id);
ConstructEntity(entity, player->GetSystemAddress());
@@ -548,23 +554,26 @@ void EntityManager::CheckGhosting(Entity* entity) {
const auto isAudioEmitter = entity->GetLOT() == 6368;
for (auto* player : Player::GetAllPlayers()) {
const auto& entityPoint = player->GetGhostReferencePoint();
for (auto* player : PlayerManager::GetAllPlayers()) {
auto* ghostComponent = player->GetComponent<GhostComponent>();
if (!ghostComponent) continue;
const auto& entityPoint = ghostComponent->GetGhostReferencePoint();
const int32_t id = entity->GetObjectID();
const auto observed = player->IsObserved(id);
const auto observed = ghostComponent->IsObserved(id);
const auto distance = NiPoint3::DistanceSquared(referencePoint, entityPoint);
if (observed && distance > ghostingDistanceMax) {
player->GhostEntity(id);
ghostComponent->GhostEntity(id);
DestructEntity(entity, player->GetSystemAddress());
entity->SetObservers(entity->GetObservers() - 1);
} else if (!observed && ghostingDistanceMin > distance) {
player->ObserveEntity(id);
ghostComponent->ObserveEntity(id);
ConstructEntity(entity, player->GetSystemAddress());

View File

@@ -12,22 +12,7 @@
#include "CppScripts.h"
#include "Loot.h"
#include "eReplicaComponentType.h"
namespace {
std::vector<Player*> m_Players;
};
const std::vector<Player*>& Player::GetAllPlayers() {
return m_Players;
}
void Player::SetGhostReferencePoint(const NiPoint3& value) {
m_GhostReferencePoint = value;
}
void Player::SetGhostOverridePoint(const NiPoint3& value) {
m_GhostOverridePoint = value;
}
#include "PlayerManager.h"
void Player::SetRespawnPos(const NiPoint3& position) {
if (!m_Character) return;
@@ -54,122 +39,17 @@ Player::Player(const LWOOBJID& objectID, const EntityInfo info, User* user, Enti
m_SystemAddress = m_ParentUser->GetSystemAddress();
m_DroppedCoins = 0;
m_GhostReferencePoint = NiPoint3::ZERO;
m_GhostOverridePoint = NiPoint3::ZERO;
m_GhostOverride = false;
int32_t initialObservedEntitiesCapacity = 256;
m_ObservedEntities.resize(initialObservedEntitiesCapacity);
m_Character->SetEntity(this);
const auto& iter = std::find(m_Players.begin(), m_Players.end(), this);
if (iter == m_Players.end()) {
m_Players.push_back(this);
}
}
void Player::AddLimboConstruction(LWOOBJID objectId) {
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
if (iter == m_LimboConstructions.end()) {
m_LimboConstructions.push_back(objectId);
}
}
void Player::RemoveLimboConstruction(LWOOBJID objectId) {
const auto iter = std::find(m_LimboConstructions.begin(), m_LimboConstructions.end(), objectId);
if (iter != m_LimboConstructions.end()) {
m_LimboConstructions.erase(iter);
}
}
void Player::ConstructLimboEntities() {
for (const auto& objectId : m_LimboConstructions) {
auto* entity = Game::entityManager->GetEntity(objectId);
if (!entity) continue;
Game::entityManager->ConstructEntity(entity, m_SystemAddress);
}
m_LimboConstructions.clear();
}
void Player::ObserveEntity(int32_t id) {
for (auto& observedEntity : m_ObservedEntities) {
if (observedEntity == 0 || observedEntity == id) {
observedEntity = id;
return;
}
}
m_ObservedEntities.reserve(m_ObservedEntities.size() + 1);
m_ObservedEntities.push_back(id);
}
bool Player::IsObserved(int32_t id) {
return std::find(m_ObservedEntities.begin(), m_ObservedEntities.end(), id) != m_ObservedEntities.end();
}
void Player::GhostEntity(int32_t id) {
for (auto& observedEntity : m_ObservedEntities) {
if (observedEntity == id) {
observedEntity = 0;
}
}
}
Player* Player::GetPlayer(const SystemAddress& sysAddr) {
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
return static_cast<Player*>(entity);
}
Player* Player::GetPlayer(const std::string& name) {
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
Player* player = nullptr;
for (auto* character : characters) {
if (!character->IsPlayer()) continue;
if (GeneralUtils::CaseInsensitiveStringCompare(name, character->GetCharacter()->GetName())) {
player = dynamic_cast<Player*>(character);
}
}
return player;
}
Player* Player::GetPlayer(LWOOBJID playerID) {
Player* playerToReturn = nullptr;
for (auto* player : m_Players) {
if (player->GetObjectID() == playerID) {
playerToReturn = player;
}
}
return playerToReturn;
PlayerManager::AddPlayer(this);
}
Player::~Player() {
LOG("Deleted player");
for (auto& observedEntity : m_ObservedEntities) {
if (observedEntity == 0) continue;
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
if (!entity) continue;
entity->SetObservers(entity->GetObservers() - 1);
}
m_LimboConstructions.clear();
const auto iter = std::find(m_Players.begin(), m_Players.end(), this);
if (iter == m_Players.end()) {
// Make sure the player exists first. Remove afterwards to prevent the OnPlayerExist functions from not being able to find the player.
if (!PlayerManager::RemovePlayer(this)) {
LOG("Unable to find player to remove from manager.");
return;
}
@@ -188,6 +68,4 @@ Player::~Player() {
}
}
}
m_Players.erase(iter);
}

View File

@@ -26,14 +26,6 @@ public:
const NiQuaternion& GetRespawnRotation() const override { return m_respawnRot; };
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
bool GetGhostOverride() const { return m_GhostOverride; };
std::map<LWOOBJID, Loot::Info>& GetDroppedLoot() { return m_DroppedLoot; };
uint64_t GetDroppedCoins() const { return m_DroppedCoins; };
@@ -42,8 +34,6 @@ public:
* Setters
*/
void SetGhostOverride(bool value) { m_GhostOverride = value; };
void SetDroppedCoins(const uint64_t value) { m_DroppedCoins = value; };
void SetSystemAddress(const SystemAddress& value) override;
@@ -52,38 +42,10 @@ public:
void SetRespawnRot(const NiQuaternion& rotation) override;
void SetGhostReferencePoint(const NiPoint3& value);
void SetGhostOverridePoint(const NiPoint3& value);
/**
* Ghosting
*/
void AddLimboConstruction(LWOOBJID objectId);
void RemoveLimboConstruction(LWOOBJID objectId);
void ConstructLimboEntities();
void ObserveEntity(const int32_t id);
bool IsObserved(const int32_t id);
void GhostEntity(const int32_t id);
/**
* Static methods
*/
static Player* GetPlayer(const SystemAddress& sysAddr);
static Player* GetPlayer(const std::string& name);
static Player* GetPlayer(LWOOBJID playerID);
static const std::vector<Player*>& GetAllPlayers();
~Player() override;
private:
SystemAddress m_SystemAddress;
@@ -94,16 +56,6 @@ private:
User* m_ParentUser;
NiPoint3 m_GhostReferencePoint;
NiPoint3 m_GhostOverridePoint;
bool m_GhostOverride;
std::vector<int32_t> m_ObservedEntities;
std::vector<LWOOBJID> m_LimboConstructions;
std::map<LWOOBJID, Loot::Info> m_DroppedLoot;
uint64_t m_DroppedCoins;

68
dGame/PlayerManager.cpp Normal file
View File

@@ -0,0 +1,68 @@
#include "PlayerManager.h"
#include "Character.h"
#include "Player.h"
#include "User.h"
#include "UserManager.h"
#include "eReplicaComponentType.h"
namespace {
std::vector<Player*> m_Players;
};
const std::vector<Player*>& PlayerManager::GetAllPlayers() {
return m_Players;
}
void PlayerManager::AddPlayer(Player* player) {
const auto& iter = std::find(m_Players.begin(), m_Players.end(), player);
if (iter == m_Players.end()) {
m_Players.push_back(player);
}
}
bool PlayerManager::RemovePlayer(Player* player) {
const auto iter = std::find(m_Players.begin(), m_Players.end(), player);
const bool toReturn = iter != m_Players.end();
if (toReturn) {
m_Players.erase(iter);
}
return toReturn;
}
Player* PlayerManager::GetPlayer(const SystemAddress& sysAddr) {
auto* entity = UserManager::Instance()->GetUser(sysAddr)->GetLastUsedChar()->GetEntity();
return static_cast<Player*>(entity);
}
Player* PlayerManager::GetPlayer(const std::string& name) {
const auto characters = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::CHARACTER);
Player* player = nullptr;
for (auto* character : characters) {
if (!character->IsPlayer()) continue;
if (GeneralUtils::CaseInsensitiveStringCompare(name, character->GetCharacter()->GetName())) {
player = dynamic_cast<Player*>(character);
break;
}
}
return player;
}
Player* PlayerManager::GetPlayer(LWOOBJID playerID) {
Player* playerToReturn = nullptr;
for (auto* player : m_Players) {
if (player->GetObjectID() == playerID) {
playerToReturn = player;
break;
}
}
return playerToReturn;
}

25
dGame/PlayerManager.h Normal file
View File

@@ -0,0 +1,25 @@
#ifndef __PLAYERMANAGER__H__
#define __PLAYERMANAGER__H__
#include "dCommonVars.h"
#include <string>
class Player;
struct SystemAddress;
namespace PlayerManager {
void AddPlayer(Player* player);
bool RemovePlayer(Player* player);
Player* GetPlayer(const SystemAddress& sysAddr);
Player* GetPlayer(const std::string& name);
Player* GetPlayer(LWOOBJID playerID);
const std::vector<Player*>& GetAllPlayers();
};
#endif //!__PLAYERMANAGER__H__

View File

@@ -1,4 +1,57 @@
#include "GhostComponent.h"
// TODO Move ghosting related code from Player to here
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {}
GhostComponent::GhostComponent(Entity* parent) : Component(parent) {
m_GhostReferencePoint = NiPoint3::ZERO;
m_GhostOverridePoint = NiPoint3::ZERO;
m_GhostOverride = false;
}
GhostComponent::~GhostComponent() {
for (auto& observedEntity : m_ObservedEntities) {
if (observedEntity == 0) continue;
auto* entity = Game::entityManager->GetGhostCandidate(observedEntity);
if (!entity) continue;
entity->SetObservers(entity->GetObservers() - 1);
}
}
void GhostComponent::SetGhostReferencePoint(const NiPoint3& value) {
m_GhostReferencePoint = value;
}
void GhostComponent::SetGhostOverridePoint(const NiPoint3& value) {
m_GhostOverridePoint = value;
}
void GhostComponent::AddLimboConstruction(LWOOBJID objectId) {
m_LimboConstructions.insert(objectId);
}
void GhostComponent::RemoveLimboConstruction(LWOOBJID objectId) {
m_LimboConstructions.erase(objectId);
}
void GhostComponent::ConstructLimboEntities() {
for (const auto& objectId : m_LimboConstructions) {
auto* entity = Game::entityManager->GetEntity(objectId);
if (!entity) continue;
Game::entityManager->ConstructEntity(entity, m_Parent->GetSystemAddress());
}
m_LimboConstructions.clear();
}
void GhostComponent::ObserveEntity(int32_t id) {
m_ObservedEntities.insert(id);
}
bool GhostComponent::IsObserved(int32_t id) {
return m_ObservedEntities.contains(id);
}
void GhostComponent::GhostEntity(int32_t id) {
m_ObservedEntities.erase(id);
}

View File

@@ -3,11 +3,52 @@
#include "Component.h"
#include "eReplicaComponentType.h"
#include <unordered_set>
class NiPoint3;
class GhostComponent : public Component {
public:
static inline const eReplicaComponentType ComponentType = eReplicaComponentType::GHOST;
GhostComponent(Entity* parent);
~GhostComponent() override;
void SetGhostOverride(bool value) { m_GhostOverride = value; };
const NiPoint3& GetGhostReferencePoint() const { return m_GhostOverride ? m_GhostOverridePoint : m_GhostReferencePoint; };
const NiPoint3& GetOriginGhostReferencePoint() const { return m_GhostReferencePoint; };
const NiPoint3& GetGhostOverridePoint() const { return m_GhostOverridePoint; };
bool GetGhostOverride() const { return m_GhostOverride; };
void SetGhostReferencePoint(const NiPoint3& value);
void SetGhostOverridePoint(const NiPoint3& value);
void AddLimboConstruction(const LWOOBJID objectId);
void RemoveLimboConstruction(const LWOOBJID objectId);
void ConstructLimboEntities();
void ObserveEntity(const int32_t id);
bool IsObserved(const int32_t id);
void GhostEntity(const int32_t id);
private:
NiPoint3 m_GhostReferencePoint;
NiPoint3 m_GhostOverridePoint;
std::unordered_set<int32_t> m_ObservedEntities;
std::unordered_set<LWOOBJID> m_LimboConstructions;
bool m_GhostOverride;
};
#endif //!__GHOSTCOMPONENT__H__

View File

@@ -21,6 +21,7 @@
#include "eMissionTaskType.h"
#include "eObjectBits.h"
#include "CharacterComponent.h"
#include "PlayerManager.h"
#include <vector>
#include "CppScripts.h"
@@ -227,7 +228,7 @@ void PropertyManagementComponent::OnStartBuilding() {
if (ownerEntity == nullptr) return;
const auto players = Player::GetAllPlayers();
const auto players = PlayerManager::GetAllPlayers();
LWOMAPID zoneId = 1100;

View File

@@ -13,6 +13,7 @@
#include "QuickBuildComponent.h"
#include "SkillComponent.h"
#include "eEndBehavior.h"
#include "PlayerManager.h"
TriggerComponent::TriggerComponent(Entity* parent, const std::string triggerInfo): Component(parent) {
@@ -175,7 +176,7 @@ std::vector<Entity*> TriggerComponent::GatherTargets(LUTriggers::Command* comman
}
} else if (command->target == "objGroup") entities = Game::entityManager->GetEntitiesInGroup(command->targetName);
else if (command->target == "allPlayers") {
for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
entities.push_back(player);
}
} else if (command->target == "allNPCs") { /*UNUSED*/ }

View File

@@ -37,6 +37,7 @@
#include "eGameMessageType.h"
#include "ePlayerFlag.h"
#include "dConfig.h"
#include "GhostComponent.h"
#include "StringifiedEnum.h"
void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const SystemAddress& sysAddr, LWOOBJID objectID, eGameMessageType messageID) {
@@ -108,9 +109,9 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
GameMessages::SendRestoreToPostLoadStats(entity, sysAddr);
entity->SetPlayerReadyForUpdates();
auto* player = dynamic_cast<Player*>(entity);
if (player != nullptr) {
player->ConstructLimboEntities();
auto* ghostComponent = entity->GetComponent<GhostComponent>();
if (ghostComponent != nullptr) {
ghostComponent->ConstructLimboEntities();
}
InventoryComponent* inv = entity->GetComponent<InventoryComponent>();
@@ -137,14 +138,14 @@ void GameMessageHandler::HandleMessage(RakNet::BitStream* inStream, const System
Entity* zoneControl = Game::entityManager->GetZoneControlEntity();
for (CppScripts::Script* script : CppScripts::GetEntityScripts(zoneControl)) {
script->OnPlayerLoaded(zoneControl, player);
script->OnPlayerLoaded(zoneControl, entity);
}
std::vector<Entity*> scriptedActs = Game::entityManager->GetEntitiesByComponent(eReplicaComponentType::SCRIPT);
for (Entity* scriptEntity : scriptedActs) {
if (scriptEntity->GetObjectID() != zoneControl->GetObjectID()) { // Don't want to trigger twice on instance worlds
for (CppScripts::Script* script : CppScripts::GetEntityScripts(scriptEntity)) {
script->OnPlayerLoaded(scriptEntity, player);
script->OnPlayerLoaded(scriptEntity, entity);
}
}
}

View File

@@ -78,6 +78,7 @@
#include "RailActivatorComponent.h"
#include "LevelProgressionComponent.h"
#include "DonationVendorComponent.h"
#include "GhostComponent.h"
// Message includes:
#include "dZoneManager.h"
@@ -96,6 +97,7 @@
#include "eGameMessageType.h"
#include "ePetAbilityType.h"
#include "ActivityManager.h"
#include "PlayerManager.h"
#include "CDComponentsRegistryTable.h"
#include "CDObjectsTable.h"
@@ -2693,7 +2695,7 @@ void GameMessages::HandlePropertyEntranceSync(RakNet::BitStream* inStream, Entit
filterText.push_back(c);
}
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
auto* entranceComponent = entity->GetComponent<PropertyEntranceComponent>();
@@ -2720,7 +2722,7 @@ void GameMessages::HandleEnterProperty(RakNet::BitStream* inStream, Entity* enti
inStream->Read(index);
inStream->Read(returnToZone);
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
auto* entranceComponent = entity->GetComponent<PropertyEntranceComponent>();
if (entranceComponent != nullptr) {
@@ -4601,10 +4603,11 @@ void GameMessages::HandleToggleGhostReferenceOverride(RakNet::BitStream* inStrea
inStream->Read(bOverride);
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
if (player != nullptr) {
player->SetGhostOverride(bOverride);
auto* ghostComponent = entity->GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->SetGhostOverride(bOverride);
Game::entityManager->UpdateGhosting(player);
}
@@ -4616,10 +4619,11 @@ void GameMessages::HandleSetGhostReferencePosition(RakNet::BitStream* inStream,
inStream->Read(position);
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
if (player != nullptr) {
player->SetGhostOverridePoint(position);
auto* ghostComponent = entity->GetComponent<GhostComponent>();
if (ghostComponent) ghostComponent->SetGhostOverridePoint(position);
Game::entityManager->UpdateGhosting(player);
}
@@ -4880,7 +4884,7 @@ void GameMessages::HandleFireEventServerSide(RakNet::BitStream* inStream, Entity
inStream->Read(senderID);
auto* sender = Game::entityManager->GetEntity(senderID);
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
if (!player) {
return;

View File

@@ -10,6 +10,7 @@
#include "UserManager.h"
#include "dConfig.h"
#include <optional>
#include "PlayerManager.h"
Entity* GetPossessedEntity(const LWOOBJID& objId) {
auto* entity = Game::entityManager->GetEntity(objId);
@@ -49,7 +50,7 @@ void LogAndSaveFailedAntiCheatCheck(const LWOOBJID& id, const SystemAddress& sys
User* toReport = nullptr;
switch (checkType) {
case CheckType::Entity: {
auto* player = Player::GetPlayer(sysAddr);
auto* player = PlayerManager::GetPlayer(sysAddr);
auto* entity = GetPossessedEntity(id);
// If player exists and entity exists in world, use both for logging info.

View File

@@ -82,6 +82,7 @@
#include "eConnectionType.h"
#include "eChatInternalMessageType.h"
#include "eMasterMessageType.h"
#include "PlayerManager.h"
#include "CDRewardCodesTable.h"
#include "CDObjectsTable.h"
@@ -214,10 +215,10 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "who") {
ChatPackets::SendSystemMessage(
sysAddr,
u"Players in this instance: (" + GeneralUtils::to_u16string(Player::GetAllPlayers().size()) + u")"
u"Players in this instance: (" + GeneralUtils::to_u16string(PlayerManager::GetAllPlayers().size()) + u")"
);
for (auto* player : Player::GetAllPlayers()) {
for (auto* player : PlayerManager::GetAllPlayers()) {
const auto& name = player->GetCharacter()->GetName();
ChatPackets::SendSystemMessage(
@@ -473,7 +474,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "kill" && args.size() == 1 && entity->GetGMLevel() >= eGameMasterLevel::DEVELOPER) {
ChatPackets::SendSystemMessage(sysAddr, u"Brutally murdering that player, if online on this server.");
auto* player = Player::GetPlayer(args[0]);
auto* player = PlayerManager::GetPlayer(args[0]);
if (player) {
player->Smash(entity->GetObjectID());
ChatPackets::SendSystemMessage(sysAddr, u"It has been done, do you feel good about yourself now?");
@@ -993,7 +994,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "mute" && entity->GetGMLevel() >= eGameMasterLevel::JUNIOR_DEVELOPER) {
if (args.size() >= 1) {
auto* player = Player::GetPlayer(args[0]);
auto* player = PlayerManager::GetPlayer(args[0]);
uint32_t accountId = 0;
LWOOBJID characterId = 0;
@@ -1072,7 +1073,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "kick" && entity->GetGMLevel() >= eGameMasterLevel::JUNIOR_MODERATOR) {
if (args.size() == 1) {
auto* player = Player::GetPlayer(args[0]);
auto* player = PlayerManager::GetPlayer(args[0]);
std::u16string username = GeneralUtils::UTF8ToUTF16(args[0]);
if (player == nullptr) {
@@ -1090,7 +1091,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (chatCommand == "ban" && entity->GetGMLevel() >= eGameMasterLevel::SENIOR_MODERATOR) {
if (args.size() == 1) {
auto* player = Player::GetPlayer(args[0]);
auto* player = PlayerManager::GetPlayer(args[0]);
uint32_t accountId = 0;
@@ -1303,7 +1304,7 @@ void SlashCommandHandler::HandleChatCommand(const std::u16string& command, Entit
if (args.size() > 1) {
requestedPlayerToSetLevelOf = args[1];
auto requestedPlayer = Player::GetPlayer(requestedPlayerToSetLevelOf);
auto requestedPlayer = PlayerManager::GetPlayer(requestedPlayerToSetLevelOf);
if (!requestedPlayer) {
ChatPackets::SendSystemMessage(sysAddr, u"No player found with username: (" + GeneralUtils::UTF8ToUTF16(requestedPlayerToSetLevelOf) + u").");

View File

@@ -1,64 +1,8 @@
#include "PacketUtils.h"
#include <vector>
#include <fstream>
#include "Logger.h"
#include "Game.h"
uint16_t PacketUtils::ReadU16(uint32_t startLoc, Packet* packet) {
if (startLoc + 2 > packet->length) return 0;
std::vector<unsigned char> t;
for (uint32_t i = startLoc; i < startLoc + 2; i++) t.push_back(packet->data[i]);
return *(uint16_t*)t.data();
}
uint32_t PacketUtils::ReadU32(uint32_t startLoc, Packet* packet) {
if (startLoc + 4 > packet->length) return 0;
std::vector<unsigned char> t;
for (uint32_t i = startLoc; i < startLoc + 4; i++) {
t.push_back(packet->data[i]);
}
return *(uint32_t*)t.data();
}
uint64_t PacketUtils::ReadU64(uint32_t startLoc, Packet* packet) {
if (startLoc + 8 > packet->length) return 0;
std::vector<unsigned char> t;
for (uint32_t i = startLoc; i < startLoc + 8; i++) t.push_back(packet->data[i]);
return *(uint64_t*)t.data();
}
int64_t PacketUtils::ReadS64(uint32_t startLoc, Packet* packet) {
if (startLoc + 8 > packet->length) return 0;
std::vector<unsigned char> t;
for (size_t i = startLoc; i < startLoc + 8; i++) t.push_back(packet->data[i]);
return *(int64_t*)t.data();
}
std::string PacketUtils::ReadString(uint32_t startLoc, Packet* packet, bool wide, uint32_t maxLen) {
std::string readString = "";
if (wide) maxLen *= 2;
if (packet->length > startLoc) {
uint32_t i = 0;
while (packet->data[startLoc + i] != '\0' && packet->length > static_cast<uint32_t>(startLoc + i) && maxLen > i) {
readString.push_back(packet->data[startLoc + i]);
if (wide) {
i += 2; // Wide-char string
} else {
i++; // Regular string
}
}
}
return readString;
}
//! Saves a packet to the filesystem
void PacketUtils::SavePacket(const std::string& filename, const char* data, size_t length) {
//If we don't log to the console, don't save the bin files either. This takes up a lot of time.

View File

@@ -8,11 +8,6 @@
enum class eConnectionType : uint16_t;
namespace PacketUtils {
uint16_t ReadU16(uint32_t startLoc, Packet* packet);
uint32_t ReadU32(uint32_t startLoc, Packet* packet);
uint64_t ReadU64(uint32_t startLoc, Packet* packet);
int64_t ReadS64(uint32_t startLoc, Packet* packet);
std::string ReadString(uint32_t startLoc, Packet* packet, bool wide, uint32_t maxLen = 33);
void SavePacket(const std::string& filename, const char* data, size_t length);
};

View File

@@ -78,6 +78,7 @@
#include "StringifiedEnum.h"
#include "Server.h"
#include "PositionUpdate.h"
#include "PlayerManager.h"
namespace Game {
Logger* logger = nullptr;
@@ -798,7 +799,7 @@ void HandlePacket(Packet* packet) {
auto* entity = Game::entityManager->GetEntity(c->GetObjectID());
if (!entity) {
entity = Player::GetPlayer(packet->systemAddress);
entity = PlayerManager::GetPlayer(packet->systemAddress);
}
if (entity) {
@@ -1125,6 +1126,7 @@ void HandlePacket(Packet* packet) {
bitStream.Write(zone.GetInstanceID());
bitStream.Write(zone.GetCloneID());
bitStream.Write(player->GetParentUser()->GetMuteExpire());
bitStream.Write(player->GetGMLevel());
Game::chatServer->Send(&bitStream, SYSTEM_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
}
@@ -1205,7 +1207,7 @@ void HandlePacket(Packet* packet) {
return;
}
auto* entity = Player::GetPlayer(packet->systemAddress);
auto* entity = PlayerManager::GetPlayer(packet->systemAddress);
if (entity == nullptr) {
LOG("Unable to get player to parse chat moderation request");
@@ -1365,7 +1367,7 @@ void WorldShutdownProcess(uint32_t zoneId) {
for (auto i = 0; i < Game::server->GetReplicaManager()->GetParticipantCount(); ++i) {
const auto& player = Game::server->GetReplicaManager()->GetParticipantAtIndex(i);
auto* entity = Player::GetPlayer(player);
auto* entity = PlayerManager::GetPlayer(player);
LOG("Saving data!");
if (entity != nullptr && entity->GetCharacter() != nullptr) {
auto* skillComponent = entity->GetComponent<SkillComponent>();