diff --git a/Source/Client/Mode/CGameMode.h b/Source/Client/Mode/CGameMode.h index 2c6fbd7a..0e9b2f37 100644 --- a/Source/Client/Mode/CGameMode.h +++ b/Source/Client/Mode/CGameMode.h @@ -360,6 +360,7 @@ public: void ReceiveGameOptions(int count, const GameOptionEntry* entries); void ReceiveActorClanName(const unsigned char* packet); void ReceiveClanMemberCount(const unsigned char* packet); + void ReceiveClanChat(const unsigned char* packet); void ReceiveGuildEmblemVersion(std::uint32_t aid, int guildId, int emblemVersion); int RejectRequest(int, int, int, int, int); void EnsureWindow259(const unsigned char* packet); diff --git a/Source/Client/Mode/GameModeHandlers.cpp b/Source/Client/Mode/GameModeHandlers.cpp index 404464f3..384a3fff 100644 --- a/Source/Client/Mode/GameModeHandlers.cpp +++ b/Source/Client/Mode/GameModeHandlers.cpp @@ -16,6 +16,7 @@ #include "Contents/Effects/Effect.h" #include "Contents/Effects/EffectLists.h" #include "Contents/Effects/MonsterSkillEffects.h" +#include "Contents/ForbiddenWords.h" #include "Contents/Ground/TerrainHeight.h" #include "Contents/GuildMgr.h" #include "Contents/Items/ItemDescription.h" @@ -2882,3 +2883,26 @@ void CGameMode::ReceivePendingItem1718List(const unsigned char* packet) { window->SendMsg(nullptr, 0x24, 1, 0, 0, 0); window->SendMsg(nullptr, 0x17, 0, 0, 0, 0); } + +// OFFSET: 0x00D66860 +// FUNCTION: fn_22016 +void CGameMode::ReceiveClanChat(const unsigned char* packet) { + const int messageLength = *reinterpret_cast(packet + 2) - 28; + + if (messageLength < 0 || messageLength > 220) { + return; + } + + char message[220]; + std::memset(message, 0, sizeof(message)); + strcpy_s(message, sizeof(message), reinterpret_cast(packet + 28)); + + if (g_forbiddenWords.Contains(message) == true) { + std::string masked; + g_forbiddenWords.Mask(message, &masked); + } + + if (!g_serviceOptions.Get(148)) { + g_windowMgr.SendNotice(1, reinterpret_cast(message), 0xB4B4FF, 21, 0, 0); + } +} diff --git a/Source/Contents/ForbiddenWords.cpp b/Source/Contents/ForbiddenWords.cpp index 3f4cef75..fc7ebd6c 100644 --- a/Source/Contents/ForbiddenWords.cpp +++ b/Source/Contents/ForbiddenWords.cpp @@ -1,5 +1,6 @@ #include "Contents/ForbiddenWords.h" #include "File/CommonObject.h" +#include "Network/TextEncoding.h" #include "Utility/StackAlloc.h" #include @@ -10,6 +11,9 @@ #include #include +// GLOBAL: gl_24641 +ForbiddenWords g_forbiddenWords; + namespace { // OFFSET: 0x00AE7060 // FUNCTION: fn_18065 @@ -30,7 +34,8 @@ bool ForbiddenWords::Load(const char* name, CCommonObject& storage, ResourceByte std::vector tokens; const bool loaded = storage.LoadTokens(tokens, name, 1, file); - for (char* token : tokens) { + for (std::vector::iterator it = tokens.begin(); it != tokens.end(); ++it) { + char* token = *it; char* first = token; while (*first == ' ' || *first == '\t') { @@ -38,7 +43,7 @@ bool ForbiddenWords::Load(const char* name, CCommonObject& storage, ResourceByte } if (*first != '\0') { - this->words.push_back(Lowercase(token, this->codePage)); + this->words.push_back(Lowercase(token, static_cast(g_textCodePage))); } } @@ -56,7 +61,7 @@ bool ForbiddenWords::Allows(const char* text) const { } std::strncpy(storage, text, size); - const char* current = Lowercase(storage, this->codePage); + const char* current = Lowercase(storage, static_cast(g_textCodePage)); const char* end = current + std::strlen(current); while (current < end) { @@ -67,7 +72,7 @@ bool ForbiddenWords::Allows(const char* text) const { const auto skip = reinterpret_cast(close) + 8 - reinterpret_cast(open); for (std::ptrdiff_t index = 0; index < skip; ++index) { - current = CharNextExA(this->codePage, current, 0); + current = CharNextExA(static_cast(g_textCodePage), current, 0); } } @@ -78,7 +83,7 @@ bool ForbiddenWords::Allows(const char* text) const { } } - current = CharNextExA(this->codePage, current, 0); + current = CharNextExA(static_cast(g_textCodePage), current, 0); } _freea(storage); @@ -117,7 +122,7 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { } strcpy_s(scanBuffer, sizeof(scanBuffer), text); - char* current = Lowercase(scanBuffer, this->codePage); + char* current = Lowercase(scanBuffer, static_cast(g_textCodePage)); while (std::strlen(current) != 0) { const auto* open = _mbsstr(reinterpret_cast(current), reinterpret_cast("")); @@ -129,7 +134,7 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { char* next = current; for (std::ptrdiff_t index = 0; index < skip; ++index) { - next = CharNextExA(this->codePage, current, 0); + next = CharNextExA(static_cast(g_textCodePage), current, 0); } current = next; @@ -143,11 +148,11 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { } std::strcpy(matchedWord, word); - Lowercase(matchedWord, this->codePage); + Lowercase(matchedWord, static_cast(g_textCodePage)); advance = 0; const char* end = matchedWord + std::strlen(matchedWord); - for (const char* character = matchedWord; character < end; character = CharNextExA(this->codePage, character, 0)) { + for (const char* character = matchedWord; character < end; character = CharNextExA(static_cast(g_textCodePage), character, 0)) { ++advance; } @@ -172,7 +177,7 @@ void ForbiddenWords::Mask(char* text, std::string* value) const { } for (int index = 0; index < advance; ++index) { - current = CharNextExA(this->codePage, current, 0); + current = CharNextExA(static_cast(g_textCodePage), current, 0); } } diff --git a/Source/Contents/ForbiddenWords.h b/Source/Contents/ForbiddenWords.h index f75b7e5d..386f7eb5 100644 --- a/Source/Contents/ForbiddenWords.h +++ b/Source/Contents/ForbiddenWords.h @@ -8,8 +8,7 @@ class CCommonObject; class ResourceBytes; struct ForbiddenWords { - std::vector& words; - const unsigned short& codePage; + /* 0000 */ std::vector words; bool Load(const char* name, CCommonObject& storage, ResourceBytes& file); bool Allows(const char* text) const; @@ -17,4 +16,8 @@ struct ForbiddenWords { void Mask(char* text, std::string* value = nullptr) const; }; +static_assert(sizeof(ForbiddenWords) == 0xC); + +extern ForbiddenWords g_forbiddenWords; + #endif