mirror of
https://github.com/DarkflameUniverse/DarkflameServer.git
synced 2025-12-17 03:37:08 -06:00
Compare commits
17 Commits
raw-parsin
...
guild_temp
| Author | SHA1 | Date | |
|---|---|---|---|
| 6a921f4ee6 | |||
| 443f9e37e8 | |||
|
|
0f260ba682 | ||
|
|
0d668aefcf | ||
|
|
7c0fc72294 | ||
| ce3021310c | |||
| 4722c1fdea | |||
| a4bf11502f | |||
| e5f62e870b | |||
| 124e10e923 | |||
| 449202e39f | |||
| 09bd4e9089 | |||
| 2a34cff008 | |||
| 9ac11f281d | |||
| c4ae05ecee | |||
| 30fbdd3956 | |||
|
|
192948a87f |
@@ -18,6 +18,7 @@
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eClientMessageType.h"
|
||||
#include "eGameMessageType.h"
|
||||
#include "eGuildLeaveReason.h"
|
||||
|
||||
void ChatPacketHandler::HandleFriendlistRequest(Packet* packet) {
|
||||
//Get from the packet which player we want to do something with:
|
||||
@@ -363,39 +364,37 @@ void ChatPacketHandler::HandleChatMessage(Packet* packet) {
|
||||
|
||||
LOG("Got a message from (%s) [%d]: %s", senderName.c_str(), channel, message.c_str());
|
||||
|
||||
if (channel != 8) return;
|
||||
if (channel == 8) {
|
||||
|
||||
auto* team = Game::playerContainer.GetTeam(playerID);
|
||||
auto* team = playerContainer.GetTeam(playerID);
|
||||
if (!team) return;
|
||||
|
||||
if (team == nullptr) return;
|
||||
for (const auto memberId : team->memberIDs) {
|
||||
auto* otherMember = playerContainer.GetPlayerData(memberId);
|
||||
if (!otherMember) return;
|
||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||
|
||||
for (const auto memberId : team->memberIDs) {
|
||||
auto* otherMember = Game::playerContainer.GetPlayerData(memberId);
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(otherMember->playerID);
|
||||
|
||||
if (otherMember == nullptr) return;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(otherMember->playerID);
|
||||
bitStream.Write<uint8_t>(8);
|
||||
bitStream.Write<unsigned int>(69);
|
||||
bitStream.Write(LUWString(senderName));
|
||||
bitStream.Write(sender->playerID);
|
||||
bitStream.Write<uint16_t>(0);
|
||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||
bitStream.Write(LUWString(otherName));
|
||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||
bitStream.Write<uint8_t>(0); //teams?
|
||||
bitStream.Write(LUWString(message, 512));
|
||||
|
||||
const auto otherName = std::string(otherMember->playerName.c_str());
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(otherMember->playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT, eChatMessageType::PRIVATE_CHAT_MESSAGE);
|
||||
bitStream.Write(otherMember->playerID);
|
||||
bitStream.Write<uint8_t>(8);
|
||||
bitStream.Write<unsigned int>(69);
|
||||
bitStream.Write(LUWString(senderName));
|
||||
bitStream.Write(sender->playerID);
|
||||
bitStream.Write<uint16_t>(0);
|
||||
bitStream.Write<uint8_t>(0); //not mythran nametag
|
||||
bitStream.Write(LUWString(otherName));
|
||||
bitStream.Write<uint8_t>(0); //not mythran for receiver
|
||||
bitStream.Write<uint8_t>(0); //teams?
|
||||
bitStream.Write(LUWString(message, 512));
|
||||
|
||||
SystemAddress sysAddr = otherMember->sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
SystemAddress sysAddr = otherMember->sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
} else LOG("Private chat channel is %i", channel);
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandlePrivateChatMessage(Packet* packet) {
|
||||
@@ -672,6 +671,80 @@ void ChatPacketHandler::HandleTeamStatusRequest(Packet* packet) {
|
||||
}
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandleGuildLeave(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
inStream.Read(playerID);
|
||||
auto* player = playerContainer.GetPlayerData(playerID);
|
||||
if (!player) return;
|
||||
auto guild_id = Database::Get()->GetMembersGuild(playerID);
|
||||
Database::Get()->DeleteGuildMember(player->playerID);
|
||||
auto members = Database::Get()->GetGuildMembers(guild_id);
|
||||
if (members.empty()) Database::Get()->DeleteGuild(guild_id);
|
||||
|
||||
// Send the removal, need to send this to all players in guild TODO
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(player->playerID);
|
||||
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GUILD_REMOVE_PLAYER);
|
||||
bitStream.Write(eGuildLeaveReason::LEFT);
|
||||
bitStream.Write(LUWString(player->playerName));
|
||||
bitStream.Write(player->playerID);
|
||||
|
||||
SystemAddress sysAddr = player->sysAddr;
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void ChatPacketHandler::HandleGuildGetAll(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LWOOBJID playerID = LWOOBJID_EMPTY;
|
||||
inStream.Read(playerID);
|
||||
LOG("HandleGuildGetAll %llu", playerID);
|
||||
auto player = playerContainer.GetPlayerData(playerID);
|
||||
if (!player) return;
|
||||
auto guild_id = Database::Get()->GetMembersGuild(player->playerID);
|
||||
if (!guild_id) return;
|
||||
auto guild = Database::Get()->GetGuild(guild_id);
|
||||
if (!guild) return;
|
||||
auto members = Database::Get()->GetGuildMembers(guild_id);
|
||||
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
bitStream.Write(playerID);
|
||||
|
||||
//portion that will get routed:
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GUILD_DATA);
|
||||
bitStream.Write<uint8_t>(0); // has Guild data/in a guild
|
||||
bitStream.Write(LUWString(guild->name, 31)); // guild name
|
||||
bitStream.Write(LUWString("test1", 11)); // unknown
|
||||
bitStream.Write(LUWString("test2", 11)); // unknown
|
||||
bitStream.Write<uint32_t>(69); // unknown
|
||||
bitStream.Write<uint32_t>(0); // unknown
|
||||
bitStream.Write<uint32_t>(1); // unknown
|
||||
bitStream.Write<uint16_t>(0); // unknown
|
||||
bitStream.Write<uint16_t>(members.size()); // Size
|
||||
//Member data
|
||||
for (const auto &member : members) {
|
||||
bitStream.Write<uint8_t>(member.rank); // rank
|
||||
bitStream.Write<uint8_t>(1); // online status
|
||||
bitStream.Write<uint16_t>(1100); // zone
|
||||
bitStream.Write<uint16_t>(1200); // instance
|
||||
bitStream.Write<uint16_t>(1300); // clone
|
||||
bitStream.Write<uint16_t>(1200); // unknown
|
||||
bitStream.Write<LWOOBJID>(player->playerID); // playerId
|
||||
bitStream.Write(LUWString(player->playerName, 24)); // playername Wchar[24]
|
||||
bitStream.Write<uint16_t>(0); // null terminator for playername
|
||||
bitStream.Write<LWOOBJID>(0); // unknown
|
||||
bitStream.Write<LWOOBJID>(0); // unknown
|
||||
}
|
||||
|
||||
SystemAddress sysAddr = packet->systemAddress;
|
||||
SEND_PACKET;
|
||||
LOG("Send GUILD DATA");
|
||||
PacketUtils::SavePacket("GuildData.bin", (char*)bitStream.GetData(), bitStream.GetNumberOfBytesUsed());
|
||||
}
|
||||
|
||||
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {
|
||||
CBITSTREAM;
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CHAT_INTERNAL, eChatInternalMessageType::ROUTE_TO_PLAYER);
|
||||
|
||||
@@ -23,6 +23,10 @@ namespace ChatPacketHandler {
|
||||
void HandleTeamLootOption(Packet* packet);
|
||||
void HandleTeamStatusRequest(Packet* packet);
|
||||
|
||||
void HandleGuildLeave(Packet* packet);
|
||||
void HandleGuildGetAll(Packet* packet);
|
||||
|
||||
|
||||
void SendTeamInvite(PlayerData* receiver, PlayerData* sender);
|
||||
void SendTeamInviteConfirm(PlayerData* receiver, bool bLeaderIsFreeTrial, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, uint8_t ucResponseCode, std::u16string wsLeaderName);
|
||||
void SendTeamStatus(PlayerData* receiver, LWOOBJID i64LeaderID, LWOZONEID i64LeaderZoneID, uint8_t ucLootFlag, uint8_t ucNumOfOtherPlayers, std::u16string wsLeaderName);
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include "eChatMessageType.h"
|
||||
#include "eChatInternalMessageType.h"
|
||||
#include "eWorldMessageType.h"
|
||||
#include "PacketUtils.h"
|
||||
#include "ChatIgnoreList.h"
|
||||
|
||||
#include "Game.h"
|
||||
@@ -298,6 +299,41 @@ void HandlePacket(Packet* packet) {
|
||||
ChatPacketHandler::HandleTeamLootOption(packet);
|
||||
break;
|
||||
|
||||
// Guild messages
|
||||
case eChatMessageType::GUILD_CREATE:
|
||||
PacketUtils::SavePacket("GUILD_CREATE", (const char*) packet->data, packet->length);
|
||||
LOG("GUILD_CREATE");
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_INVITE:
|
||||
PacketUtils::SavePacket("GUILD_INVITE", (const char*) packet->data, packet->length);
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_INVITE_RESPONSE:
|
||||
PacketUtils::SavePacket("GUILD_INVITE_RESPONSE", (const char*) packet->data, packet->length);
|
||||
LOG("GUILD_INVITE_RESPONSE");
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_LEAVE:
|
||||
ChatPacketHandler::HandleGuildLeave(packet);
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_KICK:
|
||||
PacketUtils::SavePacket("GUILD_KICK", (const char*) packet->data, packet->length);
|
||||
LOG("GUILD_KICK");
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_GET_STATUS:
|
||||
PacketUtils::SavePacket("GUILD_GET_STATUS", (const char*) packet->data, packet->length);
|
||||
LOG("GUILD_GET_STATUS");
|
||||
break;
|
||||
|
||||
case eChatMessageType::GUILD_GET_ALL:
|
||||
PacketUtils::SavePacket("GUILD_GET_ALL", (const char*) packet->data, packet->length);
|
||||
LOG("GUILD_GET_ALL");
|
||||
ChatPacketHandler::HandleGuildGetAll(packet);
|
||||
break;
|
||||
|
||||
default:
|
||||
LOG("Unknown CHAT id: %i", int(packet->data[3]));
|
||||
}
|
||||
|
||||
13
dCommon/dEnums/eGuildCreationResponse.h
Normal file
13
dCommon/dEnums/eGuildCreationResponse.h
Normal file
@@ -0,0 +1,13 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __EGUILDCREATIONRESPONSE__H__
|
||||
#define __EGUILDCREATIONRESPONSE__H__
|
||||
|
||||
enum eGuildCreationResponse {
|
||||
CREATED = 0,
|
||||
REJECTED_BAD_NAME,
|
||||
REJECTED_EXISTS,
|
||||
UNKNOWN_ERROR
|
||||
};
|
||||
|
||||
#endif //!__EGUILDCREATIONRESPONSE__H__
|
||||
12
dCommon/dEnums/eGuildLeaveReason.h
Normal file
12
dCommon/dEnums/eGuildLeaveReason.h
Normal file
@@ -0,0 +1,12 @@
|
||||
#pragma once
|
||||
#include <cstdint>
|
||||
|
||||
#ifndef __EGUILDLEAVEREASON__H__
|
||||
#define __EGUILDLEAVEREASON__H__
|
||||
|
||||
enum class eGuildLeaveReason : uint8_t {
|
||||
LEFT = 0,
|
||||
KICKED
|
||||
};
|
||||
|
||||
#endif //!__EGUILDLEAVEREASON__H__
|
||||
14
dCommon/dEnums/eGuildRank.h
Normal file
14
dCommon/dEnums/eGuildRank.h
Normal file
@@ -0,0 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#ifndef __EGUILDRANK__H__
|
||||
#define __EGUILDRANK__H__
|
||||
|
||||
|
||||
enum eGuildRank {
|
||||
LEADER = 1,
|
||||
OFFICER,
|
||||
VETERAN,
|
||||
RECRUIT
|
||||
};
|
||||
|
||||
#endif //!__EGUILDRANK__H__
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "ICharInfo.h"
|
||||
#include "IAccounts.h"
|
||||
#include "IActivityLog.h"
|
||||
#include "IGuilds.h"
|
||||
#include "IGuildMembers.h"
|
||||
#include "IIgnoreList.h"
|
||||
#include "IAccountsRewardCodes.h"
|
||||
|
||||
@@ -28,7 +30,7 @@ namespace sql {
|
||||
class Statement;
|
||||
class PreparedStatement;
|
||||
};
|
||||
|
||||
#define _DEBUG
|
||||
#ifdef _DEBUG
|
||||
# define DLU_SQL_TRY_CATCH_RETHROW(x) do { try { x; } catch (sql::SQLException& ex) { LOG("SQL Error: %s", ex.what()); throw; } } while(0)
|
||||
#else
|
||||
@@ -40,7 +42,9 @@ class GameDatabase :
|
||||
public IMail, public ICommandLog, public IPlayerCheatDetections, public IBugReports,
|
||||
public IPropertyContents, public IProperty, public IPetNames, public ICharXml,
|
||||
public IMigrationHistory, public IUgc, public IFriends, public ICharInfo,
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList {
|
||||
public IAccounts, public IActivityLog, public IAccountsRewardCodes, public IIgnoreList,
|
||||
public IGuilds, public IGuildMembers {
|
||||
|
||||
public:
|
||||
virtual ~GameDatabase() = default;
|
||||
// TODO: These should be made private.
|
||||
|
||||
20
dDatabase/GameDatabase/ITables/IGuildMembers.h
Normal file
20
dDatabase/GameDatabase/ITables/IGuildMembers.h
Normal file
@@ -0,0 +1,20 @@
|
||||
#ifndef __IGUILDMEMBERS__H__
|
||||
#define __IGUILDMEMBERS__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
|
||||
class IGuildMembers {
|
||||
public:
|
||||
struct GuildMember {
|
||||
uint32_t id;
|
||||
uint16_t rank;
|
||||
};
|
||||
virtual void InsertGuildMember(const uint32_t guild_id, const uint32_t member_id, const uint16_t rank = 4) = 0;
|
||||
virtual void DeleteGuildMember(const uint32_t member_id) = 0;
|
||||
virtual uint32_t GetMembersGuild(const uint32_t member_id) = 0;
|
||||
virtual std::vector<GuildMember> GetGuildMembers(const uint32_t guild_id) = 0;
|
||||
virtual bool CheckIsInGuild(const uint32_t guild_id, const uint32_t character_id) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IGUILDMEMBERS__H__
|
||||
25
dDatabase/GameDatabase/ITables/IGuilds.h
Normal file
25
dDatabase/GameDatabase/ITables/IGuilds.h
Normal file
@@ -0,0 +1,25 @@
|
||||
#ifndef __IGUILDS__H__
|
||||
#define __IGUILDS__H__
|
||||
|
||||
#include <cstdint>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
class IGuilds {
|
||||
public:
|
||||
struct Guild {
|
||||
uint32_t id;
|
||||
uint32_t owner_id;
|
||||
std::string name;
|
||||
std::string motd;
|
||||
int64_t reputation;
|
||||
};
|
||||
virtual std::optional<Guild> CreateGuild(const std::string_view name, const int32_t owner_id, const uint64_t reputation) = 0;
|
||||
virtual std::optional<Guild> GetGuild(const uint32_t guild_id) = 0;
|
||||
virtual std::optional<Guild> GetGuildByName(const std::string_view name) = 0;
|
||||
virtual bool CheckGuildNameExists(const std::string_view name) = 0;
|
||||
virtual void SetMOTD(const uint32_t guild_id, const std::string_view motd) = 0;
|
||||
virtual void DeleteGuild(const uint32_t guild_id) = 0;
|
||||
};
|
||||
|
||||
#endif //!__IGUILDS__H__
|
||||
@@ -108,6 +108,17 @@ public:
|
||||
std::vector<IIgnoreList::Info> GetIgnoreList(const uint32_t playerId) override;
|
||||
void InsertRewardCode(const uint32_t account_id, const uint32_t reward_code) override;
|
||||
std::vector<uint32_t> GetRewardCodesByAccountID(const uint32_t account_id) override;
|
||||
std::optional<IGuilds::Guild> CreateGuild(const std::string_view name, const int32_t owner_id, const uint64_t reputation) override;
|
||||
std::optional<IGuilds::Guild> GetGuild(const uint32_t guild_id) override;
|
||||
std::optional<IGuilds::Guild> GetGuildByName(const std::string_view name) override;
|
||||
bool CheckGuildNameExists(const std::string_view name) override;
|
||||
void SetMOTD(const uint32_t guild_id, const std::string_view motd) override;
|
||||
void DeleteGuild(const uint32_t guild_id) override;
|
||||
void InsertGuildMember(const uint32_t guild_id, const uint32_t member_id, const uint16_t rank) override;
|
||||
void DeleteGuildMember(const uint32_t member_id) override;
|
||||
uint32_t GetMembersGuild(const uint32_t member_id) override;
|
||||
std::vector<GuildMember> GetGuildMembers(const uint32_t guild_id) override;
|
||||
bool CheckIsInGuild(const uint32_t guild_id, const uint32_t character_id) override;
|
||||
private:
|
||||
|
||||
// Generic query functions that can be used for any query.
|
||||
|
||||
@@ -7,6 +7,8 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
|
||||
"CharXml.cpp"
|
||||
"CommandLog.cpp"
|
||||
"Friends.cpp"
|
||||
"Guilds.cpp"
|
||||
"GuildMembers.cpp"
|
||||
"IgnoreList.cpp"
|
||||
"Leaderboard.cpp"
|
||||
"Mail.cpp"
|
||||
|
||||
35
dDatabase/GameDatabase/MySQL/Tables/GuildMembers.cpp
Normal file
35
dDatabase/GameDatabase/MySQL/Tables/GuildMembers.cpp
Normal file
@@ -0,0 +1,35 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
void MySQLDatabase::InsertGuildMember(const uint32_t guild_id, const uint32_t member_id, const uint16_t rank){
|
||||
ExecuteInsert("INSERT INTO guild_members (guild_id, character_id, rank) VALUES (?, ?, ?);", guild_id, member_id, rank);
|
||||
}
|
||||
|
||||
void MySQLDatabase::DeleteGuildMember(const uint32_t member_id){
|
||||
ExecuteDelete("DELETE FROM guild_members WHERE character_id = ?;", member_id);
|
||||
}
|
||||
|
||||
uint32_t MySQLDatabase::GetMembersGuild(const uint32_t member_id){
|
||||
auto res = ExecuteSelect("SELECT * FROM guild_members WHERE character_id = ?;", member_id);
|
||||
if (!res->next()) return 0;
|
||||
return res->getUInt("guild_id");
|
||||
}
|
||||
|
||||
std::vector<IGuildMembers::GuildMember> MySQLDatabase::GetGuildMembers(const uint32_t guild_id){
|
||||
auto res = ExecuteSelect("SELECT * FROM guild_members WHERE guild_id = ?;", guild_id);
|
||||
std::vector<GuildMember> toReturn;
|
||||
toReturn.reserve(res->rowsCount());
|
||||
|
||||
while (res->next()) {
|
||||
GuildMember member;
|
||||
member.id = res->getUInt("character_id");
|
||||
member.rank = res->getUInt("rank");
|
||||
toReturn.push_back(member);
|
||||
}
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
bool MySQLDatabase::CheckIsInGuild(const uint32_t guild_id, const uint32_t character_id) {
|
||||
auto res = ExecuteSelect("SELECT * FROM guild_members WHERE guild_id = ? AND character_id = ?;", guild_id, character_id);
|
||||
if (res->next()) return true;
|
||||
return false;
|
||||
}
|
||||
46
dDatabase/GameDatabase/MySQL/Tables/Guilds.cpp
Normal file
46
dDatabase/GameDatabase/MySQL/Tables/Guilds.cpp
Normal file
@@ -0,0 +1,46 @@
|
||||
#include "MySQLDatabase.h"
|
||||
|
||||
std::optional<IGuilds::Guild> MySQLDatabase::CreateGuild(const std::string_view name, const int32_t owner_id, const uint64_t reputation) {
|
||||
ExecuteInsert("INSERT INTO guilds (name, owner_id, reputation) VALUES (?, ?, ?);", name, owner_id, reputation);
|
||||
return GetGuildByName(name);
|
||||
}
|
||||
|
||||
std::optional<IGuilds::Guild> MySQLDatabase::GetGuild(const uint32_t guild_id) {
|
||||
auto return_res = ExecuteSelect("SELECT * from guilds where id = ?", guild_id);
|
||||
if (!return_res->next()) return std::nullopt;
|
||||
|
||||
IGuilds::Guild toReturn;
|
||||
toReturn.id = return_res->getInt64("id");
|
||||
toReturn.owner_id = return_res->getUInt("owner_id");
|
||||
toReturn.name = return_res->getString("name").c_str();
|
||||
toReturn.motd = return_res->getString("motd").c_str();
|
||||
toReturn.reputation = return_res->getUInt64("reputation");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
std::optional<IGuilds::Guild> MySQLDatabase::GetGuildByName(const std::string_view name) {
|
||||
auto return_res = ExecuteSelect("SELECT * from guilds where name = ?", name);
|
||||
if (!return_res->next()) return std::nullopt;
|
||||
|
||||
IGuilds::Guild toReturn;
|
||||
toReturn.id = return_res->getUInt("id");
|
||||
toReturn.owner_id = return_res->getUInt("owner_id");
|
||||
toReturn.name = return_res->getString("name").c_str();
|
||||
toReturn.motd = return_res->getString("motd").c_str();
|
||||
toReturn.reputation = return_res->getUInt64("reputation");
|
||||
|
||||
return toReturn;
|
||||
}
|
||||
|
||||
bool MySQLDatabase::CheckGuildNameExists(const std::string_view name) {
|
||||
auto res = ExecuteSelect("SELECT * FROM guilds WHERE name = ?;", name);
|
||||
return res->next();
|
||||
}
|
||||
void MySQLDatabase::SetMOTD(const uint32_t guild_id, const std::string_view motd) {
|
||||
auto res = ExecuteUpdate("Update guilds SET motd = ? WHERE id = ?;", motd, guild_id);
|
||||
if (res != 1) throw res;
|
||||
}
|
||||
|
||||
void MySQLDatabase::DeleteGuild(const uint32_t guild_id) {
|
||||
ExecuteDelete("DELETE FROM guilds where id = ?;", guild_id);
|
||||
}
|
||||
@@ -21,6 +21,8 @@
|
||||
#include "CDRewardCodesTable.h"
|
||||
#include "Mail.h"
|
||||
#include <ctime>
|
||||
#include "Database.h"
|
||||
#include "eObjectBits.h"
|
||||
|
||||
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
|
||||
m_Character = character;
|
||||
@@ -44,6 +46,7 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C
|
||||
m_CurrentActivity = eGameActivity::NONE;
|
||||
m_CountryCode = 0;
|
||||
m_LastUpdateTimestamp = std::time(nullptr);
|
||||
m_GuildID = LWOOBJID_EMPTY;
|
||||
}
|
||||
|
||||
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
|
||||
@@ -154,15 +157,15 @@ void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInit
|
||||
outBitStream->Write(m_DirtyCurrentActivity);
|
||||
if (m_DirtyCurrentActivity) outBitStream->Write(m_CurrentActivity);
|
||||
|
||||
|
||||
outBitStream->Write(m_DirtySocialInfo);
|
||||
if (m_DirtySocialInfo) {
|
||||
outBitStream->Write(m_GuildID);
|
||||
outBitStream->Write<unsigned char>(static_cast<unsigned char>(m_GuildName.size()));
|
||||
if (!m_GuildName.empty())
|
||||
outBitStream->WriteBits(reinterpret_cast<const unsigned char*>(m_GuildName.c_str()), static_cast<unsigned char>(m_GuildName.size()) * sizeof(wchar_t) * 8);
|
||||
|
||||
outBitStream->Write<uint64_t>(m_GuildID);
|
||||
outBitStream->Write<uint16_t>(m_GuildName.size());
|
||||
if (!m_GuildName.empty()) outBitStream->Write(m_GuildName);
|
||||
outBitStream->Write(m_IsLEGOClubMember);
|
||||
outBitStream->Write(m_CountryCode);
|
||||
m_DirtySocialInfo = false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -172,7 +175,6 @@ bool CharacterComponent::GetPvpEnabled() const {
|
||||
|
||||
void CharacterComponent::SetPvpEnabled(const bool value) {
|
||||
m_DirtyGMInfo = true;
|
||||
|
||||
m_PvpEnabled = value;
|
||||
}
|
||||
|
||||
@@ -183,6 +185,18 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
|
||||
m_GMLevel = gmlevel;
|
||||
}
|
||||
|
||||
void CharacterComponent::SetGuild(uint32_t guild_id, std::u16string guildName) {
|
||||
if (guild_id == 0 || guildName.empty()){
|
||||
m_GuildID = LWOOBJID_EMPTY;
|
||||
m_GuildName.clear();
|
||||
} else {
|
||||
m_GuildID = guild_id;
|
||||
GeneralUtils::SetBit(m_GuildID, eObjectBits::CHARACTER);
|
||||
m_GuildName = guildName;
|
||||
}
|
||||
m_DirtySocialInfo = true;
|
||||
}
|
||||
|
||||
void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
|
||||
tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char");
|
||||
@@ -264,17 +278,19 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
|
||||
m_EditorEnabled = false; //We're not currently in HF if we're loading in
|
||||
}
|
||||
|
||||
//Annoying guild bs:
|
||||
const tinyxml2::XMLAttribute* guildName = character->FindAttribute("gn");
|
||||
if (guildName) {
|
||||
const char* gn = guildName->Value();
|
||||
int64_t gid = 0;
|
||||
character->QueryInt64Attribute("gid", &gid);
|
||||
if (gid != 0) {
|
||||
std::string guildname(gn);
|
||||
m_GuildName = GeneralUtils::UTF8ToUTF16(guildname);
|
||||
// Guild Stuff:
|
||||
// Ensure the guild they are a part of still exists
|
||||
// Update the guild name if it has changed
|
||||
int64_t gid = 0;
|
||||
character->QueryInt64Attribute("gid", &gid);
|
||||
if (gid != 0) {
|
||||
auto guild = Database::Get()->GetGuild(gid);
|
||||
if (guild && Database::Get()->CheckIsInGuild(guild->id, m_Parent->GetCharacter()->GetID())) {
|
||||
m_GuildName = GeneralUtils::UTF8ToUTF16(guild->name);
|
||||
m_GuildID = gid;
|
||||
m_DirtySocialInfo = true;
|
||||
} else {
|
||||
SetGuild(0, u"");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -371,6 +387,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
|
||||
// End custom attributes
|
||||
//
|
||||
|
||||
if (m_GuildID != 0 || !m_GuildName.empty()) {
|
||||
character->SetAttribute("gn", GeneralUtils::UTF16ToWTF8(m_GuildName).c_str());
|
||||
character->SetAttribute("gid", m_GuildID);
|
||||
}
|
||||
|
||||
auto newUpdateTimestamp = std::time(nullptr);
|
||||
LOG("Time since last save: %d", newUpdateTimestamp - m_LastUpdateTimestamp);
|
||||
|
||||
|
||||
@@ -183,6 +183,26 @@ public:
|
||||
*/
|
||||
void SetGMLevel(eGameMasterLevel gmlevel);
|
||||
|
||||
/**
|
||||
* @brief Get the Guild ID that the character is in
|
||||
* @return const LWOOBJID& The guild
|
||||
*/
|
||||
const LWOOBJID& GetGuildID() const { return m_GuildID; }
|
||||
|
||||
/**
|
||||
* @brief Get the character's Guild's Name
|
||||
* @return const std::u16string& the guild name
|
||||
*/
|
||||
const std::u16string& GetGuildName() const { return m_GuildName; }
|
||||
|
||||
/**
|
||||
* @brief Set the character's Guild
|
||||
*
|
||||
* @param guild_id
|
||||
* @param guildName
|
||||
*/
|
||||
void SetGuild(uint32_t guild_id, std::u16string guildName);
|
||||
|
||||
/**
|
||||
* Initializes the player statistics from the string stored in the XML
|
||||
* @param statisticsString the string to parse
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
* Component that handles rigid bodies that can be interacted with, mostly client-side rendered. An example is the
|
||||
* bananas that fall from trees in GF.
|
||||
*/
|
||||
|
||||
class RigidbodyPhantomPhysicsComponent : public PhysicsComponent {
|
||||
public:
|
||||
inline static const eReplicaComponentType ComponentType = eReplicaComponentType::RIGID_BODY_PHANTOM_PHYSICS;
|
||||
|
||||
@@ -4581,6 +4581,17 @@ void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditi
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void GameMessages::SendDisplayGuildCreateBox(const LWOOBJID& objectID, bool bShow, const SystemAddress& sysAddr) {
|
||||
CBITSTREAM;
|
||||
CMSGHEADER;
|
||||
|
||||
bitStream.Write(eGameMessageType::DISPLAY_GUILD_CREATE_BOX);
|
||||
bitStream.Write(objectID);
|
||||
bitStream.Write((unsigned char)bShow);
|
||||
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
|
||||
//-----------------------------------------------------------------------------------------------------------------------------------------------
|
||||
//------------------------------------------------------------------- Handlers ------------------------------------------------------------------
|
||||
@@ -4838,7 +4849,7 @@ void GameMessages::HandleParseChatMessage(RakNet::BitStream* inStream, Entity* e
|
||||
inStream->Read(character);
|
||||
wsString.push_back(character);
|
||||
}
|
||||
|
||||
LOG("state: %i, str: %s", iClientState, GeneralUtils::UTF16ToWTF8(wsString).c_str());
|
||||
if (wsString[0] == L'/') {
|
||||
SlashCommandHandler::HandleChatCommand(wsString, entity, sysAddr);
|
||||
}
|
||||
|
||||
@@ -4,6 +4,13 @@
|
||||
#include "dCommonVars.h"
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include "NiQuaternion.h"
|
||||
#include "PropertySelectQueryProperty.h"
|
||||
#include "TradingManager.h"
|
||||
#include "LeaderboardManager.h"
|
||||
#include "MovingPlatformComponent.h"
|
||||
#include "eAninmationFlags.h"
|
||||
#include "eGuildCreationResponse.h"
|
||||
#include <vector>
|
||||
#include "eMovementPlatformState.h"
|
||||
#include "NiPoint3.h"
|
||||
@@ -586,6 +593,9 @@ namespace GameMessages {
|
||||
|
||||
void SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditionalSound, bool bPlayCountdownSound, std::u16string sndName, int32_t stateToPlaySoundOn, const SystemAddress& sysAddr);
|
||||
|
||||
//Guild messages:
|
||||
void SendDisplayGuildCreateBox(const LWOOBJID& objectID, bool bShow, const SystemAddress& sysAddr);
|
||||
|
||||
//Handlers:
|
||||
|
||||
void HandleToggleGhostReferenceOverride(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr);
|
||||
|
||||
@@ -31,10 +31,13 @@
|
||||
#include "dConfig.h"
|
||||
#include "CharacterComponent.h"
|
||||
#include "Database.h"
|
||||
#include "PacketUtils.h"
|
||||
#include "eGuildRank.h"
|
||||
#include "eGameMasterLevel.h"
|
||||
#include "eReplicaComponentType.h"
|
||||
#include "CheatDetection.h"
|
||||
#include "Amf3.h"
|
||||
#include "eObjectBits.h"
|
||||
|
||||
void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) {
|
||||
User* user = UserManager::Instance()->GetUser(sysAddr);
|
||||
@@ -389,6 +392,74 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
|
||||
WorldPackets::SendChatModerationResponse(sysAddr, bAllClean, requestID, receiver, segments);
|
||||
}
|
||||
|
||||
void ClientPackets::HandleGuildCreation(Packet* packet) {
|
||||
CINSTREAM_SKIP_HEADER;
|
||||
LUWString guildName(31);
|
||||
inStream.Read(guildName);
|
||||
|
||||
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||
if (!user) return;
|
||||
|
||||
auto character = user->GetLastUsedChar();
|
||||
if (!character) return;
|
||||
|
||||
LOG("User %s wants to create a guild with name: %s", character->GetName().c_str(), guildName.GetAsString().c_str());
|
||||
|
||||
// First, check to see if there is a guild with that name or not:
|
||||
if (Database::Get()->CheckGuildNameExists(guildName.GetAsString().c_str())) {
|
||||
LOG("But a guild already exists with that name!");
|
||||
SendGuildCreateResponse(packet->systemAddress, eGuildCreationResponse::REJECTED_EXISTS, LWOOBJID_EMPTY, guildName.string);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!Game::chatFilter->IsSentenceOkay(guildName.GetAsString().c_str(), character->GetGMLevel()).empty()) {
|
||||
LOG("But they used bad words!");
|
||||
SendGuildCreateResponse(packet->systemAddress, eGuildCreationResponse::REJECTED_BAD_NAME, LWOOBJID_EMPTY, guildName.string);
|
||||
return;
|
||||
}
|
||||
|
||||
auto entity = character->GetEntity();
|
||||
if (!entity) return;
|
||||
|
||||
// Check to see if the character is already in a guild or not:
|
||||
auto* characterComp = entity->GetComponent<CharacterComponent>();
|
||||
if (!characterComp) return;
|
||||
|
||||
if (characterComp->GetGuildID() != 0) {
|
||||
ChatPackets::SendSystemMessage(packet->systemAddress, u"You are already in a guild! Leave your current guild first.");
|
||||
return;
|
||||
}
|
||||
|
||||
LOG("Creating Guild");
|
||||
auto newGuild = Database::Get()->CreateGuild(guildName.GetAsString(), character->GetID(), characterComp->GetUScore());
|
||||
|
||||
if (!newGuild){
|
||||
LOG("Unknown error ocurred while creating a guild! Got %i", newGuild->id);
|
||||
SendGuildCreateResponse(packet->systemAddress, eGuildCreationResponse::UNKNOWN_ERROR, LWOOBJID_EMPTY, guildName.string);
|
||||
return;
|
||||
}
|
||||
|
||||
Database::Get()->InsertGuildMember(newGuild->id, character->GetID(), eGuildRank::LEADER);
|
||||
|
||||
characterComp->SetGuild(newGuild->id, guildName.string);
|
||||
SendGuildCreateResponse(packet->systemAddress, eGuildCreationResponse::CREATED, newGuild->id, guildName.string);
|
||||
AMFArrayValue data;
|
||||
data.Insert("bDisplay", true);
|
||||
GameMessages::SendUIMessageServerToSingleClient(entity, packet->systemAddress, "EnableGuild", data);
|
||||
|
||||
}
|
||||
|
||||
|
||||
void ClientPackets::SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guild_id, std::u16string& guildName) {
|
||||
CBITSTREAM;
|
||||
GeneralUtils::SetBit(guild_id, eObjectBits::CHARACTER);
|
||||
BitStreamUtils::WriteHeader(bitStream, eConnectionType::CLIENT, eClientMessageType::GUILD_CREATE_RESPONSE);
|
||||
bitStream.Write<uint8_t>(guildResponse);
|
||||
bitStream.Write(guild_id);
|
||||
bitStream.Write(LUWString(guildName));
|
||||
SEND_PACKET;
|
||||
}
|
||||
|
||||
void ClientPackets::SendTop5HelpIssues(Packet* packet) {
|
||||
auto* user = UserManager::Instance()->GetUser(packet->systemAddress);
|
||||
if (!user) return;
|
||||
|
||||
@@ -7,12 +7,18 @@
|
||||
#define CLIENTPACKETS_H
|
||||
|
||||
#include "RakNetTypes.h"
|
||||
#include "eGuildCreationResponse.h"
|
||||
#include "dCommonVars.h"
|
||||
|
||||
namespace ClientPackets {
|
||||
void HandleChatMessage(const SystemAddress& sysAddr, Packet* packet);
|
||||
void HandleClientPositionUpdate(const SystemAddress& sysAddr, Packet* packet);
|
||||
void HandleChatModerationRequest(const SystemAddress& sysAddr, Packet* packet);
|
||||
void SendTop5HelpIssues(Packet* packet);
|
||||
|
||||
// Guild stuff
|
||||
void HandleGuildCreation(Packet* packet);
|
||||
void SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guild_id, std::u16string& guildName);
|
||||
};
|
||||
|
||||
#endif // CLIENTPACKETS_H
|
||||
|
||||
@@ -139,6 +139,7 @@
|
||||
#include "TreasureChestDragonServer.h"
|
||||
#include "InstanceExitTransferPlayerToLastNonInstance.h"
|
||||
#include "FvFreeGfNinjas.h"
|
||||
#include "FvGuildCreate.h"
|
||||
#include "FvPandaServer.h"
|
||||
#include "FvPandaSpawnerServer.h"
|
||||
#include "ZoneFvProperty.h"
|
||||
@@ -583,6 +584,8 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr
|
||||
script = new InstanceExitTransferPlayerToLastNonInstance();
|
||||
else if (scriptName == "scripts\\ai\\FV\\L_NPC_FREE_GF_NINJAS.lua")
|
||||
script = new FvFreeGfNinjas();
|
||||
else if (scriptName == "scripts\\ai\\FV\\L_GUILD_CREATE.lua")
|
||||
script = new FvGuildCreate();
|
||||
else if (scriptName == "scripts\\ai\\FV\\L_FV_PANDA_SPAWNER_SERVER.lua")
|
||||
script = new FvPandaSpawnerServer();
|
||||
else if (scriptName == "scripts\\ai\\FV\\L_FV_PANDA_SERVER.lua")
|
||||
|
||||
@@ -4,6 +4,7 @@ set(DSCRIPTS_SOURCES_AI_FV
|
||||
"FvFlyingCreviceDragon.cpp"
|
||||
"FvDragonSmashingGolemQb.cpp"
|
||||
"FvFreeGfNinjas.cpp"
|
||||
"FvGuildCreate.cpp"
|
||||
"FvPandaSpawnerServer.cpp"
|
||||
"FvPandaServer.cpp"
|
||||
"FvBrickPuzzleServer.cpp"
|
||||
|
||||
12
dScripts/ai/FV/FvGuildCreate.cpp
Normal file
12
dScripts/ai/FV/FvGuildCreate.cpp
Normal file
@@ -0,0 +1,12 @@
|
||||
#include "FvGuildCreate.h"
|
||||
#include "GameMessages.h"
|
||||
#include "Amf3.h"
|
||||
|
||||
// Server script for Guild Master NPC in FV area.
|
||||
// This NPC will react to a user interaction and display
|
||||
// the guild creation screen.
|
||||
|
||||
void FvGuildCreate::OnUse(Entity* self, Entity* user) {
|
||||
AMFArrayValue args;
|
||||
GameMessages::SendUIMessageServerToSingleClient(user, user->GetSystemAddress(), "ToggleGuildCreate", args);
|
||||
}
|
||||
7
dScripts/ai/FV/FvGuildCreate.h
Normal file
7
dScripts/ai/FV/FvGuildCreate.h
Normal file
@@ -0,0 +1,7 @@
|
||||
#pragma once
|
||||
#include "CppScripts.h"
|
||||
|
||||
class FvGuildCreate : public CppScripts::Script {
|
||||
public:
|
||||
void OnUse(Entity* self, Entity* user) override;
|
||||
};
|
||||
@@ -1236,7 +1236,10 @@ void HandlePacket(Packet* packet) {
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
case eWorldMessageType::TMP_GUILD_CREATE: {
|
||||
Game::logger->Log("WorldServer", "create a guild");
|
||||
ClientPackets::HandleGuildCreation(packet);
|
||||
}
|
||||
case eWorldMessageType::UI_HELP_TOP_5: {
|
||||
ClientPackets::SendTop5HelpIssues(packet);
|
||||
break;
|
||||
|
||||
16
migrations/dlu/15_guilds.sql
Normal file
16
migrations/dlu/15_guilds.sql
Normal file
@@ -0,0 +1,16 @@
|
||||
CREATE TABLE IF NOT EXISTS guilds (
|
||||
id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY,
|
||||
name VARCHAR(35) NOT NULL,
|
||||
owner_id BIGINT NOT NULL REFERENCES charinfo(id) ON DELETE CASCADE,
|
||||
motd TEXT,
|
||||
reputation INT NOT NULL DEFAULT 0,
|
||||
created TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP()
|
||||
);
|
||||
|
||||
CREATE TABLE IF NOT EXISTS guild_members (
|
||||
guild_id BIGINT NOT NULL REFERENCES guilds(id) ON DELETE CASCADE,
|
||||
character_id BIGINT NOT NULL REFERENCES charinfo(id) ON DELETE CASCADE,
|
||||
rank INT NOT NULL DEFAULT 4,
|
||||
joined TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(),
|
||||
PRIMARY KEY (guild_id, character_id)
|
||||
);
|
||||
Reference in New Issue
Block a user