diff --git a/.gitattributes b/.gitattributes index 1202f6415..1d788f033 100644 --- a/.gitattributes +++ b/.gitattributes @@ -20,3 +20,4 @@ *.css text *.js text *.types text +*.pdf binary diff --git a/CMakeLists.txt b/CMakeLists.txt index a831e2126..8bbbeda68 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -20,7 +20,7 @@ endif() project(EQEmu VERSION 24.10.3 - LANGUAGES CXX + LANGUAGES CXX ) set_property(GLOBAL PROPERTY USE_FOLDERS ON) @@ -42,10 +42,10 @@ option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON) if(MSVC) add_compile_options(/bigobj) - add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX CRASH_LOGGING _HAS_AUTO_PTR_ETC) + add_compile_definitions(_CRT_SECURE_NO_WARNINGS NOMINMAX WIN32_LEAN_AND_MEAN CRASH_LOGGING _HAS_AUTO_PTR_ETC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /MP") - option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." ON) + option(EQEMU_DISABLE_MSVC_WARNINGS "Disable MSVC compile warnings." OFF) if(EQEMU_DISABLE_MSVC_WARNINGS) add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os) endif() diff --git a/common/CMakeLists.txt b/common/CMakeLists.txt index 3f8b29934..e9f43cec8 100644 --- a/common/CMakeLists.txt +++ b/common/CMakeLists.txt @@ -7,20 +7,20 @@ set(common_sources classes.cpp cli/eqemu_command_handler.cpp compression.cpp - condition.cpp content/world_content_service.cpp crash.cpp crc16.cpp crc32.cpp data_bucket.cpp + data_bucket.cpp + database_instances.cpp database.cpp database/database_dump_service.cpp database/database_update.cpp - database_instances.cpp dbcore.cpp deity.cpp - discord/discord.cpp discord/discord_manager.cpp + discord/discord.cpp dynamic_zone_base.cpp dynamic_zone_lockout.cpp emu_constants.cpp @@ -31,13 +31,16 @@ set(common_sources eq_packet.cpp eq_stream_ident.cpp eq_stream_proxy.cpp - eqdb.cpp eqdb_res.cpp + eqdb.cpp eqemu_config.cpp eqemu_exception.cpp eqemu_logsys.cpp eqtime.cpp event_sub.cpp + event/event_loop.cpp + event/task_scheduler.cpp + event/timer.cpp events/player_event_discord_formatter.cpp events/player_event_logs.cpp evolving_items.cpp @@ -51,62 +54,56 @@ set(common_sources ipc_mutex.cpp item_data.cpp item_instance.cpp - json/json.hpp - json/jsoncpp.cpp json_config.cpp + json/jsoncpp.cpp light_source.cpp md5.cpp - memory/ksm.hpp memory_buffer.cpp memory_mapped_file.cpp - misc.cpp + memory/ksm.cpp misc_functions.cpp - mutex.cpp + misc.cpp mysql_request_result.cpp mysql_request_row.cpp mysql_stmt.cpp - net/console_server.cpp net/console_server_connection.cpp + net/console_server.cpp net/crc32.cpp + net/dns.cpp net/eqstream.cpp net/packet.cpp net/reliable_stream_connection.cpp net/servertalk_client_connection.cpp net/servertalk_legacy_client_connection.cpp - net/servertalk_server.cpp net/servertalk_server_connection.cpp + net/servertalk_server.cpp net/tcp_connection.cpp net/tcp_server.cpp - net/websocket_server.cpp net/websocket_server_connection.cpp + net/websocket_server.cpp opcode_map.cpp opcodemgr.cpp - packet_dump.cpp packet_dump_file.cpp + packet_dump.cpp packet_functions.cpp patches/patches.cpp - patches/rof.cpp - patches/rof2.cpp - patches/rof2_limits.cpp patches/rof_limits.cpp - patches/sod.cpp + patches/rof.cpp + patches/rof2_limits.cpp + patches/rof2.cpp patches/sod_limits.cpp - patches/sof.cpp + patches/sod.cpp patches/sof_limits.cpp - patches/titanium.cpp + patches/sof.cpp patches/titanium_limits.cpp - patches/uf.cpp + patches/titanium.cpp patches/uf_limits.cpp + patches/uf.cpp + path_manager.cpp path_manager.cpp - perl_eqdb.cpp perl_eqdb_res.cpp + perl_eqdb.cpp platform.cpp - platform/inet.h - platform/platform.h - platform/posix/include_inet.h - platform/posix/include_pthreads.h - platform/win/include_windows.h - platform/win/include_winsock2.h proc_launcher.cpp process.cpp process/process.cpp @@ -123,12 +120,12 @@ set(common_sources shareddb.cpp skill_caps.cpp skills.cpp - spdat.cpp spdat_bot.cpp + spdat.cpp StackWalker/StackWalker.cpp - strings.cpp strings_legacy.cpp strings_misc.cpp + strings.cpp struct_strategy.cpp textures.cpp timer.cpp @@ -538,35 +535,32 @@ set(repositories ) set(common_headers - StackWalker/StackWalker.h additive_lagged_fibonacci_engine.h base_packet.h bazaar.h bodytypes.h + classes.h cli/argh.h cli/eqemu_command_handler.h cli/terminal_color.hpp - classes.h compression.h - condition.h content/world_content_service.h crash.h crc16.h crc32.h cron/croncpp.h - data_bucket.cpp data_verification.h + database_schema.h database.h database/database_dump_service.h - database/database_update.h - database/database_update_manifest.h database/database_update_manifest_bots.h database/database_update_manifest_custom.h - database_schema.h + database/database_update_manifest.h + database/database_update.h dbcore.h deity.h - discord/discord.h discord/discord_manager.h + discord/discord.h dynamic_zone_base.h dynamic_zone_lockout.h emu_constants.h @@ -576,24 +570,24 @@ set(common_headers emu_versions.h eq_constants.h eq_limits.h - eq_packet.h eq_packet_structs.h + eq_packet.h eq_stream_ident.h eq_stream_intf.h eq_stream_locator.h eq_stream_proxy.h - eqdb.h eqdb_res.h - eqemu_config.h + eqdb.h eqemu_config_elements.h + eqemu_config.h eqemu_exception.h - eqemu_logsys.h eqemu_logsys_log_aliases.h + eqemu_logsys.h eqtime.h + event_sub.h event/event_loop.h event/task.h event/timer.h - event_sub.h events/player_event_discord_formatter.h events/player_event_logs.h events/player_events.h @@ -614,10 +608,11 @@ set(common_headers ipc_mutex.h item_data.h item_instance.h + json_config.h + json/json_archive_single_line.h json/json-forwards.h json/json.h - json/json_archive_single_line.h - json_config.h + json/json.hpp light_source.h linked_list.h loot.h @@ -625,14 +620,14 @@ set(common_headers md5.h memory_buffer.h memory_mapped_file.h - misc.h + memory/ksm.h misc_functions.h - mutex.h + misc.h mysql_request_result.h mysql_request_row.h mysql_stmt.h - net/console_server.h net/console_server_connection.h + net/console_server.h net/crc32.h net/dns.h net/endian.h @@ -644,49 +639,54 @@ set(common_headers net/servertalk_client_connection.h net/servertalk_common.h net/servertalk_legacy_client_connection.h - net/servertalk_server.h net/servertalk_server_connection.h - net/tcp_connection.h + net/servertalk_server.h net/tcp_connection_pooling.h + net/tcp_connection.h net/tcp_server.h - net/websocket_server.h net/websocket_server_connection.h + net/websocket_server.h op_codes.h opcode_dispatch.h opcodemgr.h - packet_dump.h packet_dump_file.h + packet_dump.h packet_functions.h patches/patches.h - patches/rof.h - patches/rof2.h - patches/rof2_limits.h - patches/rof2_ops.h - patches/rof2_structs.h patches/rof_limits.h patches/rof_ops.h patches/rof_structs.h - patches/sod.h + patches/rof.h + patches/rof2_limits.h + patches/rof2_ops.h + patches/rof2_structs.h + patches/rof2.h patches/sod_limits.h patches/sod_ops.h patches/sod_structs.h - patches/sof.h + patches/sod.h patches/sof_limits.h patches/sof_ops.h patches/sof_structs.h + patches/sof.h patches/ss_declare.h patches/ss_define.h patches/ss_register.h - patches/titanium.h patches/titanium_limits.h patches/titanium_ops.h patches/titanium_structs.h - patches/uf.h + patches/titanium.h patches/uf_limits.h patches/uf_ops.h patches/uf_structs.h - path_manager.cpp + patches/uf.h platform.h + platform/inet.h + platform/platform.h + platform/posix/include_inet.h + platform/posix/include_pthreads.h + platform/win/include_windows.h + platform/win/include_winsock2.h proc_launcher.h process.h process/process.h @@ -713,6 +713,7 @@ set(common_headers skills.h spdat.h stacktrace/backward.hpp + StackWalker/StackWalker.h strings.h struct_strategy.h tasks.h @@ -729,25 +730,9 @@ set(common_headers zone_store.h ) -# Source Groups (Regex based for automatic subdirectory handling) -source_group("CLI" REGULAR_EXPRESSION "^cli/") -source_group("Content" REGULAR_EXPRESSION "^content/") -source_group("Cron" REGULAR_EXPRESSION "^cron/") -source_group("Database" REGULAR_EXPRESSION "^database/") -source_group("Discord" REGULAR_EXPRESSION "^discord/") -source_group("Event" REGULAR_EXPRESSION "^event/") -source_group("Events" REGULAR_EXPRESSION "^events/") -source_group("Http" REGULAR_EXPRESSION "^http/") -source_group("Json" REGULAR_EXPRESSION "^json/") -source_group("Memory" REGULAR_EXPRESSION "^memory/") -source_group("Net" REGULAR_EXPRESSION "^net/") -source_group("Patches" REGULAR_EXPRESSION "^patches/") -source_group("Process" REGULAR_EXPRESSION "^process/") -source_group("Repositories" REGULAR_EXPRESSION "^repositories/") -source_group("StackWalker" REGULAR_EXPRESSION "^StackWalker/") -source_group("Stacktrace" REGULAR_EXPRESSION "^stacktrace/") -source_group("Termcolor" REGULAR_EXPRESSION "^termcolor/") -source_group("Util" REGULAR_EXPRESSION "^util/") +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Header Files" FILES ${common_headers}) +source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/repositories" PREFIX "Repositories" FILES ${repositories}) option(EQEMU_ADD_PROFILER "Link with Google perftools profiler" OFF) #PRNG options diff --git a/common/StackWalker/StackWalker.cpp b/common/StackWalker/StackWalker.cpp index 5360a3efa..befbfac62 100644 --- a/common/StackWalker/StackWalker.cpp +++ b/common/StackWalker/StackWalker.cpp @@ -359,7 +359,7 @@ public: BOOL Publics; // contains public symbols }; */ -typedef struct IMAGEHLP_MODULE64_V2 { +struct IMAGEHLP_MODULE64_V2 { DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD64 BaseOfImage; // base load address of module DWORD ImageSize; // virtual size of the loaded module diff --git a/common/StackWalker/StackWalker.h b/common/StackWalker/StackWalker.h index a53c67328..d5f04e053 100644 --- a/common/StackWalker/StackWalker.h +++ b/common/StackWalker/StackWalker.h @@ -134,7 +134,7 @@ protected: CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; } CallstackEntry; - typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; + enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion); diff --git a/common/base_packet.cpp b/common/base_packet.cpp index b9f60f6a7..048bceb9c 100644 --- a/common/base_packet.cpp +++ b/common/base_packet.cpp @@ -19,44 +19,34 @@ #include "common/misc.h" #include "common/packet_dump.h" -BasePacket::BasePacket(const unsigned char *buf, uint32 len) +BasePacket::BasePacket(const unsigned char* buf, size_t len) { - pBuffer=nullptr; - size=0; - _wpos = 0; - _rpos = 0; - timestamp.tv_sec = 0; - if (len>0) { - size=len; - pBuffer= new unsigned char[len]; + if (len > 0) { + size = static_cast(len); + pBuffer = new unsigned char[len]; if (buf) { - memcpy(pBuffer,buf,len); - } else { - memset(pBuffer,0,len); + memcpy(pBuffer, buf, len); + } + else { + memset(pBuffer, 0, len); } } } -BasePacket::BasePacket(SerializeBuffer &buf) +BasePacket::BasePacket(SerializeBuffer&& buf) + : pBuffer(std::exchange(buf.m_buffer, nullptr)) { - pBuffer = buf.m_buffer; - buf.m_buffer = nullptr; - size = buf.m_pos; - buf.m_pos = 0; + // We are essentially taking ownership of this serialize buffer. + size = static_cast(std::exchange(buf.m_pos, 0)); buf.m_capacity = 0; - _wpos = 0; - _rpos = 0; - timestamp.tv_sec = 0; } BasePacket::~BasePacket() { - if (pBuffer) - delete[] pBuffer; - pBuffer=nullptr; + delete[] pBuffer; + pBuffer = nullptr; } - void BasePacket::build_raw_header_dump(char *buffer, uint16 seq) const { if (timestamp.tv_sec) { diff --git a/common/base_packet.h b/common/base_packet.h index 607e04576..b3ea8430e 100644 --- a/common/base_packet.h +++ b/common/base_packet.h @@ -23,14 +23,26 @@ #include -class BasePacket { +class BasePacket +{ +protected: + BasePacket() = default; + BasePacket(const unsigned char* buf, size_t len); + BasePacket(SerializeBuffer&& buf); + + virtual ~BasePacket(); + public: - unsigned char *pBuffer; - uint32 size, _wpos, _rpos; - uint32 src_ip,dst_ip; - uint16 src_port,dst_port; - uint32 priority; - timeval timestamp; + unsigned char* pBuffer = nullptr; + uint32 size = 0; + uint32 _wpos = 0; + uint32 _rpos = 0; + uint32 src_ip = 0; + uint32 dst_ip = 0; + uint16 src_port = 0; + uint16 dst_port = 0; + uint32 priority = 0; + timeval timestamp{}; virtual void build_raw_header_dump(char *buffer, uint16 seq=0xffff) const; virtual void build_header_dump(char *buffer) const; @@ -40,11 +52,11 @@ public: void setSrcInfo(uint32 sip, uint16 sport) { src_ip=sip; src_port=sport; } void setDstInfo(uint32 dip, uint16 dport) { dst_ip=dip; dst_port=dport; } - void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec=ts_sec; timestamp.tv_usec=ts_usec; } + void setTimeInfo(uint32 ts_sec, uint32 ts_usec) { timestamp.tv_sec = ts_sec; timestamp.tv_usec = ts_usec; } void copyInfo(const BasePacket *p) { src_ip=p->src_ip; src_port=p->src_port; dst_ip=p->dst_ip; dst_port=p->dst_port; timestamp.tv_sec=p->timestamp.tv_sec; timestamp.tv_usec=p->timestamp.tv_usec; } inline bool operator<(const BasePacket &rhs) { - return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec==rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec)); + return (timestamp.tv_sec < rhs.timestamp.tv_sec || (timestamp.tv_sec == rhs.timestamp.tv_sec && timestamp.tv_usec < rhs.timestamp.tv_usec)); } void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); } @@ -73,12 +85,6 @@ public: uint32 GetReadPosition() { return _rpos; } void SetWritePosition(uint32 Newwpos) { _wpos = Newwpos; } void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } - -protected: - virtual ~BasePacket(); - BasePacket() { pBuffer=nullptr; size=0; _wpos = 0; _rpos = 0; } - BasePacket(const unsigned char *buf, const uint32 len); - BasePacket(SerializeBuffer &buf); }; extern void DumpPacketHex(const BasePacket* app); diff --git a/common/cli/eqemu_command_handler.cpp b/common/cli/eqemu_command_handler.cpp index 2f150b621..59dec2b2d 100644 --- a/common/cli/eqemu_command_handler.cpp +++ b/common/cli/eqemu_command_handler.cpp @@ -23,12 +23,9 @@ namespace EQEmuCommand { - std::map function_map; + using CommandFunction = void(*)(int argc, char** argv, argh::parser& cmd, std::string& description); + + std::map function_map; /** * @param cmd diff --git a/common/cli/terminal_color.hpp b/common/cli/terminal_color.hpp index 90bc57071..e9ec96fa6 100644 --- a/common/cli/terminal_color.hpp +++ b/common/cli/terminal_color.hpp @@ -51,7 +51,7 @@ # include #elif defined(TERMCOLOR_OS_WINDOWS) # include -# include +# include "common/platform/win/include_windows.h" #endif diff --git a/common/condition.cpp b/common/condition.cpp deleted file mode 100644 index 657bc610d..000000000 --- a/common/condition.cpp +++ /dev/null @@ -1,146 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "condition.h" - -#ifdef _WINDOWS - - Condition::Condition() - { - m_events[SignalEvent] = CreateEvent (nullptr, // security - FALSE, // is auto-reset event? - FALSE, // is signaled initially? - nullptr); // name - m_events[BroadcastEvent] = CreateEvent (nullptr, // security - TRUE, // is auto-reset event? - FALSE, // is signaled initially? - nullptr); // name - m_waiters = 0; - InitializeCriticalSection(&CSMutex); - } - - Condition::~Condition() - { - DeleteCriticalSection(&CSMutex); - CloseHandle(m_events[SignalEvent]); - CloseHandle(m_events[BroadcastEvent]); - } - - void Condition::Signal() - { - EnterCriticalSection(&CSMutex); - if(m_waiters > 0) - SetEvent(m_events[SignalEvent]); - LeaveCriticalSection(&CSMutex); - } - - void Condition::SignalAll() - { - EnterCriticalSection(&CSMutex); - if(m_waiters > 0) - SetEvent(m_events[BroadcastEvent]); - LeaveCriticalSection(&CSMutex); - } - - void Condition::Wait() - { - EnterCriticalSection(&CSMutex); - - m_waiters++; - - - LeaveCriticalSection(&CSMutex); - int result = WaitForMultipleObjects (_eventCount, m_events, FALSE, INFINITE); - EnterCriticalSection(&CSMutex); - - m_waiters--; - - //see if we are the last person waiting on the condition, and there was a broadcast - //if so, we need to reset the broadcast event. - if(m_waiters == 0 && result == (WAIT_OBJECT_0+BroadcastEvent)) - ResetEvent(m_events[BroadcastEvent]); - - LeaveCriticalSection(&CSMutex); - } - -#else - #include - #include - #include - - Condition::Condition() - { - pthread_cond_init(&cond,nullptr); - pthread_mutex_init(&mutex,nullptr); - } - - void Condition::Signal() - { - pthread_mutex_lock(&mutex); - pthread_cond_signal(&cond); - pthread_mutex_unlock(&mutex); - } - - void Condition::SignalAll() - { - pthread_mutex_lock(&mutex); - pthread_cond_broadcast(&cond); - pthread_mutex_unlock(&mutex); - } - - void Condition::Wait() - { - pthread_mutex_lock(&mutex); - pthread_cond_wait(&cond,&mutex); - pthread_mutex_unlock(&mutex); - } - - /* - I commented this specifically because I think it might be very - difficult to write a windows counterpart to it, so I would like - to discourage its use until we can confirm that it can be reasonably - implemented on windows. - - bool Condition::TimedWait(unsigned long usec) - { - struct timeval now; - struct timespec timeout; - int retcode=0; - pthread_mutex_lock(&mutex); - gettimeofday(&now,nullptr); - now.tv_usec+=usec; - timeout.tv_sec = now.tv_sec + (now.tv_usec/1000000); - timeout.tv_nsec = (now.tv_usec%1000000) *1000; - //cout << "now=" << now.tv_sec << "."<. -*/ -#pragma once - -#include "common/mutex.h" -#include "common/platform/posix/include_pthreads.h" -#include "common/platform/win/include_windows.h" - -//Sombody, someday needs to figure out how to implement a condition -//system on windows... - - -class Condition { - private: -#ifdef WIN32 - enum { - SignalEvent = 0, - BroadcastEvent, - _eventCount - }; - - HANDLE m_events[_eventCount]; - uint32 m_waiters; - CRITICAL_SECTION CSMutex; -#else - pthread_cond_t cond; - pthread_mutex_t mutex; -#endif - public: - Condition(); - void Signal(); - void SignalAll(); - void Wait(); -// bool TimedWait(unsigned long usec); - ~Condition(); -}; diff --git a/common/content/world_content_service.cpp b/common/content/world_content_service.cpp index 1b650b82d..3bc28a7a2 100644 --- a/common/content/world_content_service.cpp +++ b/common/content/world_content_service.cpp @@ -132,7 +132,7 @@ void WorldContentService::SetContentFlags(const std::vector> 8) ^ CRC32Table[(byte) ^ ((crc32var) & 0x000000FF)]; } diff --git a/common/database.cpp b/common/database.cpp index 83ed14c90..7376cb0da 100644 --- a/common/database.cpp +++ b/common/database.cpp @@ -728,7 +728,7 @@ bool Database::LoadVariables() return true; } - LockMutex lock(&Mvarcache); + std::scoped_lock lock(Mvarcache); for (const auto& e : l) { varcache.last_update = std::time(nullptr); @@ -747,7 +747,7 @@ bool Database::LoadVariables() bool Database::GetVariable(const std::string& name, std::string& value) { - LockMutex lock(&Mvarcache); + std::scoped_lock lock(Mvarcache); if (name.empty()) { return false; diff --git a/common/database.h b/common/database.h index fdb3154b2..ab5d6c271 100644 --- a/common/database.h +++ b/common/database.h @@ -20,13 +20,12 @@ #include "common/dbcore.h" #include "common/eq_packet_structs.h" #include "common/eqemu_logsys.h" -#include "common/linked_list.h" #include "common/types.h" -#include +#include +#include #include #include -#include #define AUTHENTICATION_TIMEOUT 60 #define INVALID_ID 0xFFFFFFFF @@ -265,7 +264,7 @@ public: uint64_t GetNextTableId(const std::string& table_name); private: - Mutex Mvarcache; + std::mutex Mvarcache; VarCache_Struct varcache; /* Groups, utility methods. */ diff --git a/common/dbcore.cpp b/common/dbcore.cpp index d119ceacb..1cde3b30f 100644 --- a/common/dbcore.cpp +++ b/common/dbcore.cpp @@ -33,17 +33,9 @@ #endif DBcore::DBcore() + : mysql(mysql_init(nullptr)) + , m_mutex(std::make_shared()) { - mysql = mysql_init(nullptr); - mysqlOwner = true; - pHost = nullptr; - pUser = nullptr; - pPassword = nullptr; - pDatabase = nullptr; - pCompress = false; - pSSL = false; - pStatus = Closed; - m_mutex = new Mutex; } DBcore::~DBcore() @@ -56,20 +48,17 @@ DBcore::~DBcore() if (mysqlOwner) { mysql_close(mysql); } - - safe_delete_array(pHost); - safe_delete_array(pUser); - safe_delete_array(pPassword); - safe_delete_array(pDatabase); } // Sends the MySQL server a keepalive void DBcore::ping() { - if (!m_mutex->trylock()) { + if (!m_mutex->try_lock()) + { // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive return; } + mysql_ping(mysql); m_mutex->unlock(); } @@ -92,7 +81,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo BenchTimer timer; timer.reset(); - LockMutex lock(m_mutex); + std::scoped_lock lock(*m_mutex); // Reconnect if we are not connected before hand. if (pStatus != Connected) { @@ -217,15 +206,12 @@ bool DBcore::Open( bool iSSL ) { - LockMutex lock(m_mutex); - safe_delete_array(pHost); - safe_delete_array(pUser); - safe_delete_array(pPassword); - safe_delete_array(pDatabase); - pHost = strcpy(new char[strlen(iHost) + 1], iHost); - pUser = strcpy(new char[strlen(iUser) + 1], iUser); - pPassword = strcpy(new char[strlen(iPassword) + 1], iPassword); - pDatabase = strcpy(new char[strlen(iDatabase) + 1], iDatabase); + std::scoped_lock lock(*m_mutex); + + m_host = iHost; + m_user = iUser; + m_password = iPassword; + m_database = iDatabase; pCompress = iCompress; pPort = iPort; pSSL = iSSL; @@ -234,10 +220,12 @@ bool DBcore::Open( bool DBcore::Open(uint32 *errnum, char *errbuf) { + // Expects m_mutex to already be locked. + if (errbuf) { errbuf[0] = 0; } - LockMutex lock(m_mutex); + if (GetStatus() == Connected) { return true; } @@ -245,7 +233,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) mysql_close(mysql); mysql_init(mysql); // Initialize structure again } - if (!pHost) { + if (m_host.empty()) { return false; } /* @@ -268,11 +256,10 @@ bool DBcore::Open(uint32 *errnum, char *errbuf) mysql_options(mysql, MYSQL_OPT_SSL_ENFORCE, &off); mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &off); } - if (mysql_real_connect(mysql, pHost, pUser, pPassword, pDatabase, pPort, 0, flags)) { + if (mysql_real_connect(mysql, m_host.c_str(), m_user.c_str(), m_password.c_str(), m_database.c_str(), pPort, nullptr, flags)) { pStatus = Connected; - std::string connected_origin_host = pHost; - SetOriginHost(connected_origin_host); + SetOriginHost(m_host); return true; } @@ -293,9 +280,9 @@ const std::string &DBcore::GetOriginHost() const return origin_host; } -void DBcore::SetOriginHost(const std::string &origin_host) +void DBcore::SetOriginHost(const std::string& originHost) { - DBcore::origin_host = origin_host; + DBcore::origin_host = originHost; } std::string DBcore::Escape(const std::string& s) @@ -307,12 +294,8 @@ std::string DBcore::Escape(const std::string& s) return temp.data(); } -void DBcore::SetMutex(Mutex *mutex) +void DBcore::SetMutex(const std::shared_ptr& mutex) { - if (m_mutex && m_mutex != mutex) { - safe_delete(m_mutex); - } - DBcore::m_mutex = mutex; } @@ -326,7 +309,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query) BenchTimer timer; timer.reset(); - LockMutex lock(m_mutex); + std::scoped_lock lock(*m_mutex); // Reconnect if we are not connected before hand. if (pStatus != Connected) { @@ -449,5 +432,5 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query) mysql::PreparedStmt DBcore::Prepare(std::string query) { - return mysql::PreparedStmt(*mysql, std::move(query), m_mutex); + return mysql::PreparedStmt(*mysql, std::move(query), *m_mutex); } diff --git a/common/dbcore.h b/common/dbcore.h index eef5c1d4b..b9b25d149 100644 --- a/common/dbcore.h +++ b/common/dbcore.h @@ -17,11 +17,11 @@ */ #pragma once -#include "common/mutex.h" #include "common/mysql_request_result.h" #include "common/types.h" #include "mysql.h" +#include #include #define CR_SERVER_GONE_ERROR 2006 @@ -29,12 +29,15 @@ namespace mysql { class PreparedStmt; } -class DBcore { +class DBcore +{ public: enum eStatus { Closed, Connected, Error }; + using Mutex = std::recursive_mutex; + DBcore(); ~DBcore(); eStatus GetStatus() { return pStatus; } @@ -48,17 +51,17 @@ public: uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen); void ping(); - const std::string &GetOriginHost() const; - void SetOriginHost(const std::string &origin_host); + const std::string& GetOriginHost() const; + void SetOriginHost(const std::string& origin_host); bool DoesTableExist(const std::string& table_name); - void SetMySQL(const DBcore &o) + void SetMySQL(const DBcore& o) { mysql = o.mysql; mysqlOwner = false; } - void SetMutex(Mutex *mutex); + void SetMutex(const std::shared_ptr& mutex); // only safe on connections shared with other threads if results buffered // unsafe to use off main thread due to internal server logging @@ -81,22 +84,21 @@ protected: private: bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); - MYSQL* mysql; - bool mysqlOwner; - Mutex *m_mutex; - eStatus pStatus; + MYSQL* mysql = nullptr; + bool mysqlOwner = true; + eStatus pStatus = Closed; - std::mutex m_query_lock{}; + std::shared_ptr m_mutex; std::string origin_host; - char *pHost; - char *pUser; - char *pPassword; - char *pDatabase; - bool pCompress; - uint32 pPort; - bool pSSL; + std::string m_host; + std::string m_user; + std::string m_password; + std::string m_database; + bool pCompress = false; + uint32 pPort = 0; + bool pSSL = false; // allows multiple queries to be executed within the same query // do not use this under normal operation diff --git a/common/eq_packet.cpp b/common/eq_packet.cpp index 93b4f1052..62136ca8b 100644 --- a/common/eq_packet.cpp +++ b/common/eq_packet.cpp @@ -31,9 +31,19 @@ #include #include -EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, uint32 len) -: BasePacket(buf, len), - emu_opcode(op) +EQPacket::EQPacket() +{ +} + +EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, size_t len) + : BasePacket(buf, len) + , emu_opcode(op) +{ +} + +EQPacket::EQPacket(EmuOpcode opcode, SerializeBuffer&& buf) + : BasePacket(std::move(buf)) + , emu_opcode(opcode) { } @@ -360,17 +370,16 @@ EQRawApplicationPacket::EQRawApplicationPacket(const unsigned char *buf, const u } } -void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) { +void DumpPacket(const EQApplicationPacket* app, bool iShowInfo) +{ if (iShowInfo) { - std::cout << "Dumping Applayer: 0x" << std::hex << std::setfill('0') << std::setw(4) << app->GetOpcode() << std::dec; - std::cout << " size:" << app->size << std::endl; + printf("Dumping Applayer: 0x%04x size: %u", app->GetOpcode(), app->size); } + DumpPacketHex(app->pBuffer, app->size); -// DumpPacketAscii(app->pBuffer, app->size); } -std::string DumpPacketToString(const EQApplicationPacket* app){ - std::ostringstream out; - out << DumpPacketHexToString(app->pBuffer, app->size); - return out.str(); +std::string DumpPacketToString(const EQApplicationPacket* app) +{ + return DumpPacketHexToString(app->pBuffer, app->size); } diff --git a/common/eq_packet.h b/common/eq_packet.h index e2d0d2710..e8ad80d12 100644 --- a/common/eq_packet.h +++ b/common/eq_packet.h @@ -28,8 +28,15 @@ #include "common/emu_opcodes.h" #endif -class EQPacket : public BasePacket { +class EQPacket : public BasePacket +{ friend class EQStream; + +protected: + EQPacket(); + EQPacket(EmuOpcode opcode, const unsigned char* buf, size_t len); + EQPacket(EmuOpcode opcode, SerializeBuffer&& buf); + public: virtual ~EQPacket() {} @@ -41,19 +48,12 @@ public: virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const; void SetOpcode(EmuOpcode op) { emu_opcode = op; } - const EmuOpcode GetOpcode() const { return(emu_opcode); } -// const char *GetOpcodeName() const; + EmuOpcode GetOpcode() const { return(emu_opcode); } protected: //this is just a cache so we dont look it up several times on Get() //and it is mutable so we can store the cached copy even on a const object - EmuOpcode emu_opcode; - - EQPacket(EmuOpcode opcode, const unsigned char *buf, const uint32 len); - EQPacket(EmuOpcode opcode, SerializeBuffer &buf) : BasePacket(buf), emu_opcode(opcode) { }; -// EQPacket(const EQPacket &p) { } - EQPacket() { emu_opcode=OP_Unknown; pBuffer=nullptr; size=0; } - + EmuOpcode emu_opcode = OP_Unknown; }; class EQRawApplicationPacket; @@ -90,19 +90,43 @@ protected: uint16 opcode; }; -class EQApplicationPacket : public EQPacket { +class EQApplicationPacket : public EQPacket +{ friend class EQStream; + +public: + EQApplicationPacket() + { + } + + EQApplicationPacket(EmuOpcode op) + : EQPacket(op, nullptr, 0) + { + } + + EQApplicationPacket(EmuOpcode op, size_t len) + : EQPacket(op, nullptr, len) + { + } + EQApplicationPacket(EmuOpcode op, const unsigned char* buf, size_t len) + : EQPacket(op, buf, len) + { + } + + EQApplicationPacket(EmuOpcode op, SerializeBuffer&& buf) + : EQPacket(op, std::move(buf)) + { + } + +private: + EQApplicationPacket(const EQApplicationPacket& p) + : EQPacket(p.emu_opcode, p.pBuffer, p.size) + , app_opcode_size(p.app_opcode_size) + , opcode_bypass(p.opcode_bypass) + { + } + public: - EQApplicationPacket() : EQPacket(OP_Unknown, nullptr, 0), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op) : EQPacket(op, nullptr, 0), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, const uint32 len) : EQPacket(op, nullptr, len), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, const unsigned char *buf, const uint32 len) : EQPacket(op, buf, len), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } - EQApplicationPacket(const EmuOpcode op, SerializeBuffer &buf) : EQPacket(op, buf), opcode_bypass(0) - { app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; } bool combine(const EQApplicationPacket *rhs); uint32 serialize (uint16 opcode, unsigned char *dest) const; uint32 Size() const { return size+app_opcode_size; } @@ -119,15 +143,11 @@ public: uint16 GetProtocolOpcode() const { return protocol_opcode; } void SetProtocolOpcode(uint16 v) { protocol_opcode = v; } + protected: - - uint16 protocol_opcode; - uint8 app_opcode_size; - uint16 opcode_bypass; -private: - - EQApplicationPacket(const EQApplicationPacket &p) : EQPacket(p.emu_opcode, p.pBuffer, p.size), opcode_bypass(p.opcode_bypass) { app_opcode_size = p.app_opcode_size; } - + uint16 protocol_opcode = 0; + uint8 app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2; + uint16 opcode_bypass = 0; }; class EQRawApplicationPacket : public EQApplicationPacket { diff --git a/common/eq_stream_intf.h b/common/eq_stream_intf.h index 2c5faac55..6953f7a37 100644 --- a/common/eq_stream_intf.h +++ b/common/eq_stream_intf.h @@ -26,13 +26,13 @@ //this is the only part of an EQStream that is seen by the application. -typedef enum { +enum EQStreamState { ESTABLISHED, CLOSING, //waiting for pending data to flush. DISCONNECTING, //have sent disconnect, waiting for their disconnect reply. CLOSED, //received a disconnect from remote side. UNESTABLISHED -} EQStreamState; +}; class EQApplicationPacket; class OpcodeManager; diff --git a/common/eqemu_logsys.cpp b/common/eqemu_logsys.cpp index 7b5e218eb..1704bab4a 100644 --- a/common/eqemu_logsys.cpp +++ b/common/eqemu_logsys.cpp @@ -33,10 +33,8 @@ #include #ifdef _WINDOWS -#include +#include "common/platform/platform.h" #include -#include -#include #else #include #include diff --git a/common/mutex.h b/common/event/event_loop.cpp similarity index 55% rename from common/mutex.h rename to common/event/event_loop.cpp index 8040ec2aa..139c1657e 100644 --- a/common/mutex.h +++ b/common/event/event_loop.cpp @@ -15,36 +15,43 @@ You should have received a copy of the GNU General Public License along with this program. If not, see . */ -#pragma once -#include "common/types.h" -#include "common/platform/posix/include_pthreads.h" -#include "common/platform/win/include_windows.h" +#include "common/event/event_loop.h" +#include "uv.h" -class Mutex { -public: - Mutex(); - ~Mutex(); +namespace EQ { - void lock(); - void unlock(); - bool trylock(); -protected: -private: -#if defined _WINDOWS - CRITICAL_SECTION CSMutex; -#else - pthread_mutex_t CSMutex; -#endif -}; +EventLoop& EventLoop::Get() +{ + thread_local EventLoop inst; + return inst; +} -class LockMutex { -public: - LockMutex(Mutex* in_mut, bool iLock = true); - ~LockMutex(); - void unlock(); - void lock(); -private: - bool locked; - Mutex* mut; -}; +EventLoop::EventLoop() + : m_loop(std::make_unique()) +{ + memset(m_loop.get(), 0, sizeof(uv_loop_t)); + uv_loop_init(m_loop.get()); +} + +EventLoop::~EventLoop() +{ + uv_loop_close(m_loop.get()); +} + +void EventLoop::Process() +{ + uv_run(m_loop.get(), UV_RUN_NOWAIT); +} + +void EventLoop::Run() +{ + uv_run(m_loop.get(), UV_RUN_DEFAULT); +} + +void EventLoop::Shutdown() +{ + uv_stop(m_loop.get()); +} + +} // namespace EQ diff --git a/common/event/event_loop.h b/common/event/event_loop.h index 3c56ab949..fed72c022 100644 --- a/common/event/event_loop.h +++ b/common/event/event_loop.h @@ -17,48 +17,31 @@ */ #pragma once -#include "common/platform/win/include_windows.h" // uv.h is going to include it so let's do it first. -#include "uv.h" // FIXME: hide this +#include -#include +typedef struct uv_loop_s uv_loop_t; -namespace EQ +namespace EQ { + +class EventLoop { - class EventLoop - { - public: - static EventLoop &Get() { - static thread_local EventLoop inst; - return inst; - } +public: + static EventLoop& Get(); - ~EventLoop() { - uv_loop_close(&m_loop); - } + ~EventLoop(); + EventLoop(const EventLoop&) = delete; + EventLoop& operator=(const EventLoop&) = delete; - void Process() { - uv_run(&m_loop, UV_RUN_NOWAIT); - } + void Process(); + void Run(); + void Shutdown(); - void Run() { - uv_run(&m_loop, UV_RUN_DEFAULT); - } + uv_loop_t* Handle() { return m_loop.get(); } - void Shutdown() { - uv_stop(&m_loop); - } +private: + EventLoop(); - uv_loop_t* Handle() { return &m_loop; } + std::unique_ptr m_loop; +}; - private: - EventLoop() { - memset(&m_loop, 0, sizeof(uv_loop_t)); - uv_loop_init(&m_loop); - } - - EventLoop(const EventLoop&); - EventLoop& operator=(const EventLoop&); - - uv_loop_t m_loop; - }; -} +} // namespace EQ diff --git a/common/event/task_scheduler.cpp b/common/event/task_scheduler.cpp new file mode 100644 index 000000000..2b0fd7ef9 --- /dev/null +++ b/common/event/task_scheduler.cpp @@ -0,0 +1,128 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "task_scheduler.h" + +#include +#include +#include +#include +#include +#include + +namespace EQ::Event { + +static constexpr int DefaultThreadCount = 4; + +struct TaskScheduler::SchedulerData +{ + std::atomic_bool running{ false }; + std::vector threads; + std::mutex lock; + std::condition_variable cv; + std::queue> tasks; +}; + +TaskScheduler::TaskScheduler() + : m_data(std::make_unique()) +{ + Start(DefaultThreadCount); +} + +TaskScheduler::TaskScheduler(size_t threads) +{ + Start(threads); +} + +TaskScheduler::~TaskScheduler() +{ + Stop(); +} + +void TaskScheduler::Start(size_t threads) +{ + if (m_data->running.exchange(true)) + return; + + m_data->threads.reserve(threads); + + for (size_t i = 0; i < threads; ++i) + { + m_data->threads.emplace_back( + [this]{ ProcessWork(); }); + } +} + +void TaskScheduler::Stop() +{ + if (!m_data->running.exchange(false)) + return; + + m_data->cv.notify_all(); + + for (auto& t : m_data->threads) + { + t.join(); + } + + m_data->threads.clear(); +} + +void TaskScheduler::ProcessWork() +{ + for (;;) + { + std::function work; + + { + std::unique_lock lock(m_data->lock); + + m_data->cv.wait(lock, + [this] + { + return !m_data->running || !m_data->tasks.empty(); + }); + + if (!m_data->running) + { + return; + } + + work = std::move(m_data->tasks.front()); + m_data->tasks.pop(); + } + + work(); + } +} + +void TaskScheduler::AddTask(std::function&& task) +{ + if (!m_data->running) + { + throw std::runtime_error("Enqueue on stopped scheduler."); + } + + { + std::scoped_lock lock(m_data->lock); + m_data->tasks.push(std::move(task)); + } + m_data->cv.notify_one(); +} + +} // namespace EQ::Event diff --git a/common/event/task_scheduler.h b/common/event/task_scheduler.h index e2e855682..c63e93bdf 100644 --- a/common/event/task_scheduler.h +++ b/common/event/task_scheduler.h @@ -17,116 +17,45 @@ */ #pragma once -#include #include #include -#include -#include -#include -#include +#include -namespace EQ +namespace EQ::Event { + +class TaskScheduler { - namespace Event +public: + TaskScheduler(); + TaskScheduler(size_t threads); + + ~TaskScheduler(); + + void Start(size_t threads); + void Stop(); + + template + auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> { - class TaskScheduler - { - public: - static const int DefaultThreadCount = 4; - - TaskScheduler() : _running(false) + using return_type = typename std::invoke_result::type; + + auto task = std::make_shared>( + [fn = std::forward(fn), ...args = std::forward(args)]() mutable { - Start(DefaultThreadCount); - } - - TaskScheduler(size_t threads) : _running(false) - { - Start(threads); + return fn(std::forward(args)...); } + ); - ~TaskScheduler() { - Stop(); - } - - void Start(size_t threads) { - if (true == _running) { - return; - } - - _running = true; - - for (size_t i = 0; i < threads; ++i) { - _threads.emplace_back(std::thread(std::bind(&TaskScheduler::ProcessWork, this))); - } - } - - void Stop() { - if (false == _running) { - return; - } - - { - std::unique_lock lock(_lock); - _running = false; - } - - _cv.notify_all(); - - for (auto &t : _threads) { - t.join(); - } - } - - template - auto Enqueue(Fn&& fn, Args&&... args) -> std::future::type> { - using return_type = typename std::invoke_result::type; - - auto task = std::make_shared>( - std::bind(std::forward(fn), std::forward(args)...) - ); - - std::future res = task->get_future(); - { - std::unique_lock lock(_lock); - - if (false == _running) { - throw std::runtime_error("Enqueue on stopped scheduler."); - } - - _tasks.emplace([task]() { (*task)(); }); - } - - _cv.notify_one(); - return res; - } - - private: - void ProcessWork() { - for (;;) { - std::function work; - - { - std::unique_lock lock(_lock); - _cv.wait(lock, [this] { return !_running || !_tasks.empty(); }); - - if (false == _running) { - return; - } - - work = std::move(_tasks.front()); - _tasks.pop(); - } - - work(); - } - - } - - bool _running = true; - std::vector _threads; - std::mutex _lock; - std::condition_variable _cv; - std::queue> _tasks; - }; + AddTask([task] { (*task)(); }); + return task->get_future(); } -} + +private: + void AddTask(std::function&& task); + void ProcessWork(); + + struct SchedulerData; + std::unique_ptr m_data; +}; + +} // namespace EQ::Event diff --git a/common/event/timer.cpp b/common/event/timer.cpp new file mode 100644 index 000000000..be541c452 --- /dev/null +++ b/common/event/timer.cpp @@ -0,0 +1,90 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "common/event/timer.h" +#include "uv.h" + +namespace EQ { + +Timer::Timer(callback_t cb) + : m_cb(std::move(cb)) +{ +} + +Timer::Timer(uint64_t duration_ms, bool repeats, callback_t cb) + : m_cb(std::move(cb)) +{ + Start(duration_ms, repeats); +} + +Timer::~Timer() +{ + Stop(); +} + +void Timer::Start(uint64_t duration_ms, bool repeats) +{ + if (!m_timer) + { + uv_loop_t* loop = EventLoop::Get().Handle(); + + m_timer = std::make_unique(); + memset(m_timer.get(), 0, sizeof(uv_timer_t)); + + uv_timer_init(loop, m_timer.get()); + m_timer->data = this; + + if (repeats) + { + uv_timer_start(m_timer.get(), [](uv_timer_t* handle) + { + Timer* t = static_cast(handle->data); + t->Execute(); + }, duration_ms, duration_ms); + } + else + { + uv_timer_start(m_timer.get(), + [](uv_timer_t* handle) + { + Timer* t = static_cast(handle->data); + t->Stop(); + t->Execute(); + }, duration_ms, 0); + } + } +} + +void Timer::Stop() +{ + if (m_timer) + { + uv_close(reinterpret_cast(m_timer.release()), + [](uv_handle_t* handle) + { + delete reinterpret_cast(handle); + }); + } +} + +void Timer::Execute() +{ + m_cb(this); +} + +} // namespace EQ diff --git a/common/event/timer.h b/common/event/timer.h index 2cea8072b..61780dfe3 100644 --- a/common/event/timer.h +++ b/common/event/timer.h @@ -19,69 +19,31 @@ #include "event_loop.h" -#include #include +#include + +typedef struct uv_timer_s uv_timer_t; namespace EQ { - class Timer - { - public: - Timer(std::function cb) - { - m_timer = nullptr; - m_cb = cb; - } - Timer(uint64_t duration_ms, bool repeats, std::function cb) - { - m_timer = nullptr; - m_cb = cb; - Start(duration_ms, repeats); - } +class Timer +{ +public: + using callback_t = std::function; + + Timer(callback_t cb); + Timer(uint64_t duration_ms, bool repeats, callback_t cb); - ~Timer() - { - Stop(); - } + ~Timer(); - void Start(uint64_t duration_ms, bool repeats) { - auto loop = EventLoop::Get().Handle(); - if (!m_timer) { - m_timer = new uv_timer_t; - memset(m_timer, 0, sizeof(uv_timer_t)); - uv_timer_init(loop, m_timer); - m_timer->data = this; + void Start(uint64_t duration_ms, bool repeats); + void Stop(); - if (repeats) { - uv_timer_start(m_timer, [](uv_timer_t *handle) { - Timer *t = (Timer*)handle->data; - t->Execute(); - }, duration_ms, duration_ms); - } - else { - uv_timer_start(m_timer, [](uv_timer_t *handle) { - Timer *t = (Timer*)handle->data; - t->Stop(); - t->Execute(); - }, duration_ms, 0); - } - } - } - - void Stop() { - if (m_timer) { - uv_close((uv_handle_t*)m_timer, [](uv_handle_t* handle) { - delete (uv_timer_t *)handle; - }); - m_timer = nullptr; - } - } - private: - void Execute() { - m_cb(this); - } +private: + void Execute(); - uv_timer_t *m_timer; - std::function m_cb; - }; -} + std::unique_ptr m_timer; + callback_t m_cb; +}; + +} // namespace EQ diff --git a/common/events/player_event_logs.cpp b/common/events/player_event_logs.cpp index fd756f37a..421e9d926 100644 --- a/common/events/player_event_logs.cpp +++ b/common/events/player_event_logs.cpp @@ -56,12 +56,12 @@ void PlayerEventLogs::Init() auto s = PlayerEventLogSettingsRepository::All(*m_database); std::vector db{}; db.reserve(s.size()); - for (auto &e: s) { + for (auto& e: s) { if (e.id >= PlayerEvent::MAX) { continue; } m_settings[e.id] = e; - db.emplace_back(e.id); + db.emplace_back(static_cast(e.id)); } std::vector settings_to_insert{}; diff --git a/common/guilds.h b/common/guilds.h index eb746a00a..7e786c776 100644 --- a/common/guilds.h +++ b/common/guilds.h @@ -46,7 +46,7 @@ #define GUILD_INITIATE 7 #define GUILD_RECRUIT 8 -typedef enum { +enum GuildAction { GUILD_ACTION_BANNER_CHANGE = 1, GUILD_ACTION_BANNER_PLANT = 2, GUILD_ACTION_BANNER_REMOVE = 3, @@ -77,6 +77,6 @@ typedef enum { GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28, GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29, GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30, -} GuildAction; +}; constexpr int format_as(GuildAction action) { return static_cast(action); } diff --git a/common/inventory_profile.cpp b/common/inventory_profile.cpp index e8cb95d84..2ec3d6a08 100644 --- a/common/inventory_profile.cpp +++ b/common/inventory_profile.cpp @@ -349,7 +349,7 @@ bool EQ::InventoryProfile::SwapItem( fail_state = swapLevel; return false; } - if (source_item_instance->IsEvolving() > 0) { + if (source_item_instance->IsEvolving()) { source_item_instance->SetEvolveEquipped(true); } } diff --git a/common/ip_util.cpp b/common/ip_util.cpp index c1af78263..0801fb370 100644 --- a/common/ip_util.cpp +++ b/common/ip_util.cpp @@ -25,14 +25,24 @@ #include "common/net/dns.h" #include "fmt/format.h" -#include -#include +#include +#include #include -/** - * @param ip - * @return - */ +#ifdef _WIN32 +#include +#include +#pragma comment(lib, "Ws2_32.lib") +#else +#include +#include +#include +#include +#include +#include +#endif + + uint32_t IpUtil::IPToUInt(const std::string &ip) { int a, b, c, d; @@ -49,12 +59,6 @@ uint32_t IpUtil::IPToUInt(const std::string &ip) return addr; } -/** - * @param ip - * @param network - * @param mask - * @return - */ bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask) { uint32_t ip_addr = IpUtil::IPToUInt(ip); @@ -67,10 +71,6 @@ bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, cons return ip_addr >= net_lower && ip_addr <= net_upper; } -/** - * @param ip - * @return - */ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) { return ( @@ -80,30 +80,13 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) ); } - -#ifdef _WIN32 -#include - #include - #pragma comment(lib, "Ws2_32.lib") -#else -#include -#include -#include -#include -#include -#endif - -#include -#include -#include - std::string IpUtil::GetLocalIPAddress() { #ifdef _WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - return ""; - } + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + return ""; + } #endif char my_ip_address[INET_ADDRSTRLEN]; @@ -114,10 +97,10 @@ std::string IpUtil::GetLocalIPAddress() // Create a UDP socket #ifdef _WIN32 sockfd = socket(AF_INET, SOCK_DGRAM, 0); - if (sockfd == INVALID_SOCKET) { - WSACleanup(); - return ""; - } + if (sockfd == INVALID_SOCKET) { + WSACleanup(); + return ""; + } #else sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { @@ -200,98 +183,24 @@ std::string IpUtil::GetPublicIPAddress() return {}; } -std::string IpUtil::DNSLookupSync(const std::string &addr, int port) -{ - auto task_runner = new EQ::Event::TaskScheduler(); - auto res = task_runner->Enqueue( - [&]() -> std::string { - bool running = true; - std::string ret; - - EQ::Net::DNSLookup( - addr, port, false, [&](const std::string &addr) { - ret = addr; - if (addr.empty()) { - ret = ""; - running = false; - } - - return ret; - } - ); - - std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); - - auto &loop = EQ::EventLoop::Get(); - while (running) { - if (!ret.empty()) { - running = false; - } - - std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); - if (std::chrono::duration_cast(end - begin).count() > 1500) { - LogInfo( - "Deadline exceeded [{}]", - 1500 - ); - running = false; - } - - loop.Process(); - } - - return ret; - } - ); - - std::string result = res.get(); - safe_delete(task_runner); - - return result; -} - bool IpUtil::IsIPAddress(const std::string &ip_address) { - struct sockaddr_in sa{}; - int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); + sockaddr_in sa{}; + int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); return result != 0; } -#include -#ifdef _WIN32 -#include - #pragma comment(lib, "ws2_32.lib") // Link against Winsock library -#else -#include -#include -#include -#include -#endif - -#include -#include -#ifdef _WIN32 -#include - #include // For inet_pton - #pragma comment(lib, "ws2_32.lib") // Link against Winsock library -#else -#include -#include -#include -#include // For inet_pton -#include -#endif - -bool IpUtil::IsPortInUse(const std::string& ip, int port) { +bool IpUtil::IsPortInUse(const std::string& ip, int port) +{ bool in_use = false; #ifdef _WIN32 WSADATA wsaData; - if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { - std::cerr << "WSAStartup failed\n"; - return true; // Assume in use on failure - } + if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { + std::cerr << "WSAStartup failed\n"; + return true; // Assume in use on failure + } #endif int sock = socket(AF_INET, SOCK_STREAM, 0); @@ -319,20 +228,20 @@ bool IpUtil::IsPortInUse(const std::string& ip, int port) { std::cerr << "Invalid IP address format: " << ip << std::endl; #ifdef _WIN32 closesocket(sock); - WSACleanup(); + WSACleanup(); #else close(sock); #endif return true; // Assume in use on failure } - if (bind(sock, (struct sockaddr*)&addr, sizeof(addr)) < 0) { + if (bind(sock, (sockaddr*)&addr, sizeof(addr)) < 0) { in_use = true; // Bind failed, port is in use } #ifdef _WIN32 closesocket(sock); - WSACleanup(); + WSACleanup(); #else close(sock); #endif diff --git a/common/ip_util.h b/common/ip_util.h index 9d04263d4..f779bf875 100644 --- a/common/ip_util.h +++ b/common/ip_util.h @@ -29,10 +29,7 @@ public: static bool IsIpInPrivateRfc1918(const std::string &ip); static std::string GetLocalIPAddress(); static std::string GetPublicIPAddress(); - static std::string DNSLookupSync( - const std::string &addr, - int port - ); + static bool IsIPAddress(const std::string &ip_address); static bool IsPortInUse(const std::string& ip, int port); diff --git a/common/item_instance.cpp b/common/item_instance.cpp index 4862d103c..39271ba8e 100644 --- a/common/item_instance.cpp +++ b/common/item_instance.cpp @@ -320,6 +320,7 @@ bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) co } return ( + slot < invaug::SOCKET_COUNT && ( augment_type == -1 || ( diff --git a/common/loot.h b/common/loot.h index 9830585b8..f1a7e329d 100644 --- a/common/loot.h +++ b/common/loot.h @@ -45,5 +45,4 @@ struct LootItem { uint32 lootdrop_id; // required for zone state referencing }; -typedef std::list LootItems; - +using LootItems = std::list; diff --git a/common/memory/ksm.cpp b/common/memory/ksm.cpp new file mode 100644 index 000000000..0179a2426 --- /dev/null +++ b/common/memory/ksm.cpp @@ -0,0 +1,192 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#include "ksm.h" + + +#ifdef _WIN32 +#include +#else +#include // For madvise +#include // For sysconf, sbrk +#endif + +#ifdef _WIN32 +// Windows-specific functionality + +void* PageAlignedAllocatorBase::allocateInternal(size_t size, size_t alignment) +{ + void* ptr = malloc(size); + + if (!ptr) + { + throw std::bad_alloc(); + } + + return ptr; +} + +size_t PageAlignedAllocatorBase::getPageSize() const +{ + SYSTEM_INFO sysInfo; + GetSystemInfo(&sysInfo); + return sysInfo.dwPageSize; // Page size in bytes +} + +namespace KSM { + +// Windows-specific placeholder functions (no-op) +void CheckPageAlignment(void* ptr) +{ +} + +void* AllocatePageAligned(size_t size) +{ + return memset(malloc(size), 0, size); +} + +void MarkMemoryForKSM(void* start, size_t size) +{ +} + +void AlignHeapToPageBoundary() +{ +} + +void* MarkHeapStart() +{ + return nullptr; +} + +size_t MeasureHeapUsage(void* start) +{ + return 0; +} + +} // namespace KSM + +#else + +// Linux-specific functionality + +void* PageAlignedAllocatorBase::allocateInternal(size_t size, size_t alignment) +{ + void* ptr = nullptr; + + if (posix_memalign(&ptr, alignment, size) != 0) + { + throw std::bad_alloc(); + } + + return ptr; +} + +size_t PageAlignedAllocatorBase::getPageSize() const +{ + return static_cast(sysconf(_SC_PAGESIZE)); +} + +namespace KSM { + +void CheckPageAlignment(void* ptr) +{ + size_t page_size = sysconf(_SC_PAGESIZE); + + if (reinterpret_cast(ptr) % page_size == 0) + { + LogKSMDetail("Memory is page-aligned [{}]", ptr); + } + else + { + LogKSMDetail("Memory is NOT page-aligned [{}]", ptr); + } +} + +void* AllocatePageAligned(size_t size) +{ + size_t page_size = sysconf(_SC_PAGESIZE); + void* aligned_ptr = nullptr; + + if (posix_memalign(&aligned_ptr, page_size, size) != 0) + { + LogKSM("Failed to allocate page-aligned memory on Linux. page_size [{}] size [{}] bytes", page_size, size); + } + + std::memset(aligned_ptr, 0, size); + return aligned_ptr; +} + +void MarkMemoryForKSM(void* start, size_t size) +{ + if (madvise(start, size, MADV_MERGEABLE) == 0) + { + LogKSM("Marked memory for KSM | start [{}] size [{}] bytes", start, size); + } + else + { + perror("madvise failed"); + } +} + +void AlignHeapToPageBoundary() +{ + size_t page_size = sysconf(_SC_PAGESIZE); + if (page_size == 0) + { + LogKSM("Failed to retrieve page size SC_PAGESIZE [{}]", page_size); + return; + } + + void* current_break = sbrk(0); + if (current_break == (void*)-1) + { + LogKSM("Failed to retrieve the current program break"); + return; + } + + uintptr_t current_address = reinterpret_cast(current_break); + size_t misalignment = current_address % page_size; + + if (misalignment != 0) + { + size_t adjustment = page_size - misalignment; + if (sbrk(adjustment) == (void*)-1) + { + LogKSM("Failed to align heap to page boundary. adjustment [{}] bytes", adjustment); + return; + } + } + + LogKSMDetail("Heap aligned to next page boundary. Current break [{}]", sbrk(0)); +} + +void* MarkHeapStart() +{ + void* current_pos = sbrk(0); + AlignHeapToPageBoundary(); + return current_pos; +} + +size_t MeasureHeapUsage(void* start) +{ + void* current_break = sbrk(0); + return static_cast(current_break) - static_cast(start); +} + +} // namespace KSM + +#endif diff --git a/common/memory/ksm.h b/common/memory/ksm.h new file mode 100644 index 000000000..2d9c272ba --- /dev/null +++ b/common/memory/ksm.h @@ -0,0 +1,74 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ +#pragma once + +#include "common/eqemu_logsys.h" + +class PageAlignedAllocatorBase +{ +protected: + void* allocateInternal(size_t amount, size_t alignment); + size_t getPageSize() const; +}; + +// Page-aligned allocator for std::vector +template +class PageAlignedAllocator : public PageAlignedAllocatorBase +{ +public: + using value_type = T; + + PageAlignedAllocator() noexcept = default; + + template + PageAlignedAllocator(const PageAlignedAllocator&) noexcept {} + + T* allocate(std::size_t n) + { + size_t size = n * sizeof(T); + + return static_cast(allocateInternal(size, getPageSize())); + } + + void deallocate(T* p, std::size_t) noexcept + { + free(p); + } +}; + +template +bool operator==(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { + return true; +} + +template +bool operator!=(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { + return false; +} + +// Kernel Samepage Merging (KSM) functionality +namespace KSM { + +void CheckPageAlignment(void* ptr); +void* AllocatePageAligned(size_t size); +void MarkMemoryForKSM(void* start, size_t size); +void AlignHeapToPageBoundary(); +void* MarkHeapStart(); +size_t MeasureHeapUsage(void* start); + +} // namespace KSM diff --git a/common/memory/ksm.hpp b/common/memory/ksm.hpp deleted file mode 100644 index 9d4b28273..000000000 --- a/common/memory/ksm.hpp +++ /dev/null @@ -1,234 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#pragma once - -#include "common/eqemu_logsys.h" - -#include -#include -#include -#ifdef _WIN32 -#include // For _aligned_malloc, _aligned_free -#include -#else -#include // For madvise -#include // For sysconf, sbrk -#endif - - -// Page-aligned allocator for std::vector -template -class PageAlignedAllocator { -public: - using value_type = T; - - PageAlignedAllocator() noexcept = default; - template - PageAlignedAllocator(const PageAlignedAllocator&) noexcept {} - - T* allocate(std::size_t n) { - void* ptr = nullptr; - size_t size = n * sizeof(T); - -#ifdef _WIN32 - // Simply allocate memory without alignment - ptr = malloc(size); - if (!ptr) throw std::bad_alloc(); -#else - size_t alignment = getPageSize(); // Get the system's page size - if (posix_memalign(&ptr, alignment, size) != 0) { - throw std::bad_alloc(); - } -#endif - return static_cast(ptr); - } - - void deallocate(T* p, std::size_t) noexcept { - free(p); - } - -private: - size_t getPageSize() const - { -#ifdef _WIN32 - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwPageSize; // Page size in bytes -#else - return static_cast(sysconf(_SC_PAGESIZE)); -#endif - }; -}; - -template -bool operator==(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { - return true; -} - -template -bool operator!=(const PageAlignedAllocator&, const PageAlignedAllocator&) noexcept { - return false; -} - -// Kernel Samepage Merging (KSM) functionality -namespace KSM { - -#ifdef _WIN32 - // Windows-specific placeholder functions (no-op) - inline void CheckPageAlignment(void* ptr) { - } - - inline void* AllocatePageAligned(size_t size) { - return memset(malloc(size), 0, size); - } - - inline void MarkMemoryForKSM(void* start, size_t size) { - } - - inline void AlignHeapToPageBoundary() { - } - - inline void* MarkHeapStart() { - return nullptr; - } - - inline size_t MeasureHeapUsage(void* start) { - return 0; - } -#else - // Linux-specific functionality - inline void CheckPageAlignment(void* ptr) { - size_t page_size = sysconf(_SC_PAGESIZE); - if (reinterpret_cast(ptr) % page_size == 0) { - LogKSMDetail("Memory is page-aligned [{}]", ptr); - } else { - LogKSMDetail("Memory is NOT page-aligned [{}]", ptr); - } - } - - inline void* AllocatePageAligned(size_t size) { - size_t page_size = sysconf(_SC_PAGESIZE); - void* aligned_ptr = nullptr; - if (posix_memalign(&aligned_ptr, page_size, size) != 0) { - LogKSM("Failed to allocate page-aligned memory on Linux. page_size [{}] size [{}] bytes", page_size, size); - } - std::memset(aligned_ptr, 0, size); - return aligned_ptr; - } - - inline void MarkMemoryForKSM(void* start, size_t size) { - if (madvise(start, size, MADV_MERGEABLE) == 0) { - LogKSM("Marked memory for KSM | start [{}] size [{}] bytes", start, size); - } else { - perror("madvise failed"); - } - } - - inline void AlignHeapToPageBoundary() { - size_t page_size = sysconf(_SC_PAGESIZE); - if (page_size == 0) { - LogKSM("Failed to retrieve page size SC_PAGESIZE [{}]", page_size); - return; - } - - void* current_break = sbrk(0); - if (current_break == (void*)-1) { - LogKSM("Failed to retrieve the current program break"); - return; - } - - uintptr_t current_address = reinterpret_cast(current_break); - size_t misalignment = current_address % page_size; - - if (misalignment != 0) { - size_t adjustment = page_size - misalignment; - if (sbrk(adjustment) == (void*)-1) { - LogKSM("Failed to align heap to page boundary. adjustment [{}] bytes", adjustment); - return; - } - } - - LogKSMDetail("Heap aligned to next page boundary. Current break [{}]", sbrk(0)); - } - - inline void* MarkHeapStart() { - void* current_pos = sbrk(0); - AlignHeapToPageBoundary(); - return current_pos; - } - - inline size_t MeasureHeapUsage(void* start) { - void* current_break = sbrk(0); - return static_cast(current_break) - static_cast(start); - } -#endif - - - inline size_t getPageSize() - { -#ifdef _WIN32 - SYSTEM_INFO sysInfo; - GetSystemInfo(&sysInfo); - return sysInfo.dwPageSize; // Page size in bytes -#else - return static_cast(sysconf(_SC_PAGESIZE)); // POSIX page size -#endif - }; - - template - inline void PageAlignVectorAligned(std::vector>& vec) { - if (vec.empty()) { - return; - } - - size_t page_size = getPageSize(); - void* start = vec.data(); - size_t size = vec.size() * sizeof(T); - - // Check if the memory is page-aligned - if (reinterpret_cast(start) % page_size != 0) { - // Allocate a new aligned vector - std::vector> aligned_vec(vec.get_allocator()); - aligned_vec.reserve(vec.capacity()); // Match capacity to avoid reallocation during copy - - // Copy elements from the original vector - aligned_vec.insert(aligned_vec.end(), vec.begin(), vec.end()); - - // Swap the aligned vector with the original vector - vec.swap(aligned_vec); - - // Clear the temporary aligned vector to free its memory - aligned_vec.clear(); - - // Verify the new alignment - start = vec.data(); - if (reinterpret_cast(start) % page_size != 0) { - throw std::runtime_error("Failed to align vector memory to page boundaries."); - } - - LogKSMDetail("Vector reallocated to ensure page alignment. start [{}] size [{}] bytes", start, size); - } else { - LogKSMDetail("Vector is already page-aligned. start [{}] size [{}] bytes", start, size); - } - -#ifndef _WIN32 - // Mark memory for KSM (only on non-Windows systems) - MarkMemoryForKSM(start, size); -#endif - } -} diff --git a/common/mutex.cpp b/common/mutex.cpp deleted file mode 100644 index f8c1db00d..000000000 --- a/common/mutex.cpp +++ /dev/null @@ -1,162 +0,0 @@ -/* EQEmu: EQEmulator - - Copyright (C) 2001-2026 EQEmu Development Team - - This program is free software; you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation; either version 3 of the License, or - (at your option) any later version. - - This program is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with this program. If not, see . -*/ -#include "mutex.h" - -#include - -#define DEBUG_MUTEX_CLASS 0 -#if DEBUG_MUTEX_CLASS >= 1 -#endif - -#ifdef _WINDOWS -bool IsTryLockSupported(); -bool TrylockSupported = IsTryLockSupported(); - -bool IsTryLockSupported() { - OSVERSIONINFOEX osvi; - BOOL bOsVersionInfoEx; - - ZeroMemory(&osvi, sizeof(OSVERSIONINFOEX)); - osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFOEX); - - if( !(bOsVersionInfoEx = GetVersionEx ((OSVERSIONINFO *) &osvi)) ) - { - // If OSVERSIONINFOEX doesn't work, try OSVERSIONINFO. - osvi.dwOSVersionInfoSize = sizeof (OSVERSIONINFO); - if (! GetVersionEx ( (OSVERSIONINFO *) &osvi) ) { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() NOT supported" << std::endl; -#endif - return false; - } - } - - // Tests for Windows NT product family. - if (osvi.dwPlatformId == VER_PLATFORM_WIN32_NT && osvi.dwMajorVersion >= 4) { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() SUPPORTED" << std::endl; -#endif - return true; - } - else { -#if DEBUG_MUTEX_CLASS >= 1 - std::cout << "Mutex::trylock() NOT supported" << std::endl; -#endif - return false; - } -} -#endif - -Mutex::Mutex() { - -#if DEBUG_MUTEX_CLASS >= 7 - std::cout << "Constructing Mutex" << std::endl; -#endif -#ifdef _WINDOWS - InitializeCriticalSection(&CSMutex); -#else - pthread_mutexattr_t attr; - pthread_mutexattr_init(&attr); -#if defined(__CYGWIN__) || defined(__APPLE__) || defined(FREEBSD) - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); -#else - pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE_NP); -#endif - pthread_mutex_init(&CSMutex, &attr); - pthread_mutexattr_destroy(&attr); -#endif -} - -Mutex::~Mutex() { -#ifdef _WINDOWS - DeleteCriticalSection(&CSMutex); -#else -#endif -} - -void Mutex::lock() { -#if DEBUG_MUTEX_CLASS >= 5 - if (!trylock()) { - std::cout << "Locking Mutex: Having to wait" << std::endl; - #ifdef _WINDOWS - EnterCriticalSection(&CSMutex); - #else - pthread_mutex_lock(&CSMutex); - #endif - } -#else - #ifdef _WINDOWS - EnterCriticalSection(&CSMutex); - #else - pthread_mutex_lock(&CSMutex); - #endif -#endif -} - -bool Mutex::trylock() { -#ifdef _WINDOWS - #if(_WIN32_WINNT >= 0x0400) - if (TrylockSupported) - return TryEnterCriticalSection(&CSMutex); - else { - EnterCriticalSection(&CSMutex); - return true; - } - #else - EnterCriticalSection(&CSMutex); - return true; - #endif -#else - return (pthread_mutex_trylock(&CSMutex) == 0); -#endif -} - -void Mutex::unlock() { -#ifdef _WINDOWS - LeaveCriticalSection(&CSMutex); -#else - pthread_mutex_unlock(&CSMutex); -#endif -} - - -LockMutex::LockMutex(Mutex* in_mut, bool iLock) { - mut = in_mut; - locked = iLock; - if (locked) { - mut->lock(); - } -} - -LockMutex::~LockMutex() { - if (locked) { - mut->unlock(); - } -} - -void LockMutex::unlock() { - if (locked) - mut->unlock(); - locked = false; -} - -void LockMutex::lock() { - if (!locked) - mut->lock(); - locked = true; -} diff --git a/common/mysql_stmt.cpp b/common/mysql_stmt.cpp index 8665c16f9..53a45b327 100644 --- a/common/mysql_stmt.cpp +++ b/common/mysql_stmt.cpp @@ -18,7 +18,6 @@ #include "mysql_stmt.h" #include "common/eqemu_logsys.h" -#include "common/mutex.h" #include "common/timer.h" #include @@ -31,14 +30,19 @@ void PreparedStmt::StmtDeleter::operator()(MYSQL_STMT* stmt) noexcept // The connection must be locked when closing the stmt to avoid mysql errors // in case another thread tries to use it during the close. If the mutex is // changed to one that throws then exceptions need to be caught here. - LockMutex lock(mutex); + std::scoped_lock lock(mutex); + mysql_stmt_close(stmt); } -PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts) - : m_stmt(mysql_stmt_init(&mysql), { mutex }), m_query(std::move(query)), m_mutex(mutex), m_options(opts) +PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts) + : m_stmt(mysql_stmt_init(&mysql), { mutex }) + , m_query(std::move(query)) + , m_options(opts) + , m_mutex(mutex) { - LockMutex lock(m_mutex); + std::scoped_lock lock(m_mutex); + if (mysql_stmt_prepare(m_stmt.get(), m_query.c_str(), static_cast(m_query.size())) != 0) { ThrowError(fmt::format("Prepare error: {}", GetStmtError())); @@ -186,7 +190,7 @@ void PreparedStmt::CheckArgs(size_t argc) StmtResult PreparedStmt::DoExecute() { BenchTimer timer; - LockMutex lock(m_mutex); + std::scoped_lock lock(m_mutex); if (m_need_bind && mysql_stmt_bind_param(m_stmt.get(), m_params.data()) != 0) { diff --git a/common/mysql_stmt.h b/common/mysql_stmt.h index 63cda89d3..2402d02e0 100644 --- a/common/mysql_stmt.h +++ b/common/mysql_stmt.h @@ -17,10 +17,12 @@ */ #pragma once -#include "mysql.h" +#include "common/dbcore.h" + #include #include #include +#include #include #include #include @@ -183,7 +185,7 @@ public: int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>; PreparedStmt() = delete; - PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions opts = {}); + PreparedStmt(MYSQL& mysql, std::string query, DBcore::Mutex& mutex, StmtOptions opts = {}); const std::string& GetQuery() const { return m_query; } StmtOptions GetOptions() const { return m_options; } @@ -219,7 +221,8 @@ private: struct StmtDeleter { - Mutex* mutex = nullptr; + DBcore::Mutex& mutex; + void operator()(MYSQL_STMT* stmt) noexcept; }; @@ -232,7 +235,7 @@ private: std::string m_query; StmtOptions m_options = {}; bool m_need_bind = true; - Mutex* m_mutex = nullptr; // connection mutex + DBcore::Mutex& m_mutex; // connection mutex }; } // namespace mysql diff --git a/common/net/dns.cpp b/common/net/dns.cpp new file mode 100644 index 000000000..fa232586c --- /dev/null +++ b/common/net/dns.cpp @@ -0,0 +1,131 @@ +/* EQEmu: EQEmulator + + Copyright (C) 2001-2026 EQEmu Development Team + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 3 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program. If not, see . +*/ + +#include "dns.h" + +#include "common/eqemu_logsys.h" +#include "common/event/event_loop.h" +#include "common/event/task_scheduler.h" + +#include "uv.h" + +namespace EQ::Net { + +struct DNSBaton +{ + dns_callback_t cb; + bool ipv6; +}; + +void DNSLookup(const std::string& addr, int port, bool ipv6, dns_callback_t cb) +{ + addrinfo hints = {}; + hints.ai_family = PF_INET; + hints.ai_socktype = SOCK_STREAM; + hints.ai_protocol = IPPROTO_TCP; + + uv_loop_t* loop = EQ::EventLoop::Get().Handle(); + + uv_getaddrinfo_t* resolver = new uv_getaddrinfo_t(); + memset(resolver, 0, sizeof(uv_getaddrinfo_t)); + std::string port_str = std::to_string(port); + DNSBaton* baton = new DNSBaton(); + baton->cb = std::move(cb); + baton->ipv6 = ipv6; + resolver->data = baton; + + uv_getaddrinfo(loop, resolver, [](uv_getaddrinfo_t* req, int status, addrinfo* result) + { + DNSBaton* baton = static_cast(req->data); + + dns_callback_t dns_callback = std::move(baton->cb); + bool ipv6 = baton->ipv6; + + delete baton; + delete req; + + if (status < 0) + { + dns_callback({}); + return; + } + + char addr[40] = {}; + + if (ipv6) + { + uv_ip6_name(reinterpret_cast(result->ai_addr), addr, 40); + } + else + { + uv_ip4_name(reinterpret_cast(result->ai_addr), addr, 40); + } + + uv_freeaddrinfo(result); + + dns_callback(addr); + }, addr.c_str(), port_str.c_str(), &hints); +} + +std::string DNSLookupSync(const std::string& addr, int port, bool ipv6 /* = false */) +{ + EQ::Event::TaskScheduler task_runner; + + auto res = task_runner.Enqueue( + [addr, port, ipv6]() -> std::string + { + bool running = true; + std::string ret; + + EQ::Net::DNSLookup( + addr, port, ipv6, [&](const std::string& addr) { + ret = addr; + running = !addr.empty(); + + return ret; + } + ); + + std::chrono::steady_clock::time_point begin = std::chrono::steady_clock::now(); + + auto& loop = EQ::EventLoop::Get(); + while (running) { + if (!ret.empty()) { + running = false; + } + + std::chrono::steady_clock::time_point end = std::chrono::steady_clock::now(); + if (std::chrono::duration_cast(end - begin).count() > 1500) { + LogInfo( + "Deadline exceeded [{}]", + 1500 + ); + running = false; + } + + loop.Process(); + } + + return ret; + }); + + return res.get(); +} + + +} // namespace EQ::Net diff --git a/common/net/dns.h b/common/net/dns.h index 2b799ef4f..04f97a4e9 100644 --- a/common/net/dns.h +++ b/common/net/dns.h @@ -17,63 +17,15 @@ */ #pragma once -#include "common/event/event_loop.h" - #include #include -namespace EQ -{ - namespace Net - { - static void DNSLookup(const std::string &addr, int port, bool ipv6, std::function cb) { - struct DNSBaton - { - std::function cb; - bool ipv6; - }; +namespace EQ::Net { - addrinfo hints; - memset(&hints, 0, sizeof(addrinfo)); - hints.ai_family = PF_INET; - hints.ai_socktype = SOCK_STREAM; - hints.ai_protocol = IPPROTO_TCP; +using dns_callback_t = std::function; - auto loop = EQ::EventLoop::Get().Handle(); - uv_getaddrinfo_t *resolver = new uv_getaddrinfo_t(); - memset(resolver, 0, sizeof(uv_getaddrinfo_t)); - auto port_str = std::to_string(port); - DNSBaton *baton = new DNSBaton(); - baton->cb = cb; - baton->ipv6 = ipv6; - resolver->data = baton; +void DNSLookup(const std::string& addr, int port, bool ipv6, dns_callback_t cb); - uv_getaddrinfo(loop, resolver, [](uv_getaddrinfo_t* req, int status, addrinfo* res) { - DNSBaton *baton = (DNSBaton*)req->data; - if (status < 0) { - auto cb = baton->cb; - delete baton; - delete req; - cb(""); - return; - } +std::string DNSLookupSync(const std::string& addr, int port, bool ipv6 = false); - char addr[40] = { 0 }; - - if (baton->ipv6) { - uv_ip6_name((struct sockaddr_in6*)res->ai_addr, addr, 40); - } - else { - uv_ip4_name((struct sockaddr_in*)res->ai_addr, addr, 40); - } - - auto cb = baton->cb; - delete baton; - delete req; - uv_freeaddrinfo(res); - - cb(addr); - }, addr.c_str(), port_str.c_str(), &hints); - } - } -} +} // namespace EQ::Net diff --git a/common/net/tcp_connection.h b/common/net/tcp_connection.h index 7c421c204..fc0f86f5a 100644 --- a/common/net/tcp_connection.h +++ b/common/net/tcp_connection.h @@ -19,7 +19,9 @@ #include "common/net/tcp_connection_pooling.h" +#include "common/platform/platform.h" #include "uv.h" + #include #include #include diff --git a/common/net/websocket_server.h b/common/net/websocket_server.h index d69399a8f..9d0eee91b 100644 --- a/common/net/websocket_server.h +++ b/common/net/websocket_server.h @@ -49,9 +49,9 @@ namespace EQ WebsocketException(const std::string &msg) : _msg(msg.empty() ? "Unknown Error" : msg) { } - ~WebsocketException() throw() {} + ~WebsocketException() noexcept {} - virtual char const *what() const throw() { + virtual char const *what() const noexcept override { return _msg.c_str(); } private: diff --git a/common/op_codes.h b/common/op_codes.h index fbf0735a6..a488e8c4d 100644 --- a/common/op_codes.h +++ b/common/op_codes.h @@ -17,17 +17,16 @@ */ #pragma once - -static const char OP_SessionRequest = 0x01; -static const char OP_SessionResponse = 0x02; -static const char OP_Combined = 0x03; -static const char OP_SessionDisconnect = 0x05; -static const char OP_KeepAlive = 0x06; -static const char OP_SessionStatRequest = 0x07; -static const char OP_SessionStatResponse= 0x08; -static const char OP_Packet = 0x09; -static const char OP_Fragment = 0x0d; -static const char OP_OutOfOrderAck = 0x11; -static const char OP_Ack = 0x15; -static const char OP_AppCombined = 0x19; -static const char OP_OutOfSession = 0x1d; +static constexpr char OP_SessionRequest = 0x01; +static constexpr char OP_SessionResponse = 0x02; +static constexpr char OP_Combined = 0x03; +static constexpr char OP_SessionDisconnect = 0x05; +static constexpr char OP_KeepAlive = 0x06; +static constexpr char OP_SessionStatRequest = 0x07; +static constexpr char OP_SessionStatResponse = 0x08; +static constexpr char OP_Packet = 0x09; +static constexpr char OP_Fragment = 0x0d; +static constexpr char OP_OutOfOrderAck = 0x11; +static constexpr char OP_Ack = 0x15; +static constexpr char OP_AppCombined = 0x19; +static constexpr char OP_OutOfSession = 0x1d; diff --git a/common/opcodemgr.cpp b/common/opcodemgr.cpp index c14888e7c..d028d139b 100644 --- a/common/opcodemgr.cpp +++ b/common/opcodemgr.cpp @@ -142,10 +142,12 @@ RegularOpcodeManager::~RegularOpcodeManager() { safe_delete_array(eq_to_emu); } -bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) { +bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) +{ + std::scoped_lock lock(MOpcodes); + NormalMemStrategy s; s.it = this; - MOpcodes.lock(); loaded = true; eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE]; @@ -158,32 +160,30 @@ bool RegularOpcodeManager::LoadOpcodes(const char *filename, bool report_errors) memset(emu_to_eq, 0, sizeof(uint16)*_maxEmuOpcode); bool ret = LoadOpcodesFile(filename, &s, report_errors); - MOpcodes.unlock(); return ret; } -bool RegularOpcodeManager::ReloadOpcodes(const char *filename, bool report_errors) { - if(!loaded) - return(LoadOpcodes(filename)); +bool RegularOpcodeManager::ReloadOpcodes(const char* filename, bool report_errors) +{ + if (!loaded) + return LoadOpcodes(filename); + + std::scoped_lock lock(MOpcodes); NormalMemStrategy s; s.it = this; - MOpcodes.lock(); - memset(eq_to_emu, 0, sizeof(uint16)*MAX_EQ_OPCODE); - - bool ret = LoadOpcodesFile(filename, &s, report_errors); - - MOpcodes.unlock(); - return(ret); + memset(eq_to_emu, 0, sizeof(uint16) * MAX_EQ_OPCODE); + return LoadOpcodesFile(filename, &s, report_errors); } uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { //opcode is checked for validity in GetEQOpcode uint16 res; - MOpcodes.lock(); - res = emu_to_eq[emu_op]; - MOpcodes.unlock(); + { + std::scoped_lock lock(MOpcodes); + res = emu_to_eq[emu_op]; + } LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res); @@ -193,15 +193,18 @@ uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { return(res); } -EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) { +EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) +{ //opcode is checked for validity in GetEmuOpcode -//Disabled since current live EQ uses the entire uint16 bitspace for opcodes -// if(eq_op > MAX_EQ_OPCODE) -// return(OP_Unknown); + //Disabled since current live EQ uses the entire uint16 bitspace for opcodes + // if(eq_op > MAX_EQ_OPCODE) + // return(OP_Unknown); EmuOpcode res; - MOpcodes.lock(); - res = eq_to_emu[eq_op]; - MOpcodes.unlock(); + { + std::scoped_lock lock(MOpcodes); + res = eq_to_emu[eq_op]; + } + #ifdef DEBUG_TRANSLATE fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res); #endif diff --git a/common/opcodemgr.h b/common/opcodemgr.h index 152b652aa..ba274bf12 100644 --- a/common/opcodemgr.h +++ b/common/opcodemgr.h @@ -18,10 +18,10 @@ #pragma once #include "common/emu_opcodes.h" -#include "common/mutex.h" #include "common/types.h" #include +#include //enable the use of shared mem opcodes for world and zone only #ifdef ZONE @@ -31,7 +31,8 @@ #define SHARED_OPCODES #endif -class OpcodeManager { +class OpcodeManager +{ public: OpcodeManager(); virtual ~OpcodeManager() {} @@ -48,24 +49,27 @@ public: EmuOpcode NameSearch(const char *name); //This has to be public for stupid visual studio - class OpcodeSetStrategy { + class OpcodeSetStrategy + { public: - virtual ~OpcodeSetStrategy() {} //shut up compiler! + virtual ~OpcodeSetStrategy() = default; virtual void Set(EmuOpcode emu_op, uint16 eq_op) = 0; }; protected: bool loaded; //true if all opcodes loaded - Mutex MOpcodes; //this only protects the local machine + std::mutex MOpcodes; //this only protects the local machine //in a shared manager, this dosent protect others static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors); }; -class MutableOpcodeManager : public OpcodeManager { +class MutableOpcodeManager : public OpcodeManager +{ public: - MutableOpcodeManager() : OpcodeManager() {} - virtual bool Mutable() { return(true); } + MutableOpcodeManager() = default; + + virtual bool Mutable() override { return true; } virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) = 0; }; @@ -108,16 +112,16 @@ public: virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op); protected: - class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy { + class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy + { public: - virtual ~NormalMemStrategy() {} //shut up compiler! - RegularOpcodeManager *it; - void Set(EmuOpcode emu_op, uint16 eq_op); - }; - friend class NormalMemStrategy; + RegularOpcodeManager* it; - uint16 *emu_to_eq; - EmuOpcode *eq_to_emu; + virtual void Set(EmuOpcode emu_op, uint16 eq_op) override; + }; + + uint16* emu_to_eq; + EmuOpcode* eq_to_emu; uint32 EQOpcodeCount; uint32 EmuOpcodeCount; }; diff --git a/common/patches/rof.cpp b/common/patches/rof.cpp index 90fc99312..3ce262080 100644 --- a/common/patches/rof.cpp +++ b/common/patches/rof.cpp @@ -3221,7 +3221,7 @@ namespace RoF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/rof2.cpp b/common/patches/rof2.cpp index b240fd4b3..992f0c538 100644 --- a/common/patches/rof2.cpp +++ b/common/patches/rof2.cpp @@ -689,7 +689,7 @@ namespace RoF2 EQApplicationPacket *outapp = nullptr; if (eq->bufffade == 1) { - outapp = new EQApplicationPacket(OP_BuffCreate, 29); + outapp = new EQApplicationPacket(OP_BuffCreate, 29u); outapp->WriteUInt32(emu->entityid); outapp->WriteUInt32(0); // tic timer outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? @@ -753,7 +753,7 @@ namespace RoF2 ar(bl); //packet size - auto packet_size = bl.item_name.length() + 1 + 34; + size_t packet_size = bl.item_name.length() + 1 + 34; for (auto const &b: bl.trade_items) { packet_size += b.item_name.length() + 1; packet_size += 12; @@ -1622,7 +1622,7 @@ namespace RoF2 //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Yourname is %s", gu2->yourname); int MemberCount = 1; - int PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; + uint32 PacketLength = 8 + strlen(gu2->leadersname) + 1 + 22 + strlen(gu2->yourname) + 1; for (int i = 0; i < 5; ++i) { @@ -2207,7 +2207,7 @@ namespace RoF2 char *Buffer = (char *)in->pBuffer; - int PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; + uint32 PacketSize = sizeof(structs::MercenaryMerchantList_Struct) - 4 + emu->MercTypeCount * 4; PacketSize += (sizeof(structs::MercenaryListEntry_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount; uint32 r; @@ -3820,7 +3820,7 @@ namespace RoF2 buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; @@ -4120,8 +4120,8 @@ namespace RoF2 std::begin(emu->items), std::end(emu->items), std::begin(eq->items), - [&](const uint32 x) { - return x; + [&](uint64 x) { + return static_cast(x); } ); std::copy_n( @@ -4599,7 +4599,7 @@ namespace RoF2 int k; for (r = 0; r < entrycount; r++, emu++) { - int PacketSize = 206; + uint32 PacketSize = 206; PacketSize += strlen(emu->name); PacketSize += strlen(emu->lastName); diff --git a/common/patches/sod.cpp b/common/patches/sod.cpp index 27224e380..ca8602565 100644 --- a/common/patches/sod.cpp +++ b/common/patches/sod.cpp @@ -2128,7 +2128,7 @@ namespace SoD buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/sof.cpp b/common/patches/sof.cpp index 818bc3b8f..ed72691f6 100644 --- a/common/patches/sof.cpp +++ b/common/patches/sof.cpp @@ -1785,7 +1785,7 @@ namespace SoF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/titanium.cpp b/common/patches/titanium.cpp index c3fdf479e..395094306 100644 --- a/common/patches/titanium.cpp +++ b/common/patches/titanium.cpp @@ -1991,7 +1991,7 @@ namespace Titanium buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/patches/uf.cpp b/common/patches/uf.cpp index 05c058217..32f958b35 100644 --- a/common/patches/uf.cpp +++ b/common/patches/uf.cpp @@ -2711,7 +2711,7 @@ namespace UF buf.WriteString(new_message); - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); dest->FastQueuePacket(&outapp, ack_req); delete in; diff --git a/common/platform/win/include_winsock2.h b/common/platform/win/include_winsock2.h index 0aaf30931..e5410094e 100644 --- a/common/platform/win/include_winsock2.h +++ b/common/platform/win/include_winsock2.h @@ -19,6 +19,7 @@ #ifdef _WINDOWS +#include "common/platform/win/include_windows.h" #include #endif // _WINDOWS diff --git a/common/process.cpp b/common/process.cpp index 44554f367..54521715b 100644 --- a/common/process.cpp +++ b/common/process.cpp @@ -23,11 +23,13 @@ inline std::string random_string(size_t length) { - auto randchar = []() -> char { + auto randchar = []() -> char + { const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; const size_t max_index = (sizeof(charset) - 1); return charset[static_cast(std::rand()) % max_index]; }; + std::string str(length, 0); std::generate_n(str.begin(), length, randchar); return str; diff --git a/common/serialize_buffer.h b/common/serialize_buffer.h index fb3e2904e..9e5ba8a9b 100644 --- a/common/serialize_buffer.h +++ b/common/serialize_buffer.h @@ -27,7 +27,7 @@ class SerializeBuffer { public: - SerializeBuffer() : m_buffer(nullptr), m_capacity(0), m_pos(0) {} + SerializeBuffer() = default; explicit SerializeBuffer(size_t size) : m_capacity(size), m_pos(0) { @@ -35,8 +35,10 @@ public: memset(m_buffer, 0, size); } - SerializeBuffer(const SerializeBuffer &rhs) - : m_buffer(new unsigned char[rhs.m_capacity]), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos) + SerializeBuffer(const SerializeBuffer& rhs) + : m_buffer(new unsigned char[rhs.m_capacity]) + , m_capacity(rhs.m_capacity) + , m_pos(rhs.m_pos) { memcpy(m_buffer, rhs.m_buffer, rhs.m_capacity); } @@ -53,30 +55,31 @@ public: return *this; } - SerializeBuffer(SerializeBuffer &&rhs) : m_buffer(rhs.m_buffer), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos) + SerializeBuffer(SerializeBuffer&& rhs) + : m_buffer(std::exchange(rhs.m_buffer, nullptr)) + , m_capacity(std::exchange(rhs.m_capacity, 0)) + , m_pos(std::exchange(rhs.m_pos, 0)) { - rhs.m_buffer = nullptr; - rhs.m_capacity = 0; - rhs.m_pos = 0; } - SerializeBuffer &operator=(SerializeBuffer &&rhs) + SerializeBuffer& operator=(SerializeBuffer&& rhs) { - if (this != &rhs) { + if (this != &rhs) + { delete[] m_buffer; - m_buffer = rhs.m_buffer; - m_capacity = rhs.m_capacity; - m_pos = rhs.m_pos; - - rhs.m_buffer = nullptr; - rhs.m_capacity = 0; - rhs.m_pos = 0; + m_buffer = std::exchange(rhs.m_buffer, nullptr); + m_capacity = std::exchange(rhs.m_capacity, 0); + m_pos = std::exchange(rhs.m_pos, 0); } + return *this; } - ~SerializeBuffer() { delete[] m_buffer; } + ~SerializeBuffer() + { + delete[] m_buffer; + } void WriteUInt8(uint8_t v) { @@ -209,7 +212,8 @@ public: private: void Grow(size_t new_size); void Reset(); - unsigned char *m_buffer; - size_t m_capacity; - size_t m_pos; + + unsigned char* m_buffer = nullptr; + size_t m_capacity = 0; + size_t m_pos = 0; }; diff --git a/common/servertalk.h b/common/servertalk.h index e550dc5d1..da30dc4b1 100644 --- a/common/servertalk.h +++ b/common/servertalk.h @@ -389,35 +389,31 @@ enum { class ServerPacket { public: - ~ServerPacket() { safe_delete_array(pBuffer); } - ServerPacket(uint16 in_opcode = 0, uint32 in_size = 0) { - this->compressed = false; - size = in_size; - opcode = in_opcode; - if (size == 0) { - pBuffer = 0; - } - else { + ~ServerPacket() + { + safe_delete_array(pBuffer); + } + + ServerPacket(uint16 in_opcode = 0, size_t in_size = 0) + : size(static_cast(in_size)) + , opcode(in_opcode) + { + if (size != 0) + { pBuffer = new uchar[size]; memset(pBuffer, 0, size); } - _wpos = 0; - _rpos = 0; } - ServerPacket(uint16 in_opcode, const EQ::Net::Packet &p) { - this->compressed = false; - size = (uint32)p.Length(); - opcode = in_opcode; - if (size == 0) { - pBuffer = 0; - } - else { + ServerPacket(uint16 in_opcode, const EQ::Net::Packet& p) + : size(static_cast(p.Length())) + , opcode(in_opcode) + { + if (size != 0) + { pBuffer = new uchar[size]; memcpy(pBuffer, p.Data(), size); } - _wpos = 0; - _rpos = 0; } ServerPacket* Copy() { @@ -447,14 +443,14 @@ public: void ReadSkipBytes(uint32 count) { _rpos += count; } void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } - uint32 size; - uint16 opcode; - uchar* pBuffer; - uint32 _wpos; - uint32 _rpos; - bool compressed; - uint32 InflatedSize; - uint32 destination; + uint32 size = 0; + uint16 opcode = 0; + uchar* pBuffer = nullptr; + uint32 _wpos = 0; + uint32 _rpos = 0; + bool compressed = false; + uint32 InflatedSize = 0; + uint32 destination = 0; }; #pragma pack(push) @@ -989,11 +985,12 @@ struct LauncherConnectInfo { char name[64]; }; -typedef enum { +enum ZoneRequestCommands { ZR_Start, ZR_Restart, ZR_Stop -} ZoneRequestCommands; +}; + struct LauncherZoneRequest { uint8 command; char short_name[33]; diff --git a/common/tasks.h b/common/tasks.h index ace848f4d..2776f6686 100644 --- a/common/tasks.h +++ b/common/tasks.h @@ -38,10 +38,10 @@ #define RELOADTASKS 0 #define RELOADTASKSETS 2 -typedef enum { +enum TaskMethodType { METHODSINGLEID = 0, METHODQUEST = 2 -} TaskMethodType; +}; enum class TaskActivityType : int32_t // task element/objective { diff --git a/libs/luabind/src/inheritance.cpp b/libs/luabind/src/inheritance.cpp index 2e2ec902a..b70db95e3 100644 --- a/libs/luabind/src/inheritance.cpp +++ b/libs/luabind/src/inheritance.cpp @@ -94,7 +94,7 @@ namespace { m_cache.insert(std::make_pair( key_type(src, target, dynamic_id, object_offset) - , cache_entry(offset, distance) + , cache_entry(offset, static_cast(distance)) )); } diff --git a/loginserver/client.cpp b/loginserver/client.cpp index d9baf088f..165ac7bdc 100644 --- a/loginserver/client.cpp +++ b/loginserver/client.cpp @@ -547,7 +547,7 @@ void Client::SendExpansionPacketData(PlayerLoginReply &plrs) buf.WriteInt32(0xFFFFFFFF); } - auto out = std::make_unique(OP_LoginExpansionPacketData, buf); + auto out = std::make_unique(OP_LoginExpansionPacketData, std::move(buf)); m_connection->QueuePacket(out.get()); } diff --git a/loginserver/world_server_manager.cpp b/loginserver/world_server_manager.cpp index 118a58f5c..d519710ba 100644 --- a/loginserver/world_server_manager.cpp +++ b/loginserver/world_server_manager.cpp @@ -153,7 +153,7 @@ std::unique_ptr WorldServerManager::CreateServerListPacket( s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion()); } - return std::make_unique(OP_ServerListResponse, buf); + return std::make_unique(OP_ServerListResponse, std::move(buf)); } void WorldServerManager::SendUserLoginToWorldRequest( diff --git a/world/cli/cli_database_concurrency.cpp b/world/cli/cli_database_concurrency.cpp index 557e14174..6816d1c15 100644 --- a/world/cli/cli_database_concurrency.cpp +++ b/world/cli/cli_database_concurrency.cpp @@ -20,9 +20,12 @@ #include "common/eqemu_config.h" #include "common/repositories/zone_repository.h" +#include #include #include +using namespace std::chrono_literals; + Database db; Database db2; @@ -60,8 +63,6 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser LogInfo("Database test"); - auto mutex = new Mutex; - auto c = EQEmuConfig::get(); LogInfo("Connecting to MySQL"); if (!db.Connect( @@ -75,19 +76,19 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser return; } - db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + + db.SetMutex(sharedMutex); db2.SetMySQL(db); - db2.SetMutex(mutex); + db2.SetMutex(sharedMutex); std::thread(DatabaseTest).detach(); std::thread(DatabaseTest).detach(); std::thread(DatabaseTestSecondConnection).detach(); while (!stop) { - + std::this_thread::sleep_for(0s); } - - safe_delete(mutex); } diff --git a/world/cli/cli_database_version.cpp b/world/cli/cli_database_version.cpp index db2a41b69..907bd95ee 100644 --- a/world/cli/cli_database_version.cpp +++ b/world/cli/cli_database_version.cpp @@ -37,8 +37,5 @@ void WorldserverCLI::DatabaseVersion(int argc, char **argv, argh::parser &cmd, s v["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0; v["custom_database_version"] = CUSTOM_BINARY_DATABASE_VERSION; - std::stringstream payload; - payload << v; - - std::cout << payload.str() << std::endl; + std::cout << v << std::endl; } diff --git a/world/cli/cli_test.cpp b/world/cli/cli_test.cpp index 0353e4815..4878b4f39 100644 --- a/world/cli/cli_test.cpp +++ b/world/cli/cli_test.cpp @@ -18,7 +18,7 @@ #include "world/world_server_cli.h" #include "common/events/player_events.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include "cereal/archives/json.hpp" #include "cereal/types/vector.hpp" diff --git a/world/cli/cli_version.cpp b/world/cli/cli_version.cpp index 871b07dbd..30c070ae1 100644 --- a/world/cli/cli_version.cpp +++ b/world/cli/cli_version.cpp @@ -39,8 +39,5 @@ void WorldserverCLI::Version(int argc, char **argv, argh::parser &cmd, std::stri j["database_version"] = CURRENT_BINARY_DATABASE_VERSION; j["server_version"] = CURRENT_VERSION; - std::stringstream payload; - payload << j; - - std::cout << payload.str() << std::endl; + std::cout << j << std::endl; } diff --git a/world/cliententry.h b/world/cliententry.h index a94433b93..3da6cba84 100644 --- a/world/cliententry.h +++ b/world/cliententry.h @@ -24,14 +24,14 @@ #include -typedef enum { +enum CLE_Status { Never, Offline, Online, CharSelect, Zoning, InZone -} CLE_Status; +}; static const char *CLEStatusString[] = { "Never", diff --git a/world/eql_config.h b/world/eql_config.h index ca3ab3f73..13b9c0a62 100644 --- a/world/eql_config.h +++ b/world/eql_config.h @@ -25,10 +25,10 @@ class LauncherLink; -typedef struct { +struct LauncherZone{ std::string name; uint16 port; -} LauncherZone; +}; //a class exported to perl representing a launcher's in-DB config class EQLConfig { diff --git a/world/launcher_link.h b/world/launcher_link.h index 2e8e6bc20..d516ccc6b 100644 --- a/world/launcher_link.h +++ b/world/launcher_link.h @@ -69,10 +69,10 @@ protected: uint8 m_dynamicCount; - typedef struct { + struct ZoneState{ bool up; uint32 starts; //number of times this zone has started uint16 port; //the port this zone wants to use (0=pick one) - } ZoneState; + }; std::map m_states; }; diff --git a/world/login_server.h b/world/login_server.h index b5bd5a038..892917895 100644 --- a/world/login_server.h +++ b/world/login_server.h @@ -20,7 +20,6 @@ #include "common/eq_packet_structs.h" #include "common/event/timer.h" #include "common/linked_list.h" -#include "common/mutex.h" #include "common/net/servertalk_client_connection.h" #include "common/net/servertalk_legacy_client_connection.h" #include "common/queue.h" diff --git a/world/login_server_list.h b/world/login_server_list.h index 7bd3a812a..1911a54ee 100644 --- a/world/login_server_list.h +++ b/world/login_server_list.h @@ -18,7 +18,6 @@ #pragma once #include "common/eq_packet_structs.h" -#include "common/mutex.h" #include "common/queue.h" #include "common/servertalk.h" #include "common/timer.h" diff --git a/world/shared_task_manager.cpp b/world/shared_task_manager.cpp index d3a9bd2b9..b9692d222 100644 --- a/world/shared_task_manager.cpp +++ b/world/shared_task_manager.cpp @@ -319,14 +319,14 @@ void SharedTaskManager::LoadSharedTaskState() // load character data for member names std::vector shared_task_character_data; if (!shared_task_members_data.empty()) { - std::vector character_ids; - for (const auto &m: shared_task_members_data) { + std::vector character_ids; + for (const BaseSharedTaskMembersRepository::SharedTaskMembers& m: shared_task_members_data) { character_ids.emplace_back(m.character_id); } shared_task_character_data = CharacterDataRepository::GetWhere( *m_database, - fmt::format("id IN ({})", Strings::Join(character_ids, ",")) + fmt::format("id IN ({})", fmt::join(character_ids, ",")) ); } diff --git a/world/ucs.h b/world/ucs.h index df3ec9e6d..884628784 100644 --- a/world/ucs.h +++ b/world/ucs.h @@ -44,6 +44,6 @@ public: private: inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; } - std::shared_ptr connection; + std::shared_ptr connection; }; diff --git a/world/world_boot.cpp b/world/world_boot.cpp index 7c2afc388..4bd6c79fd 100644 --- a/world/world_boot.cpp +++ b/world/world_boot.cpp @@ -24,8 +24,7 @@ #include "common/http/httplib.h" #include "common/http/uri.h" #include "common/ip_util.h" -#include "common/net/console_server.h" -#include "common/net/servertalk_server.h" +#include "common/net/dns.h" #include "common/path_manager.h" #include "common/repositories/character_expedition_lockouts_repository.h" #include "common/repositories/character_task_timers_repository.h" @@ -33,7 +32,6 @@ #include "common/rulesys.h" #include "common/strings.h" #include "common/zone_store.h" -#include "common/zone_store.h" #include "world/adventure_manager.h" #include "world/dynamic_zone_manager.h" #include "world/login_server_list.h" @@ -49,8 +47,6 @@ extern WorldConfig Config; -auto mutex = new Mutex; - void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message) { // we don't want to loop up with chat messages @@ -180,11 +176,13 @@ bool WorldBoot::LoadDatabaseConnections() } else { content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection // it needs to be protected by a shared mutex otherwise we produce concurrency issues // when database actions are occurring in different threads - database.SetMutex(mutex); - content_db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + database.SetMutex(sharedMutex); + content_db.SetMutex(sharedMutex); } return true; @@ -456,7 +454,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues() std::string config_address = c->WorldAddress; if (!IpUtil::IsIPAddress(config_address)) { - config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000); + config_address = EQ::Net::DNSLookupSync(c->WorldAddress, 9000); LogInfo( "World config address using DNS [{}] resolves to [{}]", c->WorldAddress, @@ -634,7 +632,6 @@ void WorldBoot::CheckForPossibleConfigurationIssues() void WorldBoot::Shutdown() { - safe_delete(mutex); } void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message) diff --git a/zone/aa.h b/zone/aa.h index f5e015bc1..61ae79940 100644 --- a/zone/aa.h +++ b/zone/aa.h @@ -20,7 +20,7 @@ #define MAX_SWARM_PETS 12 //this can change as long as you make more coords (swarm_pet_x/swarm_pet_y) #define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template -typedef enum { +enum aaNonspellAction { aaActionNone = 0, aaActionAETaunt = 1, aaActionMassBuff = 2, @@ -38,7 +38,7 @@ typedef enum { aaActionLeechTouch = 14, aaActionProjectIllusion = 15, aaActionFadingMemories = 16 -} aaNonspellAction; +}; enum { //leadership AA indexes groupAAMarkNPC = 0, @@ -116,7 +116,7 @@ static const uint8 LeadershipAACosts[_maxLeaderAA][MAX_LEADERSHIP_TIERS] = { { 0, 0, 0, 0, 0, 0 }, //raidAA15 }; -typedef enum { //AA IDs +enum aaID { //AA IDs aaNone =0, aaInnateStrength =2,//implemented as bonus aaInnateStamina =7,//implemented as bonus @@ -1525,7 +1525,7 @@ typedef enum { //AA IDs aaHighestID //this should always be last, and should always //follow the highest AA ID -} aaID; +}; //Structure representing the database's swarm pet configs struct SwarmPet_Struct { diff --git a/zone/bot.cpp b/zone/bot.cpp index b543ea246..8c3f668a4 100644 --- a/zone/bot.cpp +++ b/zone/bot.cpp @@ -10580,12 +10580,12 @@ void Bot::LoadDefaultBotSettings() { m_bot_spell_settings.push_back(t); LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}] - [{} [#{}] stance]'", GetCleanName(), t.name, t.short_name, t.spell_type, Stance::GetName(bot_stance), bot_stance); - LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), + LogBotSettingsDetail("{} says, 'Hold = [{}] | Delay = [{}ms] | MinThreshold = [{}%] | MaxThreshold = [{}%]'", GetCleanName(), GetDefaultSpellTypeHold(i, bot_stance), GetDefaultSpellTypeDelay(i, bot_stance), GetDefaultSpellTypeMinThreshold(i, bot_stance), GetDefaultSpellTypeMaxThreshold(i, bot_stance)); - LogBotSettingsDetail("{} says, 'AggroCheck = [{}] | MinManaPCT = [{}\%] | MaxManaPCT = [{}\%] | MinHPPCT = [{}\% | MaxHPPCT = [{}\%]'", GetCleanName(), GetDefaultSpellTypeAggroCheck(i, bot_stance), GetDefaultSpellTypeMinManaLimit(i, bot_stance), GetDefaultSpellTypeMaxManaLimit(i, bot_stance), GetDefaultSpellTypeMinHPLimit(i, bot_stance), GetDefaultSpellTypeMaxHPLimit(i, bot_stance)); + LogBotSettingsDetail("{} says, 'AggroCheck = [{}] | MinManaPCT = [{}%] | MaxManaPCT = [{}%] | MinHPPCT = [{}% | MaxHPPCT = [{}%]'", GetCleanName(), GetDefaultSpellTypeAggroCheck(i, bot_stance), GetDefaultSpellTypeMinManaLimit(i, bot_stance), GetDefaultSpellTypeMaxManaLimit(i, bot_stance), GetDefaultSpellTypeMinHPLimit(i, bot_stance), GetDefaultSpellTypeMaxHPLimit(i, bot_stance)); LogBotSettingsDetail("{} says, 'IdlePriority = [{}] | EngagedPriority = [{}] | PursuePriority = [{}]'", GetCleanName(), GetDefaultSpellTypeIdlePriority(i, GetClass(), bot_stance), GetDefaultSpellTypeEngagedPriority(i, GetClass(), bot_stance), GetDefaultSpellTypePursuePriority(i, GetClass(), bot_stance)); LogBotSettingsDetail("{} says, 'TargetCount = [{}] | AnnounceCast = [{}]'", GetCleanName(), GetDefaultSpellTypeAEOrGroupTargetCount(i, bot_stance), GetDefaultSpellTypeAnnounceCast(i, bot_stance)); } @@ -10636,7 +10636,7 @@ void Bot::SetBotSpellRecastTimer(uint16 spell_type, Mob* tar, bool precast) { BotSpell Bot::GetSpellByHealType(uint16 spell_type, Mob* tar) { if (!TargetValidation(tar)) { - BotSpell result; + BotSpell result{}; return result; } diff --git a/zone/bot_command.cpp b/zone/bot_command.cpp index decd84e07..594d28b47 100644 --- a/zone/bot_command.cpp +++ b/zone/bot_command.cpp @@ -458,9 +458,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas return bot_id; } - bool available_flag = false; - - !database.botdb.QueryNameAvailability(bot_name, available_flag); + bool available_flag = database.botdb.QueryNameAvailability(bot_name); if (!available_flag) { bot_owner->Message( diff --git a/zone/bot_command.h b/zone/bot_command.h index 382d39794..6f3de0544 100644 --- a/zone/bot_command.h +++ b/zone/bot_command.h @@ -24,26 +24,22 @@ class Client; class Seperator; - -namespace -{ #define HP_RATIO_DELTA 5.0f - enum { EffectIDFirst = 1, EffectIDLast = 12 }; +enum { EffectIDFirst = 1, EffectIDLast = 12 }; #define VALIDATECLASSID(x) ((x >= Class::Warrior && x <= Class::Berserker) ? (x) : (0)) - // ActionableTarget action_type +// ActionableTarget action_type #define FRIENDLY true #define ENEMY false - enum { - AFT_None = 0, - AFT_Value, - AFT_GenderRace, - AFT_Race - }; -} +enum { + AFT_None = 0, + AFT_Value, + AFT_GenderRace, + AFT_Race +}; namespace MyBots { diff --git a/zone/bot_commands/bot_bot.cpp b/zone/bot_commands/bot_bot.cpp index e1f881bdf..32e99bbcd 100644 --- a/zone/bot_commands/bot_bot.cpp +++ b/zone/bot_commands/bot_bot.cpp @@ -145,9 +145,7 @@ void bot_command_clone(Client *c, const Seperator *sep) return; } - bool available_flag = false; - - !database.botdb.QueryNameAvailability(bot_name, available_flag); + bool available_flag = database.botdb.QueryNameAvailability(bot_name); if (!available_flag) { c->Message( diff --git a/zone/bot_commands/bot_pickpocket.cpp b/zone/bot_commands/bot_pickpocket.cpp index 216d9d078..a58aaa333 100644 --- a/zone/bot_commands/bot_pickpocket.cpp +++ b/zone/bot_commands/bot_pickpocket.cpp @@ -82,8 +82,8 @@ void bot_command_pickpocket(Client *c, const Seperator *sep) } // Setup variables for calcs - bool steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets); - bool steal_chance = steal_skill * 100 / (5 * over_level + 5); + uint16 steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets); + int steal_chance = steal_skill * 100 / (5 * over_level + 5); // Determine whether to steal money or an item. uint32 money[6] = { diff --git a/zone/bot_database.cpp b/zone/bot_database.cpp index 5982fc0a7..a8f1952cb 100644 --- a/zone/bot_database.cpp +++ b/zone/bot_database.cpp @@ -228,7 +228,7 @@ bool BotDatabase::LoadBotSpellCastingChances() return true; } -bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& available_flag) +bool BotDatabase::QueryNameAvailability(const std::string& bot_name) { if ( bot_name.empty() || @@ -239,8 +239,6 @@ bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& avail return false; } - available_flag = true; - return true; } diff --git a/zone/bot_database.h b/zone/bot_database.h index 31ad3368d..8fb2aa1d2 100644 --- a/zone/bot_database.h +++ b/zone/bot_database.h @@ -45,7 +45,7 @@ public: /* Bot functions */ - bool QueryNameAvailability(const std::string& bot_name, bool& available_flag); + bool QueryNameAvailability(const std::string& bot_name); bool QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count); bool LoadBotsList(const uint32 owner_id, std::list& bots_list, bool by_account = false); diff --git a/zone/cheat_manager.h b/zone/cheat_manager.h index 0c6432b5a..0b4f587cc 100644 --- a/zone/cheat_manager.h +++ b/zone/cheat_manager.h @@ -27,7 +27,7 @@ class CheatManager; class Client; -typedef enum { +enum UpdateMovementType { Collision = 1, TeleportB, TeleportA, @@ -37,18 +37,18 @@ typedef enum { SpellA, // Titanium - UF Unknown0x8, SpellB // Used in RoF+ -} UpdateMovementType; +}; -typedef enum { +enum ExemptionType { ShadowStep, KnockBack, Port, Assist, Sense, MAX_EXEMPTIONS -} ExemptionType; +}; -typedef enum { +enum CheatTypes { MQWarp, MQWarpShadowStep, MQWarpKnockBack, @@ -59,7 +59,7 @@ typedef enum { MQGhost, MQFastMem, MQWarpAbsolute -} CheatTypes; +}; class CheatManager { public: diff --git a/zone/client.cpp b/zone/client.cpp index 67462169f..56d59c4b3 100644 --- a/zone/client.cpp +++ b/zone/client.cpp @@ -1784,7 +1784,7 @@ void Client::Message(uint32 type, const char* message, ...) { buf.WriteInt32(0); buf.WriteString(buffer); - auto app = new EQApplicationPacket(OP_SpecialMesg, buf); + auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); FastQueuePacket(&app); @@ -1813,7 +1813,7 @@ void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, cons buf.WriteInt32(0); buf.WriteString(buffer); - auto app = new EQApplicationPacket(OP_SpecialMesg, buf); + auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); FastQueuePacket(&app); @@ -3869,7 +3869,7 @@ void Client::MessageString(uint32 type, uint32 string_id, const char* message1, buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime - auto outapp = std::make_unique(OP_FormattedMessage, buf); + auto outapp = std::make_unique(OP_FormattedMessage, std::move(buf)); if (distance > 0) entity_list.QueueCloseClients(this, outapp.get(), false, distance); @@ -3987,7 +3987,7 @@ void Client::FilteredMessageString(Mob *sender, uint32 type, eqFilterType filter buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime - auto outapp = std::make_unique(OP_FormattedMessage, buf); + auto outapp = std::make_unique(OP_FormattedMessage, std::move(buf)); QueuePacket(outapp.get()); } diff --git a/zone/client.h b/zone/client.h index 9dc5960e7..4e9b5e891 100644 --- a/zone/client.h +++ b/zone/client.h @@ -106,7 +106,7 @@ enum { //scribing argument to MemorizeSpell }; //Modes for the zoning state of the client. -typedef enum { +enum ZoneMode { ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac GMSummon, // Always send ZonePlayerToBind_Struct to client: Only a GM Summon GMHiddenSummon, // Always send ZonePlayerToBind_Struct to client silently: Only a GM Summon @@ -117,7 +117,7 @@ typedef enum { SummonPC, // In-zone GMMove() always: Call of the Hero spell or some other type of in zone only summons Rewind, // Summon to /rewind location. EvacToSafeCoords -} ZoneMode; +}; // translate above enum to a string std::string GetZoneModeString(ZoneMode mode); @@ -130,13 +130,13 @@ enum { HideCorpseNPC = 5 }; -typedef enum +enum ShowSpellType { Disciplines, Spells -} ShowSpellType; +}; -typedef enum +enum XTargetType { Empty = 0, Auto = 1, @@ -165,8 +165,7 @@ typedef enum MyPetTarget = 24, MyMercenary = 25, MyMercenaryTarget = 26 - -} XTargetType; +}; struct XTarget_Struct { diff --git a/zone/client_bot.cpp b/zone/client_bot.cpp index 0e914c145..eebb63556 100644 --- a/zone/client_bot.cpp +++ b/zone/client_bot.cpp @@ -252,7 +252,7 @@ void Client::LoadDefaultBotSettings() { m_bot_spell_settings.push_back(t); LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}]'", GetCleanName(), t.name, t.short_name, t.spell_type); - LogBotSettingsDetail("{} says, 'Delay = [{}ms] | MinThreshold = [{}\%] | MaxThreshold = [{}\%]'", GetCleanName(), + LogBotSettingsDetail("{} says, 'Delay = [{}ms] | MinThreshold = [{}%] | MaxThreshold = [{}%]'", GetCleanName(), GetDefaultSpellTypeDelay(i), GetDefaultSpellTypeMinThreshold(i), GetDefaultSpellTypeMaxThreshold(i)); } diff --git a/zone/client_packet.cpp b/zone/client_packet.cpp index 87a4a4009..7fc5174f6 100644 --- a/zone/client_packet.cpp +++ b/zone/client_packet.cpp @@ -3239,10 +3239,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app) } if ( - ((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) && + tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), static_cast(in_augment->augment_index)) && tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots) ) { - old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); + old_aug = tobe_auged->RemoveAugment(static_cast(in_augment->augment_index)); if (old_aug) { // An old augment was removed in order to be replaced with the new one (augment_action 2) CalcBonuses(); diff --git a/zone/command.h b/zone/command.h index 8fa473ba6..da80557c1 100644 --- a/zone/command.h +++ b/zone/command.h @@ -28,11 +28,11 @@ class Seperator; typedef void (*CmdFuncPtr)(Client *, const Seperator *); -typedef struct { +struct CommandRecord { uint8 admin; std::string description; CmdFuncPtr function; // null means perl function -} CommandRecord; +}; extern int (*command_dispatch)(Client *, std::string, bool); extern int command_count; // Commands Loaded Count diff --git a/zone/common.h b/zone/common.h index c1376bcd0..1ab8bf2d0 100644 --- a/zone/common.h +++ b/zone/common.h @@ -922,7 +922,7 @@ struct DataBucketCache enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath }; -typedef enum { +enum PetTypeOld { petFamiliar, //only listens to /pet get lost petAnimation, //does not listen to any commands petOther, @@ -930,4 +930,4 @@ typedef enum { petNPCFollow, petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands petNone = 0xFF // not a pet -} PetTypeOld; +}; diff --git a/zone/effects.cpp b/zone/effects.cpp index 06c18a41e..0d0b1ce34 100644 --- a/zone/effects.cpp +++ b/zone/effects.cpp @@ -1108,7 +1108,7 @@ void EntityList::AESpell( max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets); } else if ( IsPBAESpell(spell_id) && - IsDetrimentalSpell && + is_detrimental_spell && !is_npc ) { max_targets_allowed = RuleI(Spells, PointBlankAOEMaxTargets); diff --git a/zone/entity.cpp b/zone/entity.cpp index e1b25370f..ddbf34b6d 100644 --- a/zone/entity.cpp +++ b/zone/entity.cpp @@ -4437,7 +4437,7 @@ void EntityList::QuestJournalledSayClose( buf.WriteString(message); } - auto outapp = new EQApplicationPacket(OP_SpecialMesg, buf); + auto outapp = new EQApplicationPacket(OP_SpecialMesg, std::move(buf)); // client only bothers logging if target spawn ID matches, safe to send to everyone QueueCloseClients(sender, outapp, false, dist); diff --git a/zone/event_codes.h b/zone/event_codes.h index e363c17de..c5210633f 100644 --- a/zone/event_codes.h +++ b/zone/event_codes.h @@ -17,7 +17,7 @@ */ #pragma once -typedef enum { +enum QuestEventID { EVENT_SAY = 0, EVENT_TRADE, //being given an item or money EVENT_DEATH, //being killed @@ -169,6 +169,6 @@ typedef enum { EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT, _LargestEventID -} QuestEventID; +}; extern const char *QuestEventSubroutines[_LargestEventID]; diff --git a/zone/gm_commands/door_manipulation.cpp b/zone/gm_commands/door_manipulation.cpp index 91472865c..b518a8c06 100644 --- a/zone/gm_commands/door_manipulation.cpp +++ b/zone/gm_commands/door_manipulation.cpp @@ -447,15 +447,15 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep) if (arg1 == "setinclineinc") { std::map incline_values = { - {.01, "Upright"}, - {63.75, "45 Degrees",}, - {130, "90 Degrees"}, - {192.5, "135 Degrees"}, - {255, "180 Degrees"}, - {321.25, "225 Degrees"}, - {385, "270 Degrees"}, - {448.75, "315 Degrees"}, - {512.5, "360 Degrees"} + {.01f, "Upright"}, + {63.75f, "45 Degrees",}, + {130.f, "90 Degrees"}, + {192.5f, "135 Degrees"}, + {255.f, "180 Degrees"}, + {321.25f, "225 Degrees"}, + {385.f, "270 Degrees"}, + {448.75f, "315 Degrees"}, + {512.5f, "360 Degrees"} }; std::vector incline_normal_options; diff --git a/zone/guild.cpp b/zone/guild.cpp index 54775c62a..5ab0a6681 100644 --- a/zone/guild.cpp +++ b/zone/guild.cpp @@ -624,7 +624,7 @@ void Client::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::str out->guild_id = guild_id; out->rank_ = rank; - out->alt_banker = (alt << 1) | banker; + out->alt_banker = (alt ? 2 : 0) | (banker ? 1 : 0); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name)); QueuePacket(outapp); @@ -792,7 +792,7 @@ void EntityList::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank_, std out->guild_id = guild_id; out->rank_ = rank_; - out->alt_banker = (alt << 1) | banker; + out->alt_banker = (alt ? 2 : 0) | (banker ? 1 : 0); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name)); c.second->QueuePacket(outapp); diff --git a/zone/lua_bit.cpp b/zone/lua_bit.cpp index 5c8af6fcc..c0712529b 100644 --- a/zone/lua_bit.cpp +++ b/zone/lua_bit.cpp @@ -151,7 +151,7 @@ static const struct luaL_Reg bit_funcs[] = { */ #define BAD_SAR (bsar(-8, 2) != (SBits)-2) -int luaopen_bit(lua_State *L) +int luaopen_bit_embed(lua_State *L) { UBits b; lua_pushnumber(L, (lua_Number)1437217655L); diff --git a/zone/lua_bit.h b/zone/lua_bit.h index 10dfdb06c..e3f163cbc 100644 --- a/zone/lua_bit.h +++ b/zone/lua_bit.h @@ -17,4 +17,6 @@ */ #pragma once -int luaopen_bit(lua_State *L); +struct lua_State; + +int luaopen_bit_embed(lua_State *L); diff --git a/zone/main.cpp b/zone/main.cpp index 82a1c3cf4..9aab5adf8 100644 --- a/zone/main.cpp +++ b/zone/main.cpp @@ -26,7 +26,6 @@ #include "common/guilds.h" #include "common/memory_mapped_file.h" #include "common/misc.h" -#include "common/mutex.h" #include "common/net/eqstream.h" #include "common/opcodemgr.h" #include "common/patches/patches.h" @@ -216,8 +215,6 @@ int main(int argc, char **argv) } } - auto mutex = new Mutex; - LogInfo("Connecting to MySQL"); if (!database.Connect( Config->DatabaseHost.c_str(), @@ -245,11 +242,13 @@ int main(int argc, char **argv) } } else { content_db.SetMySQL(database); + // when database and content_db share the same underlying mysql connection // it needs to be protected by a shared mutex otherwise we produce concurrency issues // when database actions are occurring in different threads - database.SetMutex(mutex); - content_db.SetMutex(mutex); + std::shared_ptr sharedMutex = std::make_shared(); + database.SetMutex(sharedMutex); + content_db.SetMutex(sharedMutex); } //rules: @@ -661,7 +660,6 @@ int main(int argc, char **argv) LogInfo("Proper zone shutdown complete."); EQEmuLogSys::Instance()->CloseFileLogs(); - safe_delete(mutex); safe_delete(QServ); return 0; diff --git a/zone/map.cpp b/zone/map.cpp index 65d7f30d7..0fba4d021 100644 --- a/zone/map.cpp +++ b/zone/map.cpp @@ -17,7 +17,7 @@ */ #include "common/compression.h" #include "common/file.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include "common/misc_functions.h" #include "zone/client.h" #include "zone/map.h" diff --git a/zone/npc.h b/zone/npc.h index cd352833b..06ac7101e 100644 --- a/zone/npc.h +++ b/zone/npc.h @@ -32,7 +32,7 @@ #include #include -typedef struct { +struct NPCProximity { float min_x; float max_x; float min_y; @@ -41,7 +41,7 @@ typedef struct { float max_z; bool say; bool proximity_set; -} NPCProximity; +}; struct AISpells_Struct { uint32 type; // 0 = never, must be one (and only one) of the defined values diff --git a/zone/petitions.cpp b/zone/petitions.cpp index cdb946875..4cd2959bd 100644 --- a/zone/petitions.cpp +++ b/zone/petitions.cpp @@ -135,10 +135,11 @@ void PetitionList::AddPetition(Petition* pet) { } //Return Values: 0 = Ok ; -1 = Error deleting petition. -int PetitionList::DeletePetition(uint32 petnumber) { +int PetitionList::DeletePetition(uint32 petnumber) +{ LinkedListIterator iterator(list); iterator.Reset(); - LockMutex lock(&PList_Mutex); + std::scoped_lock lock(PList_Mutex); while(iterator.MoreElements()) { if (iterator.GetData()->GetID() == petnumber) { database.DeletePetitionFromDB(iterator.GetData()); @@ -179,18 +180,18 @@ void PetitionList::ClearPetitions() { return; } -void PetitionList::ReadDatabase() { - LockMutex lock(&PList_Mutex); +void PetitionList::ReadDatabase() +{ + std::scoped_lock lock(PList_Mutex); ClearPetitions(); database.RefreshPetitionsFromDB(); UpdateGMQueue(); - return; } -void PetitionList::UpdatePetition(Petition* pet) { - LockMutex lock(&PList_Mutex); +void PetitionList::UpdatePetition(Petition* pet) +{ + std::scoped_lock lock(PList_Mutex); database.UpdatePetitionToDB(pet); - return; } void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) { diff --git a/zone/petitions.h b/zone/petitions.h index 82afa24ff..82c024eeb 100644 --- a/zone/petitions.h +++ b/zone/petitions.h @@ -18,12 +18,9 @@ #pragma once #include "common/linked_list.h" -#include "common/misc_functions.h" -#include "common/mutex.h" #include "common/types.h" -#include "common/zone_store.h" -#include "zone/client.h" -#include "zone/zonedb.h" + +#include class Client; @@ -118,5 +115,5 @@ public: private: LinkedList list; - Mutex PList_Mutex; + std::mutex PList_Mutex; }; diff --git a/zone/questmgr.cpp b/zone/questmgr.cpp index 73990d562..92de69567 100644 --- a/zone/questmgr.cpp +++ b/zone/questmgr.cpp @@ -2779,18 +2779,7 @@ bool QuestManager::createBot(const char *name, const char *lastname, uint8 level } std::string test_name = name; - bool available_flag = false; - if (!database.botdb.QueryNameAvailability(test_name, available_flag)) { - initiator->Message( - Chat::White, - fmt::format( - "Failed to query name availability for '{}'.", - test_name - ).c_str() - ); - return false; - } - + bool available_flag = database.botdb.QueryNameAvailability(test_name); if (!available_flag) { initiator->Message( Chat::White, diff --git a/zone/raycast_mesh.cpp b/zone/raycast_mesh.cpp index 64e10a523..a6c92ed1b 100644 --- a/zone/raycast_mesh.cpp +++ b/zone/raycast_mesh.cpp @@ -18,7 +18,7 @@ #include "raycast_mesh.h" #include "common/eqemu_logsys.h" -#include "common/memory/ksm.hpp" +#include "common/memory/ksm.h" #include #include diff --git a/zone/shared_task_zone_messaging.cpp b/zone/shared_task_zone_messaging.cpp index a579f53c3..0d8455e5d 100644 --- a/zone/shared_task_zone_messaging.cpp +++ b/zone/shared_task_zone_messaging.cpp @@ -117,7 +117,7 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) buf.WriteInt8(m.is_leader ? 1 : 0); } - auto outapp = std::make_unique(OP_SharedTaskMemberList, buf); + auto outapp = std::make_unique(OP_SharedTaskMemberList, std::move(buf)); c->QueuePacket(outapp.get()); } @@ -141,7 +141,7 @@ void SharedTaskZoneMessaging::HandleWorldMessage(ServerPacket *pack) // live sends more after the name but it might just be garbage from // a re-used buffer (possibly a former name[64] buffer?) - auto outapp = std::make_unique(OP_SharedTaskMemberChange, buf); + auto outapp = std::make_unique(OP_SharedTaskMemberChange, std::move(buf)); c->QueuePacket(outapp.get()); } diff --git a/zone/task_manager.cpp b/zone/task_manager.cpp index 23b308201..a3af9f013 100644 --- a/zone/task_manager.cpp +++ b/zone/task_manager.cpp @@ -858,7 +858,7 @@ void TaskManager::SendTaskSelector(Client* client, Mob* mob, const std::vectorGetTaskState()->AddOffer(task_list[i], mob->GetID()); } - auto outapp = std::make_unique(OP_TaskSelectWindow, buf); + auto outapp = std::make_unique(OP_TaskSelectWindow, std::move(buf)); client->QueuePacket(outapp.get()); } @@ -883,7 +883,7 @@ void TaskManager::SendSharedTaskSelector(Client* client, Mob* mob, const std::ve client->GetTaskState()->AddOffer(task_id, mob->GetID()); } - auto outapp = std::make_unique(OP_SharedTaskSelectWindow, buf); + auto outapp = std::make_unique(OP_SharedTaskSelectWindow, std::move(buf)); client->QueuePacket(outapp.get()); } @@ -1009,7 +1009,7 @@ void TaskManager::SendTaskActivityLong( activity.SerializeObjective(buf, client->ClientVersion(), done_count); - auto outapp = std::make_unique(OP_TaskActivity, buf); + auto outapp = std::make_unique(OP_TaskActivity, std::move(buf)); client->QueuePacket(outapp.get()); } diff --git a/zone/tradeskills.cpp b/zone/tradeskills.cpp index 049bcf590..14efb1762 100644 --- a/zone/tradeskills.cpp +++ b/zone/tradeskills.cpp @@ -621,7 +621,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } if (spec.tradeskill == EQ::skills::SkillAlchemy) { - if (!user->GetClass() == Class::Shaman) { + if (user->GetClass() != Class::Shaman) { user->Message(Chat::Red, "This tradeskill can only be performed by a shaman."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); @@ -646,7 +646,7 @@ void Object::HandleAutoCombine(Client* user, const RecipeAutoCombine_Struct* rac } } else if (spec.tradeskill == EQ::skills::SkillMakePoison) { - if (!user->GetClass() == Class::Rogue) { + if (user->GetClass() != Class::Rogue) { user->Message(Chat::Red, "Only rogues can mix poisons."); auto outapp = new EQApplicationPacket(OP_TradeSkillCombine, 0); user->QueuePacket(outapp); diff --git a/zone/water_map_v1.h b/zone/water_map_v1.h index 0a3fc3298..04acf44f7 100644 --- a/zone/water_map_v1.h +++ b/zone/water_map_v1.h @@ -21,13 +21,14 @@ #pragma pack(push) #pragma pack(1) -typedef struct ZBSP_Node { + +struct ZBSP_Node { int32 node_number; float normal[3], splitdistance; int32 region; int32 special; int32 left, right; -} ZBSP_Node; +}; #pragma pack(pop) diff --git a/zone/worldserver.cpp b/zone/worldserver.cpp index a273af186..a314936ca 100644 --- a/zone/worldserver.cpp +++ b/zone/worldserver.cpp @@ -550,7 +550,7 @@ void WorldServer::HandleMessage(uint16 opcode, const EQ::Net::Packet &p) SerializeBuffer buf(100); buf.WriteString(smotd->motd); - auto outapp = std::make_unique(OP_MOTD, buf); + auto outapp = std::make_unique(OP_MOTD, std::move(buf)); entity_list.QueueClients(0, outapp.get()); break;