no crashes
This commit is contained in:
Aaron Kimbre 2023-11-21 14:16:56 -06:00
parent e5f62e870b
commit a4bf11502f
17 changed files with 286 additions and 94 deletions

View File

@ -18,6 +18,7 @@
#include "eChatInternalMessageType.h"
#include "eClientMessageType.h"
#include "eGameMessageType.h"
#include "eGuildLeaveReason.h"
extern PlayerContainer playerContainer;
@ -676,8 +677,25 @@ void ChatPacketHandler::HandleGuildLeave(Packet* packet){
CINSTREAM_SKIP_HEADER;
LWOOBJID playerID = LWOOBJID_EMPTY;
inStream.Read(playerID);
LOG("HandleGuildLeave %llu", 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){
@ -685,7 +703,42 @@ void ChatPacketHandler::HandleGuildGetAll(Packet* packet){
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.Write0();
bitStream.Write(LUWString(guild->name, 31));
bitStream.Write(LUWString("test1", 11));
bitStream.Write(LUWString("test2", 11));
bitStream.Write<uint32_t>(69);
bitStream.Write<uint32_t>(0);
bitStream.Write<uint32_t>(1);
bitStream.Write<uint8_t>(0);
bitStream.Write<uint8_t>(members.size());
//Member data
bitStream.Write1();
bitStream.Write1();
bitStream.Write<uint16_t>(1200);
bitStream.Write<uint16_t>(1);
bitStream.Write<uint16_t>(1);
bitStream.Write<uint16_t>(1);
bitStream.Write<uint32_t>(1);
bitStream.Write(LUWString(player->playerName, 25));
bitStream.Write<uint8_t>(0); //???
SystemAddress sysAddr = packet->systemAddress;
SEND_PACKET;
}
void ChatPacketHandler::SendTeamInvite(PlayerData* receiver, PlayerData* sender) {

View File

@ -19,6 +19,7 @@
#include "eChatMessageType.h"
#include "eChatInternalMessageType.h"
#include "eWorldMessageType.h"
#include "PacketUtils.h"
#include "Game.h"
@ -293,10 +294,16 @@ void HandlePacket(Packet* packet) {
// 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;
@ -305,14 +312,17 @@ void HandlePacket(Packet* 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;

View 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__

View File

@ -8,6 +8,7 @@
#include <string>
#include <vector>
#include <map>
#include <cstdint>
// CPPLinq
#ifdef _WIN32

View File

@ -21,12 +21,13 @@
#include "ICharInfo.h"
#include "IAccounts.h"
#include "IActivityLog.h"
#include "IGuilds.h"
#include "IGuildMembers.h"
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
@ -38,7 +39,7 @@ 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 IAccounts, public IActivityLog, public IGuilds, public IGuildMembers {
public:
virtual ~GameDatabase() = default;
// TODO: These should be made private.

View 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__

View 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__

View File

@ -103,6 +103,17 @@ public:
std::optional<uint32_t> GetDonationTotal(const uint32_t activityId) override;
std::optional<bool> IsPlaykeyActive(const int32_t playkeyId) override;
std::vector<IUgc::Model> GetUgcModels(const LWOOBJID& propertyId) 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.

View File

@ -6,6 +6,8 @@ set(DDATABASES_DATABASES_MYSQL_TABLES_SOURCES
"CharXml.cpp"
"CommandLog.cpp"
"Friends.cpp"
"Guilds.cpp"
"GuildMembers.cpp"
"Leaderboard.cpp"
"Mail.cpp"
"MigrationHistory.cpp"

View 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;
}

View 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);
}

View File

@ -17,6 +17,8 @@
#include "eGameMasterLevel.h"
#include "eGameActivity.h"
#include <ctime>
#include "Database.h"
#include "eObjectBits.h"
CharacterComponent::CharacterComponent(Entity* parent, Character* character) : Component(parent) {
m_Character = character;
@ -40,10 +42,7 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C
m_CurrentActivity = eGameActivity::NONE;
m_CountryCode = 0;
m_LastUpdateTimestamp = std::time(nullptr);
m_GuildID = 0;
m_GuildName = u"";
m_GuildID = LWOOBJID_EMPTY;
}
bool CharacterComponent::LandingAnimDisabled(int zoneID) {
@ -153,11 +152,9 @@ void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInit
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;
@ -180,9 +177,15 @@ void CharacterComponent::SetGMLevel(eGameMasterLevel gmlevel) {
m_GMLevel = gmlevel;
}
void CharacterComponent::SetGuild(LWOOBJID& guildID, std::u16string guildName) {
m_GuildID = guildID;
m_GuildName = guildName;
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;
}
@ -261,16 +264,20 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) {
}
// Guild Stuff:
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);
// 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())) {
LOG("Found Guild %i name %s", guild->id, guild->name.c_str());
m_GuildName = GeneralUtils::UTF8ToUTF16(guild->name);
m_GuildID = gid;
m_DirtySocialInfo = true;
} else {
LOG("Unalbe to find Guild %i name %s", guild->id, guild->name.c_str());
SetGuild(0, u"");
}
}
@ -362,7 +369,7 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) {
// End custom attributes
//
if (m_GuildID != 0 || m_GuildName != u"") {
if (m_GuildID != 0 || !m_GuildName.empty()) {
character->SetAttribute("gn", GeneralUtils::UTF16ToWTF8(m_GuildName).c_str());
character->SetAttribute("gid", m_GuildID);
}

View File

@ -197,10 +197,10 @@ public:
/**
* @brief Set the character's Guild
*
* @param guildID
* @param guild_id
* @param guildName
*/
void SetGuild(LWOOBJID& guildID, std::u16string guildName);
void SetGuild(uint32_t guild_id, std::u16string guildName);
/**
* Initializes the player statistics from the string stored in the XML

View File

@ -37,6 +37,7 @@
#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);
@ -391,36 +392,29 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa
WorldPackets::SendChatModerationResponse(sysAddr, bAllClean, requestID, receiver, segments);
}
void ClientPackets::HandleGuildCreation(const SystemAddress& sysAddr, Packet* packet) {
std::string guildName = PacketUtils::ReadString(8, packet, true);
void ClientPackets::HandleGuildCreation(Packet* packet) {
CINSTREAM_SKIP_HEADER;
LUWString guildName(31);
inStream.Read(guildName);
auto user = UserManager::Instance()->GetUser(sysAddr);
auto user = UserManager::Instance()->GetUser(packet->systemAddress);
if (!user) return;
auto character = user->GetLastUsedChar();
if (!character) return;
Game::logger->Log("ClientPackets", "User %s wants to create a guild with name: %s", character->GetName().c_str(), guildName.c_str());
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:
auto stmt = Database::CreatePreppedStmt("SELECT * FROM guilds WHERE name=?");
stmt->setString(1, guildName.c_str());
auto res = stmt->executeQuery();
if (res->rowsCount() > 0) {
Game::logger->Log("ClientPackets", "But a guild already exists with that name!");
auto usedName = GeneralUtils::UTF8ToUTF16(guildName);
SendGuildCreateResponse(sysAddr, eGuildCreationResponse::REJECTED_EXISTS, LWOOBJID_EMPTY, usedName);
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;
}
delete res;
delete stmt;
if (!Game::chatFilter->IsSentenceOkay(guildName, character->GetGMLevel()).empty()) {
Game::logger->Log("ClientPackets", "But they used bad words!");
auto usedName = GeneralUtils::UTF8ToUTF16(guildName);
SendGuildCreateResponse(sysAddr, eGuildCreationResponse::REJECTED_BAD_NAME, LWOOBJID_EMPTY, usedName);
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;
}
@ -432,61 +426,36 @@ void ClientPackets::HandleGuildCreation(const SystemAddress& sysAddr, Packet* pa
if (!characterComp) return;
if (characterComp->GetGuildID() != 0) {
ChatPackets::SendSystemMessage(sysAddr, u"You are already in a guild! Leave your current guild first.");
ChatPackets::SendSystemMessage(packet->systemAddress, u"You are already in a guild! Leave your current guild first.");
return;
}
auto creation = (uint32_t)time(nullptr);
LOG("Creating Guild");
// If not, insert our newly created guild:
auto insertGuild = Database::CreatePreppedStmt("INSERT INTO `guilds`(`name`, `owner_id`, `reputation`, `created`) VALUES (?,?,?,?)");
insertGuild->setString(1, guildName.c_str());
insertGuild->setUInt(2, character->GetID());
insertGuild->setUInt(3, characterComp->GetUScore());
insertGuild->setUInt(4, creation);
insertGuild->execute();
delete insertGuild;
auto newGuild = Database::Get()->CreateGuild(guildName.GetAsString(), character->GetID(), characterComp->GetUScore());
// Enable the guild on their character component:
auto get = Database::CreatePreppedStmt("SELECT id, name FROM guilds WHERE owner_id=?");
get->setInt(1, character->GetID());
auto* results = get->executeQuery();
LWOOBJID guildId = LWOOBJID_EMPTY;
std::u16string name;
while (results->next()) {
guildId = results->getInt(1);
name = GeneralUtils::UTF8ToUTF16(results->getString(2).c_str());
characterComp->SetGuild(guildId, name);
}
if (guildId == LWOOBJID_EMPTY){
Game::logger->Log("ClientPackets", "Unknown error ocurred while creating a guild!");
auto usedName = GeneralUtils::UTF8ToUTF16(guildName);
SendGuildCreateResponse(sysAddr, eGuildCreationResponse::UNKNOWN_ERROR, LWOOBJID_EMPTY, usedName);
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::FOUNDER);
auto insertOwner = Database::CreatePreppedStmt("INSERT INTO `guild_members`(`guild_id`, `character_id`, `rank`, `joined`) VALUES (?,?,?,?)");
insertOwner->setUInt(1, guildId);
insertOwner->setUInt(2, character->GetID());
insertOwner->setUInt(3, eGuildRank::FOUNDER);
insertOwner->setUInt(4, creation);
insertOwner->execute();
delete insertOwner;
characterComp->SetGuild(newGuild->id, guildName.string);
SendGuildCreateResponse(packet->systemAddress, eGuildCreationResponse::CREATED, newGuild->id, guildName.string);
AMFArrayValue data;
data.Insert("bOn", true);
GameMessages::SendUIMessageServerToSingleClient(entity, packet->systemAddress, "ToggleGuildUI", data);
//Send the guild create response:
SendGuildCreateResponse(sysAddr, eGuildCreationResponse::CREATED, guildId, name);
// TODO: enable guild ui here
}
void ClientPackets::SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guildID, std::u16string& guildName) {
void ClientPackets::SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guild_id, std::u16string& guildName) {
CBITSTREAM;
CMSGHEADER;
bitStream.Write(eClientMessageType::GUILD_CREATE_RESPONSE);
bitStream.Write(guildResponse);
bitStream.Write(guildID);
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;
}

View File

@ -17,8 +17,8 @@ namespace ClientPackets {
void SendTop5HelpIssues(Packet* packet);
// Guild stuff
void HandleGuildCreation(const SystemAddress& sysAddr, Packet* packet);
void SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guildID, std::u16string& guildName);
void HandleGuildCreation(Packet* packet);
void SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guild_id, std::u16string& guildName);
};
#endif // CLIENTPACKETS_H

View File

@ -1239,7 +1239,7 @@ void HandlePacket(Packet* packet) {
case eWorldMessageType::TMP_GUILD_CREATE: {
Game::logger->Log("WorldServer", "create a guild");
ClientPackets::HandleGuildCreation(packet->systemAddress, packet);
ClientPackets::HandleGuildCreation(packet);
}
case eWorldMessageType::UI_HELP_TOP_5: {
ClientPackets::SendTop5HelpIssues(packet);

View File

@ -4,13 +4,13 @@ CREATE TABLE IF NOT EXISTS guilds (
owner_id BIGINT NOT NULL REFERENCES charinfo(id) ON DELETE CASCADE,
motd TEXT,
reputation INT NOT NULL DEFAULT 0,
created BIGINT UNSIGNED 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 BIGINT UNSIGNED NOT NULL DEFAULT 0
joined TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(),
PRIMARY KEY (guild_id, character_id)
);