From ca287db536f47a0a3d3eab5ddea122aede2e81c2 Mon Sep 17 00:00:00 2001 From: Ramen2X <64166386+Ramen2X@users.noreply.github.com> Date: Mon, 6 Dec 2021 20:06:12 -0500 Subject: [PATCH 01/13] make 0_initial.sql compatible with MySQL --- migrations/dlu/0_initial.sql | 50 ++++++++++++++++++++++++------------ 1 file changed, 33 insertions(+), 17 deletions(-) diff --git a/migrations/dlu/0_initial.sql b/migrations/dlu/0_initial.sql index 178bc229..16cb3e7e 100644 --- a/migrations/dlu/0_initial.sql +++ b/migrations/dlu/0_initial.sql @@ -1,4 +1,5 @@ -CREATE OR REPLACE TABLE accounts ( +DROP TABLE IF EXISTS accounts; +CREATE TABLE accounts ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name VARCHAR(35) NOT NULL UNIQUE, password TEXT NOT NULL, @@ -10,7 +11,8 @@ CREATE OR REPLACE TABLE accounts ( mute_expire BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -CREATE OR REPLACE TABLE charinfo ( +DROP TABLE IF EXISTS charinfo; +CREATE TABLE charinfo ( id BIGINT NOT NULL PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), name VARCHAR(35) NOT NULL, @@ -21,18 +23,21 @@ CREATE OR REPLACE TABLE charinfo ( permission_map BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -CREATE OR REPLACE TABLE charxml ( +DROP TABLE IF EXISTS charxml; +CREATE TABLE charxml ( id BIGINT NOT NULL PRIMARY KEY REFERENCES charinfo(id), xml_data LONGTEXT NOT NULL ); -CREATE OR REPLACE TABLE command_log ( +DROP TABLE IF EXISTS command_log; +CREATE TABLE command_log ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, character_id BIGINT NOT NULL REFERENCES charinfo(id), command VARCHAR(256) NOT NULL ); -CREATE OR REPLACE TABLE friends ( +DROP TABLE IF EXISTS friends; +CREATE TABLE friends ( player_id BIGINT NOT NULL REFERENCES charinfo(id), friend_id BIGINT NOT NULL REFERENCES charinfo(id), best_friend BOOLEAN NOT NULL DEFAULT FALSE, @@ -40,7 +45,8 @@ CREATE OR REPLACE TABLE friends ( PRIMARY KEY (player_id, friend_id) ); -CREATE OR REPLACE TABLE leaderboard ( +DROP TABLE IF EXISTS leaderboard; +CREATE TABLE leaderboard ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, game_id INT UNSIGNED NOT NULL DEFAULT 0, last_played TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP(), @@ -49,7 +55,8 @@ CREATE OR REPLACE TABLE leaderboard ( score BIGINT UNSIGNED NOT NULL DEFAULT 0 ); -CREATE OR REPLACE TABLE mail ( +DROP TABLE IF EXISTS mail; +CREATE TABLE mail ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, sender_id INT NOT NULL DEFAULT 0, sender_name VARCHAR(35) NOT NULL DEFAULT '', @@ -65,17 +72,20 @@ CREATE OR REPLACE TABLE mail ( was_read BOOLEAN NOT NULL DEFAULT FALSE ); -CREATE OR REPLACE TABLE object_id_tracker ( +DROP TABLE IF EXISTS object_id_tracker; +CREATE TABLE object_id_tracker ( last_object_id BIGINT UNSIGNED NOT NULL DEFAULT 0 PRIMARY KEY ); -CREATE OR REPLACE TABLE pet_names ( +DROP TABLE IF EXISTS pet_names; +CREATE TABLE pet_names ( id BIGINT NOT NULL AUTO_INCREMENT PRIMARY KEY, pet_name TEXT NOT NULL, approved INT UNSIGNED NOT NULL ); -CREATE OR REPLACE TABLE play_keys ( +DROP TABLE IF EXISTS play_keys; +CREATE TABLE play_keys ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, key_string CHAR(19) NOT NULL UNIQUE, key_uses INT NOT NULL DEFAULT 1, @@ -83,7 +93,8 @@ CREATE OR REPLACE TABLE play_keys ( active BOOLEAN NOT NULL DEFAULT TRUE ); -CREATE OR REPLACE TABLE properties ( +DROP TABLE IF EXISTS properties; +CREATE TABLE properties ( id BIGINT NOT NULL PRIMARY KEY, owner_id BIGINT NOT NULL REFERENCES charinfo(id), template_id INT UNSIGNED NOT NULL, @@ -101,17 +112,19 @@ CREATE OR REPLACE TABLE properties ( zone_id INT NOT NULL ); -CREATE OR REPLACE TABLE ugc ( +DROP TABLE IF EXISTS ugc; +CREATE TABLE ugc ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, account_id INT NOT NULL REFERENCES accounts(id), character_id BIGINT NOT NULL REFERENCES charinfo(id), is_optimized BOOLEAN NOT NULL DEFAULT FALSE, lxfml MEDIUMBLOB NOT NULL, bake_ao BOOLEAN NOT NULL DEFAULT FALSE, - filename TEXT NOT NULL DEFAULT '' + filename TEXT NOT NULL DEFAULT ('') ); -CREATE OR REPLACE TABLE properties_contents ( +DROP TABLE IF EXISTS properties_contents; +CREATE TABLE properties_contents ( id BIGINT NOT NULL PRIMARY KEY, property_id BIGINT NOT NULL REFERENCES properties(id), ugc_id INT NULL REFERENCES ugc(id), @@ -125,7 +138,8 @@ CREATE OR REPLACE TABLE properties_contents ( rw FLOAT NOT NULL ); -CREATE OR REPLACE TABLE activity_log ( +DROP TABLE IF EXISTS activity_log; +CREATE TABLE activity_log ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, character_id BIGINT NOT NULL REFERENCES charinfo(id), activity INT NOT NULL, @@ -133,7 +147,8 @@ CREATE OR REPLACE TABLE activity_log ( map_id INT NOT NULL ); -CREATE OR REPLACE TABLE bug_reports ( +DROP TABLE IF EXISTS bug_reports; +CREATE TABLE bug_reports ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, body TEXT NOT NULL, client_version TEXT NOT NULL, @@ -142,7 +157,8 @@ CREATE OR REPLACE TABLE bug_reports ( submitted TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP() ); -CREATE OR REPLACE TABLE servers ( +DROP TABLE IF EXISTS servers; +CREATE TABLE servers ( id INT NOT NULL AUTO_INCREMENT PRIMARY KEY, name TEXT NOT NULL, ip TEXT NOT NULL, From 393cce885bf62048c7722215fa17507979c78b56 Mon Sep 17 00:00:00 2001 From: Jett <55758076+Jettford@users.noreply.github.com> Date: Tue, 7 Dec 2021 11:12:29 +0000 Subject: [PATCH 02/13] Windows fixes - "Fixed" segfault - Fixed logger not actually logging time --- dCommon/dLogger.cpp | 4 ++-- dNet/WorldPackets.cpp | 21 ++++++++++----------- 2 files changed, 12 insertions(+), 13 deletions(-) diff --git a/dCommon/dLogger.cpp b/dCommon/dLogger.cpp index 4cd9655a..6ee0e7d2 100644 --- a/dCommon/dLogger.cpp +++ b/dCommon/dLogger.cpp @@ -92,8 +92,8 @@ void dLogger::Log(const char * className, const char * format, ...) { va_end(args); - if (m_logToConsole) std::cout << "[" << "timeStr" << "] [" << className << "]: " << message; - mFile << "[" << "timeStr" << "] [" << className << "]: " << message; + if (m_logToConsole) std::cout << "[" << timeStr << "] [" << className << "]: " << message; + mFile << "[" << timeStr << "] [" << className << "]: " << message; #else time_t t = time(NULL); struct tm * time = localtime(&t); diff --git a/dNet/WorldPackets.cpp b/dNet/WorldPackets.cpp index 67c20c03..399ab9e5 100644 --- a/dNet/WorldPackets.cpp +++ b/dNet/WorldPackets.cpp @@ -153,27 +153,26 @@ void WorldPackets::SendCreateCharacter(const SystemAddress& sysAddr, const LWOOB delete gmlevel; delete chatmode; delete name; - + +#ifdef _WIN32 + bitStream.Write(data.GetNumberOfBytesUsed() + 1); + bitStream.Write(0); + bitStream.Write((char*)data.GetData(), data.GetNumberOfBytesUsed()); +#else //Compress the data before sending: const int reservedSize = 5 * 1024 * 1024; uint8_t compressedData[reservedSize]; size_t size = ZCompression::Compress(data.GetData(), data.GetNumberOfBytesUsed(), compressedData, reservedSize); bitStream.Write(size + 9); //size of data + header bytes (8) - bitStream.Write(1); //compressed boolean, true + bitStream.Write(1); //compressed boolean, true bitStream.Write(data.GetNumberOfBytesUsed()); bitStream.Write(size); - + for (size_t i = 0; i < size; i++) bitStream.Write(compressedData[i]); - - /* - uint32_t dataSize = data.GetNumberOfBytesUsed(); - bitStream.Write(dataSize + 8); // The data size - bitStream.Write(static_cast(0)); // Data is not compressed - bitStream.Write(data); // Write the data - */ - +#endif + PacketUtils::SavePacket("chardata.bin", (const char *)bitStream.GetData(), static_cast(bitStream.GetNumberOfBytesUsed())); SEND_PACKET Game::logger->Log("WorldPackets", "Sent CreateCharacter for ID: %llu\n", objectID); From fe5814d5ba80dfb45cba5c3286ce460c05ebf91d Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 16:31:53 +0100 Subject: [PATCH 03/13] Nice Commit! :) --- dNet/ClientPackets.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index ef5b68ef..566120f6 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -64,6 +64,8 @@ void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* pack std::string playerName = user->GetLastUsedChar()->GetName(); bool isMythran = user->GetLastUsedChar()->GetGMLevel() > 0; + Game::logger->Log("IsUserMythran", "%s", isMythran?"Yes, they are mythran\n":"No, they are not mythran\n"); + Game::logger->Log("IsMessageApproved", "%s", user->GetLastChatMessageApproved()?"Yes, Their message is approved\n":"No, their message is not approved\n"); if (!user->GetLastChatMessageApproved() && !isMythran) return; From eab32c68f39acd587caff8aa7eabb922f4423f59 Mon Sep 17 00:00:00 2001 From: "Gie \"Max\" Vanommeslaeghe" Date: Tue, 7 Dec 2021 16:36:38 +0100 Subject: [PATCH 04/13] Update CONTRIBUTING.md --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ae10ae0f..a0030f49 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -52,7 +52,7 @@ This project has gone through multiple iterations of coding style. In the code y ### General -Use 4 spaces instead of the tab character. +**Never** use spaces instead of tabs. 1 Tab = 4 space character's width by default. Use typically trailing braces everywhere (if, else, functions, structures, typedefs, class definitions, etc.) From 0db954fa72a76b2640dfebcd7987ac3e2ebe0a46 Mon Sep 17 00:00:00 2001 From: Avery Date: Tue, 7 Dec 2021 12:15:57 -0500 Subject: [PATCH 05/13] Update README.md --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b082f59a..c8afb9f0 100644 --- a/README.md +++ b/README.md @@ -80,8 +80,8 @@ sudo ln -s /usr/local/mysql-connector-c++/lib64/libssl.1.1.dylib /path/to/build/ sudo ln -s /usr/local/mysql-connector-c++/lib64/libcrypto.1.1.dylib /path/to/build/folder/libcrypto.1.1.dylib ``` -### Windows builds (native) (CURRENTLY BROKEN ONCE COMPILED) -Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). +### Windows builds (native) +Ensure that you have either the [MSVC](https://visualstudio.microsoft.com/vs/) or the [Clang](https://github.com/llvm/llvm-project/releases/) (recommended) compiler installed. You will also need to install [CMake](https://cmake.org/download/). Currently on native Windows the server will only work in Release mode. **Build the repository** ```batch From bfcce196491f629c00c1a5afc5ea546ca1dff218 Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 19:58:24 +0100 Subject: [PATCH 06/13] Nice Commit! :) --- dChatFilter/dChatFilter.cpp | 8 +++++++- dNet/ClientPackets.cpp | 1 + dWorldServer/WorldServer.cpp | 2 +- 3 files changed, 9 insertions(+), 2 deletions(-) diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index 70bd2e45..f03e5583 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -110,16 +110,22 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { segment = std::regex_replace(segment, reg, ""); size_t hash = CalculateHash(segment); + Game::logger->Log("SEGMENT", "Word: %s Hash: %zu", segment.c_str(), hash); if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { + Game::logger->Log("SENTENCEOKAY", "SENTENCE IS UNNAPROVED"); return false; } - if (!IsInWordlist(hash)) { + bool a = IsInWordlist(hash); + Game::logger->Log("ISWORDLIST", "ISINWORDLIST: %s", a?"YES":"NO"); + if (!a) { + Game::logger->Log("SENTENCEOKAY", "SENTENCE IS NOT IN WORDLIST"); m_UserUnapprovedWordCache.push_back(hash); return false; } } + Game::logger->Log("SENTENCEOKAY", "SENTENCE IS OKAY TO SEND"); return true; } diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 566120f6..2da9629e 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -295,6 +295,7 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa std::unordered_map unacceptedItems; bool bAllClean = Game::chatFilter->IsSentenceOkay(message, user->GetLastUsedChar()->GetGMLevel()); + Game::logger->Log("BALLCLEAN", "%s", bAllClean?"Is Clean":"IS NOT CLEAN!!!"); if (!bAllClean) { unacceptedItems.insert(std::make_pair((char)0, (char)message.length())); } diff --git a/dWorldServer/WorldServer.cpp b/dWorldServer/WorldServer.cpp index 54633cff..5d155f29 100644 --- a/dWorldServer/WorldServer.cpp +++ b/dWorldServer/WorldServer.cpp @@ -833,7 +833,7 @@ void HandlePacket(Packet* packet) { } if (packet->data[1] != WORLD) return; - + switch (packet->data[3]) { case MSG_WORLD_CLIENT_VALIDATION: { std::string username = PacketUtils::ReadString(0x08, packet, true); From c48f4b08a2bb0f3e9e303a6488e01485616a9136 Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 20:19:47 +0100 Subject: [PATCH 07/13] Nice Commit! :) --- README.md | 9 +++++++++ dChatFilter/dChatFilter.cpp | 10 ++-------- dNet/ClientPackets.cpp | 1 - 3 files changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index b082f59a..2d17b127 100644 --- a/README.md +++ b/README.md @@ -162,6 +162,15 @@ certutil -hashfile SHA256 * Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `names`, and `maps` in your client `res` directory to the server `build/res` directory * Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes` +**Fix chatplus_en_us.txt** +* If the file has been made in windows it has to be converted to support unix. Inside of WSL run this command +* Move yourself into build/res using cd if you are not yet in there. +```bash +cd build/res +sudo apt install dos2unix +dos2unix -o chatplus_en_us.txt chatplus_en_us.txt +``` + **Setup locale** * In the `build` directory create a `locale` directory if it does not already exist * Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index f03e5583..f211243e 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -83,7 +83,7 @@ void dChatFilter::ReadWordlistDCF(const std::string& filepath) { } void dChatFilter::ExportWordlistToDCF(const std::string& filepath) { - std::ofstream file(filepath, std::ios::binary); + std::ofstream file(filepath, std::ios::binary | std::ios_base::out ); if (file) { BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion)); @@ -110,22 +110,16 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { segment = std::regex_replace(segment, reg, ""); size_t hash = CalculateHash(segment); - Game::logger->Log("SEGMENT", "Word: %s Hash: %zu", segment.c_str(), hash); if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { - Game::logger->Log("SENTENCEOKAY", "SENTENCE IS UNNAPROVED"); return false; } - bool a = IsInWordlist(hash); - Game::logger->Log("ISWORDLIST", "ISINWORDLIST: %s", a?"YES":"NO"); - if (!a) { - Game::logger->Log("SENTENCEOKAY", "SENTENCE IS NOT IN WORDLIST"); + if (!IsInWordlist(hash)) { m_UserUnapprovedWordCache.push_back(hash); return false; } } - Game::logger->Log("SENTENCEOKAY", "SENTENCE IS OKAY TO SEND"); return true; } diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 2da9629e..566120f6 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -295,7 +295,6 @@ void ClientPackets::HandleChatModerationRequest(const SystemAddress& sysAddr, Pa std::unordered_map unacceptedItems; bool bAllClean = Game::chatFilter->IsSentenceOkay(message, user->GetLastUsedChar()->GetGMLevel()); - Game::logger->Log("BALLCLEAN", "%s", bAllClean?"Is Clean":"IS NOT CLEAN!!!"); if (!bAllClean) { unacceptedItems.insert(std::make_pair((char)0, (char)message.length())); } From d2fe15679cc6db46453adb6112bdecbcc2364f2b Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 20:35:12 +0100 Subject: [PATCH 08/13] Nice Commit! :) --- README.md | 9 --------- dChatFilter/dChatFilter.cpp | 15 ++++++++++++++- dNet/ClientPackets.cpp | 2 -- 3 files changed, 14 insertions(+), 12 deletions(-) diff --git a/README.md b/README.md index 2d17b127..b082f59a 100644 --- a/README.md +++ b/README.md @@ -162,15 +162,6 @@ certutil -hashfile SHA256 * Copy over or create symlinks from `macros`, `BrickModels`, `chatplus_en_us.txt`, `names`, and `maps` in your client `res` directory to the server `build/res` directory * Unzip the navmeshes [here](./resources/navmeshes.zip) and place them in `build/res/maps/navmeshes` -**Fix chatplus_en_us.txt** -* If the file has been made in windows it has to be converted to support unix. Inside of WSL run this command -* Move yourself into build/res using cd if you are not yet in there. -```bash -cd build/res -sudo apt install dos2unix -dos2unix -o chatplus_en_us.txt chatplus_en_us.txt -``` - **Setup locale** * In the `build` directory create a `locale` directory if it does not already exist * Copy over or create symlinks from `locale.xml` in your client `locale` directory to the `build/locale` directory diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index f211243e..862045eb 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -105,9 +105,22 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { std::string segment; std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)"); + + + + #ifdef _win32 + while (std::getline(file, line)) { + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); //Remove nix line-endings + std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase + m_Words.push_back(CalculateHash(line)); + } + #else while (std::getline(sMessage, segment, ' ')) { + #endif + + std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase - segment = std::regex_replace(segment, reg, ""); + segment = std::regex_replace(segment, reg, ""); size_t hash = CalculateHash(segment); diff --git a/dNet/ClientPackets.cpp b/dNet/ClientPackets.cpp index 566120f6..ef5b68ef 100644 --- a/dNet/ClientPackets.cpp +++ b/dNet/ClientPackets.cpp @@ -64,8 +64,6 @@ void ClientPackets::HandleChatMessage(const SystemAddress& sysAddr, Packet* pack std::string playerName = user->GetLastUsedChar()->GetName(); bool isMythran = user->GetLastUsedChar()->GetGMLevel() > 0; - Game::logger->Log("IsUserMythran", "%s", isMythran?"Yes, they are mythran\n":"No, they are not mythran\n"); - Game::logger->Log("IsMessageApproved", "%s", user->GetLastChatMessageApproved()?"Yes, Their message is approved\n":"No, their message is not approved\n"); if (!user->GetLastChatMessageApproved() && !isMythran) return; From bcb0454916146dcddccf22680f813f52fa13c9db Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 20:38:05 +0100 Subject: [PATCH 09/13] fixed --- dChatFilter/dChatFilter.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index 862045eb..16748ede 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -113,7 +113,6 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); //Remove nix line-endings std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase m_Words.push_back(CalculateHash(line)); - } #else while (std::getline(sMessage, segment, ' ')) { #endif From eede772b53574afe09c084346a7cdfb3031517db Mon Sep 17 00:00:00 2001 From: TomNordesen Date: Tue, 7 Dec 2021 20:43:42 +0100 Subject: [PATCH 10/13] Nice Commit! :) --- dChatFilter/dChatFilter.cpp | 20 ++++---------------- 1 file changed, 4 insertions(+), 16 deletions(-) diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index 16748ede..65fb6ea0 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -102,26 +102,14 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { if (message.empty()) return true; std::stringstream sMessage(message); - std::string segment; + std::string line; std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)"); - - - - #ifdef _win32 - while (std::getline(file, line)) { + while (std::getline(sMessage, line)) { line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); //Remove nix line-endings std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase - m_Words.push_back(CalculateHash(line)); - #else - while (std::getline(sMessage, segment, ' ')) { - #endif - - - std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase - segment = std::regex_replace(segment, reg, ""); - - size_t hash = CalculateHash(segment); + line = std::regex_replace(line, reg, ""); + size_t hash = CalculateHash(line); if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { return false; From e967bf23980c2309eb6c3cb0a5c490330c221800 Mon Sep 17 00:00:00 2001 From: wincent Date: Tue, 7 Dec 2021 21:03:55 +0100 Subject: [PATCH 11/13] Updated solution --- dChatFilter/dChatFilter.cpp | 34 +++++++++++++++++++--------------- dChatFilter/dChatFilter.h | 4 ++-- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/dChatFilter/dChatFilter.cpp b/dChatFilter/dChatFilter.cpp index 65fb6ea0..7f8187a5 100644 --- a/dChatFilter/dChatFilter.cpp +++ b/dChatFilter/dChatFilter.cpp @@ -21,8 +21,9 @@ dChatFilter::dChatFilter(const std::string& filepath, bool dontGenerateDCF) { ReadWordlistPlaintext(filepath + ".txt"); if (!m_DontGenerateDCF) ExportWordlistToDCF(filepath + ".dcf"); } - else { - ReadWordlistDCF(filepath + ".dcf"); + else if (!ReadWordlistDCF(filepath + ".dcf")) { + ReadWordlistPlaintext(filepath + ".txt"); + ExportWordlistToDCF(filepath + ".dcf"); } //Read player names that are ok as well: @@ -46,24 +47,24 @@ void dChatFilter::ReadWordlistPlaintext(const std::string& filepath) { if (file) { std::string line; while (std::getline(file, line)) { + line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase m_Words.push_back(CalculateHash(line)); } } } -void dChatFilter::ReadWordlistDCF(const std::string& filepath) { +bool dChatFilter::ReadWordlistDCF(const std::string& filepath) { std::ifstream file(filepath, std::ios::binary); if (file) { fileHeader hdr; BinaryIO::BinaryRead(file, hdr); if (hdr.header != header) { - std::cout << "Wrong file header!" << std::endl; file.close(); - return; + return false; } - if (hdr.formatVersion <= formatVersion) { + if (hdr.formatVersion == formatVersion) { size_t wordsToRead = 0; BinaryIO::BinaryRead(file, wordsToRead); m_Words.reserve(wordsToRead); @@ -73,17 +74,20 @@ void dChatFilter::ReadWordlistDCF(const std::string& filepath) { BinaryIO::BinaryRead(file, word); m_Words.push_back(word); } + + return true; } else { - std::cout << "Newer file or corrupt" << std::endl; file.close(); - return; + return false; } } + + return false; } void dChatFilter::ExportWordlistToDCF(const std::string& filepath) { - std::ofstream file(filepath, std::ios::binary | std::ios_base::out ); + std::ofstream file(filepath, std::ios::binary | std::ios_base::out); if (file) { BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::header)); BinaryIO::BinaryWrite(file, uint32_t(dChatFilterDCF::formatVersion)); @@ -102,14 +106,14 @@ bool dChatFilter::IsSentenceOkay(const std::string& message, int gmLevel) { if (message.empty()) return true; std::stringstream sMessage(message); - std::string line; + std::string segment; std::regex reg("(!*|\\?*|\\;*|\\.*|\\,*)"); - while (std::getline(sMessage, line)) { - line.erase(std::remove(line.begin(), line.end(), '\r'), line.end()); //Remove nix line-endings - std::transform(line.begin(), line.end(), line.begin(), ::tolower); //Transform to lowercase - line = std::regex_replace(line, reg, ""); - size_t hash = CalculateHash(line); + while (std::getline(sMessage, segment, ' ')) { + std::transform(segment.begin(), segment.end(), segment.begin(), ::tolower); //Transform to lowercase + segment = std::regex_replace(segment, reg, ""); + + size_t hash = CalculateHash(segment); if (std::find(m_UserUnapprovedWordCache.begin(), m_UserUnapprovedWordCache.end(), hash) != m_UserUnapprovedWordCache.end()) { return false; diff --git a/dChatFilter/dChatFilter.h b/dChatFilter/dChatFilter.h index 644f78d7..e8ae67d0 100644 --- a/dChatFilter/dChatFilter.h +++ b/dChatFilter/dChatFilter.h @@ -6,7 +6,7 @@ namespace dChatFilterDCF { static const uint32_t header = ('D' + ('C' << 8) + ('F' << 16) + ('B' << 24)); - static const uint32_t formatVersion = 1; + static const uint32_t formatVersion = 2; struct fileHeader { uint32_t header; @@ -21,7 +21,7 @@ public: ~dChatFilter(); void ReadWordlistPlaintext(const std::string & filepath); - void ReadWordlistDCF(const std::string & filepath); + bool ReadWordlistDCF(const std::string & filepath); void ExportWordlistToDCF(const std::string & filepath); bool IsSentenceOkay(const std::string& message, int gmLevel); From 002f3b6c0e5aa50f4ec479934a1a94aaf5c0f1a7 Mon Sep 17 00:00:00 2001 From: red031000 Date: Tue, 7 Dec 2021 08:03:15 +0000 Subject: [PATCH 12/13] separate AgSpaceStuff and AgShipShake --- CMakeLists.txt | 2 +- dScripts/AgShipShake.cpp | 93 +++++++++++++++++++++++++++++++++++++++ dScripts/AgShipShake.h | 18 ++++++++ dScripts/AgSpaceStuff.cpp | 74 ------------------------------- dScripts/AgSpaceStuff.h | 10 ----- dScripts/CppScripts.cpp | 5 ++- 6 files changed, 116 insertions(+), 86 deletions(-) create mode 100644 dScripts/AgShipShake.cpp create mode 100644 dScripts/AgShipShake.h diff --git a/CMakeLists.txt b/CMakeLists.txt index cf7988c8..9789aff8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -95,7 +95,7 @@ if (__include_backtrace__ AND __compile_backtrace__) link_directories(${backtrace_SOURCE_DIR}/.libs/) include_directories(${backtrace_SOURCE_DIR}) -endif(__include_backtrace__) +endif(__include_backtrace__ AND __compile_backtrace__) endif() endif(UNIX) diff --git a/dScripts/AgShipShake.cpp b/dScripts/AgShipShake.cpp new file mode 100644 index 00000000..643bc695 --- /dev/null +++ b/dScripts/AgShipShake.cpp @@ -0,0 +1,93 @@ +#include "AgShipShake.h" +#include "GeneralUtils.h" +#include "GameMessages.h" +#include "dZoneManager.h" +#include "EntityManager.h" +#include "Game.h" + +void AgShipShake::OnStartup(Entity* self) { + EntityInfo info{}; + + info.pos = { -418, 585, -30 }; + info.lot = 33; + info.spawnerID = self->GetObjectID(); + + auto* ref = EntityManager::Instance()->CreateEntity(info); + + EntityManager::Instance()->ConstructEntity(ref); + + self->SetVar(u"ShakeObject", ref->GetObjectID()); + + self->AddTimer("ShipShakeIdle", 1.0f); + self->SetVar(u"RandomTime", 10); +} + +void AgShipShake::OnTimerDone(Entity* self, std::string timerName) { + if (timerName == "ShipShakeExplode") { + DoShake(self, true); + } + else if (timerName == "ShipShakeIdle") { + DoShake(self, false); + } +} + +void AgShipShake::DoShake(Entity* self, bool explodeIdle) { + if (!explodeIdle) { + auto* ref = EntityManager::Instance()->GetEntity(self->GetVar(u"ShakeObject")); + + const auto randomTime = self->GetVar(u"RandomTime"); + auto time = GeneralUtils::GenerateRandomNumber(0, randomTime + 1); + + if (time < randomTime / 2) { + time += randomTime / 2; + } + + self->AddTimer("ShipShakeIdle", static_cast(time)); + + if (ref) + GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f); + + auto* debrisObject = GetEntityInGroup(DebrisFX); + + if (debrisObject) + GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + + const auto randomFx = GeneralUtils::GenerateRandomNumber(0, 3); + + auto* shipFxObject = GetEntityInGroup(ShipFX); + if (shipFxObject) { + std::string effectType = "shipboom" + std::to_string(randomFx); + GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true); + } + + self->AddTimer("ShipShakeExplode", 5.0f); + + auto* shipFxObject2 = GetEntityInGroup(ShipFX2); + if (shipFxObject2) + GameMessages::SendPlayAnimation(shipFxObject2, u"explosion"); + } + else { + auto* shipFxObject = GetEntityInGroup(ShipFX); + auto* shipFxObject2 = GetEntityInGroup(ShipFX2); + + if (shipFxObject) + GameMessages::SendPlayAnimation(shipFxObject, u"idle"); + + if (shipFxObject2) + GameMessages::SendPlayAnimation(shipFxObject2, u"idle"); + } +} + +Entity* AgShipShake::GetEntityInGroup(const std::string& group) { + auto entities = EntityManager::Instance()->GetEntitiesInGroup(group); + Entity* en = nullptr; + + for (auto entity : entities) { + if (entity) { + en = entity; + break; + } + } + + return en; +} diff --git a/dScripts/AgShipShake.h b/dScripts/AgShipShake.h new file mode 100644 index 00000000..b1e1b557 --- /dev/null +++ b/dScripts/AgShipShake.h @@ -0,0 +1,18 @@ +#pragma once +#include "CppScripts.h" + +class AgShipShake : public CppScripts::Script { +public: + void OnStartup(Entity* self); + void OnTimerDone(Entity* self, std::string timerName); + void DoShake(Entity* self, bool explodeIdle); + + std::string DebrisFX = "DebrisFX"; + std::string ShipFX = "ShipFX"; + std::string ShipFX2 = "ShipFX2"; + std::u16string FXName = u"camshake-bridge"; + +private: + Entity* GetEntityInGroup(const std::string& group); +}; + diff --git a/dScripts/AgSpaceStuff.cpp b/dScripts/AgSpaceStuff.cpp index 2550f001..1e82237e 100644 --- a/dScripts/AgSpaceStuff.cpp +++ b/dScripts/AgSpaceStuff.cpp @@ -1,7 +1,6 @@ #include "AgSpaceStuff.h" #include "GeneralUtils.h" #include "GameMessages.h" -#include "dZoneManager.h" #include "EntityManager.h" #include "Game.h" @@ -17,11 +16,6 @@ void AgSpaceStuff::OnStartup(Entity* self) { auto* ref = EntityManager::Instance()->CreateEntity(info); EntityManager::Instance()->ConstructEntity(ref); - - self->SetVar(u"ShakeObject", ref->GetObjectID()); - - self->AddTimer("ShipShakeIdle", 1.0f); - self->SetVar(u"RandomTime", 10); } void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) { @@ -38,72 +32,4 @@ void AgSpaceStuff::OnTimerDone(Entity* self, std::string timerName) { GameMessages::SendPlayAnimation(self, u"path_0" + (GeneralUtils::to_u16string(pathType))); self->AddTimer("FloaterScale", randTime); } - else if (timerName == "ShipShakeExplode") { - DoShake(self, true); - } - else if (timerName == "ShipShakeIdle") { - DoShake(self, false); - } -} - -void AgSpaceStuff::DoShake(Entity* self, bool explodeIdle) { - - if (!explodeIdle) { - auto* ref = EntityManager::Instance()->GetEntity(self->GetVar(u"ShakeObject")); - - const auto randomTime = self->GetVar(u"RandomTime"); - auto time = GeneralUtils::GenerateRandomNumber(0, randomTime + 1); - - if (time < randomTime / 2) { - time += randomTime / 2; - } - - self->AddTimer("ShipShakeIdle", static_cast(time)); - - if (ref) - GameMessages::SendPlayEmbeddedEffectOnAllClientsNearObject(ref, FXName, ref->GetObjectID(), 500.0f); - - auto* debrisObject = GetEntityInGroup(DebrisFX); - - if (debrisObject) - GameMessages::SendPlayFXEffect(debrisObject, -1, u"DebrisFall", "Debris", LWOOBJID_EMPTY, 1.0f, 1.0f, true); - - const auto randomFx = GeneralUtils::GenerateRandomNumber(0, 3); - - auto* shipFxObject = GetEntityInGroup(ShipFX); - if (shipFxObject) { - std::string effectType = "shipboom" + std::to_string(randomFx); - GameMessages::SendPlayFXEffect(shipFxObject, 559, GeneralUtils::ASCIIToUTF16(effectType), "FX", LWOOBJID_EMPTY, 1.0f, 1.0f, true); - } - - self->AddTimer("ShipShakeExplode", 5.0f); - - auto* shipFxObject2 = GetEntityInGroup(ShipFX2); - if (shipFxObject2) - GameMessages::SendPlayAnimation(shipFxObject2, u"explosion"); - } - else { - auto* shipFxObject = GetEntityInGroup(ShipFX); - auto* shipFxObject2 = GetEntityInGroup(ShipFX2); - - if (shipFxObject) - GameMessages::SendPlayAnimation(shipFxObject, u"idle"); - - if (shipFxObject2) - GameMessages::SendPlayAnimation(shipFxObject2, u"idle"); - } -} - -Entity* AgSpaceStuff::GetEntityInGroup(const std::string& group) { - auto entities = EntityManager::Instance()->GetEntitiesInGroup(group); - Entity* en = nullptr; - - for (auto entity : entities) { - if (entity) { - en = entity; - break; - } - } - - return en; } diff --git a/dScripts/AgSpaceStuff.h b/dScripts/AgSpaceStuff.h index 8d816691..13b29f1c 100644 --- a/dScripts/AgSpaceStuff.h +++ b/dScripts/AgSpaceStuff.h @@ -5,14 +5,4 @@ class AgSpaceStuff : public CppScripts::Script { public: void OnStartup(Entity* self); void OnTimerDone(Entity* self, std::string timerName); - void DoShake(Entity* self, bool explodeIdle); - - std::string DebrisFX = "DebrisFX"; - std::string ShipFX = "ShipFX"; - std::string ShipFX2 = "ShipFX2"; - std::u16string FXName = u"camshake-bridge"; - -private: - Entity* GetEntityInGroup(const std::string& group); }; - diff --git a/dScripts/CppScripts.cpp b/dScripts/CppScripts.cpp index 99702805..a07d4f52 100644 --- a/dScripts/CppScripts.cpp +++ b/dScripts/CppScripts.cpp @@ -15,6 +15,7 @@ //VE / AG scripts: #include "AgShipPlayerDeathTrigger.h" #include "AgShipPlayerShockServer.h" +#include "AgShipShake.h" #include "AgSpaceStuff.h" #include "AgImagSmashable.h" #include "NpcNpSpacemanBob.h" @@ -290,7 +291,9 @@ CppScripts::Script* CppScripts::GetScript(Entity* parent, const std::string& scr script = new AgShipPlayerDeathTrigger(); else if (scriptName == "scripts\\ai\\NP\\L_NPC_NP_SPACEMAN_BOB.lua") script = new NpcNpSpacemanBob(); - else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua") // Broken, will (sometimes) display all animations at once on initial login + else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_SHAKE.lua") + script = new AgShipShake(); + else if (scriptName == "scripts\\ai\\AG\\L_AG_SPACE_STUFF.lua") script = new AgSpaceStuff(); else if (scriptName == "scripts\\ai\\AG\\L_AG_SHIP_PLAYER_SHOCK_SERVER.lua") script = new AgShipPlayerShockServer(); From 7bead89e39226d8e43bb3951377406a588e7cd09 Mon Sep 17 00:00:00 2001 From: red031000 Date: Tue, 7 Dec 2021 20:43:22 +0000 Subject: [PATCH 13/13] fix a bug with timer erasing --- dGame/Entity.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/dGame/Entity.cpp b/dGame/Entity.cpp index c98323a9..1d31eb8d 100644 --- a/dGame/Entity.cpp +++ b/dGame/Entity.cpp @@ -1222,13 +1222,19 @@ void Entity::UpdateXMLDoc(tinyxml2::XMLDocument* doc) { } void Entity::Update(const float deltaTime) { - for (int i = 0; i < m_Timers.size(); i++) { + int timerSize = m_Timers.size(); + for (int i = 0; i < timerSize; i++) { m_Timers[i]->Update(deltaTime); if (m_Timers[i]->GetTime() <= 0) { const auto timerName = m_Timers[i]->GetName(); - delete m_Timers[i]; - m_Timers.erase(m_Timers.begin() + i); + do { //sometimes, due to a race condition, m_Timers.erase doesn't actually erase, repeat until it does + if (m_Timers[i]->GetName() != timerName) { + break; + } + delete m_Timers[i]; + m_Timers.erase(m_Timers.begin() + i); + } while (m_Timers.size() == timerSize); //timer size indicates whether it's actually successfully been erased or not for (CppScripts::Script* script : CppScripts::GetEntityScripts(this)) { script->OnTimerDone(this, timerName);