mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-16 20:24:39 -06:00
Compare commits
8 Commits
mail-fix
...
achievemen
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c27d734b7e | ||
|
|
fb942e4692 | ||
|
|
3bccbbd1ef | ||
|
|
6b0f3a66e9 | ||
|
|
f5c212fb86 | ||
|
|
99f6cf2d92 | ||
|
|
bc0f3d9163 | ||
|
|
20d5a9b6d8 |
12
.github/workflows/build-and-test.yml
vendored
12
.github/workflows/build-and-test.yml
vendored
@@ -16,12 +16,12 @@ jobs:
|
||||
os: [ windows-2022, ubuntu-22.04, macos-13 ]
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@85e6279cec87321a52edac9c87bce653a07cf6c2
|
||||
with:
|
||||
submodules: true
|
||||
- name: Add msbuild to PATH (Windows only)
|
||||
if: ${{ matrix.os == 'windows-2022' }}
|
||||
uses: microsoft/setup-msbuild@v2
|
||||
uses: microsoft/setup-msbuild@767f00a3f09872d96a0cb9fcd5e6a4ff33311330
|
||||
with:
|
||||
vs-version: '[17,18)'
|
||||
msbuild-architecture: x64
|
||||
@@ -30,12 +30,16 @@ jobs:
|
||||
run: |
|
||||
brew install openssl@3
|
||||
sudo xcode-select -s /Applications/Xcode_15.2.app/Contents/Developer
|
||||
- name: Get CMake 3.x
|
||||
uses: lukka/get-cmake@28983e0d3955dba2bb0a6810caae0c6cf268ec0c
|
||||
with:
|
||||
cmakeVersion: "~3.25.0" # <--= optional, use most recent 3.25.x version
|
||||
- name: cmake
|
||||
uses: lukka/run-cmake@v10
|
||||
uses: lukka/run-cmake@67c73a83a46f86c4e0b96b741ac37ff495478c38
|
||||
with:
|
||||
workflowPreset: "ci-${{matrix.os}}"
|
||||
- name: artifacts
|
||||
uses: actions/upload-artifact@v4
|
||||
uses: actions/upload-artifact@6027e3dd177782cd8ab9af838c04fd81a07f1d47
|
||||
with:
|
||||
name: build-${{matrix.os}}
|
||||
path: |
|
||||
|
||||
@@ -78,7 +78,7 @@ git clone --recursive https://github.com/DarkflameUniverse/DarkflameServer
|
||||
|
||||
### Windows packages
|
||||
Ensure that you have either the [MSVC C++ compiler](https://visualstudio.microsoft.com/vs/features/cplusplus/) (recommended) or the [Clang compiler](https://github.com/llvm/llvm-project/releases/) installed.
|
||||
You'll also need to download and install [CMake](https://cmake.org/download/) (version <font size="4">**CMake version 3.25**</font> or later!).
|
||||
You'll also need to download and install [CMake](https://cmake.org/download/) (<font size="4">**version 3.25**</font> up to <font size="4">**version 3.31**</font>!).
|
||||
|
||||
### MacOS packages
|
||||
Ensure you have [brew](https://brew.sh) installed.
|
||||
@@ -100,7 +100,7 @@ sudo apt install build-essential gcc zlib1g-dev libssl-dev openssl mariadb-serve
|
||||
```
|
||||
|
||||
#### Required CMake version
|
||||
This project uses <font size="4">**CMake version 3.25**</font> or higher and as such you will need to ensure you have this version installed.
|
||||
This project uses <font size="4">**CMake version 3.25**</font> up to <font size="4">**version 3.31**</font> and as such you will need to ensure you have this version installed.
|
||||
You can check your CMake version by using the following command in a terminal.
|
||||
```bash
|
||||
cmake --version
|
||||
|
||||
@@ -73,7 +73,7 @@ void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||
data.Serialize(bitStream);
|
||||
}
|
||||
|
||||
SystemAddress sysAddr = player.sysAddr;
|
||||
SystemAddress sysAddr = player.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -122,7 +122,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
requesteeFriendData.isOnline = false;
|
||||
requesteeFriendData.zoneID = requestor.zoneID;
|
||||
requestee.friends.push_back(requesteeFriendData);
|
||||
requestee.sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
|
||||
requestee.worldServerSysAddr = UNASSIGNED_SYSTEM_ADDRESS;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -189,8 +189,8 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
Database::Get()->SetBestFriendStatus(requestorPlayerID, requestee.playerID, bestFriendStatus);
|
||||
// Sent the best friend update here if the value is 3
|
||||
if (bestFriendStatus == 3U) {
|
||||
if (requestee.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee, requestor, eAddFriendResponseType::ACCEPTED, false, true);
|
||||
if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::ACCEPTED, false, true);
|
||||
if (requestee.worldServerSysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestee, requestor, eAddFriendResponseType::ACCEPTED, false, true);
|
||||
if (requestor.worldServerSysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::ACCEPTED, false, true);
|
||||
|
||||
for (auto& friendData : requestor.friends) {
|
||||
if (friendData.friendID == requestee.playerID) {
|
||||
@@ -211,7 +211,7 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (requestor.sysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
||||
if (requestor.worldServerSysAddr != UNASSIGNED_SYSTEM_ADDRESS) SendFriendResponse(requestor, requestee, eAddFriendResponseType::WAITINGAPPROVAL, true, true);
|
||||
}
|
||||
} else {
|
||||
auto maxFriends = Game::playerContainer.GetMaxNumberOfFriends();
|
||||
@@ -384,7 +384,7 @@ void ChatPacketHandler::HandleWho(Packet* packet) {
|
||||
bitStream.Write(player.zoneID.GetCloneID());
|
||||
bitStream.Write(request.playerName);
|
||||
|
||||
SystemAddress sysAddr = sender.sysAddr;
|
||||
SystemAddress sysAddr = sender.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -418,7 +418,7 @@ void ChatPacketHandler::HandleShowAll(Packet* packet) {
|
||||
}
|
||||
}
|
||||
}
|
||||
SystemAddress sysAddr = sender.sysAddr;
|
||||
SystemAddress sysAddr = sender.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -519,6 +519,28 @@ void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
SendPrivateChatMessage(sender, receiver, sender, message, eChatChannel::GENERAL, eChatMessageResponseCode::NOTFRIENDS);
|
||||
}
|
||||
|
||||
void ChatPacketHandler::OnAchievementNotify(RakNet::BitStream& bitstream, const SystemAddress& sysAddr) {
|
||||
ChatPackets::AchievementNotify notify{};
|
||||
notify.Deserialize(bitstream);
|
||||
const auto& playerData = Game::playerContainer.GetPlayerData(notify.earnerName.GetAsString());
|
||||
if (!playerData) return;
|
||||
|
||||
for (const auto& myFriend : playerData.friends) {
|
||||
auto& friendData = Game::playerContainer.GetPlayerData(myFriend.friendID);
|
||||
if (friendData) {
|
||||
notify.targetPlayerName.string = GeneralUtils::ASCIIToUTF16(friendData.playerName);
|
||||
LOG_DEBUG("Sending achievement notify to %s", notify.targetPlayerName.GetAsString().c_str());
|
||||
|
||||
RakNet::BitStream worldStream;
|
||||
BitStreamUtils::WriteHeader(worldStream, eConnectionType::CHAT, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
worldStream.Write(friendData.playerID);
|
||||
notify.WriteHeader(worldStream);
|
||||
notify.Serialize(worldStream);
|
||||
Game::server->Send(worldStream, friendData.worldServerSysAddr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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, MessageType::Chat::WORLD_ROUTE_PACKET);
|
||||
@@ -537,7 +559,7 @@ void ChatPacketHandler::SendPrivateChatMessage(const PlayerData& sender, const P
|
||||
bitStream.Write(responseCode);
|
||||
bitStream.Write(message);
|
||||
|
||||
SystemAddress sysAddr = routeTo.sysAddr;
|
||||
SystemAddress sysAddr = routeTo.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -772,7 +794,7 @@ void ChatPacketHandler::SendTeamInvite(const PlayerData& receiver, const PlayerD
|
||||
bitStream.Write(LUWString(sender.playerName.c_str()));
|
||||
bitStream.Write(sender.playerID);
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -799,7 +821,7 @@ void ChatPacketHandler::SendTeamInviteConfirm(const PlayerData& receiver, bool b
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -824,7 +846,7 @@ void ChatPacketHandler::SendTeamStatus(const PlayerData& receiver, LWOOBJID i64L
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -841,7 +863,7 @@ void ChatPacketHandler::SendTeamSetLeader(const PlayerData& receiver, LWOOBJID i
|
||||
|
||||
bitStream.Write(i64PlayerID);
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -870,7 +892,7 @@ void ChatPacketHandler::SendTeamAddPlayer(const PlayerData& receiver, bool bIsFr
|
||||
}
|
||||
bitStream.Write(zoneID);
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -896,7 +918,7 @@ void ChatPacketHandler::SendTeamRemovePlayer(const PlayerData& receiver, bool bD
|
||||
bitStream.Write(character);
|
||||
}
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -917,7 +939,7 @@ void ChatPacketHandler::SendTeamSetOffWorldFlag(const PlayerData& receiver, LWOO
|
||||
}
|
||||
bitStream.Write(zoneID);
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -959,7 +981,7 @@ void ChatPacketHandler::SendFriendUpdate(const PlayerData& friendData, const Pla
|
||||
bitStream.Write<uint8_t>(isBestFriend); //isBFF
|
||||
bitStream.Write<uint8_t>(0); //isFTP
|
||||
|
||||
SystemAddress sysAddr = friendData.sysAddr;
|
||||
SystemAddress sysAddr = friendData.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -981,7 +1003,7 @@ void ChatPacketHandler::SendFriendRequest(const PlayerData& receiver, const Play
|
||||
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.
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -994,7 +1016,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::ADD_FRIEND_RESPONSE);
|
||||
bitStream.Write(responseCode);
|
||||
// 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.worldServerSysAddr != UNASSIGNED_SYSTEM_ADDRESS);
|
||||
// Then write the player name
|
||||
bitStream.Write(LUWString(sender.playerName));
|
||||
// Then if this is an acceptance code, write the following extra info.
|
||||
@@ -1004,7 +1026,7 @@ void ChatPacketHandler::SendFriendResponse(const PlayerData& receiver, const Pla
|
||||
bitStream.Write(isBestFriendRequest); //isBFF
|
||||
bitStream.Write<uint8_t>(0); //isFTP
|
||||
}
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -1018,6 +1040,6 @@ void ChatPacketHandler::SendRemoveFriend(const PlayerData& receiver, std::string
|
||||
bitStream.Write<uint8_t>(isSuccessful); //isOnline
|
||||
bitStream.Write(LUWString(personToRemove));
|
||||
|
||||
SystemAddress sysAddr = receiver.sysAddr;
|
||||
SystemAddress sysAddr = receiver.worldServerSysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
@@ -64,6 +64,7 @@ namespace ChatPacketHandler {
|
||||
void HandleTeamPromote(Packet* packet);
|
||||
void HandleTeamLootOption(Packet* packet);
|
||||
void HandleTeamStatusRequest(Packet* packet);
|
||||
void OnAchievementNotify(RakNet::BitStream& bitstream, const SystemAddress& sysAddr);
|
||||
|
||||
void SendTeamInvite(const PlayerData& receiver, const PlayerData& sender);
|
||||
void SendTeamInviteConfirm(const PlayerData& receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
|
||||
|
||||
@@ -224,6 +224,10 @@ void HandlePacket(Packet* packet) {
|
||||
if (connection != eConnectionType::CHAT) return;
|
||||
inStream.Read(chatMessageID);
|
||||
|
||||
// Our packing byte wasnt there? Probably a false packet
|
||||
if (inStream.GetNumberOfUnreadBits() < 8) return;
|
||||
inStream.IgnoreBytes(1);
|
||||
|
||||
switch (chatMessageID) {
|
||||
case MessageType::Chat::GM_MUTE:
|
||||
Game::playerContainer.MuteUpdate(packet);
|
||||
@@ -322,6 +326,9 @@ void HandlePacket(Packet* packet) {
|
||||
case MessageType::Chat::SHOW_ALL:
|
||||
ChatPacketHandler::HandleShowAll(packet);
|
||||
break;
|
||||
case MessageType::Chat::ACHIEVEMENT_NOTIFY:
|
||||
ChatPacketHandler::OnAchievementNotify(inStream, packet->systemAddress);
|
||||
break;
|
||||
case MessageType::Chat::USER_CHANNEL_CHAT_MESSAGE:
|
||||
case MessageType::Chat::WORLD_DISCONNECT_REQUEST:
|
||||
case MessageType::Chat::WORLD_PROXIMITY_RESPONSE:
|
||||
@@ -357,7 +364,6 @@ void HandlePacket(Packet* packet) {
|
||||
case MessageType::Chat::UGCMANIFEST_REPORT_DONE_BLUEPRINT:
|
||||
case MessageType::Chat::UGCC_REQUEST:
|
||||
case MessageType::Chat::WORLD_PLAYERS_PET_MODERATED_ACKNOWLEDGE:
|
||||
case MessageType::Chat::ACHIEVEMENT_NOTIFY:
|
||||
case MessageType::Chat::GM_CLOSE_PRIVATE_CHAT_WINDOW:
|
||||
case MessageType::Chat::PLAYER_READY:
|
||||
case MessageType::Chat::GET_DONATION_TOTAL:
|
||||
|
||||
@@ -52,7 +52,7 @@ void PlayerContainer::InsertPlayer(Packet* packet) {
|
||||
if (!inStream.Read(data.zoneID)) return;
|
||||
if (!inStream.Read(data.muteExpire)) return;
|
||||
if (!inStream.Read(data.gmLevel)) return;
|
||||
data.sysAddr = packet->systemAddress;
|
||||
data.worldServerSysAddr = packet->systemAddress;
|
||||
|
||||
m_Names[data.playerID] = GeneralUtils::UTF8ToUTF16(data.playerName);
|
||||
m_PlayerCount++;
|
||||
@@ -241,7 +241,7 @@ void PlayerContainer::AddMember(TeamData* team, LWOOBJID playerID) {
|
||||
LOG("Tried to add player to team that already had 4 players");
|
||||
const auto& player = GetPlayerData(playerID);
|
||||
if (!player) return;
|
||||
ChatPackets::SendSystemMessage(player.sysAddr, u"The teams is full! You have not been added to a team!");
|
||||
ChatPackets::SendSystemMessage(player.worldServerSysAddr, u"The teams is full! You have not been added to a team!");
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ struct PlayerData {
|
||||
return muteExpire == 1 || muteExpire > time(NULL);
|
||||
}
|
||||
|
||||
SystemAddress sysAddr{};
|
||||
SystemAddress worldServerSysAddr{};
|
||||
LWOZONEID zoneID{};
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
time_t muteExpire = 0;
|
||||
|
||||
@@ -98,6 +98,7 @@ public:
|
||||
constexpr LWOZONEID() noexcept = default;
|
||||
constexpr LWOZONEID(const LWOMAPID& mapID, const LWOINSTANCEID& instanceID, const LWOCLONEID& cloneID) noexcept { m_MapID = mapID; m_InstanceID = instanceID; m_CloneID = cloneID; }
|
||||
constexpr LWOZONEID(const LWOZONEID& replacement) noexcept { *this = replacement; }
|
||||
constexpr bool operator==(const LWOZONEID&) const = default;
|
||||
|
||||
private:
|
||||
LWOMAPID m_MapID = LWOMAPID_INVALID; //1000 for VE, 1100 for AG, etc...
|
||||
|
||||
@@ -204,6 +204,7 @@ void Character::DoQuickXMLDataParse() {
|
||||
while (currentChild) {
|
||||
const auto* temp = currentChild->Attribute("v");
|
||||
const auto* id = currentChild->Attribute("id");
|
||||
const auto* si = currentChild->Attribute("si");
|
||||
if (temp && id) {
|
||||
uint32_t index = 0;
|
||||
uint64_t value = 0;
|
||||
@@ -212,6 +213,9 @@ void Character::DoQuickXMLDataParse() {
|
||||
value = std::stoull(temp);
|
||||
|
||||
m_PlayerFlags.insert(std::make_pair(index, value));
|
||||
} else if (si) {
|
||||
auto value = GeneralUtils::TryParse<uint32_t>(si);
|
||||
if (value) m_SessionFlags.insert(value.value());
|
||||
}
|
||||
currentChild = currentChild->NextSiblingElement();
|
||||
}
|
||||
|
||||
@@ -512,7 +512,7 @@ void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||
|
||||
auto* mission = new Mission(this, missionId);
|
||||
|
||||
mission->LoadFromXml(*doneM);
|
||||
mission->LoadFromXmlDone(*doneM);
|
||||
|
||||
doneM = doneM->NextSiblingElement();
|
||||
|
||||
@@ -527,9 +527,9 @@ void MissionComponent::LoadFromXml(const tinyxml2::XMLDocument& doc) {
|
||||
|
||||
currentM->QueryAttribute("id", &missionId);
|
||||
|
||||
auto* mission = new Mission(this, missionId);
|
||||
auto* mission = m_Missions.contains(missionId) ? m_Missions[missionId] : new Mission(this, missionId);
|
||||
|
||||
mission->LoadFromXml(*currentM);
|
||||
mission->LoadFromXmlCur(*currentM);
|
||||
|
||||
if (currentM->QueryAttribute("o", &missionOrder) == tinyxml2::XML_SUCCESS && mission->IsMission()) {
|
||||
mission->SetUniqueMissionOrderID(missionOrder);
|
||||
@@ -565,20 +565,23 @@ void MissionComponent::UpdateXml(tinyxml2::XMLDocument& doc) {
|
||||
auto* mission = pair.second;
|
||||
|
||||
if (mission) {
|
||||
const auto complete = mission->IsComplete();
|
||||
const auto completions = mission->GetCompletions();
|
||||
|
||||
auto* m = doc.NewElement("m");
|
||||
|
||||
if (complete) {
|
||||
mission->UpdateXml(*m);
|
||||
if (completions > 0) {
|
||||
mission->UpdateXmlDone(*m);
|
||||
|
||||
done->LinkEndChild(m);
|
||||
|
||||
continue;
|
||||
if (mission->IsComplete()) continue;
|
||||
|
||||
m = doc.NewElement("m");
|
||||
}
|
||||
|
||||
if (mission->IsMission()) m->SetAttribute("o", mission->GetUniqueMissionOrderID());
|
||||
|
||||
mission->UpdateXml(*m);
|
||||
mission->UpdateXmlCur(*m);
|
||||
|
||||
cur->LinkEndChild(m);
|
||||
}
|
||||
|
||||
@@ -27,6 +27,8 @@
|
||||
#include "Character.h"
|
||||
|
||||
#include "CDMissionEmailTable.h"
|
||||
#include "ChatPackets.h"
|
||||
#include "PlayerManager.h"
|
||||
|
||||
Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) {
|
||||
m_MissionComponent = missionComponent;
|
||||
@@ -65,7 +67,7 @@ Mission::Mission(MissionComponent* missionComponent, const uint32_t missionId) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
|
||||
void Mission::LoadFromXmlDone(const tinyxml2::XMLElement& element) {
|
||||
// Start custom XML
|
||||
if (element.Attribute("state") != nullptr) {
|
||||
m_State = static_cast<eMissionState>(std::stoul(element.Attribute("state")));
|
||||
@@ -76,11 +78,15 @@ void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
|
||||
m_Completions = std::stoul(element.Attribute("cct"));
|
||||
|
||||
m_Timestamp = std::stoul(element.Attribute("cts"));
|
||||
|
||||
if (IsComplete()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void Mission::LoadFromXmlCur(const tinyxml2::XMLElement& element) {
|
||||
// Start custom XML
|
||||
if (element.Attribute("state") != nullptr) {
|
||||
m_State = static_cast<eMissionState>(std::stoul(element.Attribute("state")));
|
||||
}
|
||||
// End custom XML
|
||||
|
||||
auto* task = element.FirstChildElement();
|
||||
|
||||
@@ -132,7 +138,7 @@ void Mission::LoadFromXml(const tinyxml2::XMLElement& element) {
|
||||
}
|
||||
}
|
||||
|
||||
void Mission::UpdateXml(tinyxml2::XMLElement& element) {
|
||||
void Mission::UpdateXmlDone(tinyxml2::XMLElement& element) {
|
||||
// Start custom XML
|
||||
element.SetAttribute("state", static_cast<unsigned int>(m_State));
|
||||
// End custom XML
|
||||
@@ -141,15 +147,21 @@ void Mission::UpdateXml(tinyxml2::XMLElement& element) {
|
||||
|
||||
element.SetAttribute("id", static_cast<unsigned int>(info.id));
|
||||
|
||||
if (m_Completions > 0) {
|
||||
element.SetAttribute("cct", static_cast<unsigned int>(m_Completions));
|
||||
element.SetAttribute("cct", static_cast<unsigned int>(m_Completions));
|
||||
|
||||
element.SetAttribute("cts", static_cast<unsigned int>(m_Timestamp));
|
||||
element.SetAttribute("cts", static_cast<unsigned int>(m_Timestamp));
|
||||
}
|
||||
|
||||
if (IsComplete()) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
void Mission::UpdateXmlCur(tinyxml2::XMLElement& element) {
|
||||
// Start custom XML
|
||||
element.SetAttribute("state", static_cast<unsigned int>(m_State));
|
||||
// End custom XML
|
||||
|
||||
element.DeleteChildren();
|
||||
|
||||
element.SetAttribute("id", static_cast<unsigned int>(info.id));
|
||||
|
||||
if (IsComplete()) return;
|
||||
|
||||
for (auto* task : m_Tasks) {
|
||||
if (task->GetType() == eMissionTaskType::COLLECTION ||
|
||||
@@ -345,12 +357,25 @@ void Mission::Complete(const bool yieldRewards) {
|
||||
for (const auto& email : missionEmails) {
|
||||
const auto missionEmailBase = "MissionEmail_" + std::to_string(email.ID) + "_";
|
||||
|
||||
if (email.messageType == 1) {
|
||||
if (email.messageType == 1 /* Send an email to the player */) {
|
||||
const auto subject = "%[" + missionEmailBase + "subjectText]";
|
||||
const auto body = "%[" + missionEmailBase + "bodyText]";
|
||||
const auto sender = "%[" + missionEmailBase + "senderName]";
|
||||
|
||||
Mail::SendMail(LWOOBJID_EMPTY, sender, GetAssociate(), subject, body, email.attachmentLOT, 1);
|
||||
} else if (email.messageType == 2 /* Send an announcement in chat */) {
|
||||
auto* character = entity->GetCharacter();
|
||||
|
||||
ChatPackets::AchievementNotify notify{};
|
||||
notify.missionEmailID = email.ID;
|
||||
notify.earningPlayerID = entity->GetObjectID();
|
||||
notify.earnerName.string = character ? GeneralUtils::ASCIIToUTF16(character->GetName()) : u"";
|
||||
|
||||
// Manual write since it's sent to chat server and not a game client
|
||||
RakNet::BitStream bitstream;
|
||||
notify.WriteHeader(bitstream);
|
||||
notify.Serialize(bitstream);
|
||||
Game::chatServer->Send(&bitstream, HIGH_PRIORITY, RELIABLE, 0, Game::chatSysAddr, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,8 +28,13 @@ public:
|
||||
Mission(MissionComponent* missionComponent, uint32_t missionId);
|
||||
~Mission();
|
||||
|
||||
void LoadFromXml(const tinyxml2::XMLElement& element);
|
||||
void UpdateXml(tinyxml2::XMLElement& element);
|
||||
// XML functions to load and save completed mission state to xml
|
||||
void LoadFromXmlDone(const tinyxml2::XMLElement& element);
|
||||
void UpdateXmlDone(tinyxml2::XMLElement& element);
|
||||
|
||||
// XML functions to load and save current mission state and task data to xml
|
||||
void LoadFromXmlCur(const tinyxml2::XMLElement& element);
|
||||
void UpdateXmlCur(tinyxml2::XMLElement& element);
|
||||
|
||||
/**
|
||||
* Returns the ID of this mission
|
||||
|
||||
@@ -181,6 +181,7 @@ namespace Mail {
|
||||
|
||||
void AttachmentCollectRequest::Handle() {
|
||||
AttachmentCollectResponse response;
|
||||
response.mailID = mailID;
|
||||
auto inv = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (mailID > 0 && playerID == player->GetObjectID() && inv) {
|
||||
|
||||
@@ -273,6 +273,16 @@ Instance* InstanceManager::FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instance* InstanceManager::FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID) {
|
||||
for (Instance* i : m_Instances) {
|
||||
if (i && i->GetMapID() == mapID && i->GetInstanceID() == instanceID && !i->GetShutdownComplete() && !i->GetIsShuttingDown()) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
Instance* InstanceManager::CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password) {
|
||||
auto* instance = FindPrivateInstance(password);
|
||||
|
||||
|
||||
@@ -76,25 +76,25 @@ public:
|
||||
void Shutdown();
|
||||
|
||||
private:
|
||||
std::string m_IP;
|
||||
uint32_t m_Port;
|
||||
LWOZONEID m_ZoneID;
|
||||
int m_MaxClientsSoftCap;
|
||||
int m_MaxClientsHardCap;
|
||||
int m_CurrentClientCount;
|
||||
std::vector<Player> m_Players;
|
||||
SystemAddress m_SysAddr;
|
||||
bool m_Ready;
|
||||
bool m_IsShuttingDown;
|
||||
std::vector<PendingInstanceRequest> m_PendingRequests;
|
||||
std::vector<PendingInstanceRequest> m_PendingAffirmations;
|
||||
std::string m_IP{};
|
||||
uint32_t m_Port{};
|
||||
LWOZONEID m_ZoneID{};
|
||||
int m_MaxClientsSoftCap{};
|
||||
int m_MaxClientsHardCap{};
|
||||
int m_CurrentClientCount{};
|
||||
std::vector<Player> m_Players{};
|
||||
SystemAddress m_SysAddr{};
|
||||
bool m_Ready{};
|
||||
bool m_IsShuttingDown{};
|
||||
std::vector<PendingInstanceRequest> m_PendingRequests{};
|
||||
std::vector<PendingInstanceRequest> m_PendingAffirmations{};
|
||||
|
||||
uint32_t m_AffirmationTimeout;
|
||||
uint32_t m_AffirmationTimeout{};
|
||||
|
||||
bool m_IsPrivate;
|
||||
std::string m_Password;
|
||||
bool m_IsPrivate{};
|
||||
std::string m_Password{};
|
||||
|
||||
bool m_Shutdown;
|
||||
bool m_Shutdown{};
|
||||
|
||||
//Private functions:
|
||||
};
|
||||
@@ -125,6 +125,7 @@ public:
|
||||
|
||||
Instance* FindInstance(LWOMAPID mapID, bool isFriendTransfer, LWOCLONEID cloneId = 0);
|
||||
Instance* FindInstance(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||
Instance* FindInstanceWithPrivate(LWOMAPID mapID, LWOINSTANCEID instanceID);
|
||||
|
||||
Instance* CreatePrivateInstance(LWOMAPID mapID, LWOCLONEID cloneID, const std::string& password);
|
||||
Instance* FindPrivateInstance(const std::string& password);
|
||||
|
||||
@@ -42,6 +42,7 @@
|
||||
#include "Server.h"
|
||||
#include "CDZoneTableTable.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
#ifdef DARKFLAME_PLATFORM_UNIX
|
||||
|
||||
@@ -556,7 +557,7 @@ void HandlePacket(Packet* packet) {
|
||||
Instance* in = Game::im->GetInstance(zoneID, false, zoneClone);
|
||||
|
||||
for (auto* instance : Game::im->GetInstances()) {
|
||||
LOG("Instance: %i/%i/%i -> %i", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in);
|
||||
LOG("Instance: %i/%i/%i -> %i %s", instance->GetMapID(), instance->GetCloneID(), instance->GetInstanceID(), instance == in, instance->GetSysAddr().ToString());
|
||||
}
|
||||
|
||||
if (in && !in->GetIsReady()) //Instance not ready, make a pending request
|
||||
@@ -597,15 +598,10 @@ void HandlePacket(Packet* packet) {
|
||||
if (!Game::im->IsPortInUse(theirPort)) {
|
||||
Instance* in = new Instance(theirIP.string, theirPort, theirZoneID, theirInstanceID, 0, 12, 12);
|
||||
|
||||
SystemAddress copy;
|
||||
copy.binaryAddress = packet->systemAddress.binaryAddress;
|
||||
copy.port = packet->systemAddress.port;
|
||||
|
||||
in->SetSysAddr(copy);
|
||||
in->SetSysAddr(packet->systemAddress);
|
||||
Game::im->AddInstance(in);
|
||||
} else {
|
||||
auto instance = Game::im->FindInstance(
|
||||
theirZoneID, static_cast<uint16_t>(theirInstanceID));
|
||||
auto* instance = Game::im->FindInstanceWithPrivate(theirZoneID, static_cast<LWOINSTANCEID>(theirInstanceID));
|
||||
if (instance) {
|
||||
instance->SetSysAddr(packet->systemAddress);
|
||||
}
|
||||
@@ -613,22 +609,14 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
if (theirServerType == ServerType::Chat) {
|
||||
SystemAddress copy;
|
||||
copy.binaryAddress = packet->systemAddress.binaryAddress;
|
||||
copy.port = packet->systemAddress.port;
|
||||
|
||||
chatServerMasterPeerSysAddr = copy;
|
||||
chatServerMasterPeerSysAddr = packet->systemAddress;
|
||||
}
|
||||
|
||||
if (theirServerType == ServerType::Auth) {
|
||||
SystemAddress copy;
|
||||
copy.binaryAddress = packet->systemAddress.binaryAddress;
|
||||
copy.port = packet->systemAddress.port;
|
||||
|
||||
authServerMasterPeerSysAddr = copy;
|
||||
authServerMasterPeerSysAddr = packet->systemAddress;
|
||||
}
|
||||
|
||||
LOG("Received server info, instance: %i port: %i", theirInstanceID, theirPort);
|
||||
LOG("Received %s server info, instance: %i port: %i", StringifiedEnum::ToString(theirServerType).data(), theirInstanceID, theirPort);
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -692,7 +680,7 @@ void HandlePacket(Packet* packet) {
|
||||
if (instance) {
|
||||
instance->AddPlayer(Player());
|
||||
} else {
|
||||
printf("Instance missing? What?");
|
||||
LOG("Instance missing? What?");
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -733,8 +721,8 @@ void HandlePacket(Packet* packet) {
|
||||
inStream.Read<char>(character);
|
||||
password += character;
|
||||
}
|
||||
|
||||
Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str());
|
||||
auto* newInst = Game::im->CreatePrivateInstance(mapId, cloneId, password.c_str());
|
||||
LOG("Creating private zone %i/%i/%i with password %s", newInst->GetMapID(), newInst->GetCloneID(), newInst->GetInstanceID(), password.c_str());
|
||||
|
||||
break;
|
||||
}
|
||||
@@ -835,11 +823,10 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
case MessageType::Master::SHUTDOWN_RESPONSE: {
|
||||
RakNet::BitStream inStream(packet->data, packet->length, false);
|
||||
uint64_t header = inStream.Read(header);
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
|
||||
auto* instance = Game::im->GetInstanceBySysAddr(packet->systemAddress);
|
||||
|
||||
LOG("Got shutdown response from %s", packet->systemAddress.ToString());
|
||||
if (instance == nullptr) {
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -107,3 +107,28 @@ void ChatPackets::Announcement::Send() {
|
||||
bitStream.Write(message);
|
||||
SEND_PACKET_BROADCAST;
|
||||
}
|
||||
|
||||
void ChatPackets::AchievementNotify::Serialize(RakNet::BitStream& bitstream) const {
|
||||
bitstream.Write<uint64_t>(0); // Packing
|
||||
bitstream.Write<uint32_t>(0); // Packing
|
||||
bitstream.Write<uint8_t>(0); // Packing
|
||||
bitstream.Write(targetPlayerName);
|
||||
bitstream.Write<uint64_t>(0); // Packing / No way to know meaning because of not enough data.
|
||||
bitstream.Write<uint32_t>(0); // Packing / No way to know meaning because of not enough data.
|
||||
bitstream.Write<uint16_t>(0); // Packing / No way to know meaning because of not enough data.
|
||||
bitstream.Write<uint8_t>(0); // Packing / No way to know meaning because of not enough data.
|
||||
bitstream.Write(missionEmailID);
|
||||
bitstream.Write(earningPlayerID);
|
||||
bitstream.Write(earnerName);
|
||||
}
|
||||
|
||||
bool ChatPackets::AchievementNotify::Deserialize(RakNet::BitStream& bitstream) {
|
||||
bitstream.IgnoreBytes(13);
|
||||
VALIDATE_READ(bitstream.Read(targetPlayerName));
|
||||
bitstream.IgnoreBytes(15);
|
||||
VALIDATE_READ(bitstream.Read(missionEmailID));
|
||||
VALIDATE_READ(bitstream.Read(earningPlayerID));
|
||||
VALIDATE_READ(bitstream.Read(earnerName));
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -10,6 +10,8 @@ struct SystemAddress;
|
||||
|
||||
#include <string>
|
||||
#include "dCommonVars.h"
|
||||
#include "MessageType/Chat.h"
|
||||
#include "BitStreamUtils.h"
|
||||
|
||||
struct ShowAllRequest{
|
||||
LWOOBJID requestor = LWOOBJID_EMPTY;
|
||||
@@ -34,6 +36,16 @@ namespace ChatPackets {
|
||||
void Send();
|
||||
};
|
||||
|
||||
struct AchievementNotify : public LUBitStream {
|
||||
LUWString targetPlayerName{};
|
||||
uint32_t missionEmailID{};
|
||||
LWOOBJID earningPlayerID{};
|
||||
LUWString earnerName{};
|
||||
AchievementNotify() : LUBitStream(eConnectionType::CHAT, MessageType::Chat::ACHIEVEMENT_NOTIFY) {}
|
||||
void Serialize(RakNet::BitStream& bitstream) const override;
|
||||
bool Deserialize(RakNet::BitStream& bitstream) override;
|
||||
};
|
||||
|
||||
void SendChatMessage(const SystemAddress& sysAddr, char chatChannel, const std::string& senderName, LWOOBJID playerObjectID, bool senderMythran, const std::u16string& message);
|
||||
void SendSystemMessage(const SystemAddress& sysAddr, const std::u16string& message, bool broadcast = false);
|
||||
void SendMessageFail(const SystemAddress& sysAddr);
|
||||
|
||||
Reference in New Issue
Block a user