From 30fbdd3956bc3b132c5bca6cae2aa194444a2795 Mon Sep 17 00:00:00 2001 From: Aaron Kimbre Date: Tue, 20 Dec 2022 08:14:58 -0600 Subject: [PATCH] WIP --- dChatServer/ChatServer.cpp | 13 ++++ dCommon/dEnums/dCommonVars.h | 7 -- dCommon/dEnums/dMessageIdentifiers.h | 18 +++++ dCommon/dEnums/eGuildCreationResponse.h | 13 ++++ dCommon/dEnums/eGuildRank.h | 14 ++++ dGame/dComponents/CharacterComponent.cpp | 19 ++++- dGame/dComponents/CharacterComponent.h | 20 +++++ dGame/dGameMessages/GameMessages.cpp | 21 ++++++ dGame/dGameMessages/GameMessages.h | 5 ++ dNet/ClientPackets.cpp | 93 +++++++++++++++++++++++- dNet/ClientPackets.h | 4 + dWorldServer/WorldServer.cpp | 5 ++ migrations/dlu/8_guilds.sql | 15 ++++ 13 files changed, 237 insertions(+), 10 deletions(-) create mode 100644 dCommon/dEnums/eGuildCreationResponse.h create mode 100644 dCommon/dEnums/eGuildRank.h create mode 100644 migrations/dlu/8_guilds.sql diff --git a/dChatServer/ChatServer.cpp b/dChatServer/ChatServer.cpp index f3b2c123..8c3543fa 100644 --- a/dChatServer/ChatServer.cpp +++ b/dChatServer/ChatServer.cpp @@ -288,6 +288,19 @@ void HandlePacket(Packet* packet) { ChatPacketHandler::HandleTeamLootOption(packet); break; + // Guild messages + case MSG_CHAT_GUILD_CREATE: + Game::logger->Log("ChatPackets", "GuildCreate"); + break; + + case MSG_CHAT_GUILD_GET_ALL: + Game::logger->Log("ChatPackets", "GuildGetAll"); + break; + + case MSG_CHAT_GUILD_GET_STATUS: + Game::logger->Log("ChatPackets", "GuildGetStatus"); + break; + default: Game::logger->Log("ChatServer", "Unknown CHAT id: %i", int(packet->data[3])); } diff --git a/dCommon/dEnums/dCommonVars.h b/dCommon/dEnums/dCommonVars.h index 14865a89..d13e8b94 100644 --- a/dCommon/dEnums/dCommonVars.h +++ b/dCommon/dEnums/dCommonVars.h @@ -472,13 +472,6 @@ enum eGameActivities : uint32_t { ACTIVITY_PET_TAMING }; -enum eGuildCreationResponses { - CREATED = 0, - REJECTED_BAD_NAME, - REJECTED_EXISTS, - UNKNOWN_ERROR -}; - enum ePlayerFlags { BTARR_TESTING = 0, PLAYER_HAS_ENTERED_PET_RANCH = 1, diff --git a/dCommon/dEnums/dMessageIdentifiers.h b/dCommon/dEnums/dMessageIdentifiers.h index 129585a0..67ea3537 100644 --- a/dCommon/dEnums/dMessageIdentifiers.h +++ b/dCommon/dEnums/dMessageIdentifiers.h @@ -355,9 +355,27 @@ enum GAME_MSG : unsigned short { GAME_MSG_REGISTER_PET_DBID = 566, GAME_MSG_SHOW_ACTIVITY_COUNTDOWN = 568, GAME_MSG_START_ACTIVITY_TIME = 576, + GAME_MSG_GUILD_GET_SIZE = 580, + GAME_MSG_SET_CHAR_GUILD_INFO = 581, + GAME_MSG_GET_CHAR_GUILD_INFO = 582, + GAME_MSG_GET_CHAR_IS_IN_GUILD = 583, + GAME_MSG_RE_RENDER_NAME_BILLBOARD = 584, + GAME_MSG_IS_IN_LOCAL_CHAR_PROXIMTY = 585, + GAME_MSG_GUILD_SET_STATUS = 586, + GAME_MSG_GUILD_ADD_PLAYER = 587, + GAME_MSG_GUILD_REMOVE_PLAYER = 588, + GAME_MSG_GUILD_UPDATE_PLAYER_NAME = 589, + GAME_MSG_GUILD_SET_PLAYER_RANK = 590, + GAME_MSG_GUILD_SET_ONLINE_STATUS = 591, + GAME_MSG_GUILD_INVITE = 592, + GAME_MSG_REQUEST_GUILD_DATA = 593, + GAME_MSG_POPULATE_GUILD = 594, + GAME_MSG_GET_CACHED_GUILD_DATA = 595, + GAME_MSG_GUILD_RENDER_NAME = 596, GAME_MSG_ACTIVITY_PAUSE = 602, GAME_MSG_USE_NON_EQUIPMENT_ITEM = 603, GAME_MSG_USE_ITEM_RESULT = 607, + GAME_MSG_DISPLAY_GUILD_CREATE_BOX = 626, GAME_MSG_COMMAND_PET = 640, GAME_MSG_PET_RESPONSE = 641, GAME_MSG_REQUEST_ACTIVITY_SUMMARY_LEADERBOARD_DATA = 648, diff --git a/dCommon/dEnums/eGuildCreationResponse.h b/dCommon/dEnums/eGuildCreationResponse.h new file mode 100644 index 00000000..6badbf6a --- /dev/null +++ b/dCommon/dEnums/eGuildCreationResponse.h @@ -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__ diff --git a/dCommon/dEnums/eGuildRank.h b/dCommon/dEnums/eGuildRank.h new file mode 100644 index 00000000..3d9c9376 --- /dev/null +++ b/dCommon/dEnums/eGuildRank.h @@ -0,0 +1,14 @@ +#pragma once + +#ifndef __EGUILDRANK__H__ +#define __EGUILDRANK__H__ + + +enum eGuildRank { + FOUNDER = 1, + RANK2, + RANK3, + MEMBER +}; + +#endif //!__EGUILDRANK__H__ diff --git a/dGame/dComponents/CharacterComponent.cpp b/dGame/dComponents/CharacterComponent.cpp index 424be0ac..b987fb00 100644 --- a/dGame/dComponents/CharacterComponent.cpp +++ b/dGame/dComponents/CharacterComponent.cpp @@ -36,6 +36,9 @@ CharacterComponent::CharacterComponent(Entity* parent, Character* character) : C m_CurrentActivity = 0; m_CountryCode = 0; m_LastUpdateTimestamp = std::time(nullptr); + + m_GuildID = 0; + m_GuildName = u""; } bool CharacterComponent::LandingAnimDisabled(int zoneID) { @@ -143,6 +146,7 @@ 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); @@ -152,6 +156,7 @@ void CharacterComponent::Serialize(RakNet::BitStream* outBitStream, bool bIsInit outBitStream->Write(m_IsLEGOClubMember); outBitStream->Write(m_CountryCode); + m_DirtySocialInfo = false; } } @@ -161,7 +166,6 @@ bool CharacterComponent::GetPvpEnabled() const { void CharacterComponent::SetPvpEnabled(const bool value) { m_DirtyGMInfo = true; - m_PvpEnabled = value; } @@ -172,6 +176,12 @@ void CharacterComponent::SetGMLevel(int gmlevel) { m_GMLevel = gmlevel; } +void CharacterComponent::SetGuild(LWOOBJID& guildID, std::u16string guildName) { + m_GuildID = guildID; + m_GuildName = guildName; + m_DirtySocialInfo = true; +} + void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { tinyxml2::XMLElement* character = doc->FirstChildElement("obj")->FirstChildElement("char"); @@ -246,7 +256,7 @@ void CharacterComponent::LoadFromXml(tinyxml2::XMLDocument* doc) { m_EditorEnabled = false; //We're not currently in HF if we're loading in } - //Annoying guild bs: + // Guild Stuff: const tinyxml2::XMLAttribute* guildName = character->FindAttribute("gn"); if (guildName) { const char* gn = guildName->Value(); @@ -348,6 +358,11 @@ void CharacterComponent::UpdateXml(tinyxml2::XMLDocument* doc) { // End custom attributes // + if (m_GuildID != 0 || m_GuildName != u"") { + character->SetAttribute("gn", GeneralUtils::UTF16ToWTF8(m_GuildName).c_str()); + character->SetAttribute("gid", m_GuildID); + } + auto newUpdateTimestamp = std::time(nullptr); Game::logger->Log("TotalTimePlayed", "Time since last save: %d", newUpdateTimestamp - m_LastUpdateTimestamp); diff --git a/dGame/dComponents/CharacterComponent.h b/dGame/dComponents/CharacterComponent.h index 196dfa01..f0238a08 100644 --- a/dGame/dComponents/CharacterComponent.h +++ b/dGame/dComponents/CharacterComponent.h @@ -179,6 +179,26 @@ public: */ void SetGMLevel(int 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 guildID + * @param guildName + */ + void SetGuild(LWOOBJID& guildID, std::u16string guildName); + /** * Initializes the player statistics from the string stored in the XML * @param statisticsString the string to parse diff --git a/dGame/dGameMessages/GameMessages.cpp b/dGame/dGameMessages/GameMessages.cpp index 9753868d..3984f736 100644 --- a/dGame/dGameMessages/GameMessages.cpp +++ b/dGame/dGameMessages/GameMessages.cpp @@ -4541,6 +4541,26 @@ void GameMessages::SendShowActivityCountdown(LWOOBJID objectId, bool bPlayAdditi SEND_PACKET; } +void GameMessages::SendDisplayGuildCreateBox(const LWOOBJID& objectID, bool bShow, const SystemAddress& sysAddr) { + CBITSTREAM; + CMSGHEADER; + + bitStream.Write((unsigned short)GAME_MSG_DISPLAY_GUILD_CREATE_BOX); + bitStream.Write(objectID); + bitStream.Write((unsigned char)bShow); + + SEND_PACKET; +} + +void GameMessages::SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guildID, std::u16string& guildName) { + CBITSTREAM; + CMSGHEADER; + bitStream.Write(MSG_CLIENT_GUILD_CREATE_RESPONSE); + bitStream.Write(guildResponse); + bitStream.Write(guildID); + PacketUtils::WriteWString(bitStream, guildName, 33); + SEND_PACKET; +} //----------------------------------------------------------------------------------------------------------------------------------------------- //------------------------------------------------------------------- Handlers ------------------------------------------------------------------ @@ -6008,3 +6028,4 @@ void GameMessages::HandleUpdatePlayerStatistic(RakNet::BitStream* inStream, Enti characterComponent->UpdatePlayerStatistic((StatisticID)updateID, (uint64_t)std::max(updateValue, int64_t(0))); } } + diff --git a/dGame/dGameMessages/GameMessages.h b/dGame/dGameMessages/GameMessages.h index 8a1c2fe5..bacbc53d 100644 --- a/dGame/dGameMessages/GameMessages.h +++ b/dGame/dGameMessages/GameMessages.h @@ -14,6 +14,7 @@ #include "LeaderboardManager.h" #include "MovingPlatformComponent.h" #include "eAninmationFlags.h" +#include "eGuildCreationResponse.h" class NiQuaternion; class User; @@ -537,6 +538,10 @@ 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); + void SendGuildCreateResponse(const SystemAddress& sysAddr, eGuildCreationResponse guildResponse, LWOOBJID guildID, std::u16string& guildName); + //Handlers: void HandleToggleGhostReferenceOverride(RakNet::BitStream* inStream, Entity* entity, const SystemAddress& sysAddr); diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 39e835d2..c0ce7b99 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -31,7 +31,8 @@ #include "dConfig.h" #include "CharacterComponent.h" #include "Database.h" - +#include "PacketUtils.h" +#include "eGuildRank.h" void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* packet) { @@ -370,3 +371,93 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa user->SetLastChatMessageApproved(bAllClean); WorldPackets::SendChatModerationResponse(sysAddr, bAllClean, requestID, receiver, segments); } + +void ClientPackets::HandleGuildCreation(const SystemAddress& sysAddr, Packet* packet) { + std::string guildName = PacketUtils::ReadString(8, packet, true); + + auto user = UserManager::Instance()->GetUser(sysAddr); + 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()); + + // 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); + GameMessages::SendGuildCreateResponse(sysAddr, eGuildCreationResponse::REJECTED_EXISTS, LWOOBJID_EMPTY, usedName); + return; + } + + delete res; + delete stmt; + + // if (!Game::chatFilter->IsSentenceOkay(guildName, 1).empty()) { + // Game::logger->Log("ClientPackets", "But they used bad words!"); + // auto usedName = GeneralUtils::UTF8ToUTF16(guildName); + // GameMessages::SendGuildCreateResponse(sysAddr, eGuildCreationResponse::REJECTED_BAD_NAME, LWOOBJID_EMPTY, usedName); + // 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(); + if (!characterComp) return; + + if (characterComp->GetGuildID() != 0) { + ChatPackets::SendSystemMessage(sysAddr, u"You are already in a guild! Leave your current guild first."); + return; + } + + auto creation = (uint32_t)time(nullptr); + + // If not, insert our newly created guild: + auto insertGuild = Database::CreatePreppedStmt("INSERT INTO `guilds`(`name`, `owner`, `uscore`, `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; + + // Enable the guild on their character component: + auto get = Database::CreatePreppedStmt("SELECT id, name FROM guilds WHERE owner=?"); + 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); + GameMessages::SendGuildCreateResponse(sysAddr, eGuildCreationResponse::UNKNOWN_ERROR, LWOOBJID_EMPTY, usedName); + return; + } + + 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; + + //Send the guild create response: + GameMessages::SendGuildCreateResponse(sysAddr, eGuildCreationResponse::CREATED, guildId, name); +} + + diff --git a/dNet/ClientPackets.h b/dNet/ClientPackets.h index a36384e2..95201cb8 100644 --- a/dNet/ClientPackets.h +++ b/dNet/ClientPackets.h @@ -7,11 +7,15 @@ #define CLIENTPACKETS_H #include "RakNetTypes.h" +#include "eGuildCreationResponse.h" namespace ClientPackets { void HandleChatMessage(const SystemAddress& sysAddr, Packet* packet); void HandleClientPositionUpdate(const SystemAddress& sysAddr, Packet* packet); void HandleChatModerationRequest(const SystemAddress& sysAddr, Packet* packet); + + // Guild stuff + void HandleGuildCreation(const SystemAddress& sysAddr, Packet* packet); }; #endif // CLIENTPACKETS_H diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index d204d5c9..efd109fc 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -1239,6 +1239,11 @@ void HandlePacket(Packet* packet) { break; } + case MSG_WORLD_CLIENT_TMP_GUILD_CREATE: { + Game::logger->Log("WorldServer", "create a guild"); + ClientPackets::HandleGuildCreation(packet->systemAddress, packet); + } + default: Game::server->GetLogger()->Log("HandlePacket", "Unknown world packet received: %i", int(packet->data[3])); } diff --git a/migrations/dlu/8_guilds.sql b/migrations/dlu/8_guilds.sql new file mode 100644 index 00000000..69b30497 --- /dev/null +++ b/migrations/dlu/8_guilds.sql @@ -0,0 +1,15 @@ +CREATE TABLE IF NOT EXISTS guilds ( + id BIGINT NOT NULL PRIMARY KEY, + name VARCHAR(35) NOT NULL, + owner BIGINT NOT NULL REFERENCES charinfo(id), + motd TEXT, + uscore INT NOT NULL DEFAULT 0, + created BIGINT UNSIGNED NOT NULL DEFAULT 0 +); + +CREATE TABLE IF NOT EXISTS guild_members ( + guild_id BIGINT NOT NULL REFERENCES guilds(id), + character_id BIGINT NOT NULL REFERENCES charinfo(id), + rank INT NOT NULL DEFAULT 4, + joined BIGINT UNSIGNED NOT NULL DEFAULT 0 +);