mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-20 11:59:40 -06:00
Compare commits
7 Commits
mailv2
...
quickbuild
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a0913ff23d | ||
|
|
b738504812 | ||
|
|
c968dc9028 | ||
|
|
2209a4432f | ||
|
|
c855a6b9cf | ||
|
|
8abc545bd1 | ||
|
|
136133dde2 |
@@ -70,12 +70,15 @@ int main(int argc, char** argv) {
|
||||
//Find out the master's IP:
|
||||
std::string masterIP;
|
||||
uint32_t masterPort = 1500;
|
||||
std::string masterPassword;
|
||||
|
||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||
if (masterInfo) {
|
||||
masterIP = masterInfo->ip;
|
||||
masterPort = masterInfo->port;
|
||||
masterPassword = masterInfo->password;
|
||||
}
|
||||
|
||||
LOG("Master is at %s:%d", masterIP.c_str(), masterPort);
|
||||
|
||||
Game::randomEngine = std::mt19937(time(0));
|
||||
@@ -89,7 +92,7 @@ int main(int argc, char** argv) {
|
||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal);
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Auth, Game::config, &Game::lastSignal, masterPassword);
|
||||
|
||||
//Run it until server gets a kill message from Master:
|
||||
auto t = std::chrono::high_resolution_clock::now();
|
||||
|
||||
@@ -103,7 +103,8 @@ void ChatPacketHandler::HandleFriendRequest(Packet* packet) {
|
||||
return;
|
||||
};
|
||||
|
||||
auto& requestee = Game::playerContainer.GetPlayerDataMutable(playerName);
|
||||
// Intentional copy
|
||||
PlayerData requestee = Game::playerContainer.GetPlayerData(playerName);
|
||||
|
||||
// Check if player is online first
|
||||
if (isBestFriendRequest && !requestee) {
|
||||
@@ -188,19 +189,24 @@ 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) {
|
||||
requestee.countOfBestFriends += 1;
|
||||
requestor.countOfBestFriends += 1;
|
||||
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);
|
||||
|
||||
for (auto& friendData : requestor.friends) {
|
||||
if (friendData.friendID == requestee.playerID) {
|
||||
friendData.isBestFriend = true;
|
||||
}
|
||||
}
|
||||
for (auto& friendData : requestee.friends) {
|
||||
if (friendData.friendID == requestor.playerID) {
|
||||
friendData.isBestFriend = true;
|
||||
requestor.countOfBestFriends += 1;
|
||||
|
||||
auto& toModify = Game::playerContainer.GetPlayerDataMutable(playerName);
|
||||
if (toModify) {
|
||||
for (auto& friendData : toModify.friends) {
|
||||
if (friendData.friendID == requestor.playerID) {
|
||||
friendData.isBestFriend = true;
|
||||
}
|
||||
}
|
||||
toModify.countOfBestFriends += 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,10 +92,12 @@ int main(int argc, char** argv) {
|
||||
//Find out the master's IP:
|
||||
std::string masterIP;
|
||||
uint32_t masterPort = 1000;
|
||||
std::string masterPassword;
|
||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||
if (masterInfo) {
|
||||
masterIP = masterInfo->ip;
|
||||
masterPort = masterInfo->port;
|
||||
masterPassword = masterInfo->password;
|
||||
}
|
||||
//It's safe to pass 'localhost' here, as the IP is only used as the external IP.
|
||||
std::string ourIP = "localhost";
|
||||
@@ -104,7 +106,7 @@ int main(int argc, char** argv) {
|
||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal);
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::Chat, Game::config, &Game::lastSignal, masterPassword);
|
||||
|
||||
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "Logger.h"
|
||||
#include "Game.h"
|
||||
|
||||
#include <type_traits>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
|
||||
@@ -257,10 +258,10 @@ public:
|
||||
*
|
||||
* @param key The key to remove from the associative portion
|
||||
*/
|
||||
void Remove(const std::string& key, const bool deleteValue = true) {
|
||||
void Remove(const std::string& key) {
|
||||
const AMFAssociative::const_iterator it = m_Associative.find(key);
|
||||
if (it != m_Associative.cend()) {
|
||||
if (deleteValue) m_Associative.erase(it);
|
||||
m_Associative.erase(it);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -343,6 +344,11 @@ public:
|
||||
return index < m_Dense.size() ? m_Dense.at(index).get() : nullptr;
|
||||
}
|
||||
|
||||
void Reset() {
|
||||
m_Associative.clear();
|
||||
m_Dense.clear();
|
||||
}
|
||||
|
||||
private:
|
||||
/**
|
||||
* The associative portion. These values are key'd with strings to an AMFValue.
|
||||
|
||||
@@ -7,8 +7,7 @@ enum class eConnectionType : uint16_t {
|
||||
CHAT,
|
||||
WORLD = 4,
|
||||
CLIENT,
|
||||
MASTER,
|
||||
UNKNOWN
|
||||
MASTER
|
||||
};
|
||||
|
||||
#endif //!__ECONNECTIONTYPE__H__
|
||||
|
||||
@@ -8,10 +8,27 @@
|
||||
#include "dCommonVars.h"
|
||||
#include "NiQuaternion.h"
|
||||
#include "NiPoint3.h"
|
||||
#include "MailInfo.h"
|
||||
|
||||
|
||||
class IMail {
|
||||
public:
|
||||
struct MailInfo {
|
||||
std::string senderUsername;
|
||||
std::string recipient;
|
||||
std::string subject;
|
||||
std::string body;
|
||||
uint64_t id{};
|
||||
uint32_t senderId{};
|
||||
uint32_t receiverId{};
|
||||
uint64_t timeSent{};
|
||||
bool wasRead{};
|
||||
struct {
|
||||
LWOOBJID itemID{};
|
||||
int32_t itemCount{};
|
||||
LOT itemLOT{};
|
||||
LWOOBJID itemSubkey{};
|
||||
};
|
||||
};
|
||||
|
||||
// Insert a new mail into the database.
|
||||
virtual void InsertNewMail(const MailInfo& mail) = 0;
|
||||
|
||||
|
||||
@@ -9,10 +9,11 @@ public:
|
||||
struct MasterInfo {
|
||||
std::string ip;
|
||||
uint32_t port{};
|
||||
std::string password{};
|
||||
};
|
||||
|
||||
// Set the master server ip and port.
|
||||
virtual void SetMasterIp(const std::string_view ip, const uint32_t port) = 0;
|
||||
virtual void SetMasterInfo(const MasterInfo& info) = 0;
|
||||
|
||||
// Get the master server info.
|
||||
virtual std::optional<MasterInfo> GetMasterInfo() = 0;
|
||||
|
||||
@@ -79,14 +79,14 @@ public:
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewMail(const IMail::MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::istringstream& sd0Data,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const uint32_t characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||
std::vector<IMail::MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<IMail::MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
@@ -96,7 +96,7 @@ public:
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
|
||||
@@ -1,7 +1,6 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
|
||||
void MySQLDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
void MySQLDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `mail` "
|
||||
"(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`)"
|
||||
@@ -19,17 +18,17 @@ void MySQLDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
mail.itemCount);
|
||||
}
|
||||
|
||||
std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
std::vector<IMail::MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
auto res = ExecuteSelect(
|
||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||
" FROM mail WHERE receiver_id=? limit ?;",
|
||||
characterId, numberOfMail);
|
||||
|
||||
std::vector<MailInfo> toReturn;
|
||||
std::vector<IMail::MailInfo> toReturn;
|
||||
toReturn.reserve(res->rowsCount());
|
||||
|
||||
while (res->next()) {
|
||||
MailInfo mail;
|
||||
IMail::MailInfo mail;
|
||||
mail.id = res->getUInt64("id");
|
||||
mail.subject = res->getString("subject").c_str();
|
||||
mail.body = res->getString("body").c_str();
|
||||
@@ -47,14 +46,14 @@ std::vector<MailInfo> MySQLDatabase::GetMailForPlayer(const uint32_t characterId
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
||||
std::optional<IMail::MailInfo> MySQLDatabase::GetMail(const uint64_t mailId) {
|
||||
auto res = ExecuteSelect("SELECT attachment_lot, attachment_count FROM mail WHERE id=? LIMIT 1;", mailId);
|
||||
|
||||
if (!res->next()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
MailInfo toReturn;
|
||||
IMail::MailInfo toReturn;
|
||||
toReturn.itemLOT = res->getInt("attachment_lot");
|
||||
toReturn.itemCount = res->getInt("attachment_count");
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||
void MySQLDatabase::SetMasterInfo(const MasterInfo& info) {
|
||||
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||
// since it would be two queries anyways.
|
||||
ExecuteDelete("TRUNCATE TABLE servers;");
|
||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`, `master_password`) VALUES ('master', ?, ?, 0, 171022, ?)", info.ip, info.port, info.password);
|
||||
}
|
||||
|
||||
std::optional<IServers::MasterInfo> MySQLDatabase::GetMasterInfo() {
|
||||
auto result = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||
auto result = ExecuteSelect("SELECT ip, port, master_password FROM servers WHERE name='master' LIMIT 1;");
|
||||
|
||||
if (!result->next()) {
|
||||
return std::nullopt;
|
||||
@@ -18,6 +18,7 @@ std::optional<IServers::MasterInfo> MySQLDatabase::GetMasterInfo() {
|
||||
|
||||
toReturn.ip = result->getString("ip").c_str();
|
||||
toReturn.port = result->getInt("port");
|
||||
toReturn.password = result->getString("master_password").c_str();
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -77,14 +77,14 @@ public:
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewMail(const IMail::MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::istringstream& sd0Data,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const uint32_t characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||
std::vector<IMail::MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<IMail::MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
@@ -94,7 +94,7 @@ public:
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
void SQLiteDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
||||
ExecuteInsert(
|
||||
"INSERT INTO `mail` "
|
||||
"(`sender_id`, `sender_name`, `receiver_id`, `receiver_name`, `time_sent`, `subject`, `body`, `attachment_id`, `attachment_lot`, `attachment_subkey`, `attachment_count`, `was_read`)"
|
||||
@@ -18,16 +18,16 @@ void SQLiteDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
mail.itemCount);
|
||||
}
|
||||
|
||||
std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
std::vector<IMail::MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
auto [_, res] = ExecuteSelect(
|
||||
"SELECT id, subject, body, sender_name, attachment_id, attachment_lot, attachment_subkey, attachment_count, was_read, time_sent"
|
||||
" FROM mail WHERE receiver_id=? limit ?;",
|
||||
characterId, numberOfMail);
|
||||
|
||||
std::vector<MailInfo> toReturn;
|
||||
std::vector<IMail::MailInfo> toReturn;
|
||||
|
||||
while (!res.eof()) {
|
||||
MailInfo mail;
|
||||
IMail::MailInfo mail;
|
||||
mail.id = res.getInt64Field("id");
|
||||
mail.subject = res.getStringField("subject");
|
||||
mail.body = res.getStringField("body");
|
||||
@@ -46,14 +46,14 @@ std::vector<MailInfo> SQLiteDatabase::GetMailForPlayer(const uint32_t characterI
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
std::optional<MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
||||
std::optional<IMail::MailInfo> SQLiteDatabase::GetMail(const uint64_t mailId) {
|
||||
auto [_, res] = ExecuteSelect("SELECT attachment_lot, attachment_count FROM mail WHERE id=? LIMIT 1;", mailId);
|
||||
|
||||
if (res.eof()) {
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
MailInfo toReturn;
|
||||
IMail::MailInfo toReturn;
|
||||
toReturn.itemLOT = res.getIntField("attachment_lot");
|
||||
toReturn.itemCount = res.getIntField("attachment_count");
|
||||
|
||||
|
||||
@@ -1,14 +1,14 @@
|
||||
#include "SQLiteDatabase.h"
|
||||
|
||||
void SQLiteDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||
void SQLiteDatabase::SetMasterInfo(const MasterInfo& info) {
|
||||
// We only want our 1 entry anyways, so we can just delete all and reinsert the one we want
|
||||
// since it would be two queries anyways.
|
||||
ExecuteDelete("DELETE FROM servers;");
|
||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`) VALUES ('master', ?, ?, 0, 171022)", ip, port);
|
||||
ExecuteInsert("INSERT INTO `servers` (`name`, `ip`, `port`, `state`, `version`, `master_password`) VALUES ('master', ?, ?, 0, 171022 ?)", info.ip, info.port, info.password);
|
||||
}
|
||||
|
||||
std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
||||
auto [_, result] = ExecuteSelect("SELECT ip, port FROM servers WHERE name='master' LIMIT 1;");
|
||||
auto [_, result] = ExecuteSelect("SELECT ip, port, master_password FROM servers WHERE name='master' LIMIT 1;");
|
||||
|
||||
if (result.eof()) {
|
||||
return std::nullopt;
|
||||
@@ -18,6 +18,7 @@ std::optional<IServers::MasterInfo> SQLiteDatabase::GetMasterInfo() {
|
||||
|
||||
toReturn.ip = result.getStringField("ip");
|
||||
toReturn.port = result.getIntField("port");
|
||||
toReturn.password = result.getStringField("master_password");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
@@ -184,7 +184,7 @@ void TestSQLDatabase::InsertCheatDetection(const IPlayerCheatDetections::Info& i
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::InsertNewMail(const MailInfo& mail) {
|
||||
void TestSQLDatabase::InsertNewMail(const IMail::MailInfo& mail) {
|
||||
|
||||
}
|
||||
|
||||
@@ -192,11 +192,11 @@ void TestSQLDatabase::InsertNewUgcModel(std::istringstream& sd0Data, const uint3
|
||||
|
||||
}
|
||||
|
||||
std::vector<MailInfo> TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
std::vector<IMail::MailInfo> TestSQLDatabase::GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::optional<MailInfo> TestSQLDatabase::GetMail(const uint64_t mailId) {
|
||||
std::optional<IMail::MailInfo> TestSQLDatabase::GetMail(const uint64_t mailId) {
|
||||
return {};
|
||||
}
|
||||
|
||||
@@ -236,7 +236,7 @@ void TestSQLDatabase::InsertNewAccount(const std::string_view username, const st
|
||||
|
||||
}
|
||||
|
||||
void TestSQLDatabase::SetMasterIp(const std::string_view ip, const uint32_t port) {
|
||||
void TestSQLDatabase::SetMasterInfo(const IServers::MasterInfo& info) {
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -56,14 +56,14 @@ class TestSQLDatabase : public GameDatabase {
|
||||
void UpdatePerformanceCost(const LWOZONEID& zoneId, const float performanceCost) override;
|
||||
void InsertNewBugReport(const IBugReports::Info& info) override;
|
||||
void InsertCheatDetection(const IPlayerCheatDetections::Info& info) override;
|
||||
void InsertNewMail(const MailInfo& mail) override;
|
||||
void InsertNewMail(const IMail::MailInfo& mail) override;
|
||||
void InsertNewUgcModel(
|
||||
std::istringstream& sd0Data,
|
||||
const uint32_t blueprintId,
|
||||
const uint32_t accountId,
|
||||
const uint32_t characterId) override;
|
||||
std::vector<MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<MailInfo> GetMail(const uint64_t mailId) override;
|
||||
std::vector<IMail::MailInfo> GetMailForPlayer(const uint32_t characterId, const uint32_t numberOfMail) override;
|
||||
std::optional<IMail::MailInfo> GetMail(const uint64_t mailId) override;
|
||||
uint32_t GetUnreadMailCount(const uint32_t characterId) override;
|
||||
void MarkMailRead(const uint64_t mailId) override;
|
||||
void DeleteMail(const uint64_t mailId) override;
|
||||
@@ -73,7 +73,7 @@ class TestSQLDatabase : public GameDatabase {
|
||||
void UpdateAccountBan(const uint32_t accountId, const bool banned) override;
|
||||
void UpdateAccountPassword(const uint32_t accountId, const std::string_view bcryptpassword) override;
|
||||
void InsertNewAccount(const std::string_view username, const std::string_view bcryptpassword) override;
|
||||
void SetMasterIp(const std::string_view ip, const uint32_t port) override;
|
||||
void SetMasterInfo(const IServers::MasterInfo& info) override;
|
||||
std::optional<uint32_t> GetCurrentPersistentId() override;
|
||||
void InsertDefaultPersistentId() override;
|
||||
void UpdatePersistentId(const uint32_t id) override;
|
||||
|
||||
@@ -786,7 +786,7 @@ void CharacterComponent::AwardClaimCodes() {
|
||||
subject << "%[RewardCodes_" << rewardCode << "_subjectText]";
|
||||
std::ostringstream body;
|
||||
body << "%[RewardCodes_" << rewardCode << "_bodyText]";
|
||||
Mail::SendMail(m_Parent, subject.str(), body.str(), attachmentLOT, 1);
|
||||
Mail::SendMail(LWOOBJID_EMPTY, "%[MAIL_SYSTEM_NOTIFICATION]", m_Parent, subject.str(), body.str(), attachmentLOT, 1);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -274,7 +274,7 @@ void InventoryComponent::AddItem(
|
||||
|
||||
switch (sourceType) {
|
||||
case 0:
|
||||
Mail::SendMail(m_Parent, "%[MAIL_ACTIVITY_OVERFLOW_HEADER]", "%[MAIL_ACTIVITY_OVERFLOW_BODY]", lot, size);
|
||||
Mail::SendMail(LWOOBJID_EMPTY, "Darkflame Universe", m_Parent, "Lost Reward", "You received an item and didn't have room for it.", lot, size);
|
||||
break;
|
||||
|
||||
case 1:
|
||||
|
||||
@@ -99,8 +99,17 @@ void MissionComponent::AcceptMission(const uint32_t missionId, const bool skipCh
|
||||
mission->Accept();
|
||||
|
||||
this->m_Missions.insert_or_assign(missionId, mission);
|
||||
|
||||
if (missionId == 1728) {
|
||||
//Needs to send a mail
|
||||
|
||||
auto address = m_Parent->GetSystemAddress();
|
||||
|
||||
Mail::HandleNotificationRequest(address, m_Parent->GetObjectID());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void MissionComponent::CompleteMission(const uint32_t missionId, const bool skipChecks, const bool yieldRewards) {
|
||||
// Get the mission first
|
||||
auto* mission = this->GetMission(missionId);
|
||||
|
||||
@@ -84,11 +84,12 @@ dpEntity* PhysicsComponent::CreatePhysicsEntity(eReplicaComponentType type) {
|
||||
} else if (info->physicsAsset == "env\\env_won_fv_gas-blocking-volume.hkx") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 390.496826f, 111.467964f, 600.821534f, true);
|
||||
m_Position.y -= (111.467964f * m_Parent->GetDefaultScale()) / 2;
|
||||
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume1_CaveExit.hkx") {
|
||||
// Leaving these out for now since they cause more issues than they solve in racing tracks without proper OBB checks.
|
||||
} /* else if (info->physicsAsset == "env\\GFTrack_DeathVolume1_CaveExit.hkx") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 112.416870f, 50.363434f, 87.679268f);
|
||||
} else if (info->physicsAsset == "env\\GFTrack_DeathVolume2_RoadGaps.hkx") {
|
||||
toReturn = new dpEntity(m_Parent->GetObjectID(), 48.386536f, 50.363434f, 259.361755f);
|
||||
} else {
|
||||
} */ else {
|
||||
// LOG_DEBUG("This one is supposed to have %s", info->physicsAsset.c_str());
|
||||
|
||||
//add fallback cube:
|
||||
|
||||
@@ -105,16 +105,6 @@ void QuickBuildComponent::Serialize(RakNet::BitStream& outBitStream, bool bIsIni
|
||||
void QuickBuildComponent::Update(float deltaTime) {
|
||||
SetActivator(GetActivator());
|
||||
|
||||
// Serialize the quickbuild every so often, fixes the odd bug where the quickbuild is not buildable
|
||||
/*if (m_SoftTimer > 0.0f) {
|
||||
m_SoftTimer -= deltaTime;
|
||||
}
|
||||
else {
|
||||
m_SoftTimer = 5.0f;
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
}*/
|
||||
|
||||
switch (m_State) {
|
||||
case eQuickBuildState::OPEN: {
|
||||
SpawnActivator();
|
||||
@@ -125,11 +115,10 @@ void QuickBuildComponent::Update(float deltaTime) {
|
||||
|
||||
if (isSmashGroup) {
|
||||
ModifyIncompleteTimer(deltaTime);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
// For reset times < 0 this has to be handled manually
|
||||
if (m_TimeBeforeSmash > 0) {
|
||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f && !m_ShowResetEffect) {
|
||||
SetShowResetEffect(true);
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@@ -149,11 +138,10 @@ void QuickBuildComponent::Update(float deltaTime) {
|
||||
}
|
||||
case eQuickBuildState::COMPLETED: {
|
||||
ModifyTimer(deltaTime);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
// For reset times < 0 this has to be handled manually
|
||||
if (m_ResetTime > 0) {
|
||||
if (m_Timer >= m_ResetTime - 4.0f) {
|
||||
if (m_Timer >= m_ResetTime - 4.0f && !m_ShowResetEffect) {
|
||||
SetShowResetEffect(true);
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
@@ -210,11 +198,10 @@ void QuickBuildComponent::Update(float deltaTime) {
|
||||
}
|
||||
case eQuickBuildState::INCOMPLETE: {
|
||||
ModifyIncompleteTimer(deltaTime);
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
// For reset times < 0 this has to be handled manually
|
||||
if (m_TimeBeforeSmash > 0) {
|
||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f) {
|
||||
if (m_TimerIncomplete >= m_TimeBeforeSmash - 4.0f && !m_ShowResetEffect) {
|
||||
SetShowResetEffect(true);
|
||||
|
||||
Game::entityManager->SerializeEntity(m_Parent);
|
||||
|
||||
@@ -26,278 +26,12 @@
|
||||
#include "eMissionTaskType.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "User.h"
|
||||
#include "StringifiedEnum.h"
|
||||
|
||||
namespace {
|
||||
const std::string DefaultSender = "%[MAIL_SYSTEM_NOTIFICATION]";
|
||||
}
|
||||
|
||||
namespace Mail {
|
||||
std::map<eMessageID, std::function<std::unique_ptr<MailLUBitStream>()>> g_Handlers = {
|
||||
{eMessageID::SendRequest, []() {
|
||||
return std::make_unique<SendRequest>();
|
||||
}},
|
||||
{eMessageID::DataRequest, []() {
|
||||
return std::make_unique<DataRequest>();
|
||||
}},
|
||||
{eMessageID::AttachmentCollectRequest, []() {
|
||||
return std::make_unique<AttachmentCollectRequest>();
|
||||
}},
|
||||
{eMessageID::DeleteRequest, []() {
|
||||
return std::make_unique<DeleteRequest>();
|
||||
}},
|
||||
{eMessageID::ReadRequest, []() {
|
||||
return std::make_unique<ReadRequest>();
|
||||
}},
|
||||
{eMessageID::NotificationRequest, []() {
|
||||
return std::make_unique<NotificationRequest>();
|
||||
}},
|
||||
};
|
||||
|
||||
void MailLUBitStream::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(messageID);
|
||||
}
|
||||
|
||||
bool MailLUBitStream::Deserialize(RakNet::BitStream& bitstream) {
|
||||
VALIDATE_READ(bitstream.Read(messageID));
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SendRequest::Deserialize(RakNet::BitStream& bitStream) {
|
||||
VALIDATE_READ(mailInfo.Deserialize(bitStream));
|
||||
return true;
|
||||
}
|
||||
|
||||
void SendRequest::Handle() {
|
||||
SendResponse response;
|
||||
auto* character = player->GetCharacter();
|
||||
if (character && !(character->HasPermission(ePermissionMap::RestrictedMailAccess) || character->GetParentUser()->GetIsMuted())) {
|
||||
mailInfo.recipient = std::regex_replace(mailInfo.recipient, std::regex("[^0-9a-zA-Z]+"), "");
|
||||
auto receiverID = Database::Get()->GetCharacterInfo(mailInfo.recipient);
|
||||
|
||||
if (!receiverID) {
|
||||
response.status = eSendResponse::RecipientNotFound;
|
||||
} else if (GeneralUtils::CaseInsensitiveStringCompare(mailInfo.recipient, character->GetName()) || receiverID->id == character->GetID()) {
|
||||
response.status = eSendResponse::CannotMailSelf;
|
||||
} else {
|
||||
uint32_t mailCost = Game::zoneManager->GetWorldConfig()->mailBaseFee;
|
||||
uint32_t stackSize = 0;
|
||||
|
||||
auto inventoryComponent = player->GetComponent<InventoryComponent>();
|
||||
Item* item = nullptr;
|
||||
|
||||
bool hasAttachment = mailInfo.itemID != 0 && mailInfo.itemCount > 0;
|
||||
|
||||
if (hasAttachment) {
|
||||
item = inventoryComponent->FindItemById(mailInfo.itemID);
|
||||
if (item) {
|
||||
mailCost += (item->GetInfo().baseValue * Game::zoneManager->GetWorldConfig()->mailPercentAttachmentFee);
|
||||
mailInfo.itemLOT = item->GetLot();
|
||||
}
|
||||
}
|
||||
|
||||
if (hasAttachment && !item) {
|
||||
response.status = eSendResponse::AttachmentNotFound;
|
||||
} else if (player->GetCharacter()->GetCoins() - mailCost < 0) {
|
||||
response.status = eSendResponse::NotEnoughCoins;
|
||||
} else {
|
||||
bool removeSuccess = true;
|
||||
// Remove coins and items from the sender
|
||||
player->GetCharacter()->SetCoins(player->GetCharacter()->GetCoins() - mailCost, eLootSourceType::MAIL);
|
||||
if (inventoryComponent && hasAttachment && item) {
|
||||
removeSuccess = inventoryComponent->RemoveItem(mailInfo.itemLOT, mailInfo.itemCount, INVALID, true);
|
||||
auto* missionComponent = player->GetComponent<MissionComponent>();
|
||||
if (missionComponent && removeSuccess) missionComponent->Progress(eMissionTaskType::GATHER, mailInfo.itemLOT, LWOOBJID_EMPTY, "", -mailInfo.itemCount);
|
||||
}
|
||||
|
||||
// we passed all the checks, now we can actully send the mail
|
||||
if (removeSuccess) {
|
||||
mailInfo.senderId = character->GetID();
|
||||
mailInfo.senderUsername = character->GetName();
|
||||
mailInfo.receiverId = receiverID->id;
|
||||
mailInfo.itemSubkey = LWOOBJID_EMPTY;
|
||||
|
||||
//clear out the attachementID
|
||||
mailInfo.itemID = 0;
|
||||
|
||||
Database::Get()->InsertNewMail(mailInfo);
|
||||
response.status = eSendResponse::Success;
|
||||
character->SaveXMLToDatabase();
|
||||
} else {
|
||||
response.status = eSendResponse::AttachmentNotFound;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
response.status = eSendResponse::SenderAccountIsMuted;
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
void SendResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(status);
|
||||
}
|
||||
|
||||
void NotificationResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(status);
|
||||
bitStream.Write<uint64_t>(0); // unused
|
||||
bitStream.Write<uint64_t>(0); // unused
|
||||
bitStream.Write(auctionID);
|
||||
bitStream.Write<uint64_t>(0); // unused
|
||||
bitStream.Write(mailCount);
|
||||
bitStream.Write<uint32_t>(0); // packing
|
||||
}
|
||||
|
||||
void DataRequest::Handle() {
|
||||
const auto* character = player->GetCharacter();
|
||||
if (!character) return;
|
||||
auto playerMail = Database::Get()->GetMailForPlayer(character->GetID(), 20);
|
||||
DataResponse response;
|
||||
response.playerMail = playerMail;
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
void DataResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(this->throttled);
|
||||
|
||||
bitStream.Write<uint16_t>(this->playerMail.size());
|
||||
bitStream.Write<uint16_t>(0); // packing
|
||||
for (const auto& mail : this->playerMail) {
|
||||
mail.Serialize(bitStream);
|
||||
}
|
||||
}
|
||||
|
||||
bool AttachmentCollectRequest::Deserialize(RakNet::BitStream& bitStream) {
|
||||
uint32_t unknown;
|
||||
VALIDATE_READ(bitStream.Read(unknown));
|
||||
VALIDATE_READ(bitStream.Read(mailID));
|
||||
VALIDATE_READ(bitStream.Read(playerID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void AttachmentCollectRequest::Handle() {
|
||||
AttachmentCollectResponse response;
|
||||
auto inv = player->GetComponent<InventoryComponent>();
|
||||
|
||||
if (mailID > 0 && playerID == player->GetObjectID() && inv) {
|
||||
auto playerMail = Database::Get()->GetMail(mailID);
|
||||
if (!playerMail) {
|
||||
response.status = eAttachmentCollectResponse::MailNotFound;
|
||||
} else if (!inv->HasSpaceForLoot({ {playerMail->itemLOT, playerMail->itemCount} })) {
|
||||
response.status = eAttachmentCollectResponse::NoSpaceInInventory;
|
||||
} else {
|
||||
inv->AddItem(playerMail->itemLOT, playerMail->itemCount, eLootSourceType::MAIL);
|
||||
Database::Get()->ClaimMailItem(mailID);
|
||||
response.status = eAttachmentCollectResponse::Success;
|
||||
}
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
void AttachmentCollectResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(status);
|
||||
bitStream.Write(mailID);
|
||||
}
|
||||
|
||||
bool DeleteRequest::Deserialize(RakNet::BitStream& bitStream) {
|
||||
int32_t unknown;
|
||||
VALIDATE_READ(bitStream.Read(unknown));
|
||||
VALIDATE_READ(bitStream.Read(mailID));
|
||||
VALIDATE_READ(bitStream.Read(playerID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeleteRequest::Handle() {
|
||||
DeleteResponse response;
|
||||
response.mailID = mailID;
|
||||
|
||||
auto mailData = Database::Get()->GetMail(mailID);
|
||||
if (mailData && !(mailData->itemLOT != 0 && mailData->itemCount > 0)) {
|
||||
Database::Get()->DeleteMail(mailID);
|
||||
response.status = eDeleteResponse::Success;
|
||||
} else if (mailData && mailData->itemLOT != 0 && mailData->itemCount > 0) {
|
||||
response.status = eDeleteResponse::HasAttachments;
|
||||
} else {
|
||||
response.status = eDeleteResponse::NotFound;
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
void DeleteResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(status);
|
||||
bitStream.Write(mailID);
|
||||
}
|
||||
|
||||
bool ReadRequest::Deserialize(RakNet::BitStream& bitStream) {
|
||||
int32_t unknown;
|
||||
VALIDATE_READ(bitStream.Read(unknown));
|
||||
VALIDATE_READ(bitStream.Read(mailID));
|
||||
return true;
|
||||
}
|
||||
|
||||
void ReadRequest::Handle() {
|
||||
ReadResponse response;
|
||||
response.mailID = mailID;
|
||||
|
||||
if (Database::Get()->GetMail(mailID)) {
|
||||
response.status = eReadResponse::Success;
|
||||
Database::Get()->MarkMailRead(mailID);
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
|
||||
void ReadResponse::Serialize(RakNet::BitStream& bitStream) const {
|
||||
MailLUBitStream::Serialize(bitStream);
|
||||
bitStream.Write(status);
|
||||
bitStream.Write(mailID);
|
||||
}
|
||||
|
||||
void NotificationRequest::Handle() {
|
||||
NotificationResponse response;
|
||||
auto character = player->GetCharacter();
|
||||
if (character) {
|
||||
auto unreadMailCount = Database::Get()->GetUnreadMailCount(character->GetID());
|
||||
response.status = eNotificationResponse::NewMail;
|
||||
response.mailCount = unreadMailCount;
|
||||
}
|
||||
response.Send(sysAddr);
|
||||
}
|
||||
}
|
||||
|
||||
// Non Stuct Functions
|
||||
void Mail::HandleMail(RakNet::BitStream& inStream, const SystemAddress& sysAddr, Entity* player) {
|
||||
MailLUBitStream data;
|
||||
if (!data.Deserialize(inStream)) {
|
||||
LOG_DEBUG("Error Reading Mail header");
|
||||
return;
|
||||
}
|
||||
|
||||
auto it = g_Handlers.find(data.messageID);
|
||||
if (it != g_Handlers.end()) {
|
||||
auto request = it->second();
|
||||
request->sysAddr = sysAddr;
|
||||
request->player = player;
|
||||
if (!request->Deserialize(inStream)) {
|
||||
LOG_DEBUG("Error Reading Mail Request: %s", StringifiedEnum::ToString(data.messageID).data());
|
||||
return;
|
||||
}
|
||||
request->Handle();
|
||||
} else {
|
||||
LOG_DEBUG("Unhandled Mail Request with ID: %i", data.messageID);
|
||||
}
|
||||
}
|
||||
|
||||
void Mail::SendMail(const Entity* recipient, const std::string& subject, const std::string& body, const LOT attachment,
|
||||
const uint16_t attachmentCount) {
|
||||
SendMail(
|
||||
LWOOBJID_EMPTY,
|
||||
DefaultSender,
|
||||
ServerName,
|
||||
recipient->GetObjectID(),
|
||||
recipient->GetCharacter()->GetName(),
|
||||
subject,
|
||||
@@ -312,7 +46,7 @@ void Mail::SendMail(const LWOOBJID recipient, const std::string& recipientName,
|
||||
const std::string& body, const LOT attachment, const uint16_t attachmentCount, const SystemAddress& sysAddr) {
|
||||
SendMail(
|
||||
LWOOBJID_EMPTY,
|
||||
DefaultSender,
|
||||
ServerName,
|
||||
recipient,
|
||||
recipientName,
|
||||
subject,
|
||||
@@ -341,7 +75,7 @@ void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, const
|
||||
void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, LWOOBJID recipient,
|
||||
const std::string& recipientName, const std::string& subject, const std::string& body, const LOT attachment,
|
||||
const uint16_t attachmentCount, const SystemAddress& sysAddr) {
|
||||
MailInfo mailInsert;
|
||||
IMail::MailInfo mailInsert;
|
||||
mailInsert.senderUsername = senderName;
|
||||
mailInsert.recipient = recipientName;
|
||||
mailInsert.subject = subject;
|
||||
@@ -356,7 +90,316 @@ void Mail::SendMail(const LWOOBJID sender, const std::string& senderName, LWOOBJ
|
||||
Database::Get()->InsertNewMail(mailInsert);
|
||||
|
||||
if (sysAddr == UNASSIGNED_SYSTEM_ADDRESS) return; // TODO: Echo to chat server
|
||||
NotificationResponse response;
|
||||
response.status = eNotificationResponse::NewMail;
|
||||
response.Send(sysAddr);
|
||||
|
||||
SendNotification(sysAddr, 1); //Show the "one new mail" message
|
||||
}
|
||||
|
||||
void Mail::HandleMailStuff(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity) {
|
||||
int mailStuffID = 0;
|
||||
packet.Read(mailStuffID);
|
||||
|
||||
auto returnVal = std::async(std::launch::async, [&packet, &sysAddr, entity, mailStuffID]() {
|
||||
Mail::MailMessageID stuffID = MailMessageID(mailStuffID);
|
||||
switch (stuffID) {
|
||||
case MailMessageID::AttachmentCollect:
|
||||
Mail::HandleAttachmentCollect(packet, sysAddr, entity);
|
||||
break;
|
||||
case MailMessageID::DataRequest:
|
||||
Mail::HandleDataRequest(packet, sysAddr, entity);
|
||||
break;
|
||||
case MailMessageID::MailDelete:
|
||||
Mail::HandleMailDelete(packet, sysAddr);
|
||||
break;
|
||||
case MailMessageID::MailRead:
|
||||
Mail::HandleMailRead(packet, sysAddr);
|
||||
break;
|
||||
case MailMessageID::NotificationRequest:
|
||||
Mail::HandleNotificationRequest(sysAddr, entity->GetObjectID());
|
||||
break;
|
||||
case MailMessageID::Send:
|
||||
Mail::HandleSendMail(packet, sysAddr, entity);
|
||||
break;
|
||||
default:
|
||||
LOG("Unhandled and possibly undefined MailStuffID: %i", int(stuffID));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
void Mail::HandleSendMail(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity) {
|
||||
//std::string subject = GeneralUtils::WStringToString(ReadFromPacket(packet, 50));
|
||||
//std::string body = GeneralUtils::WStringToString(ReadFromPacket(packet, 400));
|
||||
//std::string recipient = GeneralUtils::WStringToString(ReadFromPacket(packet, 32));
|
||||
|
||||
// Check if the player has restricted mail access
|
||||
auto* character = entity->GetCharacter();
|
||||
|
||||
if (!character) return;
|
||||
|
||||
if (character->HasPermission(ePermissionMap::RestrictedMailAccess)) {
|
||||
// Send a message to the player
|
||||
ChatPackets::SendSystemMessage(
|
||||
sysAddr,
|
||||
u"This character has restricted mail access."
|
||||
);
|
||||
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::AccountIsMuted);
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
LUWString subjectRead(50);
|
||||
packet.Read(subjectRead);
|
||||
|
||||
LUWString bodyRead(400);
|
||||
packet.Read(bodyRead);
|
||||
|
||||
LUWString recipientRead(32);
|
||||
packet.Read(recipientRead);
|
||||
|
||||
const std::string subject = subjectRead.GetAsString();
|
||||
const std::string body = bodyRead.GetAsString();
|
||||
|
||||
//Cleanse recipient:
|
||||
const std::string recipient = std::regex_replace(recipientRead.GetAsString(), std::regex("[^0-9a-zA-Z]+"), "");
|
||||
|
||||
uint64_t unknown64 = 0;
|
||||
LWOOBJID attachmentID;
|
||||
uint16_t attachmentCount;
|
||||
|
||||
packet.Read(unknown64);
|
||||
packet.Read(attachmentID);
|
||||
packet.Read(attachmentCount); //We don't care about the rest of the packet.
|
||||
uint32_t itemID = static_cast<uint32_t>(attachmentID);
|
||||
LOT itemLOT = 0;
|
||||
//Inventory::InventoryType itemType;
|
||||
int mailCost = Game::zoneManager->GetWorldConfig()->mailBaseFee;
|
||||
int stackSize = 0;
|
||||
auto inv = static_cast<InventoryComponent*>(entity->GetComponent(eReplicaComponentType::INVENTORY));
|
||||
Item* item = nullptr;
|
||||
|
||||
if (itemID > 0 && attachmentCount > 0 && inv) {
|
||||
item = inv->FindItemById(attachmentID);
|
||||
if (item) {
|
||||
mailCost += (item->GetInfo().baseValue * Game::zoneManager->GetWorldConfig()->mailPercentAttachmentFee);
|
||||
stackSize = item->GetCount();
|
||||
itemLOT = item->GetLot();
|
||||
} else {
|
||||
Mail::SendSendResponse(sysAddr, MailSendResponse::AttachmentNotFound);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
//Check if we can even send this mail (negative coins bug):
|
||||
if (entity->GetCharacter()->GetCoins() - mailCost < 0) {
|
||||
Mail::SendSendResponse(sysAddr, MailSendResponse::NotEnoughCoins);
|
||||
return;
|
||||
}
|
||||
|
||||
//Get the receiver's id:
|
||||
auto receiverID = Database::Get()->GetCharacterInfo(recipient);
|
||||
|
||||
if (!receiverID) {
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::RecipientNotFound);
|
||||
return;
|
||||
}
|
||||
|
||||
//Check if we have a valid receiver:
|
||||
if (GeneralUtils::CaseInsensitiveStringCompare(recipient, character->GetName()) || receiverID->id == character->GetID()) {
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::CannotMailSelf);
|
||||
return;
|
||||
} else {
|
||||
IMail::MailInfo mailInsert;
|
||||
mailInsert.senderUsername = character->GetName();
|
||||
mailInsert.recipient = recipient;
|
||||
mailInsert.subject = subject;
|
||||
mailInsert.body = body;
|
||||
mailInsert.senderId = character->GetID();
|
||||
mailInsert.receiverId = receiverID->id;
|
||||
mailInsert.itemCount = attachmentCount;
|
||||
mailInsert.itemID = itemID;
|
||||
mailInsert.itemLOT = itemLOT;
|
||||
mailInsert.itemSubkey = LWOOBJID_EMPTY;
|
||||
Database::Get()->InsertNewMail(mailInsert);
|
||||
}
|
||||
|
||||
Mail::SendSendResponse(sysAddr, Mail::MailSendResponse::Success);
|
||||
entity->GetCharacter()->SetCoins(entity->GetCharacter()->GetCoins() - mailCost, eLootSourceType::MAIL);
|
||||
|
||||
LOG("Seeing if we need to remove item with ID/count/LOT: %i %i %i", itemID, attachmentCount, itemLOT);
|
||||
|
||||
if (inv && itemLOT != 0 && attachmentCount > 0 && item) {
|
||||
LOG("Trying to remove item with ID/count/LOT: %i %i %i", itemID, attachmentCount, itemLOT);
|
||||
inv->RemoveItem(itemLOT, attachmentCount, INVALID, true);
|
||||
|
||||
auto* missionCompoent = entity->GetComponent<MissionComponent>();
|
||||
|
||||
if (missionCompoent != nullptr) {
|
||||
missionCompoent->Progress(eMissionTaskType::GATHER, itemLOT, LWOOBJID_EMPTY, "", -attachmentCount);
|
||||
}
|
||||
}
|
||||
|
||||
character->SaveXMLToDatabase();
|
||||
}
|
||||
|
||||
void Mail::HandleDataRequest(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player) {
|
||||
auto playerMail = Database::Get()->GetMailForPlayer(player->GetCharacter()->GetID(), 20);
|
||||
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
bitStream.Write(int(MailMessageID::MailData));
|
||||
bitStream.Write(int(0)); // throttled
|
||||
|
||||
bitStream.Write<uint16_t>(playerMail.size()); // size
|
||||
bitStream.Write<uint16_t>(0);
|
||||
|
||||
for (const auto& mail : playerMail) {
|
||||
bitStream.Write(mail.id); //MailID
|
||||
|
||||
const LUWString subject(mail.subject, 50);
|
||||
bitStream.Write(subject); //subject
|
||||
const LUWString body(mail.body, 400);
|
||||
bitStream.Write(body); //body
|
||||
const LUWString sender(mail.senderUsername, 32);
|
||||
bitStream.Write(sender); //sender
|
||||
bitStream.Write(uint32_t(0)); // packing
|
||||
|
||||
bitStream.Write(uint64_t(0)); // attachedCurrency
|
||||
|
||||
bitStream.Write(mail.itemID); //Attachment ID
|
||||
LOT lot = mail.itemLOT;
|
||||
if (lot <= 0) bitStream.Write(LOT(-1));
|
||||
else bitStream.Write(lot);
|
||||
bitStream.Write(uint32_t(0)); // packing
|
||||
|
||||
bitStream.Write(mail.itemSubkey); // Attachment subKey
|
||||
|
||||
bitStream.Write<uint16_t>(mail.itemCount); // Attachment count
|
||||
bitStream.Write(uint8_t(0)); // subject type (used for auction)
|
||||
bitStream.Write(uint8_t(0)); // packing
|
||||
bitStream.Write(uint32_t(0)); // packing
|
||||
|
||||
bitStream.Write<uint64_t>(mail.timeSent); // expiration date
|
||||
bitStream.Write<uint64_t>(mail.timeSent);// send date
|
||||
bitStream.Write<uint8_t>(mail.wasRead); //was read
|
||||
|
||||
bitStream.Write(uint8_t(0)); // isLocalized
|
||||
bitStream.Write(uint16_t(0)); // packing
|
||||
bitStream.Write(uint32_t(0)); // packing
|
||||
}
|
||||
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
}
|
||||
|
||||
void Mail::HandleAttachmentCollect(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player) {
|
||||
int unknown;
|
||||
uint64_t mailID;
|
||||
LWOOBJID playerID;
|
||||
packet.Read(unknown);
|
||||
packet.Read(mailID);
|
||||
packet.Read(playerID);
|
||||
|
||||
if (mailID > 0 && playerID == player->GetObjectID()) {
|
||||
auto playerMail = Database::Get()->GetMail(mailID);
|
||||
|
||||
LOT attachmentLOT = 0;
|
||||
uint32_t attachmentCount = 0;
|
||||
|
||||
if (playerMail) {
|
||||
attachmentLOT = playerMail->itemLOT;
|
||||
attachmentCount = playerMail->itemCount;
|
||||
}
|
||||
|
||||
auto inv = player->GetComponent<InventoryComponent>();
|
||||
if (!inv) return;
|
||||
|
||||
inv->AddItem(attachmentLOT, attachmentCount, eLootSourceType::MAIL);
|
||||
|
||||
Mail::SendAttachmentRemoveConfirm(sysAddr, mailID);
|
||||
|
||||
Database::Get()->ClaimMailItem(mailID);
|
||||
}
|
||||
}
|
||||
|
||||
void Mail::HandleMailDelete(RakNet::BitStream& packet, const SystemAddress& sysAddr) {
|
||||
int unknown;
|
||||
uint64_t mailID;
|
||||
LWOOBJID playerID;
|
||||
packet.Read(unknown);
|
||||
packet.Read(mailID);
|
||||
packet.Read(playerID);
|
||||
|
||||
if (mailID > 0) Mail::SendDeleteConfirm(sysAddr, mailID, playerID);
|
||||
}
|
||||
|
||||
void Mail::HandleMailRead(RakNet::BitStream& packet, const SystemAddress& sysAddr) {
|
||||
int unknown;
|
||||
uint64_t mailID;
|
||||
packet.Read(unknown);
|
||||
packet.Read(mailID);
|
||||
|
||||
if (mailID > 0) Mail::SendReadConfirm(sysAddr, mailID);
|
||||
}
|
||||
|
||||
void Mail::HandleNotificationRequest(const SystemAddress& sysAddr, uint32_t objectID) {
|
||||
auto unreadMailCount = Database::Get()->GetUnreadMailCount(objectID);
|
||||
|
||||
if (unreadMailCount > 0) Mail::SendNotification(sysAddr, unreadMailCount);
|
||||
}
|
||||
|
||||
void Mail::SendSendResponse(const SystemAddress& sysAddr, MailSendResponse response) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
bitStream.Write(int(MailMessageID::SendResponse));
|
||||
bitStream.Write(int(response));
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
}
|
||||
|
||||
void Mail::SendNotification(const SystemAddress& sysAddr, int mailCount) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
uint64_t messageType = 2;
|
||||
uint64_t s1 = 0;
|
||||
uint64_t s2 = 0;
|
||||
uint64_t s3 = 0;
|
||||
uint64_t s4 = 0;
|
||||
|
||||
bitStream.Write(messageType);
|
||||
bitStream.Write(s1);
|
||||
bitStream.Write(s2);
|
||||
bitStream.Write(s3);
|
||||
bitStream.Write(s4);
|
||||
bitStream.Write(mailCount);
|
||||
bitStream.Write(int(0)); //Unknown
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
}
|
||||
|
||||
void Mail::SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t mailID) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
bitStream.Write(int(MailMessageID::AttachmentCollectConfirm));
|
||||
bitStream.Write(int(0)); //unknown
|
||||
bitStream.Write(mailID);
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
}
|
||||
|
||||
void Mail::SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
bitStream.Write(int(MailMessageID::MailDeleteConfirm));
|
||||
bitStream.Write(int(0)); //unknown
|
||||
bitStream.Write(mailID);
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
|
||||
Database::Get()->DeleteMail(mailID);
|
||||
}
|
||||
|
||||
void Mail::SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID) {
|
||||
RakNet::BitStream bitStream;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, MessageType::Client::MAIL);
|
||||
bitStream.Write(int(MailMessageID::MailReadConfirm));
|
||||
bitStream.Write(int(0)); //unknown
|
||||
bitStream.Write(mailID);
|
||||
Game::server->Send(bitStream, sysAddr, false);
|
||||
|
||||
Database::Get()->MarkMailRead(mailID);
|
||||
}
|
||||
|
||||
@@ -1,210 +1,43 @@
|
||||
#ifndef __MAIL_H__
|
||||
#define __MAIL_H__
|
||||
|
||||
#include <cstdint>
|
||||
#pragma once
|
||||
#include "BitStream.h"
|
||||
#include "RakNetTypes.h"
|
||||
#include "dCommonVars.h"
|
||||
#include "BitStreamUtils.h"
|
||||
#include "MailInfo.h"
|
||||
|
||||
class Entity;
|
||||
|
||||
namespace Mail {
|
||||
enum class eMessageID : uint32_t {
|
||||
SendRequest = 0,
|
||||
SendResponse,
|
||||
NotificationResponse,
|
||||
DataRequest,
|
||||
DataResponse,
|
||||
AttachmentCollectRequest,
|
||||
AttachmentCollectResponse,
|
||||
DeleteRequest,
|
||||
DeleteResponse,
|
||||
ReadRequest,
|
||||
ReadResponse,
|
||||
NotificationRequest,
|
||||
AuctionCreate,
|
||||
AuctionCreationResponse,
|
||||
AuctionCancel,
|
||||
AuctionCancelResponse,
|
||||
AuctionList,
|
||||
AuctionListResponse,
|
||||
AuctionBid,
|
||||
AuctionBidResponse,
|
||||
UnknownError
|
||||
enum class MailMessageID {
|
||||
Send = 0x00,
|
||||
SendResponse = 0x01,
|
||||
DataRequest = 0x03,
|
||||
MailData = 0x04,
|
||||
AttachmentCollect = 0x05,
|
||||
AttachmentCollectConfirm = 0x06,
|
||||
MailDelete = 0x07,
|
||||
MailDeleteConfirm = 0x08,
|
||||
MailRead = 0x09,
|
||||
MailReadConfirm = 0x0a,
|
||||
NotificationRequest = 0x0b
|
||||
};
|
||||
|
||||
enum class eSendResponse : uint32_t {
|
||||
enum class MailSendResponse {
|
||||
Success = 0,
|
||||
NotEnoughCoins,
|
||||
AttachmentNotFound,
|
||||
ItemCannotBeMailed,
|
||||
CannotMailSelf,
|
||||
RecipientNotFound,
|
||||
RecipientDifferentFaction,
|
||||
UnHandled7,
|
||||
DifferentFaction,
|
||||
Unknown,
|
||||
ModerationFailure,
|
||||
SenderAccountIsMuted,
|
||||
UnHandled10,
|
||||
AccountIsMuted,
|
||||
UnknownFailure,
|
||||
RecipientIsIgnored,
|
||||
UnHandled12,
|
||||
RecipientIsFTP,
|
||||
UnknownError
|
||||
UnknownFailure3,
|
||||
RecipientIsFTP
|
||||
};
|
||||
|
||||
enum class eDeleteResponse : uint32_t {
|
||||
Success = 0,
|
||||
HasAttachments,
|
||||
NotFound,
|
||||
Throttled,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum class eAttachmentCollectResponse : uint32_t {
|
||||
Success = 0,
|
||||
AttachmentNotFound,
|
||||
NoSpaceInInventory,
|
||||
MailNotFound,
|
||||
Throttled,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum class eNotificationResponse : uint32_t {
|
||||
NewMail = 0,
|
||||
UnHandled,
|
||||
AuctionWon,
|
||||
AuctionSold,
|
||||
AuctionOutbided,
|
||||
AuctionExpired,
|
||||
AuctionCancelled,
|
||||
AuctionUpdated,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum class eReadResponse : uint32_t {
|
||||
Success = 0,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum class eAuctionCreateResponse : uint32_t {
|
||||
Success = 0,
|
||||
NotEnoughMoney,
|
||||
ItemNotFound,
|
||||
ItemNotSellable,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
enum class eAuctionCancelResponse : uint32_t {
|
||||
NotFound = 0,
|
||||
NotYours,
|
||||
HasBid,
|
||||
NoLongerExists,
|
||||
UnknownError
|
||||
};
|
||||
|
||||
struct MailLUBitStream : public LUBitStream {
|
||||
eMessageID messageID = eMessageID::UnknownError;
|
||||
SystemAddress sysAddr = UNASSIGNED_SYSTEM_ADDRESS;
|
||||
Entity* player = nullptr;
|
||||
|
||||
MailLUBitStream() = default;
|
||||
MailLUBitStream(eMessageID _messageID) : LUBitStream(eConnectionType::CLIENT, MessageType::Client::MAIL), messageID{_messageID} {};
|
||||
|
||||
virtual void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
virtual bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
virtual void Handle() override {};
|
||||
};
|
||||
|
||||
struct SendRequest : public MailLUBitStream {
|
||||
MailInfo mailInfo;
|
||||
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct SendResponse :public MailLUBitStream {
|
||||
eSendResponse status = eSendResponse::UnknownError;
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct NotificationResponse : public MailLUBitStream {
|
||||
eNotificationResponse status = eNotificationResponse::UnknownError;
|
||||
LWOOBJID auctionID = LWOOBJID_EMPTY;
|
||||
uint32_t mailCount = 1;
|
||||
NotificationResponse() : MailLUBitStream(eMessageID::NotificationResponse) {};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct DataRequest : public MailLUBitStream {
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override { return true; };
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct DataResponse : public MailLUBitStream {
|
||||
uint32_t throttled = 0;
|
||||
std::vector<MailInfo> playerMail;
|
||||
|
||||
DataResponse() : MailLUBitStream(eMessageID::DataResponse) {};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
|
||||
};
|
||||
|
||||
struct AttachmentCollectRequest : public MailLUBitStream {
|
||||
uint64_t mailID = 0;
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
|
||||
AttachmentCollectRequest() : MailLUBitStream(eMessageID::AttachmentCollectRequest) {};
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct AttachmentCollectResponse : public MailLUBitStream {
|
||||
eAttachmentCollectResponse status = eAttachmentCollectResponse::UnknownError;
|
||||
uint64_t mailID = 0;
|
||||
AttachmentCollectResponse() : MailLUBitStream(eMessageID::AttachmentCollectResponse) {};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct DeleteRequest : public MailLUBitStream {
|
||||
uint64_t mailID = 0;
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
|
||||
DeleteRequest() : MailLUBitStream(eMessageID::DeleteRequest) {};
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct DeleteResponse : public MailLUBitStream {
|
||||
eDeleteResponse status = eDeleteResponse::UnknownError;
|
||||
uint64_t mailID = 0;
|
||||
DeleteResponse() : MailLUBitStream(eMessageID::DeleteResponse) {};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct ReadRequest : public MailLUBitStream {
|
||||
uint64_t mailID = 0;
|
||||
|
||||
ReadRequest() : MailLUBitStream(eMessageID::ReadRequest) {};
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override;
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
struct ReadResponse : public MailLUBitStream {
|
||||
uint64_t mailID = 0;
|
||||
eReadResponse status = eReadResponse::UnknownError;
|
||||
|
||||
ReadResponse() : MailLUBitStream(eMessageID::ReadResponse) {};
|
||||
void Serialize(RakNet::BitStream& bitStream) const override;
|
||||
};
|
||||
|
||||
struct NotificationRequest : public MailLUBitStream {
|
||||
NotificationRequest() : MailLUBitStream(eMessageID::NotificationRequest) {};
|
||||
bool Deserialize(RakNet::BitStream& bitStream) override { return true; };
|
||||
void Handle() override;
|
||||
};
|
||||
|
||||
void HandleMail(RakNet::BitStream& inStream, const SystemAddress& sysAddr, Entity* player);
|
||||
const std::string ServerName = "Darkflame Universe";
|
||||
|
||||
void SendMail(
|
||||
const Entity* recipient,
|
||||
@@ -245,6 +78,18 @@ namespace Mail {
|
||||
uint16_t attachmentCount,
|
||||
const SystemAddress& sysAddr
|
||||
);
|
||||
|
||||
void HandleMailStuff(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity);
|
||||
void HandleSendMail(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* entity);
|
||||
void HandleDataRequest(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player);
|
||||
void HandleAttachmentCollect(RakNet::BitStream& packet, const SystemAddress& sysAddr, Entity* player);
|
||||
void HandleMailDelete(RakNet::BitStream& packet, const SystemAddress& sysAddr);
|
||||
void HandleMailRead(RakNet::BitStream& packet, const SystemAddress& sysAddr);
|
||||
void HandleNotificationRequest(const SystemAddress& sysAddr, uint32_t objectID);
|
||||
|
||||
void SendSendResponse(const SystemAddress& sysAddr, MailSendResponse response);
|
||||
void SendNotification(const SystemAddress& sysAddr, int mailCount);
|
||||
void SendAttachmentRemoveConfirm(const SystemAddress& sysAddr, uint64_t mailID);
|
||||
void SendDeleteConfirm(const SystemAddress& sysAddr, uint64_t mailID, LWOOBJID playerID);
|
||||
void SendReadConfirm(const SystemAddress& sysAddr, uint64_t mailID);
|
||||
};
|
||||
|
||||
#endif // !__MAIL_H__
|
||||
|
||||
@@ -996,7 +996,7 @@ void SlashCommandHandler::Startup() {
|
||||
Command RequestMailCountCommand{
|
||||
.help = "Gets the players mail count",
|
||||
.info = "Sends notification with number of unread messages in the player's mailbox",
|
||||
.aliases = { "requestmailcount", "checkmail" },
|
||||
.aliases = { "requestmailcount" },
|
||||
.handle = GMZeroCommands::RequestMailCount,
|
||||
.requiredLevel = eGameMasterLevel::CIVILIAN
|
||||
};
|
||||
|
||||
@@ -102,7 +102,7 @@ namespace GMGreaterThanZeroCommands {
|
||||
return;
|
||||
}
|
||||
|
||||
MailInfo mailInsert;
|
||||
IMail::MailInfo mailInsert;
|
||||
mailInsert.senderId = entity->GetObjectID();
|
||||
mailInsert.senderUsername = "Darkflame Universe";
|
||||
mailInsert.receiverId = receiverID;
|
||||
|
||||
@@ -12,7 +12,6 @@
|
||||
#include "VanityUtilities.h"
|
||||
#include "WorldPackets.h"
|
||||
#include "ZoneInstanceManager.h"
|
||||
#include "Database.h"
|
||||
|
||||
// Components
|
||||
#include "BuffComponent.h"
|
||||
@@ -217,10 +216,7 @@ namespace GMZeroCommands {
|
||||
}
|
||||
|
||||
void RequestMailCount(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
Mail::NotificationResponse response;
|
||||
response.status = Mail::eNotificationResponse::NewMail;
|
||||
response.mailCount = Database::Get()->GetUnreadMailCount(entity->GetCharacter()->GetID());
|
||||
response.Send(sysAddr);
|
||||
Mail::HandleNotificationRequest(entity->GetSystemAddress(), entity->GetObjectID());
|
||||
}
|
||||
|
||||
void InstanceInfo(Entity* entity, const SystemAddress& sysAddr, const std::string args) {
|
||||
|
||||
@@ -62,6 +62,14 @@ std::map<uint32_t, std::string> activeSessions;
|
||||
SystemAddress authServerMasterPeerSysAddr;
|
||||
SystemAddress chatServerMasterPeerSysAddr;
|
||||
|
||||
int GenerateBCryptPassword(const std::string& password, const int workFactor, char salt[BCRYPT_HASHSIZE], char hash[BCRYPT_HASHSIZE]) {
|
||||
int32_t bcryptState = ::bcrypt_gensalt(workFactor, salt);
|
||||
assert(bcryptState == 0);
|
||||
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
||||
assert(bcryptState == 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int main(int argc, char** argv) {
|
||||
constexpr uint32_t masterFramerate = mediumFramerate;
|
||||
constexpr uint32_t masterFrameDelta = mediumFrameDelta;
|
||||
@@ -94,7 +102,7 @@ int main(int argc, char** argv) {
|
||||
std::string(folder) +
|
||||
") folder from your download to the binary directory or re-run cmake.";
|
||||
LOG("%s", msg.c_str());
|
||||
// toss an error box up for windows users running the download
|
||||
// toss an error box up for windows users running the download
|
||||
#ifdef DARKFLAME_PLATFORM_WIN32
|
||||
MessageBoxA(nullptr, msg.c_str(), "Missing Folder", MB_OK | MB_ICONERROR);
|
||||
#endif
|
||||
@@ -238,10 +246,7 @@ int main(int argc, char** argv) {
|
||||
// Regenerate hash based on new password
|
||||
char salt[BCRYPT_HASHSIZE];
|
||||
char hash[BCRYPT_HASHSIZE];
|
||||
int32_t bcryptState = ::bcrypt_gensalt(12, salt);
|
||||
assert(bcryptState == 0);
|
||||
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
||||
assert(bcryptState == 0);
|
||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
||||
|
||||
Database::Get()->UpdateAccountPassword(accountId->id, std::string(hash, BCRYPT_HASHSIZE));
|
||||
|
||||
@@ -279,10 +284,7 @@ int main(int argc, char** argv) {
|
||||
//Generate new hash for bcrypt
|
||||
char salt[BCRYPT_HASHSIZE];
|
||||
char hash[BCRYPT_HASHSIZE];
|
||||
int32_t bcryptState = ::bcrypt_gensalt(12, salt);
|
||||
assert(bcryptState == 0);
|
||||
bcryptState = ::bcrypt_hashpw(password.c_str(), salt, hash);
|
||||
assert(bcryptState == 0);
|
||||
assert(GenerateBCryptPassword(password, 12, salt, hash) == 0);
|
||||
|
||||
//Create account
|
||||
try {
|
||||
@@ -318,15 +320,24 @@ int main(int argc, char** argv) {
|
||||
const auto externalIPString = Game::config->GetValue("external_ip");
|
||||
if (!externalIPString.empty()) ourIP = externalIPString;
|
||||
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal);
|
||||
char salt[BCRYPT_HASHSIZE];
|
||||
char hash[BCRYPT_HASHSIZE];
|
||||
const auto& cfgPassword = Game::config->GetValue("master_password");
|
||||
GenerateBCryptPassword(!cfgPassword.empty() ? cfgPassword : "3.25DARKFLAME1", 13, salt, hash);
|
||||
|
||||
Game::server = new dServer(ourIP, ourPort, 0, maxClients, true, false, Game::logger, "", 0, ServerType::Master, Game::config, &Game::lastSignal, hash);
|
||||
|
||||
std::string master_server_ip = "localhost";
|
||||
const auto masterServerIPString = Game::config->GetValue("master_ip");
|
||||
if (!masterServerIPString.empty()) master_server_ip = masterServerIPString;
|
||||
|
||||
if (master_server_ip == "") master_server_ip = Game::server->GetIP();
|
||||
IServers::MasterInfo info;
|
||||
info.ip = master_server_ip;
|
||||
info.port = Game::server->GetPort();
|
||||
info.password = hash;
|
||||
|
||||
Database::Get()->SetMasterIp(master_server_ip, Game::server->GetPort());
|
||||
Database::Get()->SetMasterInfo(info);
|
||||
|
||||
//Create additional objects here:
|
||||
PersistentIDManager::Initialize();
|
||||
|
||||
@@ -1,30 +0,0 @@
|
||||
#include "BitStreamUtils.h"
|
||||
#include "dServer.h"
|
||||
#include "BitStream.h"
|
||||
#include "PacketUtils.h"
|
||||
|
||||
|
||||
void LUBitStream::WriteHeader(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write<MessageID>(ID_USER_PACKET_ENUM);
|
||||
bitStream.Write(this->connectionType);
|
||||
bitStream.Write(this->internalPacketID);
|
||||
bitStream.Write<uint8_t>(0); // padding
|
||||
}
|
||||
|
||||
bool LUBitStream::ReadHeader(RakNet::BitStream& bitStream) {
|
||||
MessageID messageID;
|
||||
bitStream.Read(messageID);
|
||||
if (messageID != ID_USER_PACKET_ENUM) return false;
|
||||
VALIDATE_READ(bitStream.Read(this->connectionType));
|
||||
VALIDATE_READ(bitStream.Read(this->internalPacketID));
|
||||
uint8_t padding;
|
||||
VALIDATE_READ(bitStream.Read<uint8_t>(padding));
|
||||
return true;
|
||||
}
|
||||
|
||||
void LUBitStream::Send(const SystemAddress& sysAddr) const {
|
||||
RakNet::BitStream bitStream;
|
||||
this->WriteHeader(bitStream);
|
||||
this->Serialize(bitStream);
|
||||
Game::server->Send(bitStream, sysAddr, sysAddr == UNASSIGNED_SYSTEM_ADDRESS);
|
||||
}
|
||||
@@ -2,13 +2,12 @@
|
||||
#define __BITSTREAMUTILS__H__
|
||||
|
||||
#include "GeneralUtils.h"
|
||||
#include "BitStream.h"
|
||||
#include "MessageIdentifiers.h"
|
||||
#include "eConnectionType.h"
|
||||
#include "BitStream.h"
|
||||
#include <string>
|
||||
#include <algorithm>
|
||||
|
||||
#define VALIDATE_READ(x) do { if (!x) return false; } while (0)
|
||||
enum class eConnectionType : uint16_t;
|
||||
|
||||
struct LUString {
|
||||
std::string string;
|
||||
@@ -46,28 +45,6 @@ struct LUWString {
|
||||
};
|
||||
};
|
||||
|
||||
struct LUBitStream {
|
||||
eConnectionType connectionType = eConnectionType::UNKNOWN;
|
||||
uint32_t internalPacketID = 0xFFFFFFFF;
|
||||
|
||||
LUBitStream() = default;
|
||||
|
||||
template <typename T>
|
||||
LUBitStream(eConnectionType connectionType, T internalPacketID) {
|
||||
this->connectionType = connectionType;
|
||||
this->internalPacketID = static_cast<uint32_t>(internalPacketID);
|
||||
}
|
||||
|
||||
void WriteHeader(RakNet::BitStream& bitStream) const;
|
||||
bool ReadHeader(RakNet::BitStream& bitStream);
|
||||
void Send(const SystemAddress& sysAddr) const;
|
||||
|
||||
virtual void Serialize(RakNet::BitStream& bitStream) const {}
|
||||
virtual bool Deserialize(RakNet::BitStream& bitStream) { return true; }
|
||||
virtual void Handle() {};
|
||||
};
|
||||
|
||||
|
||||
namespace BitStreamUtils {
|
||||
template<typename T>
|
||||
void WriteHeader(RakNet::BitStream& bitStream, eConnectionType connectionType, T internalPacketID) {
|
||||
@@ -76,6 +53,7 @@ namespace BitStreamUtils {
|
||||
bitStream.Write(static_cast<uint32_t>(internalPacketID));
|
||||
bitStream.Write<uint8_t>(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
namespace RakNet {
|
||||
|
||||
@@ -1,9 +1,7 @@
|
||||
set(DNET_SOURCES "AuthPackets.cpp"
|
||||
"BitStreamUtils.cpp"
|
||||
"ChatPackets.cpp"
|
||||
"ClientPackets.cpp"
|
||||
"dServer.cpp"
|
||||
"MailInfo.cpp"
|
||||
"MasterPackets.cpp"
|
||||
"PacketUtils.cpp"
|
||||
"WorldPackets.cpp"
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
#include "MailInfo.h"
|
||||
#include "BitStream.h"
|
||||
#include "DluAssert.h"
|
||||
|
||||
void MailInfo::Serialize(RakNet::BitStream& bitStream) const {
|
||||
bitStream.Write(id);
|
||||
const LUWString subject(this->subject, 50);
|
||||
bitStream.Write(subject);
|
||||
const LUWString body(this->body, 400);
|
||||
bitStream.Write(body);
|
||||
const LUWString sender(this->senderUsername, 32);
|
||||
bitStream.Write(sender);
|
||||
bitStream.Write<uint32_t>(0); // packing
|
||||
|
||||
bitStream.Write<uint64_t>(0); // attachedCurrency
|
||||
bitStream.Write(itemID);
|
||||
|
||||
LOT lot = itemLOT;
|
||||
if (lot <= 0) bitStream.Write<LOT>(LOT_NULL);
|
||||
else bitStream.Write(lot);
|
||||
bitStream.Write<uint32_t>(0); // packing
|
||||
|
||||
bitStream.Write(itemSubkey);
|
||||
|
||||
bitStream.Write(itemCount);
|
||||
bitStream.Write<uint8_t>(0); // subject type (used for auction)
|
||||
bitStream.Write<uint8_t>(0); // packing
|
||||
bitStream.Write<uint32_t>(0); // packing
|
||||
|
||||
bitStream.Write<uint64_t>(timeSent); // expiration date
|
||||
bitStream.Write<uint64_t>(timeSent);// send date
|
||||
bitStream.Write<uint8_t>(wasRead); // was read
|
||||
|
||||
bitStream.Write<uint8_t>(0); // isLocalized
|
||||
bitStream.Write<uint16_t>(1033); // language code
|
||||
bitStream.Write<uint32_t>(0); // packing
|
||||
}
|
||||
|
||||
bool MailInfo::Deserialize(RakNet::BitStream& bitStream) {
|
||||
LUWString subject(50);
|
||||
VALIDATE_READ(bitStream.Read(subject));
|
||||
this->subject = subject.GetAsString();
|
||||
|
||||
LUWString body(400);
|
||||
VALIDATE_READ(bitStream.Read(body));
|
||||
this->body = body.GetAsString();
|
||||
|
||||
LUWString recipientName(32);
|
||||
VALIDATE_READ(bitStream.Read(recipientName));
|
||||
this->recipient = recipientName.GetAsString();
|
||||
|
||||
uint64_t unknown;
|
||||
VALIDATE_READ(bitStream.Read(unknown));
|
||||
|
||||
VALIDATE_READ(bitStream.Read(itemID));
|
||||
VALIDATE_READ(bitStream.Read(itemCount));
|
||||
VALIDATE_READ(bitStream.Read(languageCode));
|
||||
bitStream.IgnoreBytes(4); // padding
|
||||
|
||||
DluAssert(bitStream.GetNumberOfUnreadBits() == 0);
|
||||
|
||||
return true;
|
||||
}
|
||||
@@ -1,34 +0,0 @@
|
||||
#ifndef __MAILINFO_H__
|
||||
#define __MAILINFO_H__
|
||||
|
||||
#include <string>
|
||||
#include <cstdint>
|
||||
#include "dCommonVars.h"
|
||||
|
||||
namespace RakNet {
|
||||
class BitStream;
|
||||
}
|
||||
|
||||
struct MailInfo {
|
||||
std::string senderUsername;
|
||||
std::string recipient;
|
||||
std::string subject;
|
||||
std::string body;
|
||||
uint64_t id{};
|
||||
uint32_t senderId{};
|
||||
uint32_t receiverId{};
|
||||
uint64_t timeSent{};
|
||||
bool wasRead{};
|
||||
uint16_t languageCode{};
|
||||
struct {
|
||||
LWOOBJID itemID{};
|
||||
int16_t itemCount{};
|
||||
LOT itemLOT{};
|
||||
LWOOBJID itemSubkey{};
|
||||
};
|
||||
|
||||
void Serialize(RakNet::BitStream& bitStream) const;
|
||||
bool Deserialize(RakNet::BitStream& bitStream);
|
||||
};
|
||||
|
||||
#endif // __MAILINFO_H__
|
||||
@@ -3,4 +3,3 @@
|
||||
#include "RakPeer.h"
|
||||
|
||||
#define NET_PASSWORD_EXTERNAL "3.25 ND1"
|
||||
#define NET_PASSWORD_INTERNAL "3.25 DARKFLAME1"
|
||||
|
||||
@@ -40,7 +40,21 @@ public:
|
||||
}
|
||||
} ReceiveDownloadCompleteCB;
|
||||
|
||||
dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnections, bool isInternal, bool useEncryption, Logger* logger, const std::string masterIP, int masterPort, ServerType serverType, dConfig* config, Game::signal_t* lastSignal, unsigned int zoneID) {
|
||||
dServer::dServer(
|
||||
const std::string& ip,
|
||||
int port,
|
||||
int instanceID,
|
||||
int maxConnections,
|
||||
bool isInternal,
|
||||
bool useEncryption,
|
||||
Logger* logger,
|
||||
const std::string masterIP,
|
||||
int masterPort,
|
||||
ServerType serverType,
|
||||
dConfig* config,
|
||||
Game::signal_t* lastSignal,
|
||||
const std::string& masterPassword,
|
||||
unsigned int zoneID) {
|
||||
mIP = ip;
|
||||
mPort = port;
|
||||
mZoneID = zoneID;
|
||||
@@ -56,6 +70,7 @@ dServer::dServer(const std::string& ip, int port, int instanceID, int maxConnect
|
||||
mReplicaManager = nullptr;
|
||||
mServerType = serverType;
|
||||
mConfig = config;
|
||||
mMasterPassword = masterPassword;
|
||||
mShouldShutdown = lastSignal;
|
||||
//Attempt to start our server here:
|
||||
mIsOkay = Startup();
|
||||
@@ -203,11 +218,11 @@ bool dServer::Startup() {
|
||||
if (!mPeer->Startup(mMaxConnections, 10, &mSocketDescriptor, 1)) return false;
|
||||
|
||||
if (mIsInternal) {
|
||||
mPeer->SetIncomingPassword("3.25 DARKFLAME1", 15);
|
||||
mPeer->SetIncomingPassword(mMasterPassword.c_str(), mMasterPassword.size());
|
||||
} else {
|
||||
UpdateBandwidthLimit();
|
||||
UpdateMaximumMtuSize();
|
||||
mPeer->SetIncomingPassword("3.25 ND1", 8);
|
||||
mPeer->SetIncomingPassword(NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
||||
}
|
||||
|
||||
mPeer->SetMaximumIncomingConnections(mMaxConnections);
|
||||
@@ -257,7 +272,7 @@ void dServer::SetupForMasterConnection() {
|
||||
|
||||
bool dServer::ConnectToMaster() {
|
||||
//LOG("Connection to Master %s:%d", mMasterIP.c_str(), mMasterPort);
|
||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, "3.25 DARKFLAME1", 15);
|
||||
return mMasterPeer->Connect(mMasterIP.c_str(), mMasterPort, mMasterPassword.c_str(), mMasterPassword.size());
|
||||
}
|
||||
|
||||
void dServer::UpdateReplica() {
|
||||
|
||||
@@ -46,6 +46,7 @@ public:
|
||||
ServerType serverType,
|
||||
dConfig* config,
|
||||
Game::signal_t* shouldShutdown,
|
||||
const std::string& masterPassword,
|
||||
unsigned int zoneID = 0);
|
||||
~dServer();
|
||||
|
||||
@@ -121,4 +122,5 @@ protected:
|
||||
std::string mMasterIP;
|
||||
int mMasterPort;
|
||||
std::chrono::steady_clock::time_point mStartTime = std::chrono::steady_clock::now();
|
||||
std::string mMasterPassword;
|
||||
};
|
||||
|
||||
@@ -10,49 +10,38 @@ void NsLegoClubDoor::OnStartup(Entity* self) {
|
||||
self->SetVar(u"teleportString", m_TeleportString);
|
||||
self->SetVar(u"spawnPoint", m_SpawnPoint);
|
||||
|
||||
args = {};
|
||||
teleportArgs.Reset();
|
||||
|
||||
args.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
||||
args.Insert("strIdentifier", "choiceDoor");
|
||||
args.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
||||
teleportArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
||||
teleportArgs.Insert("strIdentifier", "choiceDoor");
|
||||
teleportArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
||||
|
||||
AMFArrayValue* choiceOptions = args.InsertArray("options");
|
||||
auto& choiceOptions = *teleportArgs.InsertArray("options");
|
||||
|
||||
{
|
||||
AMFArrayValue* nsArgs = choiceOptions->PushArray();
|
||||
auto& nsArgs = *choiceOptions.PushArray();
|
||||
|
||||
nsArgs->Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
|
||||
nsArgs->Insert("caption", "%[UI_CHOICE_NS]");
|
||||
nsArgs->Insert("identifier", "zoneID_1200");
|
||||
nsArgs->Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
|
||||
nsArgs.Insert("image", "textures/ui/zone_thumnails/Nimbus_Station.dds");
|
||||
nsArgs.Insert("caption", "%[UI_CHOICE_NS]");
|
||||
nsArgs.Insert("identifier", "zoneID_1200");
|
||||
nsArgs.Insert("tooltipText", "%[UI_CHOICE_NS_HOVER]");
|
||||
}
|
||||
|
||||
{
|
||||
AMFArrayValue* ntArgs = choiceOptions->PushArray();
|
||||
auto& ntArgs = *choiceOptions.PushArray();
|
||||
|
||||
ntArgs->Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
|
||||
ntArgs->Insert("caption", "%[UI_CHOICE_NT]");
|
||||
ntArgs->Insert("identifier", "zoneID_1900");
|
||||
ntArgs->Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
|
||||
ntArgs.Insert("image", "textures/ui/zone_thumnails/Nexus_Tower.dds");
|
||||
ntArgs.Insert("caption", "%[UI_CHOICE_NT]");
|
||||
ntArgs.Insert("identifier", "zoneID_1900");
|
||||
ntArgs.Insert("tooltipText", "%[UI_CHOICE_NT_HOVER]");
|
||||
}
|
||||
|
||||
options = choiceOptions;
|
||||
}
|
||||
|
||||
void NsLegoClubDoor::OnUse(Entity* self, Entity* user) {
|
||||
auto* player = user;
|
||||
|
||||
if (CheckChoice(self, player)) {
|
||||
AMFArrayValue multiArgs;
|
||||
|
||||
multiArgs.Insert("callbackClient", std::to_string(self->GetObjectID()));
|
||||
multiArgs.Insert("strIdentifier", "choiceDoor");
|
||||
multiArgs.Insert("title", "%[UI_CHOICE_DESTINATION]");
|
||||
multiArgs.Insert("options", static_cast<AMFBaseValue*>(options));
|
||||
|
||||
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", multiArgs);
|
||||
|
||||
multiArgs.Remove("options", false); // We do not want the local amf to delete the options!
|
||||
GameMessages::SendUIMessageServerToSingleClient(player, player->GetSystemAddress(), "QueueChoiceBox", teleportArgs);
|
||||
} else if (self->GetVar<int32_t>(u"currentZone") != m_ChoiceZoneID) {
|
||||
AMFArrayValue multiArgs;
|
||||
multiArgs.Insert("state", "Lobby");
|
||||
|
||||
@@ -19,6 +19,5 @@ private:
|
||||
std::string m_SpawnPoint = "NS_LEGO_Club";
|
||||
std::u16string m_TeleportAnim = u"lup-teleport";
|
||||
std::u16string m_TeleportString = u"ROCKET_TOOLTIP_USE_THE_GATEWAY_TO_TRAVEL_TO_LUP_WORLD";
|
||||
AMFArrayValue args = {};
|
||||
AMFArrayValue* options = {};
|
||||
AMFArrayValue teleportArgs{};
|
||||
};
|
||||
|
||||
@@ -36,14 +36,14 @@ void AgSpiderBossMessage::OnCollisionPhantom(Entity* self, Entity* target) {
|
||||
|
||||
auto box = GetBox(self);
|
||||
// knockback the target
|
||||
auto forward = target->GetRotation().GetForwardVector();
|
||||
auto forward = self->GetRotation().GetForwardVector();
|
||||
box.boxTarget = target->GetObjectID();
|
||||
GameMessages::SendPlayFXEffect(target->GetObjectID(), 1378, u"create", "pushBack");
|
||||
RenderComponent::PlayAnimation(target, "knockback-recovery");
|
||||
forward.y += 15;
|
||||
forward.x *= 100;
|
||||
forward.z *= 100;
|
||||
GameMessages::SendKnockback(target->GetObjectID(), self->GetObjectID(), self->GetObjectID(), 0, forward);
|
||||
GameMessages::SendKnockback(target->GetObjectID(), LWOOBJID_EMPTY, LWOOBJID_EMPTY, 0, forward);
|
||||
|
||||
if (box.isTouch || box.isDisplayed) return;
|
||||
box.boxSelf = self->GetObjectID();
|
||||
|
||||
@@ -202,11 +202,13 @@ int main(int argc, char** argv) {
|
||||
//Find out the master's IP:
|
||||
std::string masterIP = "localhost";
|
||||
uint32_t masterPort = 1000;
|
||||
std::string masterPassword;
|
||||
auto masterInfo = Database::Get()->GetMasterInfo();
|
||||
|
||||
if (masterInfo) {
|
||||
masterIP = masterInfo->ip;
|
||||
masterPort = masterInfo->port;
|
||||
masterPassword = masterInfo->password;
|
||||
}
|
||||
|
||||
UserManager::Instance()->Initialize();
|
||||
@@ -214,7 +216,7 @@ int main(int argc, char** argv) {
|
||||
const bool dontGenerateDCF = GeneralUtils::TryParse<bool>(Game::config->GetValue("dont_generate_dcf")).value_or(false);
|
||||
Game::chatFilter = new dChatFilter(Game::assetManager->GetResPath().string() + "/chatplus_en_us", dontGenerateDCF);
|
||||
|
||||
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, zoneID);
|
||||
Game::server = new dServer(masterIP, ourPort, instanceID, maxClients, false, true, Game::logger, masterIP, masterPort, ServerType::World, Game::config, &Game::lastSignal, masterPassword, zoneID);
|
||||
|
||||
//Connect to the chat server:
|
||||
uint32_t chatPort = 1501;
|
||||
@@ -223,7 +225,7 @@ int main(int argc, char** argv) {
|
||||
auto chatSock = SocketDescriptor(static_cast<uint16_t>(ourPort + 2), 0);
|
||||
Game::chatServer = RakNetworkFactory::GetRakPeerInterface();
|
||||
Game::chatServer->Startup(1, 30, &chatSock, 1);
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
||||
|
||||
//Set up other things:
|
||||
Game::randomEngine = std::mt19937(time(0));
|
||||
@@ -371,7 +373,7 @@ int main(int argc, char** argv) {
|
||||
if (framesSinceChatDisconnect >= chatReconnectionTime) {
|
||||
framesSinceChatDisconnect = 0;
|
||||
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, "3.25 ND1", 8);
|
||||
Game::chatServer->Connect(masterIP.c_str(), chatPort, NET_PASSWORD_EXTERNAL, strnlen(NET_PASSWORD_EXTERNAL, sizeof(NET_PASSWORD_EXTERNAL)));
|
||||
}
|
||||
} else framesSinceChatDisconnect = 0;
|
||||
|
||||
@@ -831,20 +833,15 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
if (packet->data[0] != ID_USER_PACKET_ENUM || packet->length < 4) return;
|
||||
|
||||
CINSTREAM;
|
||||
LUBitStream luBitStream;
|
||||
luBitStream.ReadHeader(inStream);
|
||||
|
||||
if (luBitStream.connectionType == eConnectionType::SERVER) {
|
||||
if (static_cast<MessageType::Server>(luBitStream.internalPacketID) == MessageType::Server::VERSION_CONFIRM) {
|
||||
if (static_cast<eConnectionType>(packet->data[1]) == eConnectionType::SERVER) {
|
||||
if (static_cast<MessageType::Server>(packet->data[3]) == MessageType::Server::VERSION_CONFIRM) {
|
||||
AuthPackets::HandleHandshake(Game::server, packet);
|
||||
}
|
||||
}
|
||||
|
||||
if (luBitStream.connectionType != eConnectionType::WORLD) return;
|
||||
if (static_cast<eConnectionType>(packet->data[1]) != eConnectionType::WORLD) return;
|
||||
|
||||
switch (static_cast<MessageType::World>(luBitStream.internalPacketID)) {
|
||||
switch (static_cast<MessageType::World>(packet->data[3])) {
|
||||
case MessageType::World::VALIDATION: {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LUWString username;
|
||||
@@ -1190,7 +1187,11 @@ void HandlePacket(Packet* packet) {
|
||||
}
|
||||
|
||||
case MessageType::World::MAIL: {
|
||||
Mail::HandleMail(inStream, packet->systemAddress, UserManager::Instance()->GetUser(packet->systemAddress)->GetLastUsedChar()->GetEntity());
|
||||
RakNet::BitStream bitStream(packet->data, packet->length, false);
|
||||
// FIXME: Change this to the macro to skip the header...
|
||||
LWOOBJID space;
|
||||
bitStream.Read(space);
|
||||
Mail::HandleMailStuff(bitStream, packet->systemAddress, UserManager::Instance()->GetUser(packet->systemAddress)->GetLastUsedChar()->GetEntity());
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
1
migrations/dlu/mysql/18_master_password.sql
Normal file
1
migrations/dlu/mysql/18_master_password.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE servers ADD COLUMN master_password TEXT NOT NULL DEFAULT ('3.25 DARKFLAME1');
|
||||
1
migrations/dlu/sqlite/1_master_password.sql
Normal file
1
migrations/dlu/sqlite/1_master_password.sql
Normal file
@@ -0,0 +1 @@
|
||||
ALTER TABLE servers ADD COLUMN master_password TEXT NOT NULL DEFAULT ('3.25 DARKFLAME1');
|
||||
@@ -9,3 +9,5 @@ world_port_start=3000
|
||||
|
||||
# 0 or 1, should autostart auth, chat, and char servers
|
||||
prestart_servers=1
|
||||
|
||||
master_password=3.25DARKFLAME1
|
||||
|
||||
Reference in New Issue
Block a user