Warning fixes, general cleanup (#5053)
Some checks failed
Build / Linux (push) Has been cancelled
Build / Windows (push) Has been cancelled

This commit is contained in:
brainiac 2026-04-04 23:27:21 -07:00 committed by GitHub
parent 435224631f
commit 491b1edd12
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
107 changed files with 1279 additions and 1542 deletions

1
.gitattributes vendored
View File

@ -20,3 +20,4 @@
*.css text *.css text
*.js text *.js text
*.types text *.types text
*.pdf binary

View File

@ -20,7 +20,7 @@ endif()
project(EQEmu project(EQEmu
VERSION 24.10.3 VERSION 24.10.3
LANGUAGES CXX LANGUAGES CXX
) )
set_property(GLOBAL PROPERTY USE_FOLDERS ON) set_property(GLOBAL PROPERTY USE_FOLDERS ON)
@ -42,10 +42,10 @@ option(EQEMU_BUILD_PCH "Build with precompiled headers (Windows)" ON)
if(MSVC) if(MSVC)
add_compile_options(/bigobj) 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") 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) if(EQEMU_DISABLE_MSVC_WARNINGS)
add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os) add_compile_options(/W0 /wd4005 /wd4996 /nologo /Os)
endif() endif()

View File

@ -7,20 +7,20 @@ set(common_sources
classes.cpp classes.cpp
cli/eqemu_command_handler.cpp cli/eqemu_command_handler.cpp
compression.cpp compression.cpp
condition.cpp
content/world_content_service.cpp content/world_content_service.cpp
crash.cpp crash.cpp
crc16.cpp crc16.cpp
crc32.cpp crc32.cpp
data_bucket.cpp data_bucket.cpp
data_bucket.cpp
database_instances.cpp
database.cpp database.cpp
database/database_dump_service.cpp database/database_dump_service.cpp
database/database_update.cpp database/database_update.cpp
database_instances.cpp
dbcore.cpp dbcore.cpp
deity.cpp deity.cpp
discord/discord.cpp
discord/discord_manager.cpp discord/discord_manager.cpp
discord/discord.cpp
dynamic_zone_base.cpp dynamic_zone_base.cpp
dynamic_zone_lockout.cpp dynamic_zone_lockout.cpp
emu_constants.cpp emu_constants.cpp
@ -31,13 +31,16 @@ set(common_sources
eq_packet.cpp eq_packet.cpp
eq_stream_ident.cpp eq_stream_ident.cpp
eq_stream_proxy.cpp eq_stream_proxy.cpp
eqdb.cpp
eqdb_res.cpp eqdb_res.cpp
eqdb.cpp
eqemu_config.cpp eqemu_config.cpp
eqemu_exception.cpp eqemu_exception.cpp
eqemu_logsys.cpp eqemu_logsys.cpp
eqtime.cpp eqtime.cpp
event_sub.cpp event_sub.cpp
event/event_loop.cpp
event/task_scheduler.cpp
event/timer.cpp
events/player_event_discord_formatter.cpp events/player_event_discord_formatter.cpp
events/player_event_logs.cpp events/player_event_logs.cpp
evolving_items.cpp evolving_items.cpp
@ -51,62 +54,56 @@ set(common_sources
ipc_mutex.cpp ipc_mutex.cpp
item_data.cpp item_data.cpp
item_instance.cpp item_instance.cpp
json/json.hpp
json/jsoncpp.cpp
json_config.cpp json_config.cpp
json/jsoncpp.cpp
light_source.cpp light_source.cpp
md5.cpp md5.cpp
memory/ksm.hpp
memory_buffer.cpp memory_buffer.cpp
memory_mapped_file.cpp memory_mapped_file.cpp
misc.cpp memory/ksm.cpp
misc_functions.cpp misc_functions.cpp
mutex.cpp misc.cpp
mysql_request_result.cpp mysql_request_result.cpp
mysql_request_row.cpp mysql_request_row.cpp
mysql_stmt.cpp mysql_stmt.cpp
net/console_server.cpp
net/console_server_connection.cpp net/console_server_connection.cpp
net/console_server.cpp
net/crc32.cpp net/crc32.cpp
net/dns.cpp
net/eqstream.cpp net/eqstream.cpp
net/packet.cpp net/packet.cpp
net/reliable_stream_connection.cpp net/reliable_stream_connection.cpp
net/servertalk_client_connection.cpp net/servertalk_client_connection.cpp
net/servertalk_legacy_client_connection.cpp net/servertalk_legacy_client_connection.cpp
net/servertalk_server.cpp
net/servertalk_server_connection.cpp net/servertalk_server_connection.cpp
net/servertalk_server.cpp
net/tcp_connection.cpp net/tcp_connection.cpp
net/tcp_server.cpp net/tcp_server.cpp
net/websocket_server.cpp
net/websocket_server_connection.cpp net/websocket_server_connection.cpp
net/websocket_server.cpp
opcode_map.cpp opcode_map.cpp
opcodemgr.cpp opcodemgr.cpp
packet_dump.cpp
packet_dump_file.cpp packet_dump_file.cpp
packet_dump.cpp
packet_functions.cpp packet_functions.cpp
patches/patches.cpp patches/patches.cpp
patches/rof.cpp
patches/rof2.cpp
patches/rof2_limits.cpp
patches/rof_limits.cpp patches/rof_limits.cpp
patches/sod.cpp patches/rof.cpp
patches/rof2_limits.cpp
patches/rof2.cpp
patches/sod_limits.cpp patches/sod_limits.cpp
patches/sof.cpp patches/sod.cpp
patches/sof_limits.cpp patches/sof_limits.cpp
patches/titanium.cpp patches/sof.cpp
patches/titanium_limits.cpp patches/titanium_limits.cpp
patches/uf.cpp patches/titanium.cpp
patches/uf_limits.cpp patches/uf_limits.cpp
patches/uf.cpp
path_manager.cpp
path_manager.cpp path_manager.cpp
perl_eqdb.cpp
perl_eqdb_res.cpp perl_eqdb_res.cpp
perl_eqdb.cpp
platform.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 proc_launcher.cpp
process.cpp process.cpp
process/process.cpp process/process.cpp
@ -123,12 +120,12 @@ set(common_sources
shareddb.cpp shareddb.cpp
skill_caps.cpp skill_caps.cpp
skills.cpp skills.cpp
spdat.cpp
spdat_bot.cpp spdat_bot.cpp
spdat.cpp
StackWalker/StackWalker.cpp StackWalker/StackWalker.cpp
strings.cpp
strings_legacy.cpp strings_legacy.cpp
strings_misc.cpp strings_misc.cpp
strings.cpp
struct_strategy.cpp struct_strategy.cpp
textures.cpp textures.cpp
timer.cpp timer.cpp
@ -538,35 +535,32 @@ set(repositories
) )
set(common_headers set(common_headers
StackWalker/StackWalker.h
additive_lagged_fibonacci_engine.h additive_lagged_fibonacci_engine.h
base_packet.h base_packet.h
bazaar.h bazaar.h
bodytypes.h bodytypes.h
classes.h
cli/argh.h cli/argh.h
cli/eqemu_command_handler.h cli/eqemu_command_handler.h
cli/terminal_color.hpp cli/terminal_color.hpp
classes.h
compression.h compression.h
condition.h
content/world_content_service.h content/world_content_service.h
crash.h crash.h
crc16.h crc16.h
crc32.h crc32.h
cron/croncpp.h cron/croncpp.h
data_bucket.cpp
data_verification.h data_verification.h
database_schema.h
database.h database.h
database/database_dump_service.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_bots.h
database/database_update_manifest_custom.h database/database_update_manifest_custom.h
database_schema.h database/database_update_manifest.h
database/database_update.h
dbcore.h dbcore.h
deity.h deity.h
discord/discord.h
discord/discord_manager.h discord/discord_manager.h
discord/discord.h
dynamic_zone_base.h dynamic_zone_base.h
dynamic_zone_lockout.h dynamic_zone_lockout.h
emu_constants.h emu_constants.h
@ -576,24 +570,24 @@ set(common_headers
emu_versions.h emu_versions.h
eq_constants.h eq_constants.h
eq_limits.h eq_limits.h
eq_packet.h
eq_packet_structs.h eq_packet_structs.h
eq_packet.h
eq_stream_ident.h eq_stream_ident.h
eq_stream_intf.h eq_stream_intf.h
eq_stream_locator.h eq_stream_locator.h
eq_stream_proxy.h eq_stream_proxy.h
eqdb.h
eqdb_res.h eqdb_res.h
eqemu_config.h eqdb.h
eqemu_config_elements.h eqemu_config_elements.h
eqemu_config.h
eqemu_exception.h eqemu_exception.h
eqemu_logsys.h
eqemu_logsys_log_aliases.h eqemu_logsys_log_aliases.h
eqemu_logsys.h
eqtime.h eqtime.h
event_sub.h
event/event_loop.h event/event_loop.h
event/task.h event/task.h
event/timer.h event/timer.h
event_sub.h
events/player_event_discord_formatter.h events/player_event_discord_formatter.h
events/player_event_logs.h events/player_event_logs.h
events/player_events.h events/player_events.h
@ -614,10 +608,11 @@ set(common_headers
ipc_mutex.h ipc_mutex.h
item_data.h item_data.h
item_instance.h item_instance.h
json_config.h
json/json_archive_single_line.h
json/json-forwards.h json/json-forwards.h
json/json.h json/json.h
json/json_archive_single_line.h json/json.hpp
json_config.h
light_source.h light_source.h
linked_list.h linked_list.h
loot.h loot.h
@ -625,14 +620,14 @@ set(common_headers
md5.h md5.h
memory_buffer.h memory_buffer.h
memory_mapped_file.h memory_mapped_file.h
misc.h memory/ksm.h
misc_functions.h misc_functions.h
mutex.h misc.h
mysql_request_result.h mysql_request_result.h
mysql_request_row.h mysql_request_row.h
mysql_stmt.h mysql_stmt.h
net/console_server.h
net/console_server_connection.h net/console_server_connection.h
net/console_server.h
net/crc32.h net/crc32.h
net/dns.h net/dns.h
net/endian.h net/endian.h
@ -644,49 +639,54 @@ set(common_headers
net/servertalk_client_connection.h net/servertalk_client_connection.h
net/servertalk_common.h net/servertalk_common.h
net/servertalk_legacy_client_connection.h net/servertalk_legacy_client_connection.h
net/servertalk_server.h
net/servertalk_server_connection.h net/servertalk_server_connection.h
net/tcp_connection.h net/servertalk_server.h
net/tcp_connection_pooling.h net/tcp_connection_pooling.h
net/tcp_connection.h
net/tcp_server.h net/tcp_server.h
net/websocket_server.h
net/websocket_server_connection.h net/websocket_server_connection.h
net/websocket_server.h
op_codes.h op_codes.h
opcode_dispatch.h opcode_dispatch.h
opcodemgr.h opcodemgr.h
packet_dump.h
packet_dump_file.h packet_dump_file.h
packet_dump.h
packet_functions.h packet_functions.h
patches/patches.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_limits.h
patches/rof_ops.h patches/rof_ops.h
patches/rof_structs.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_limits.h
patches/sod_ops.h patches/sod_ops.h
patches/sod_structs.h patches/sod_structs.h
patches/sof.h patches/sod.h
patches/sof_limits.h patches/sof_limits.h
patches/sof_ops.h patches/sof_ops.h
patches/sof_structs.h patches/sof_structs.h
patches/sof.h
patches/ss_declare.h patches/ss_declare.h
patches/ss_define.h patches/ss_define.h
patches/ss_register.h patches/ss_register.h
patches/titanium.h
patches/titanium_limits.h patches/titanium_limits.h
patches/titanium_ops.h patches/titanium_ops.h
patches/titanium_structs.h patches/titanium_structs.h
patches/uf.h patches/titanium.h
patches/uf_limits.h patches/uf_limits.h
patches/uf_ops.h patches/uf_ops.h
patches/uf_structs.h patches/uf_structs.h
path_manager.cpp patches/uf.h
platform.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 proc_launcher.h
process.h process.h
process/process.h process/process.h
@ -713,6 +713,7 @@ set(common_headers
skills.h skills.h
spdat.h spdat.h
stacktrace/backward.hpp stacktrace/backward.hpp
StackWalker/StackWalker.h
strings.h strings.h
struct_strategy.h struct_strategy.h
tasks.h tasks.h
@ -729,25 +730,9 @@ set(common_headers
zone_store.h zone_store.h
) )
# Source Groups (Regex based for automatic subdirectory handling) source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Source Files" FILES ${common_sources})
source_group("CLI" REGULAR_EXPRESSION "^cli/") source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}" PREFIX "Header Files" FILES ${common_headers})
source_group("Content" REGULAR_EXPRESSION "^content/") source_group(TREE "${CMAKE_CURRENT_SOURCE_DIR}/repositories" PREFIX "Repositories" FILES ${repositories})
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/")
option(EQEMU_ADD_PROFILER "Link with Google perftools profiler" OFF) option(EQEMU_ADD_PROFILER "Link with Google perftools profiler" OFF)
#PRNG options #PRNG options

View File

@ -359,7 +359,7 @@ public:
BOOL Publics; // contains public symbols BOOL Publics; // contains public symbols
}; };
*/ */
typedef struct IMAGEHLP_MODULE64_V2 { struct IMAGEHLP_MODULE64_V2 {
DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64) DWORD SizeOfStruct; // set to sizeof(IMAGEHLP_MODULE64)
DWORD64 BaseOfImage; // base load address of module DWORD64 BaseOfImage; // base load address of module
DWORD ImageSize; // virtual size of the loaded module DWORD ImageSize; // virtual size of the loaded module

View File

@ -134,7 +134,7 @@ protected:
CHAR loadedImageName[STACKWALK_MAX_NAMELEN]; CHAR loadedImageName[STACKWALK_MAX_NAMELEN];
} CallstackEntry; } CallstackEntry;
typedef enum CallstackEntryType {firstEntry, nextEntry, lastEntry}; enum CallstackEntryType {firstEntry, nextEntry, lastEntry};
virtual void OnSymInit(LPCSTR szSearchPath, DWORD symOptions, LPCSTR szUserName); 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); virtual void OnLoadModule(LPCSTR img, LPCSTR mod, DWORD64 baseAddr, DWORD size, DWORD result, LPCSTR symType, LPCSTR pdbName, ULONGLONG fileVersion);

View File

@ -19,44 +19,34 @@
#include "common/misc.h" #include "common/misc.h"
#include "common/packet_dump.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; if (len > 0) {
size=0; size = static_cast<uint32>(len);
_wpos = 0; pBuffer = new unsigned char[len];
_rpos = 0;
timestamp.tv_sec = 0;
if (len>0) {
size=len;
pBuffer= new unsigned char[len];
if (buf) { if (buf) {
memcpy(pBuffer,buf,len); memcpy(pBuffer, buf, len);
} else { }
memset(pBuffer,0,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; // We are essentially taking ownership of this serialize buffer.
buf.m_buffer = nullptr; size = static_cast<uint32>(std::exchange(buf.m_pos, 0));
size = buf.m_pos;
buf.m_pos = 0;
buf.m_capacity = 0; buf.m_capacity = 0;
_wpos = 0;
_rpos = 0;
timestamp.tv_sec = 0;
} }
BasePacket::~BasePacket() BasePacket::~BasePacket()
{ {
if (pBuffer) delete[] pBuffer;
delete[] pBuffer; pBuffer = nullptr;
pBuffer=nullptr;
} }
void BasePacket::build_raw_header_dump(char *buffer, uint16 seq) const void BasePacket::build_raw_header_dump(char *buffer, uint16 seq) const
{ {
if (timestamp.tv_sec) { if (timestamp.tv_sec) {

View File

@ -23,14 +23,26 @@
#include <cstdio> #include <cstdio>
class BasePacket { class BasePacket
{
protected:
BasePacket() = default;
BasePacket(const unsigned char* buf, size_t len);
BasePacket(SerializeBuffer&& buf);
virtual ~BasePacket();
public: public:
unsigned char *pBuffer; unsigned char* pBuffer = nullptr;
uint32 size, _wpos, _rpos; uint32 size = 0;
uint32 src_ip,dst_ip; uint32 _wpos = 0;
uint16 src_port,dst_port; uint32 _rpos = 0;
uint32 priority; uint32 src_ip = 0;
timeval timestamp; 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_raw_header_dump(char *buffer, uint16 seq=0xffff) const;
virtual void build_header_dump(char *buffer) 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 setSrcInfo(uint32 sip, uint16 sport) { src_ip=sip; src_port=sport; }
void setDstInfo(uint32 dip, uint16 dport) { dst_ip=dip; dst_port=dport; } 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; } 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) { 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); } void WriteUInt8(uint8 value) { *(uint8 *)(pBuffer + _wpos) = value; _wpos += sizeof(uint8); }
@ -73,12 +85,6 @@ public:
uint32 GetReadPosition() { return _rpos; } uint32 GetReadPosition() { return _rpos; }
void SetWritePosition(uint32 Newwpos) { _wpos = Newwpos; } void SetWritePosition(uint32 Newwpos) { _wpos = Newwpos; }
void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } 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); extern void DumpPacketHex(const BasePacket* app);

View File

@ -23,12 +23,9 @@
namespace EQEmuCommand { namespace EQEmuCommand {
std::map<std::string, void (*)( using CommandFunction = void(*)(int argc, char** argv, argh::parser& cmd, std::string& description);
int argc,
char **argv, std::map<std::string, CommandFunction> function_map;
argh::parser &cmd,
std::string &description
)> function_map;
/** /**
* @param cmd * @param cmd

View File

@ -51,7 +51,7 @@
# include <unistd.h> # include <unistd.h>
#elif defined(TERMCOLOR_OS_WINDOWS) #elif defined(TERMCOLOR_OS_WINDOWS)
# include <io.h> # include <io.h>
# include <windows.h> # include "common/platform/win/include_windows.h"
#endif #endif

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <pthread.h>
#include <sys/time.h>
#include <errno.h>
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 << "."<<now.tv_usec << endl;
//cout << "timeout=" << timeout.tv_sec << "."<<timeout.tv_nsec << endl;
retcode=pthread_cond_timedwait(&cond,&mutex,&timeout);
pthread_mutex_unlock(&mutex);
return retcode!=ETIMEDOUT;
}
*/
Condition::~Condition()
{
pthread_mutex_lock(&mutex);
pthread_cond_destroy(&cond);
pthread_mutex_unlock(&mutex);
pthread_mutex_destroy(&mutex);
}
#endif

View File

@ -1,51 +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 <http://www.gnu.org/licenses/>.
*/
#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();
};

View File

@ -132,7 +132,7 @@ void WorldContentService::SetContentFlags(const std::vector<ContentFlagsReposito
bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag) bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
{ {
for (auto &f: GetContentFlags()) { for (auto &f: GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == true) { if (f.flag_name == content_flag && f.enabled == 1) {
return true; return true;
} }
} }
@ -147,7 +147,7 @@ bool WorldContentService::IsContentFlagEnabled(const std::string &content_flag)
bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag) bool WorldContentService::IsContentFlagDisabled(const std::string &content_flag)
{ {
for (auto &f: GetContentFlags()) { for (auto &f: GetContentFlags()) {
if (f.flag_name == content_flag && f.enabled == false) { if (f.flag_name == content_flag && f.enabled == 0) {
return true; return true;
} }
} }

View File

@ -125,6 +125,6 @@ uint32 CRC32::Update(const uint8* buf, uint32 bufsize, uint32 crc32var) {
return crc32var; return crc32var;
} }
inline void CRC32::Calc(const uint8 byte, uint32& crc32var) { void CRC32::Calc(const uint8 byte, uint32& crc32var) {
crc32var = ((crc32var) >> 8) ^ CRC32Table[(byte) ^ ((crc32var) & 0x000000FF)]; crc32var = ((crc32var) >> 8) ^ CRC32Table[(byte) ^ ((crc32var) & 0x000000FF)];
} }

View File

@ -728,7 +728,7 @@ bool Database::LoadVariables()
return true; return true;
} }
LockMutex lock(&Mvarcache); std::scoped_lock lock(Mvarcache);
for (const auto& e : l) { for (const auto& e : l) {
varcache.last_update = std::time(nullptr); varcache.last_update = std::time(nullptr);
@ -747,7 +747,7 @@ bool Database::LoadVariables()
bool Database::GetVariable(const std::string& name, std::string& value) bool Database::GetVariable(const std::string& name, std::string& value)
{ {
LockMutex lock(&Mvarcache); std::scoped_lock lock(Mvarcache);
if (name.empty()) { if (name.empty()) {
return false; return false;

View File

@ -20,13 +20,12 @@
#include "common/dbcore.h" #include "common/dbcore.h"
#include "common/eq_packet_structs.h" #include "common/eq_packet_structs.h"
#include "common/eqemu_logsys.h" #include "common/eqemu_logsys.h"
#include "common/linked_list.h"
#include "common/types.h" #include "common/types.h"
#include <cmath> #include <map>
#include <mutex>
#include <string> #include <string>
#include <vector> #include <vector>
#include <map>
#define AUTHENTICATION_TIMEOUT 60 #define AUTHENTICATION_TIMEOUT 60
#define INVALID_ID 0xFFFFFFFF #define INVALID_ID 0xFFFFFFFF
@ -265,7 +264,7 @@ public:
uint64_t GetNextTableId(const std::string& table_name); uint64_t GetNextTableId(const std::string& table_name);
private: private:
Mutex Mvarcache; std::mutex Mvarcache;
VarCache_Struct varcache; VarCache_Struct varcache;
/* Groups, utility methods. */ /* Groups, utility methods. */

View File

@ -33,17 +33,9 @@
#endif #endif
DBcore::DBcore() DBcore::DBcore()
: mysql(mysql_init(nullptr))
, m_mutex(std::make_shared<Mutex>())
{ {
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() DBcore::~DBcore()
@ -56,20 +48,17 @@ DBcore::~DBcore()
if (mysqlOwner) { if (mysqlOwner) {
mysql_close(mysql); 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 // Sends the MySQL server a keepalive
void DBcore::ping() 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 // well, if's it's locked, someone's using it. If someone's using it, it doesnt need a keepalive
return; return;
} }
mysql_ping(mysql); mysql_ping(mysql);
m_mutex->unlock(); m_mutex->unlock();
} }
@ -92,7 +81,7 @@ MySQLRequestResult DBcore::QueryDatabase(const char *query, uint32 querylen, boo
BenchTimer timer; BenchTimer timer;
timer.reset(); timer.reset();
LockMutex lock(m_mutex); std::scoped_lock lock(*m_mutex);
// Reconnect if we are not connected before hand. // Reconnect if we are not connected before hand.
if (pStatus != Connected) { if (pStatus != Connected) {
@ -217,15 +206,12 @@ bool DBcore::Open(
bool iSSL bool iSSL
) )
{ {
LockMutex lock(m_mutex); std::scoped_lock lock(*m_mutex);
safe_delete_array(pHost);
safe_delete_array(pUser); m_host = iHost;
safe_delete_array(pPassword); m_user = iUser;
safe_delete_array(pDatabase); m_password = iPassword;
pHost = strcpy(new char[strlen(iHost) + 1], iHost); m_database = iDatabase;
pUser = strcpy(new char[strlen(iUser) + 1], iUser);
pPassword = strcpy(new char[strlen(iPassword) + 1], iPassword);
pDatabase = strcpy(new char[strlen(iDatabase) + 1], iDatabase);
pCompress = iCompress; pCompress = iCompress;
pPort = iPort; pPort = iPort;
pSSL = iSSL; pSSL = iSSL;
@ -234,10 +220,12 @@ bool DBcore::Open(
bool DBcore::Open(uint32 *errnum, char *errbuf) bool DBcore::Open(uint32 *errnum, char *errbuf)
{ {
// Expects m_mutex to already be locked.
if (errbuf) { if (errbuf) {
errbuf[0] = 0; errbuf[0] = 0;
} }
LockMutex lock(m_mutex);
if (GetStatus() == Connected) { if (GetStatus() == Connected) {
return true; return true;
} }
@ -245,7 +233,7 @@ bool DBcore::Open(uint32 *errnum, char *errbuf)
mysql_close(mysql); mysql_close(mysql);
mysql_init(mysql); // Initialize structure again mysql_init(mysql); // Initialize structure again
} }
if (!pHost) { if (m_host.empty()) {
return false; 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_ENFORCE, &off);
mysql_options(mysql, MYSQL_OPT_SSL_VERIFY_SERVER_CERT, &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; pStatus = Connected;
std::string connected_origin_host = pHost; SetOriginHost(m_host);
SetOriginHost(connected_origin_host);
return true; return true;
} }
@ -293,9 +280,9 @@ const std::string &DBcore::GetOriginHost() const
return origin_host; 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) std::string DBcore::Escape(const std::string& s)
@ -307,12 +294,8 @@ std::string DBcore::Escape(const std::string& s)
return temp.data(); return temp.data();
} }
void DBcore::SetMutex(Mutex *mutex) void DBcore::SetMutex(const std::shared_ptr<Mutex>& mutex)
{ {
if (m_mutex && m_mutex != mutex) {
safe_delete(m_mutex);
}
DBcore::m_mutex = mutex; DBcore::m_mutex = mutex;
} }
@ -326,7 +309,7 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
BenchTimer timer; BenchTimer timer;
timer.reset(); timer.reset();
LockMutex lock(m_mutex); std::scoped_lock lock(*m_mutex);
// Reconnect if we are not connected before hand. // Reconnect if we are not connected before hand.
if (pStatus != Connected) { if (pStatus != Connected) {
@ -449,5 +432,5 @@ MySQLRequestResult DBcore::QueryDatabaseMulti(const std::string &query)
mysql::PreparedStmt DBcore::Prepare(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);
} }

View File

@ -17,11 +17,11 @@
*/ */
#pragma once #pragma once
#include "common/mutex.h"
#include "common/mysql_request_result.h" #include "common/mysql_request_result.h"
#include "common/types.h" #include "common/types.h"
#include "mysql.h" #include "mysql.h"
#include <memory>
#include <mutex> #include <mutex>
#define CR_SERVER_GONE_ERROR 2006 #define CR_SERVER_GONE_ERROR 2006
@ -29,12 +29,15 @@
namespace mysql { class PreparedStmt; } namespace mysql { class PreparedStmt; }
class DBcore { class DBcore
{
public: public:
enum eStatus { enum eStatus {
Closed, Connected, Error Closed, Connected, Error
}; };
using Mutex = std::recursive_mutex;
DBcore(); DBcore();
~DBcore(); ~DBcore();
eStatus GetStatus() { return pStatus; } eStatus GetStatus() { return pStatus; }
@ -48,17 +51,17 @@ public:
uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen); uint32 DoEscapeString(char *tobuf, const char *frombuf, uint32 fromlen);
void ping(); void ping();
const std::string &GetOriginHost() const; const std::string& GetOriginHost() const;
void SetOriginHost(const std::string &origin_host); void SetOriginHost(const std::string& origin_host);
bool DoesTableExist(const std::string& table_name); bool DoesTableExist(const std::string& table_name);
void SetMySQL(const DBcore &o) void SetMySQL(const DBcore& o)
{ {
mysql = o.mysql; mysql = o.mysql;
mysqlOwner = false; mysqlOwner = false;
} }
void SetMutex(Mutex *mutex); void SetMutex(const std::shared_ptr<Mutex>& mutex);
// only safe on connections shared with other threads if results buffered // only safe on connections shared with other threads if results buffered
// unsafe to use off main thread due to internal server logging // unsafe to use off main thread due to internal server logging
@ -81,22 +84,21 @@ protected:
private: private:
bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr); bool Open(uint32 *errnum = nullptr, char *errbuf = nullptr);
MYSQL* mysql; MYSQL* mysql = nullptr;
bool mysqlOwner; bool mysqlOwner = true;
Mutex *m_mutex; eStatus pStatus = Closed;
eStatus pStatus;
std::mutex m_query_lock{}; std::shared_ptr<Mutex> m_mutex;
std::string origin_host; std::string origin_host;
char *pHost; std::string m_host;
char *pUser; std::string m_user;
char *pPassword; std::string m_password;
char *pDatabase; std::string m_database;
bool pCompress; bool pCompress = false;
uint32 pPort; uint32 pPort = 0;
bool pSSL; bool pSSL = false;
// allows multiple queries to be executed within the same query // allows multiple queries to be executed within the same query
// do not use this under normal operation // do not use this under normal operation

View File

@ -31,9 +31,19 @@
#include <iomanip> #include <iomanip>
#include <iostream> #include <iostream>
EQPacket::EQPacket(EmuOpcode op, const unsigned char *buf, uint32 len) EQPacket::EQPacket()
: BasePacket(buf, len), {
emu_opcode(op) }
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) { if (iShowInfo) {
std::cout << "Dumping Applayer: 0x" << std::hex << std::setfill('0') << std::setw(4) << app->GetOpcode() << std::dec; printf("Dumping Applayer: 0x%04x size: %u", app->GetOpcode(), app->size);
std::cout << " size:" << app->size << std::endl;
} }
DumpPacketHex(app->pBuffer, app->size); DumpPacketHex(app->pBuffer, app->size);
// DumpPacketAscii(app->pBuffer, app->size);
} }
std::string DumpPacketToString(const EQApplicationPacket* app){ std::string DumpPacketToString(const EQApplicationPacket* app)
std::ostringstream out; {
out << DumpPacketHexToString(app->pBuffer, app->size); return DumpPacketHexToString(app->pBuffer, app->size);
return out.str();
} }

View File

@ -28,8 +28,15 @@
#include "common/emu_opcodes.h" #include "common/emu_opcodes.h"
#endif #endif
class EQPacket : public BasePacket { class EQPacket : public BasePacket
{
friend class EQStream; friend class EQStream;
protected:
EQPacket();
EQPacket(EmuOpcode opcode, const unsigned char* buf, size_t len);
EQPacket(EmuOpcode opcode, SerializeBuffer&& buf);
public: public:
virtual ~EQPacket() {} virtual ~EQPacket() {}
@ -41,19 +48,12 @@ public:
virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const; virtual void DumpRawHeaderNoTime(uint16 seq=0xffff, FILE *to = stdout) const;
void SetOpcode(EmuOpcode op) { emu_opcode = op; } void SetOpcode(EmuOpcode op) { emu_opcode = op; }
const EmuOpcode GetOpcode() const { return(emu_opcode); } EmuOpcode GetOpcode() const { return(emu_opcode); }
// const char *GetOpcodeName() const;
protected: protected:
//this is just a cache so we dont look it up several times on Get() //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 //and it is mutable so we can store the cached copy even on a const object
EmuOpcode emu_opcode; EmuOpcode emu_opcode = OP_Unknown;
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; }
}; };
class EQRawApplicationPacket; class EQRawApplicationPacket;
@ -90,19 +90,43 @@ protected:
uint16 opcode; uint16 opcode;
}; };
class EQApplicationPacket : public EQPacket { class EQApplicationPacket : public EQPacket
{
friend class EQStream; 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: 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); bool combine(const EQApplicationPacket *rhs);
uint32 serialize (uint16 opcode, unsigned char *dest) const; uint32 serialize (uint16 opcode, unsigned char *dest) const;
uint32 Size() const { return size+app_opcode_size; } uint32 Size() const { return size+app_opcode_size; }
@ -119,15 +143,11 @@ public:
uint16 GetProtocolOpcode() const { return protocol_opcode; } uint16 GetProtocolOpcode() const { return protocol_opcode; }
void SetProtocolOpcode(uint16 v) { protocol_opcode = v; } void SetProtocolOpcode(uint16 v) { protocol_opcode = v; }
protected: protected:
uint16 protocol_opcode = 0;
uint16 protocol_opcode; uint8 app_opcode_size = GetExecutablePlatform() == ExePlatformUCS ? 1 : 2;
uint8 app_opcode_size; uint16 opcode_bypass = 0;
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; }
}; };
class EQRawApplicationPacket : public EQApplicationPacket { class EQRawApplicationPacket : public EQApplicationPacket {

View File

@ -26,13 +26,13 @@
//this is the only part of an EQStream that is seen by the application. //this is the only part of an EQStream that is seen by the application.
typedef enum { enum EQStreamState {
ESTABLISHED, ESTABLISHED,
CLOSING, //waiting for pending data to flush. CLOSING, //waiting for pending data to flush.
DISCONNECTING, //have sent disconnect, waiting for their disconnect reply. DISCONNECTING, //have sent disconnect, waiting for their disconnect reply.
CLOSED, //received a disconnect from remote side. CLOSED, //received a disconnect from remote side.
UNESTABLISHED UNESTABLISHED
} EQStreamState; };
class EQApplicationPacket; class EQApplicationPacket;
class OpcodeManager; class OpcodeManager;

View File

@ -33,10 +33,8 @@
#include <sys/stat.h> #include <sys/stat.h>
#ifdef _WINDOWS #ifdef _WINDOWS
#include <conio.h> #include "common/platform/platform.h"
#include <direct.h> #include <direct.h>
#include <process.h>
#include <windows.h>
#else #else
#include <sys/stat.h> #include <sys/stat.h>
#include <thread> #include <thread>

View File

@ -15,36 +15,43 @@
You should have received a copy of the GNU General Public License You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>. along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
#pragma once
#include "common/types.h" #include "common/event/event_loop.h"
#include "common/platform/posix/include_pthreads.h" #include "uv.h"
#include "common/platform/win/include_windows.h"
class Mutex { namespace EQ {
public:
Mutex();
~Mutex();
void lock(); EventLoop& EventLoop::Get()
void unlock(); {
bool trylock(); thread_local EventLoop inst;
protected: return inst;
private: }
#if defined _WINDOWS
CRITICAL_SECTION CSMutex;
#else
pthread_mutex_t CSMutex;
#endif
};
class LockMutex { EventLoop::EventLoop()
public: : m_loop(std::make_unique<uv_loop_t>())
LockMutex(Mutex* in_mut, bool iLock = true); {
~LockMutex(); memset(m_loop.get(), 0, sizeof(uv_loop_t));
void unlock(); uv_loop_init(m_loop.get());
void lock(); }
private:
bool locked; EventLoop::~EventLoop()
Mutex* mut; {
}; 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

View File

@ -17,48 +17,31 @@
*/ */
#pragma once #pragma once
#include "common/platform/win/include_windows.h" // uv.h is going to include it so let's do it first. #include <memory>
#include "uv.h" // FIXME: hide this
#include <cstring> typedef struct uv_loop_s uv_loop_t;
namespace EQ namespace EQ {
class EventLoop
{ {
class EventLoop public:
{ static EventLoop& Get();
public:
static EventLoop &Get() {
static thread_local EventLoop inst;
return inst;
}
~EventLoop() { ~EventLoop();
uv_loop_close(&m_loop); EventLoop(const EventLoop&) = delete;
} EventLoop& operator=(const EventLoop&) = delete;
void Process() { void Process();
uv_run(&m_loop, UV_RUN_NOWAIT); void Run();
} void Shutdown();
void Run() { uv_loop_t* Handle() { return m_loop.get(); }
uv_run(&m_loop, UV_RUN_DEFAULT);
}
void Shutdown() { private:
uv_stop(&m_loop); EventLoop();
}
uv_loop_t* Handle() { return &m_loop; } std::unique_ptr<uv_loop_t> m_loop;
};
private: } // namespace EQ
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;
};
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "task_scheduler.h"
#include <atomic>
#include <condition_variable>
#include <mutex>
#include <queue>
#include <thread>
#include <vector>
namespace EQ::Event {
static constexpr int DefaultThreadCount = 4;
struct TaskScheduler::SchedulerData
{
std::atomic_bool running{ false };
std::vector<std::thread> threads;
std::mutex lock;
std::condition_variable cv;
std::queue<std::function<void()>> tasks;
};
TaskScheduler::TaskScheduler()
: m_data(std::make_unique<SchedulerData>())
{
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<void()> 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<void()>&& 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

View File

@ -17,116 +17,45 @@
*/ */
#pragma once #pragma once
#include <condition_variable>
#include <functional> #include <functional>
#include <future> #include <future>
#include <mutex> #include <memory>
#include <queue>
#include <thread>
#include <vector>
namespace EQ namespace EQ::Event {
class TaskScheduler
{ {
namespace Event public:
TaskScheduler();
TaskScheduler(size_t threads);
~TaskScheduler();
void Start(size_t threads);
void Stop();
template <typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type>
{ {
class TaskScheduler using return_type = typename std::invoke_result<Fn, Args...>::type;
{
public: auto task = std::make_shared<std::packaged_task<return_type()>>(
static const int DefaultThreadCount = 4; [fn = std::forward<Fn>(fn), ...args = std::forward<Args>(args)]() mutable
TaskScheduler() : _running(false)
{ {
Start(DefaultThreadCount); return fn(std::forward<Args>(args)...);
}
TaskScheduler(size_t threads) : _running(false)
{
Start(threads);
} }
);
~TaskScheduler() { AddTask([task] { (*task)(); });
Stop(); return task->get_future();
}
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<std::mutex> lock(_lock);
_running = false;
}
_cv.notify_all();
for (auto &t : _threads) {
t.join();
}
}
template<typename Fn, typename... Args>
auto Enqueue(Fn&& fn, Args&&... args) -> std::future<typename std::invoke_result<Fn, Args...>::type> {
using return_type = typename std::invoke_result<Fn, Args...>::type;
auto task = std::make_shared<std::packaged_task<return_type()>>(
std::bind(std::forward<Fn>(fn), std::forward<Args>(args)...)
);
std::future<return_type> res = task->get_future();
{
std::unique_lock<std::mutex> 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<void()> work;
{
std::unique_lock<std::mutex> 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<std::thread> _threads;
std::mutex _lock;
std::condition_variable _cv;
std::queue<std::function<void()>> _tasks;
};
} }
}
private:
void AddTask(std::function<void()>&& task);
void ProcessWork();
struct SchedulerData;
std::unique_ptr<SchedulerData> m_data;
};
} // namespace EQ::Event

90
common/event/timer.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<uv_timer_t>();
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<Timer*>(handle->data);
t->Execute();
}, duration_ms, duration_ms);
}
else
{
uv_timer_start(m_timer.get(),
[](uv_timer_t* handle)
{
Timer* t = static_cast<Timer*>(handle->data);
t->Stop();
t->Execute();
}, duration_ms, 0);
}
}
}
void Timer::Stop()
{
if (m_timer)
{
uv_close(reinterpret_cast<uv_handle_t*>(m_timer.release()),
[](uv_handle_t* handle)
{
delete reinterpret_cast<uv_timer_t*>(handle);
});
}
}
void Timer::Execute()
{
m_cb(this);
}
} // namespace EQ

View File

@ -19,69 +19,31 @@
#include "event_loop.h" #include "event_loop.h"
#include <cstring>
#include <functional> #include <functional>
#include <memory>
typedef struct uv_timer_s uv_timer_t;
namespace EQ { namespace EQ {
class Timer
{
public:
Timer(std::function<void(Timer *)> cb)
{
m_timer = nullptr;
m_cb = cb;
}
Timer(uint64_t duration_ms, bool repeats, std::function<void(Timer *)> cb) class Timer
{ {
m_timer = nullptr; public:
m_cb = cb; using callback_t = std::function<void(Timer*)>;
Start(duration_ms, repeats);
} Timer(callback_t cb);
Timer(uint64_t duration_ms, bool repeats, callback_t cb);
~Timer() ~Timer();
{
Stop();
}
void Start(uint64_t duration_ms, bool repeats) { void Start(uint64_t duration_ms, bool repeats);
auto loop = EventLoop::Get().Handle(); void Stop();
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;
if (repeats) { private:
uv_timer_start(m_timer, [](uv_timer_t *handle) { void Execute();
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);
}
uv_timer_t *m_timer; std::unique_ptr<uv_timer_t> m_timer;
std::function<void(Timer*)> m_cb; callback_t m_cb;
}; };
}
} // namespace EQ

View File

@ -56,12 +56,12 @@ void PlayerEventLogs::Init()
auto s = PlayerEventLogSettingsRepository::All(*m_database); auto s = PlayerEventLogSettingsRepository::All(*m_database);
std::vector<int> db{}; std::vector<int> db{};
db.reserve(s.size()); db.reserve(s.size());
for (auto &e: s) { for (auto& e: s) {
if (e.id >= PlayerEvent::MAX) { if (e.id >= PlayerEvent::MAX) {
continue; continue;
} }
m_settings[e.id] = e; m_settings[e.id] = e;
db.emplace_back(e.id); db.emplace_back(static_cast<int>(e.id));
} }
std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings_to_insert{}; std::vector<PlayerEventLogSettingsRepository::PlayerEventLogSettings> settings_to_insert{};

View File

@ -46,7 +46,7 @@
#define GUILD_INITIATE 7 #define GUILD_INITIATE 7
#define GUILD_RECRUIT 8 #define GUILD_RECRUIT 8
typedef enum { enum GuildAction {
GUILD_ACTION_BANNER_CHANGE = 1, GUILD_ACTION_BANNER_CHANGE = 1,
GUILD_ACTION_BANNER_PLANT = 2, GUILD_ACTION_BANNER_PLANT = 2,
GUILD_ACTION_BANNER_REMOVE = 3, GUILD_ACTION_BANNER_REMOVE = 3,
@ -77,6 +77,6 @@ typedef enum {
GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28, GUILD_ACTION_REAL_ESTATE_GUILD_PLOT_SELL = 28,
GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29, GUILD_ACTION_REAL_ESTATE_MODIFY_TROPHIES = 29,
GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30, GUILD_ACTION_MEMBERS_DEMOTE_SELF = 30,
} GuildAction; };
constexpr int format_as(GuildAction action) { return static_cast<int>(action); } constexpr int format_as(GuildAction action) { return static_cast<int>(action); }

View File

@ -349,7 +349,7 @@ bool EQ::InventoryProfile::SwapItem(
fail_state = swapLevel; fail_state = swapLevel;
return false; return false;
} }
if (source_item_instance->IsEvolving() > 0) { if (source_item_instance->IsEvolving()) {
source_item_instance->SetEvolveEquipped(true); source_item_instance->SetEvolveEquipped(true);
} }
} }

View File

@ -25,14 +25,24 @@
#include "common/net/dns.h" #include "common/net/dns.h"
#include "fmt/format.h" #include "fmt/format.h"
#include <cstring> #include <iostream>
#include <csignal> #include <string>
#include <vector> #include <vector>
/** #ifdef _WIN32
* @param ip #include <winsock2.h>
* @return #include <ws2tcpip.h>
*/ #pragma comment(lib, "Ws2_32.lib")
#else
#include <arpa/inet.h>
#include <fcntl.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
uint32_t IpUtil::IPToUInt(const std::string &ip) uint32_t IpUtil::IPToUInt(const std::string &ip)
{ {
int a, b, c, d; int a, b, c, d;
@ -49,12 +59,6 @@ uint32_t IpUtil::IPToUInt(const std::string &ip)
return addr; return addr;
} }
/**
* @param ip
* @param network
* @param mask
* @return
*/
bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask) bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask)
{ {
uint32_t ip_addr = IpUtil::IPToUInt(ip); 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; return ip_addr >= net_lower && ip_addr <= net_upper;
} }
/**
* @param ip
* @return
*/
bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip) bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
{ {
return ( return (
@ -80,30 +80,13 @@ bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
); );
} }
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "Ws2_32.lib")
#else
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <unistd.h>
#include <fcntl.h>
#endif
#include <iostream>
#include <string>
#include <cstring>
std::string IpUtil::GetLocalIPAddress() std::string IpUtil::GetLocalIPAddress()
{ {
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
return ""; return "";
} }
#endif #endif
char my_ip_address[INET_ADDRSTRLEN]; char my_ip_address[INET_ADDRSTRLEN];
@ -114,10 +97,10 @@ std::string IpUtil::GetLocalIPAddress()
// Create a UDP socket // Create a UDP socket
#ifdef _WIN32 #ifdef _WIN32
sockfd = socket(AF_INET, SOCK_DGRAM, 0); sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd == INVALID_SOCKET) { if (sockfd == INVALID_SOCKET) {
WSACleanup(); WSACleanup();
return ""; return "";
} }
#else #else
sockfd = socket(AF_INET, SOCK_DGRAM, 0); sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) { if (sockfd < 0) {
@ -200,98 +183,24 @@ std::string IpUtil::GetPublicIPAddress()
return {}; 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<std::chrono::milliseconds>(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) bool IpUtil::IsIPAddress(const std::string &ip_address)
{ {
struct sockaddr_in sa{}; sockaddr_in sa{};
int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr)); int result = inet_pton(AF_INET, ip_address.c_str(), &(sa.sin_addr));
return result != 0; return result != 0;
} }
#include <iostream> bool IpUtil::IsPortInUse(const std::string& ip, int port)
#ifdef _WIN32 {
#include <winsock2.h>
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <unistd.h>
#endif
#include <iostream>
#include <string>
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h> // For inet_pton
#pragma comment(lib, "ws2_32.lib") // Link against Winsock library
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h> // For inet_pton
#include <unistd.h>
#endif
bool IpUtil::IsPortInUse(const std::string& ip, int port) {
bool in_use = false; bool in_use = false;
#ifdef _WIN32 #ifdef _WIN32
WSADATA wsaData; WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) { if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) {
std::cerr << "WSAStartup failed\n"; std::cerr << "WSAStartup failed\n";
return true; // Assume in use on failure return true; // Assume in use on failure
} }
#endif #endif
int sock = socket(AF_INET, SOCK_STREAM, 0); 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; std::cerr << "Invalid IP address format: " << ip << std::endl;
#ifdef _WIN32 #ifdef _WIN32
closesocket(sock); closesocket(sock);
WSACleanup(); WSACleanup();
#else #else
close(sock); close(sock);
#endif #endif
return true; // Assume in use on failure 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 in_use = true; // Bind failed, port is in use
} }
#ifdef _WIN32 #ifdef _WIN32
closesocket(sock); closesocket(sock);
WSACleanup(); WSACleanup();
#else #else
close(sock); close(sock);
#endif #endif

View File

@ -29,10 +29,7 @@ public:
static bool IsIpInPrivateRfc1918(const std::string &ip); static bool IsIpInPrivateRfc1918(const std::string &ip);
static std::string GetLocalIPAddress(); static std::string GetLocalIPAddress();
static std::string GetPublicIPAddress(); static std::string GetPublicIPAddress();
static std::string DNSLookupSync(
const std::string &addr,
int port
);
static bool IsIPAddress(const std::string &ip_address); static bool IsIPAddress(const std::string &ip_address);
static bool IsPortInUse(const std::string& ip, int port); static bool IsPortInUse(const std::string& ip, int port);

View File

@ -320,6 +320,7 @@ bool EQ::ItemInstance::IsAugmentSlotAvailable(int32 augment_type, uint8 slot) co
} }
return ( return (
slot < invaug::SOCKET_COUNT &&
( (
augment_type == -1 || augment_type == -1 ||
( (

View File

@ -45,5 +45,4 @@ struct LootItem {
uint32 lootdrop_id; // required for zone state referencing uint32 lootdrop_id; // required for zone state referencing
}; };
typedef std::list<LootItem*> LootItems; using LootItems = std::list<LootItem*>;

192
common/memory/ksm.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "ksm.h"
#ifdef _WIN32
#include <windows.h>
#else
#include <sys/mman.h> // For madvise
#include <unistd.h> // 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<size_t>(sysconf(_SC_PAGESIZE));
}
namespace KSM {
void CheckPageAlignment(void* ptr)
{
size_t page_size = sysconf(_SC_PAGESIZE);
if (reinterpret_cast<uintptr_t>(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<uintptr_t>(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<char*>(current_break) - static_cast<char*>(start);
}
} // namespace KSM
#endif

74
common/memory/ksm.h Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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 <typename T>
class PageAlignedAllocator : public PageAlignedAllocatorBase
{
public:
using value_type = T;
PageAlignedAllocator() noexcept = default;
template <typename U>
PageAlignedAllocator(const PageAlignedAllocator<U>&) noexcept {}
T* allocate(std::size_t n)
{
size_t size = n * sizeof(T);
return static_cast<T*>(allocateInternal(size, getPageSize()));
}
void deallocate(T* p, std::size_t) noexcept
{
free(p);
}
};
template <typename T, typename U>
bool operator==(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) noexcept {
return true;
}
template <typename T, typename U>
bool operator!=(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) 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

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "common/eqemu_logsys.h"
#include <iostream>
#include <vector>
#include <cstring>
#ifdef _WIN32
#include <malloc.h> // For _aligned_malloc, _aligned_free
#include <windows.h>
#else
#include <sys/mman.h> // For madvise
#include <unistd.h> // For sysconf, sbrk
#endif
// Page-aligned allocator for std::vector
template <typename T>
class PageAlignedAllocator {
public:
using value_type = T;
PageAlignedAllocator() noexcept = default;
template <typename U>
PageAlignedAllocator(const PageAlignedAllocator<U>&) 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<T*>(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<size_t>(sysconf(_SC_PAGESIZE));
#endif
};
};
template <typename T, typename U>
bool operator==(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) noexcept {
return true;
}
template <typename T, typename U>
bool operator!=(const PageAlignedAllocator<T>&, const PageAlignedAllocator<U>&) 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<uintptr_t>(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<uintptr_t>(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<char*>(current_break) - static_cast<char*>(start);
}
#endif
inline size_t getPageSize()
{
#ifdef _WIN32
SYSTEM_INFO sysInfo;
GetSystemInfo(&sysInfo);
return sysInfo.dwPageSize; // Page size in bytes
#else
return static_cast<size_t>(sysconf(_SC_PAGESIZE)); // POSIX page size
#endif
};
template <typename T>
inline void PageAlignVectorAligned(std::vector<T, PageAlignedAllocator<T>>& 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<std::uintptr_t>(start) % page_size != 0) {
// Allocate a new aligned vector
std::vector<T, PageAlignedAllocator<T>> 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<std::uintptr_t>(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
}
}

View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#include "mutex.h"
#include <iostream>
#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;
}

View File

@ -18,7 +18,6 @@
#include "mysql_stmt.h" #include "mysql_stmt.h"
#include "common/eqemu_logsys.h" #include "common/eqemu_logsys.h"
#include "common/mutex.h"
#include "common/timer.h" #include "common/timer.h"
#include <charconv> #include <charconv>
@ -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 // 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 // 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. // changed to one that throws then exceptions need to be caught here.
LockMutex lock(mutex); std::scoped_lock lock(mutex);
mysql_stmt_close(stmt); mysql_stmt_close(stmt);
} }
PreparedStmt::PreparedStmt(MYSQL& mysql, std::string query, Mutex* mutex, StmtOptions 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_mutex(mutex), m_options(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<unsigned long>(m_query.size())) != 0) if (mysql_stmt_prepare(m_stmt.get(), m_query.c_str(), static_cast<unsigned long>(m_query.size())) != 0)
{ {
ThrowError(fmt::format("Prepare error: {}", GetStmtError())); ThrowError(fmt::format("Prepare error: {}", GetStmtError()));
@ -186,7 +190,7 @@ void PreparedStmt::CheckArgs(size_t argc)
StmtResult PreparedStmt::DoExecute() StmtResult PreparedStmt::DoExecute()
{ {
BenchTimer timer; 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) if (m_need_bind && mysql_stmt_bind_param(m_stmt.get(), m_params.data()) != 0)
{ {

View File

@ -17,10 +17,12 @@
*/ */
#pragma once #pragma once
#include "mysql.h" #include "common/dbcore.h"
#include <cassert> #include <cassert>
#include <cstring> #include <cstring>
#include <memory> #include <memory>
#include <mutex>
#include <optional> #include <optional>
#include <span> #include <span>
#include <string_view> #include <string_view>
@ -183,7 +185,7 @@ public:
int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>; int64_t, uint64_t, float, double, bool, std::string_view, std::nullptr_t>;
PreparedStmt() = delete; 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; } const std::string& GetQuery() const { return m_query; }
StmtOptions GetOptions() const { return m_options; } StmtOptions GetOptions() const { return m_options; }
@ -219,7 +221,8 @@ private:
struct StmtDeleter struct StmtDeleter
{ {
Mutex* mutex = nullptr; DBcore::Mutex& mutex;
void operator()(MYSQL_STMT* stmt) noexcept; void operator()(MYSQL_STMT* stmt) noexcept;
}; };
@ -232,7 +235,7 @@ private:
std::string m_query; std::string m_query;
StmtOptions m_options = {}; StmtOptions m_options = {};
bool m_need_bind = true; bool m_need_bind = true;
Mutex* m_mutex = nullptr; // connection mutex DBcore::Mutex& m_mutex; // connection mutex
}; };
} // namespace mysql } // namespace mysql

131
common/net/dns.cpp Normal file
View File

@ -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 <http://www.gnu.org/licenses/>.
*/
#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<DNSBaton*>(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<sockaddr_in6*>(result->ai_addr), addr, 40);
}
else
{
uv_ip4_name(reinterpret_cast<sockaddr_in*>(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<std::chrono::milliseconds>(end - begin).count() > 1500) {
LogInfo(
"Deadline exceeded [{}]",
1500
);
running = false;
}
loop.Process();
}
return ret;
});
return res.get();
}
} // namespace EQ::Net

View File

@ -17,63 +17,15 @@
*/ */
#pragma once #pragma once
#include "common/event/event_loop.h"
#include <functional> #include <functional>
#include <string> #include <string>
namespace EQ namespace EQ::Net {
{
namespace Net
{
static void DNSLookup(const std::string &addr, int port, bool ipv6, std::function<void(const std::string&)> cb) {
struct DNSBaton
{
std::function<void(const std::string&)> cb;
bool ipv6;
};
addrinfo hints; using dns_callback_t = std::function<void(const std::string&)>;
memset(&hints, 0, sizeof(addrinfo));
hints.ai_family = PF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
auto loop = EQ::EventLoop::Get().Handle(); void DNSLookup(const std::string& addr, int port, bool ipv6, dns_callback_t cb);
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;
uv_getaddrinfo(loop, resolver, [](uv_getaddrinfo_t* req, int status, addrinfo* res) { std::string DNSLookupSync(const std::string& addr, int port, bool ipv6 = false);
DNSBaton *baton = (DNSBaton*)req->data;
if (status < 0) {
auto cb = baton->cb;
delete baton;
delete req;
cb("");
return;
}
char addr[40] = { 0 }; } // namespace EQ::Net
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);
}
}
}

View File

@ -19,7 +19,9 @@
#include "common/net/tcp_connection_pooling.h" #include "common/net/tcp_connection_pooling.h"
#include "common/platform/platform.h"
#include "uv.h" #include "uv.h"
#include <functional> #include <functional>
#include <memory> #include <memory>
#include <string> #include <string>

View File

@ -49,9 +49,9 @@ namespace EQ
WebsocketException(const std::string &msg) WebsocketException(const std::string &msg)
: _msg(msg.empty() ? "Unknown Error" : 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(); return _msg.c_str();
} }
private: private:

View File

@ -17,17 +17,16 @@
*/ */
#pragma once #pragma once
static constexpr char OP_SessionRequest = 0x01;
static const char OP_SessionRequest = 0x01; static constexpr char OP_SessionResponse = 0x02;
static const char OP_SessionResponse = 0x02; static constexpr char OP_Combined = 0x03;
static const char OP_Combined = 0x03; static constexpr char OP_SessionDisconnect = 0x05;
static const char OP_SessionDisconnect = 0x05; static constexpr char OP_KeepAlive = 0x06;
static const char OP_KeepAlive = 0x06; static constexpr char OP_SessionStatRequest = 0x07;
static const char OP_SessionStatRequest = 0x07; static constexpr char OP_SessionStatResponse = 0x08;
static const char OP_SessionStatResponse= 0x08; static constexpr char OP_Packet = 0x09;
static const char OP_Packet = 0x09; static constexpr char OP_Fragment = 0x0d;
static const char OP_Fragment = 0x0d; static constexpr char OP_OutOfOrderAck = 0x11;
static const char OP_OutOfOrderAck = 0x11; static constexpr char OP_Ack = 0x15;
static const char OP_Ack = 0x15; static constexpr char OP_AppCombined = 0x19;
static const char OP_AppCombined = 0x19; static constexpr char OP_OutOfSession = 0x1d;
static const char OP_OutOfSession = 0x1d;

View File

@ -142,10 +142,12 @@ RegularOpcodeManager::~RegularOpcodeManager() {
safe_delete_array(eq_to_emu); 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; NormalMemStrategy s;
s.it = this; s.it = this;
MOpcodes.lock();
loaded = true; loaded = true;
eq_to_emu = new EmuOpcode[MAX_EQ_OPCODE]; 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); memset(emu_to_eq, 0, sizeof(uint16)*_maxEmuOpcode);
bool ret = LoadOpcodesFile(filename, &s, report_errors); bool ret = LoadOpcodesFile(filename, &s, report_errors);
MOpcodes.unlock();
return ret; return ret;
} }
bool RegularOpcodeManager::ReloadOpcodes(const char *filename, bool report_errors) { bool RegularOpcodeManager::ReloadOpcodes(const char* filename, bool report_errors)
if(!loaded) {
return(LoadOpcodes(filename)); if (!loaded)
return LoadOpcodes(filename);
std::scoped_lock lock(MOpcodes);
NormalMemStrategy s; NormalMemStrategy s;
s.it = this; s.it = this;
MOpcodes.lock();
memset(eq_to_emu, 0, sizeof(uint16)*MAX_EQ_OPCODE); memset(eq_to_emu, 0, sizeof(uint16) * MAX_EQ_OPCODE);
return LoadOpcodesFile(filename, &s, report_errors);
bool ret = LoadOpcodesFile(filename, &s, report_errors);
MOpcodes.unlock();
return(ret);
} }
uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) { uint16 RegularOpcodeManager::EmuToEQ(const EmuOpcode emu_op) {
//opcode is checked for validity in GetEQOpcode //opcode is checked for validity in GetEQOpcode
uint16 res; uint16 res;
MOpcodes.lock(); {
res = emu_to_eq[emu_op]; std::scoped_lock lock(MOpcodes);
MOpcodes.unlock(); res = emu_to_eq[emu_op];
}
LogNetcodeDetail("[Opcode Manager] Translate emu [{}] ({:#06x}) eq [{:#06x}]", OpcodeNames[emu_op], emu_op, res); 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); return(res);
} }
EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op) { EmuOpcode RegularOpcodeManager::EQToEmu(const uint16 eq_op)
{
//opcode is checked for validity in GetEmuOpcode //opcode is checked for validity in GetEmuOpcode
//Disabled since current live EQ uses the entire uint16 bitspace for opcodes //Disabled since current live EQ uses the entire uint16 bitspace for opcodes
// if(eq_op > MAX_EQ_OPCODE) // if(eq_op > MAX_EQ_OPCODE)
// return(OP_Unknown); // return(OP_Unknown);
EmuOpcode res; EmuOpcode res;
MOpcodes.lock(); {
res = eq_to_emu[eq_op]; std::scoped_lock lock(MOpcodes);
MOpcodes.unlock(); res = eq_to_emu[eq_op];
}
#ifdef DEBUG_TRANSLATE #ifdef DEBUG_TRANSLATE
fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res); fprintf(stderr, "M Translate EQ 0x%.4x to Emu %s (%d)\n", eq_op, OpcodeNames[res], res);
#endif #endif

View File

@ -18,10 +18,10 @@
#pragma once #pragma once
#include "common/emu_opcodes.h" #include "common/emu_opcodes.h"
#include "common/mutex.h"
#include "common/types.h" #include "common/types.h"
#include <map> #include <map>
#include <mutex>
//enable the use of shared mem opcodes for world and zone only //enable the use of shared mem opcodes for world and zone only
#ifdef ZONE #ifdef ZONE
@ -31,7 +31,8 @@
#define SHARED_OPCODES #define SHARED_OPCODES
#endif #endif
class OpcodeManager { class OpcodeManager
{
public: public:
OpcodeManager(); OpcodeManager();
virtual ~OpcodeManager() {} virtual ~OpcodeManager() {}
@ -48,24 +49,27 @@ public:
EmuOpcode NameSearch(const char *name); EmuOpcode NameSearch(const char *name);
//This has to be public for stupid visual studio //This has to be public for stupid visual studio
class OpcodeSetStrategy { class OpcodeSetStrategy
{
public: public:
virtual ~OpcodeSetStrategy() {} //shut up compiler! virtual ~OpcodeSetStrategy() = default;
virtual void Set(EmuOpcode emu_op, uint16 eq_op) = 0; virtual void Set(EmuOpcode emu_op, uint16 eq_op) = 0;
}; };
protected: protected:
bool loaded; //true if all opcodes loaded 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 //in a shared manager, this dosent protect others
static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors); static bool LoadOpcodesFile(const char *filename, OpcodeSetStrategy *s, bool report_errors);
}; };
class MutableOpcodeManager : public OpcodeManager { class MutableOpcodeManager : public OpcodeManager
{
public: public:
MutableOpcodeManager() : OpcodeManager() {} MutableOpcodeManager() = default;
virtual bool Mutable() { return(true); }
virtual bool Mutable() override { return true; }
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) = 0; virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op) = 0;
}; };
@ -108,16 +112,16 @@ public:
virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op); virtual void SetOpcode(EmuOpcode emu_op, uint16 eq_op);
protected: protected:
class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy { class NormalMemStrategy : public OpcodeManager::OpcodeSetStrategy
{
public: public:
virtual ~NormalMemStrategy() {} //shut up compiler! RegularOpcodeManager* it;
RegularOpcodeManager *it;
void Set(EmuOpcode emu_op, uint16 eq_op);
};
friend class NormalMemStrategy;
uint16 *emu_to_eq; virtual void Set(EmuOpcode emu_op, uint16 eq_op) override;
EmuOpcode *eq_to_emu; };
uint16* emu_to_eq;
EmuOpcode* eq_to_emu;
uint32 EQOpcodeCount; uint32 EQOpcodeCount;
uint32 EmuOpcodeCount; uint32 EmuOpcodeCount;
}; };

View File

@ -3221,7 +3221,7 @@ namespace RoF
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;

View File

@ -689,7 +689,7 @@ namespace RoF2
EQApplicationPacket *outapp = nullptr; EQApplicationPacket *outapp = nullptr;
if (eq->bufffade == 1) if (eq->bufffade == 1)
{ {
outapp = new EQApplicationPacket(OP_BuffCreate, 29); outapp = new EQApplicationPacket(OP_BuffCreate, 29u);
outapp->WriteUInt32(emu->entityid); outapp->WriteUInt32(emu->entityid);
outapp->WriteUInt32(0); // tic timer outapp->WriteUInt32(0); // tic timer
outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ? outapp->WriteUInt8(0); // Type of OP_BuffCreate packet ?
@ -753,7 +753,7 @@ namespace RoF2
ar(bl); ar(bl);
//packet size //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) { for (auto const &b: bl.trade_items) {
packet_size += b.item_name.length() + 1; packet_size += b.item_name.length() + 1;
packet_size += 12; packet_size += 12;
@ -1622,7 +1622,7 @@ namespace RoF2
//Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Yourname is %s", gu2->yourname); //Log.LogDebugType(Logs::General, Logs::Netcode, "[ERROR] Yourname is %s", gu2->yourname);
int MemberCount = 1; 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) for (int i = 0; i < 5; ++i)
{ {
@ -2207,7 +2207,7 @@ namespace RoF2
char *Buffer = (char *)in->pBuffer; 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; PacketSize += (sizeof(structs::MercenaryListEntry_Struct) - sizeof(structs::MercenaryStance_Struct)) * emu->MercCount;
uint32 r; uint32 r;
@ -3820,7 +3820,7 @@ namespace RoF2
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;
@ -4120,8 +4120,8 @@ namespace RoF2
std::begin(emu->items), std::begin(emu->items),
std::end(emu->items), std::end(emu->items),
std::begin(eq->items), std::begin(eq->items),
[&](const uint32 x) { [&](uint64 x) {
return x; return static_cast<uint32>(x);
} }
); );
std::copy_n( std::copy_n(
@ -4599,7 +4599,7 @@ namespace RoF2
int k; int k;
for (r = 0; r < entrycount; r++, emu++) { for (r = 0; r < entrycount; r++, emu++) {
int PacketSize = 206; uint32 PacketSize = 206;
PacketSize += strlen(emu->name); PacketSize += strlen(emu->name);
PacketSize += strlen(emu->lastName); PacketSize += strlen(emu->lastName);

View File

@ -2128,7 +2128,7 @@ namespace SoD
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;

View File

@ -1785,7 +1785,7 @@ namespace SoF
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;

View File

@ -1991,7 +1991,7 @@ namespace Titanium
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;

View File

@ -2711,7 +2711,7 @@ namespace UF
buf.WriteString(new_message); 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); dest->FastQueuePacket(&outapp, ack_req);
delete in; delete in;

View File

@ -19,6 +19,7 @@
#ifdef _WINDOWS #ifdef _WINDOWS
#include "common/platform/win/include_windows.h"
#include <WinSock2.h> #include <WinSock2.h>
#endif // _WINDOWS #endif // _WINDOWS

View File

@ -23,11 +23,13 @@
inline std::string random_string(size_t length) inline std::string random_string(size_t length)
{ {
auto randchar = []() -> char { auto randchar = []() -> char
{
const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz"; const char charset[] = "0123456789" "ABCDEFGHIJKLMNOPQRSTUVWXYZ" "abcdefghijklmnopqrstuvwxyz";
const size_t max_index = (sizeof(charset) - 1); const size_t max_index = (sizeof(charset) - 1);
return charset[static_cast<size_t>(std::rand()) % max_index]; return charset[static_cast<size_t>(std::rand()) % max_index];
}; };
std::string str(length, 0); std::string str(length, 0);
std::generate_n(str.begin(), length, randchar); std::generate_n(str.begin(), length, randchar);
return str; return str;

View File

@ -27,7 +27,7 @@
class SerializeBuffer class SerializeBuffer
{ {
public: public:
SerializeBuffer() : m_buffer(nullptr), m_capacity(0), m_pos(0) {} SerializeBuffer() = default;
explicit SerializeBuffer(size_t size) : m_capacity(size), m_pos(0) explicit SerializeBuffer(size_t size) : m_capacity(size), m_pos(0)
{ {
@ -35,8 +35,10 @@ public:
memset(m_buffer, 0, size); memset(m_buffer, 0, size);
} }
SerializeBuffer(const SerializeBuffer &rhs) SerializeBuffer(const SerializeBuffer& rhs)
: m_buffer(new unsigned char[rhs.m_capacity]), m_capacity(rhs.m_capacity), m_pos(rhs.m_pos) : 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); memcpy(m_buffer, rhs.m_buffer, rhs.m_capacity);
} }
@ -53,30 +55,31 @@ public:
return *this; 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; delete[] m_buffer;
m_buffer = rhs.m_buffer; m_buffer = std::exchange(rhs.m_buffer, nullptr);
m_capacity = rhs.m_capacity; m_capacity = std::exchange(rhs.m_capacity, 0);
m_pos = rhs.m_pos; m_pos = std::exchange(rhs.m_pos, 0);
rhs.m_buffer = nullptr;
rhs.m_capacity = 0;
rhs.m_pos = 0;
} }
return *this; return *this;
} }
~SerializeBuffer() { delete[] m_buffer; } ~SerializeBuffer()
{
delete[] m_buffer;
}
void WriteUInt8(uint8_t v) void WriteUInt8(uint8_t v)
{ {
@ -209,7 +212,8 @@ public:
private: private:
void Grow(size_t new_size); void Grow(size_t new_size);
void Reset(); void Reset();
unsigned char *m_buffer;
size_t m_capacity; unsigned char* m_buffer = nullptr;
size_t m_pos; size_t m_capacity = 0;
size_t m_pos = 0;
}; };

View File

@ -389,35 +389,31 @@ enum {
class ServerPacket class ServerPacket
{ {
public: public:
~ServerPacket() { safe_delete_array(pBuffer); } ~ServerPacket()
ServerPacket(uint16 in_opcode = 0, uint32 in_size = 0) { {
this->compressed = false; safe_delete_array(pBuffer);
size = in_size; }
opcode = in_opcode;
if (size == 0) { ServerPacket(uint16 in_opcode = 0, size_t in_size = 0)
pBuffer = 0; : size(static_cast<uint32>(in_size))
} , opcode(in_opcode)
else { {
if (size != 0)
{
pBuffer = new uchar[size]; pBuffer = new uchar[size];
memset(pBuffer, 0, size); memset(pBuffer, 0, size);
} }
_wpos = 0;
_rpos = 0;
} }
ServerPacket(uint16 in_opcode, const EQ::Net::Packet &p) { ServerPacket(uint16 in_opcode, const EQ::Net::Packet& p)
this->compressed = false; : size(static_cast<uint32>(p.Length()))
size = (uint32)p.Length(); , opcode(in_opcode)
opcode = in_opcode; {
if (size == 0) { if (size != 0)
pBuffer = 0; {
}
else {
pBuffer = new uchar[size]; pBuffer = new uchar[size];
memcpy(pBuffer, p.Data(), size); memcpy(pBuffer, p.Data(), size);
} }
_wpos = 0;
_rpos = 0;
} }
ServerPacket* Copy() { ServerPacket* Copy() {
@ -447,14 +443,14 @@ public:
void ReadSkipBytes(uint32 count) { _rpos += count; } void ReadSkipBytes(uint32 count) { _rpos += count; }
void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; } void SetReadPosition(uint32 Newrpos) { _rpos = Newrpos; }
uint32 size; uint32 size = 0;
uint16 opcode; uint16 opcode = 0;
uchar* pBuffer; uchar* pBuffer = nullptr;
uint32 _wpos; uint32 _wpos = 0;
uint32 _rpos; uint32 _rpos = 0;
bool compressed; bool compressed = false;
uint32 InflatedSize; uint32 InflatedSize = 0;
uint32 destination; uint32 destination = 0;
}; };
#pragma pack(push) #pragma pack(push)
@ -989,11 +985,12 @@ struct LauncherConnectInfo {
char name[64]; char name[64];
}; };
typedef enum { enum ZoneRequestCommands {
ZR_Start, ZR_Start,
ZR_Restart, ZR_Restart,
ZR_Stop ZR_Stop
} ZoneRequestCommands; };
struct LauncherZoneRequest { struct LauncherZoneRequest {
uint8 command; uint8 command;
char short_name[33]; char short_name[33];

View File

@ -38,10 +38,10 @@
#define RELOADTASKS 0 #define RELOADTASKS 0
#define RELOADTASKSETS 2 #define RELOADTASKSETS 2
typedef enum { enum TaskMethodType {
METHODSINGLEID = 0, METHODSINGLEID = 0,
METHODQUEST = 2 METHODQUEST = 2
} TaskMethodType; };
enum class TaskActivityType : int32_t // task element/objective enum class TaskActivityType : int32_t // task element/objective
{ {

View File

@ -94,7 +94,7 @@ namespace
{ {
m_cache.insert(std::make_pair( m_cache.insert(std::make_pair(
key_type(src, target, dynamic_id, object_offset) key_type(src, target, dynamic_id, object_offset)
, cache_entry(offset, distance) , cache_entry(offset, static_cast<int>(distance))
)); ));
} }

View File

@ -547,7 +547,7 @@ void Client::SendExpansionPacketData(PlayerLoginReply &plrs)
buf.WriteInt32(0xFFFFFFFF); buf.WriteInt32(0xFFFFFFFF);
} }
auto out = std::make_unique<EQApplicationPacket>(OP_LoginExpansionPacketData, buf); auto out = std::make_unique<EQApplicationPacket>(OP_LoginExpansionPacketData, std::move(buf));
m_connection->QueuePacket(out.get()); m_connection->QueuePacket(out.get());
} }

View File

@ -153,7 +153,7 @@ std::unique_ptr<EQApplicationPacket> WorldServerManager::CreateServerListPacket(
s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion()); s->SerializeForClientServerList(buf, use_local_ip, client->GetClientVersion());
} }
return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, buf); return std::make_unique<EQApplicationPacket>(OP_ServerListResponse, std::move(buf));
} }
void WorldServerManager::SendUserLoginToWorldRequest( void WorldServerManager::SendUserLoginToWorldRequest(

View File

@ -20,9 +20,12 @@
#include "common/eqemu_config.h" #include "common/eqemu_config.h"
#include "common/repositories/zone_repository.h" #include "common/repositories/zone_repository.h"
#include <chrono>
#include <csignal> #include <csignal>
#include <thread> #include <thread>
using namespace std::chrono_literals;
Database db; Database db;
Database db2; Database db2;
@ -60,8 +63,6 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser
LogInfo("Database test"); LogInfo("Database test");
auto mutex = new Mutex;
auto c = EQEmuConfig::get(); auto c = EQEmuConfig::get();
LogInfo("Connecting to MySQL"); LogInfo("Connecting to MySQL");
if (!db.Connect( if (!db.Connect(
@ -75,19 +76,19 @@ void WorldserverCLI::TestDatabaseConcurrency(int argc, char **argv, argh::parser
return; return;
} }
db.SetMutex(mutex); std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
db.SetMutex(sharedMutex);
db2.SetMySQL(db); db2.SetMySQL(db);
db2.SetMutex(mutex); db2.SetMutex(sharedMutex);
std::thread(DatabaseTest).detach(); std::thread(DatabaseTest).detach();
std::thread(DatabaseTest).detach(); std::thread(DatabaseTest).detach();
std::thread(DatabaseTestSecondConnection).detach(); std::thread(DatabaseTestSecondConnection).detach();
while (!stop) { while (!stop) {
std::this_thread::sleep_for(0s);
} }
safe_delete(mutex);
} }

View File

@ -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["bots_database_version"] = RuleB(Bots, Enabled) ? CURRENT_BINARY_BOTS_DATABASE_VERSION : 0;
v["custom_database_version"] = CUSTOM_BINARY_DATABASE_VERSION; v["custom_database_version"] = CUSTOM_BINARY_DATABASE_VERSION;
std::stringstream payload; std::cout << v << std::endl;
payload << v;
std::cout << payload.str() << std::endl;
} }

View File

@ -18,7 +18,7 @@
#include "world/world_server_cli.h" #include "world/world_server_cli.h"
#include "common/events/player_events.h" #include "common/events/player_events.h"
#include "common/memory/ksm.hpp" #include "common/memory/ksm.h"
#include "cereal/archives/json.hpp" #include "cereal/archives/json.hpp"
#include "cereal/types/vector.hpp" #include "cereal/types/vector.hpp"

View File

@ -39,8 +39,5 @@ void WorldserverCLI::Version(int argc, char **argv, argh::parser &cmd, std::stri
j["database_version"] = CURRENT_BINARY_DATABASE_VERSION; j["database_version"] = CURRENT_BINARY_DATABASE_VERSION;
j["server_version"] = CURRENT_VERSION; j["server_version"] = CURRENT_VERSION;
std::stringstream payload; std::cout << j << std::endl;
payload << j;
std::cout << payload.str() << std::endl;
} }

View File

@ -24,14 +24,14 @@
#include <vector> #include <vector>
typedef enum { enum CLE_Status {
Never, Never,
Offline, Offline,
Online, Online,
CharSelect, CharSelect,
Zoning, Zoning,
InZone InZone
} CLE_Status; };
static const char *CLEStatusString[] = { static const char *CLEStatusString[] = {
"Never", "Never",

View File

@ -25,10 +25,10 @@
class LauncherLink; class LauncherLink;
typedef struct { struct LauncherZone{
std::string name; std::string name;
uint16 port; uint16 port;
} LauncherZone; };
//a class exported to perl representing a launcher's in-DB config //a class exported to perl representing a launcher's in-DB config
class EQLConfig { class EQLConfig {

View File

@ -69,10 +69,10 @@ protected:
uint8 m_dynamicCount; uint8 m_dynamicCount;
typedef struct { struct ZoneState{
bool up; bool up;
uint32 starts; //number of times this zone has started uint32 starts; //number of times this zone has started
uint16 port; //the port this zone wants to use (0=pick one) uint16 port; //the port this zone wants to use (0=pick one)
} ZoneState; };
std::map<std::string, ZoneState> m_states; std::map<std::string, ZoneState> m_states;
}; };

View File

@ -20,7 +20,6 @@
#include "common/eq_packet_structs.h" #include "common/eq_packet_structs.h"
#include "common/event/timer.h" #include "common/event/timer.h"
#include "common/linked_list.h" #include "common/linked_list.h"
#include "common/mutex.h"
#include "common/net/servertalk_client_connection.h" #include "common/net/servertalk_client_connection.h"
#include "common/net/servertalk_legacy_client_connection.h" #include "common/net/servertalk_legacy_client_connection.h"
#include "common/queue.h" #include "common/queue.h"

View File

@ -18,7 +18,6 @@
#pragma once #pragma once
#include "common/eq_packet_structs.h" #include "common/eq_packet_structs.h"
#include "common/mutex.h"
#include "common/queue.h" #include "common/queue.h"
#include "common/servertalk.h" #include "common/servertalk.h"
#include "common/timer.h" #include "common/timer.h"

View File

@ -319,14 +319,14 @@ void SharedTaskManager::LoadSharedTaskState()
// load character data for member names // load character data for member names
std::vector<CharacterDataRepository::CharacterData> shared_task_character_data; std::vector<CharacterDataRepository::CharacterData> shared_task_character_data;
if (!shared_task_members_data.empty()) { if (!shared_task_members_data.empty()) {
std::vector<uint32_t> character_ids; std::vector<int64_t> character_ids;
for (const auto &m: shared_task_members_data) { for (const BaseSharedTaskMembersRepository::SharedTaskMembers& m: shared_task_members_data) {
character_ids.emplace_back(m.character_id); character_ids.emplace_back(m.character_id);
} }
shared_task_character_data = CharacterDataRepository::GetWhere( shared_task_character_data = CharacterDataRepository::GetWhere(
*m_database, *m_database,
fmt::format("id IN ({})", Strings::Join(character_ids, ",")) fmt::format("id IN ({})", fmt::join(character_ids, ","))
); );
} }

View File

@ -44,6 +44,6 @@ public:
private: private:
inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; } inline std::string GetIP() const { return (connection && connection->Handle()) ? connection->Handle()->RemoteIP() : 0; }
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
std::shared_ptr<EQ::Net::ServertalkServerConnection> connection;
}; };

View File

@ -24,8 +24,7 @@
#include "common/http/httplib.h" #include "common/http/httplib.h"
#include "common/http/uri.h" #include "common/http/uri.h"
#include "common/ip_util.h" #include "common/ip_util.h"
#include "common/net/console_server.h" #include "common/net/dns.h"
#include "common/net/servertalk_server.h"
#include "common/path_manager.h" #include "common/path_manager.h"
#include "common/repositories/character_expedition_lockouts_repository.h" #include "common/repositories/character_expedition_lockouts_repository.h"
#include "common/repositories/character_task_timers_repository.h" #include "common/repositories/character_task_timers_repository.h"
@ -33,7 +32,6 @@
#include "common/rulesys.h" #include "common/rulesys.h"
#include "common/strings.h" #include "common/strings.h"
#include "common/zone_store.h" #include "common/zone_store.h"
#include "common/zone_store.h"
#include "world/adventure_manager.h" #include "world/adventure_manager.h"
#include "world/dynamic_zone_manager.h" #include "world/dynamic_zone_manager.h"
#include "world/login_server_list.h" #include "world/login_server_list.h"
@ -49,8 +47,6 @@
extern WorldConfig Config; extern WorldConfig Config;
auto mutex = new Mutex;
void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message) void WorldBoot::GMSayHookCallBackProcessWorld(uint16 log_category, const char *func, std::string message)
{ {
// we don't want to loop up with chat messages // we don't want to loop up with chat messages
@ -180,11 +176,13 @@ bool WorldBoot::LoadDatabaseConnections()
} }
else { else {
content_db.SetMySQL(database); content_db.SetMySQL(database);
// when database and content_db share the same underlying mysql connection // 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 // it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads // when database actions are occurring in different threads
database.SetMutex(mutex); std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
content_db.SetMutex(mutex); database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
} }
return true; return true;
@ -456,7 +454,7 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
std::string config_address = c->WorldAddress; std::string config_address = c->WorldAddress;
if (!IpUtil::IsIPAddress(config_address)) { if (!IpUtil::IsIPAddress(config_address)) {
config_address = IpUtil::DNSLookupSync(c->WorldAddress, 9000); config_address = EQ::Net::DNSLookupSync(c->WorldAddress, 9000);
LogInfo( LogInfo(
"World config address using DNS [{}] resolves to [{}]", "World config address using DNS [{}] resolves to [{}]",
c->WorldAddress, c->WorldAddress,
@ -634,7 +632,6 @@ void WorldBoot::CheckForPossibleConfigurationIssues()
void WorldBoot::Shutdown() void WorldBoot::Shutdown()
{ {
safe_delete(mutex);
} }
void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message) void WorldBoot::SendDiscordMessage(int webhook_id, const std::string &message)

View File

@ -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 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 #define WAKE_THE_DEAD_NPCTYPEID 500 //We use first pet in pets table as a template
typedef enum { enum aaNonspellAction {
aaActionNone = 0, aaActionNone = 0,
aaActionAETaunt = 1, aaActionAETaunt = 1,
aaActionMassBuff = 2, aaActionMassBuff = 2,
@ -38,7 +38,7 @@ typedef enum {
aaActionLeechTouch = 14, aaActionLeechTouch = 14,
aaActionProjectIllusion = 15, aaActionProjectIllusion = 15,
aaActionFadingMemories = 16 aaActionFadingMemories = 16
} aaNonspellAction; };
enum { //leadership AA indexes enum { //leadership AA indexes
groupAAMarkNPC = 0, groupAAMarkNPC = 0,
@ -116,7 +116,7 @@ static const uint8 LeadershipAACosts[_maxLeaderAA][MAX_LEADERSHIP_TIERS] = {
{ 0, 0, 0, 0, 0, 0 }, //raidAA15 { 0, 0, 0, 0, 0, 0 }, //raidAA15
}; };
typedef enum { //AA IDs enum aaID { //AA IDs
aaNone =0, aaNone =0,
aaInnateStrength =2,//implemented as bonus aaInnateStrength =2,//implemented as bonus
aaInnateStamina =7,//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 aaHighestID //this should always be last, and should always
//follow the highest AA ID //follow the highest AA ID
} aaID; };
//Structure representing the database's swarm pet configs //Structure representing the database's swarm pet configs
struct SwarmPet_Struct { struct SwarmPet_Struct {

View File

@ -10580,12 +10580,12 @@ void Bot::LoadDefaultBotSettings() {
m_bot_spell_settings.push_back(t); 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, '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), GetDefaultSpellTypeHold(i, bot_stance),
GetDefaultSpellTypeDelay(i, bot_stance), GetDefaultSpellTypeDelay(i, bot_stance),
GetDefaultSpellTypeMinThreshold(i, bot_stance), GetDefaultSpellTypeMinThreshold(i, bot_stance),
GetDefaultSpellTypeMaxThreshold(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, '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)); 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) { BotSpell Bot::GetSpellByHealType(uint16 spell_type, Mob* tar) {
if (!TargetValidation(tar)) { if (!TargetValidation(tar)) {
BotSpell result; BotSpell result{};
return result; return result;
} }

View File

@ -458,9 +458,7 @@ uint32 helper_bot_create(Client *bot_owner, std::string bot_name, uint8 bot_clas
return bot_id; return bot_id;
} }
bool available_flag = false; bool available_flag = database.botdb.QueryNameAvailability(bot_name);
!database.botdb.QueryNameAvailability(bot_name, available_flag);
if (!available_flag) { if (!available_flag) {
bot_owner->Message( bot_owner->Message(

View File

@ -24,26 +24,22 @@
class Client; class Client;
class Seperator; class Seperator;
namespace
{
#define HP_RATIO_DELTA 5.0f #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)) #define VALIDATECLASSID(x) ((x >= Class::Warrior && x <= Class::Berserker) ? (x) : (0))
// ActionableTarget action_type // ActionableTarget action_type
#define FRIENDLY true #define FRIENDLY true
#define ENEMY false #define ENEMY false
enum { enum {
AFT_None = 0, AFT_None = 0,
AFT_Value, AFT_Value,
AFT_GenderRace, AFT_GenderRace,
AFT_Race AFT_Race
}; };
}
namespace MyBots namespace MyBots
{ {

View File

@ -145,9 +145,7 @@ void bot_command_clone(Client *c, const Seperator *sep)
return; return;
} }
bool available_flag = false; bool available_flag = database.botdb.QueryNameAvailability(bot_name);
!database.botdb.QueryNameAvailability(bot_name, available_flag);
if (!available_flag) { if (!available_flag) {
c->Message( c->Message(

View File

@ -82,8 +82,8 @@ void bot_command_pickpocket(Client *c, const Seperator *sep)
} }
// Setup variables for calcs // Setup variables for calcs
bool steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets); uint16 steal_skill = my_bot->GetSkill(EQ::skills::SkillPickPockets);
bool steal_chance = steal_skill * 100 / (5 * over_level + 5); int steal_chance = steal_skill * 100 / (5 * over_level + 5);
// Determine whether to steal money or an item. // Determine whether to steal money or an item.
uint32 money[6] = { uint32 money[6] = {

View File

@ -228,7 +228,7 @@ bool BotDatabase::LoadBotSpellCastingChances()
return true; return true;
} }
bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& available_flag) bool BotDatabase::QueryNameAvailability(const std::string& bot_name)
{ {
if ( if (
bot_name.empty() || bot_name.empty() ||
@ -239,8 +239,6 @@ bool BotDatabase::QueryNameAvailability(const std::string& bot_name, bool& avail
return false; return false;
} }
available_flag = true;
return true; return true;
} }

View File

@ -45,7 +45,7 @@ public:
/* Bot functions */ /* 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 QueryBotCount(const uint32 owner_id, int class_id, uint32& bot_count, uint32& bot_class_count);
bool LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list, bool by_account = false); bool LoadBotsList(const uint32 owner_id, std::list<BotsAvailableList>& bots_list, bool by_account = false);

View File

@ -27,7 +27,7 @@
class CheatManager; class CheatManager;
class Client; class Client;
typedef enum { enum UpdateMovementType {
Collision = 1, Collision = 1,
TeleportB, TeleportB,
TeleportA, TeleportA,
@ -37,18 +37,18 @@ typedef enum {
SpellA, // Titanium - UF SpellA, // Titanium - UF
Unknown0x8, Unknown0x8,
SpellB // Used in RoF+ SpellB // Used in RoF+
} UpdateMovementType; };
typedef enum { enum ExemptionType {
ShadowStep, ShadowStep,
KnockBack, KnockBack,
Port, Port,
Assist, Assist,
Sense, Sense,
MAX_EXEMPTIONS MAX_EXEMPTIONS
} ExemptionType; };
typedef enum { enum CheatTypes {
MQWarp, MQWarp,
MQWarpShadowStep, MQWarpShadowStep,
MQWarpKnockBack, MQWarpKnockBack,
@ -59,7 +59,7 @@ typedef enum {
MQGhost, MQGhost,
MQFastMem, MQFastMem,
MQWarpAbsolute MQWarpAbsolute
} CheatTypes; };
class CheatManager { class CheatManager {
public: public:

View File

@ -1784,7 +1784,7 @@ void Client::Message(uint32 type, const char* message, ...) {
buf.WriteInt32(0); buf.WriteInt32(0);
buf.WriteString(buffer); buf.WriteString(buffer);
auto app = new EQApplicationPacket(OP_SpecialMesg, buf); auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf));
FastQueuePacket(&app); FastQueuePacket(&app);
@ -1813,7 +1813,7 @@ void Client::FilteredMessage(Mob *sender, uint32 type, eqFilterType filter, cons
buf.WriteInt32(0); buf.WriteInt32(0);
buf.WriteString(buffer); buf.WriteString(buffer);
auto app = new EQApplicationPacket(OP_SpecialMesg, buf); auto app = new EQApplicationPacket(OP_SpecialMesg, std::move(buf));
FastQueuePacket(&app); 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 buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime
auto outapp = std::make_unique<EQApplicationPacket>(OP_FormattedMessage, buf); auto outapp = std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buf));
if (distance > 0) if (distance > 0)
entity_list.QueueCloseClients(this, outapp.get(), false, distance); 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 buf.WriteInt8(0); // prevent oob in packet translation, maybe clean that up sometime
auto outapp = std::make_unique<EQApplicationPacket>(OP_FormattedMessage, buf); auto outapp = std::make_unique<EQApplicationPacket>(OP_FormattedMessage, std::move(buf));
QueuePacket(outapp.get()); QueuePacket(outapp.get());
} }

View File

@ -106,7 +106,7 @@ enum { //scribing argument to MemorizeSpell
}; };
//Modes for the zoning state of the client. //Modes for the zoning state of the client.
typedef enum { enum ZoneMode {
ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac ZoneToSafeCoords, // Always send ZonePlayerToBind_Struct to client: Succor/Evac
GMSummon, // Always send ZonePlayerToBind_Struct to client: Only a GM Summon GMSummon, // Always send ZonePlayerToBind_Struct to client: Only a GM Summon
GMHiddenSummon, // Always send ZonePlayerToBind_Struct to client silently: 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 SummonPC, // In-zone GMMove() always: Call of the Hero spell or some other type of in zone only summons
Rewind, // Summon to /rewind location. Rewind, // Summon to /rewind location.
EvacToSafeCoords EvacToSafeCoords
} ZoneMode; };
// translate above enum to a string // translate above enum to a string
std::string GetZoneModeString(ZoneMode mode); std::string GetZoneModeString(ZoneMode mode);
@ -130,13 +130,13 @@ enum {
HideCorpseNPC = 5 HideCorpseNPC = 5
}; };
typedef enum enum ShowSpellType
{ {
Disciplines, Disciplines,
Spells Spells
} ShowSpellType; };
typedef enum enum XTargetType
{ {
Empty = 0, Empty = 0,
Auto = 1, Auto = 1,
@ -165,8 +165,7 @@ typedef enum
MyPetTarget = 24, MyPetTarget = 24,
MyMercenary = 25, MyMercenary = 25,
MyMercenaryTarget = 26 MyMercenaryTarget = 26
};
} XTargetType;
struct XTarget_Struct struct XTarget_Struct
{ {

View File

@ -252,7 +252,7 @@ void Client::LoadDefaultBotSettings() {
m_bot_spell_settings.push_back(t); m_bot_spell_settings.push_back(t);
LogBotSettingsDetail("{} says, 'Setting defaults for {} ({}) [#{}]'", GetCleanName(), t.name, t.short_name, t.spell_type); 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), GetDefaultSpellTypeDelay(i),
GetDefaultSpellTypeMinThreshold(i), GetDefaultSpellTypeMaxThreshold(i)); GetDefaultSpellTypeMinThreshold(i), GetDefaultSpellTypeMaxThreshold(i));
} }

View File

@ -3239,10 +3239,10 @@ void Client::Handle_OP_AugmentItem(const EQApplicationPacket *app)
} }
if ( if (
((tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), in_augment->augment_index)) != -1) && tobe_auged->IsAugmentSlotAvailable(new_aug->GetAugmentType(), static_cast<uint8>(in_augment->augment_index)) &&
tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots) tobe_auged->AvailableWearSlot(new_aug->GetItem()->Slots)
) { ) {
old_aug = tobe_auged->RemoveAugment(in_augment->augment_index); old_aug = tobe_auged->RemoveAugment(static_cast<uint8>(in_augment->augment_index));
if (old_aug) { // An old augment was removed in order to be replaced with the new one (augment_action 2) if (old_aug) { // An old augment was removed in order to be replaced with the new one (augment_action 2)
CalcBonuses(); CalcBonuses();

View File

@ -28,11 +28,11 @@ class Seperator;
typedef void (*CmdFuncPtr)(Client *, const Seperator *); typedef void (*CmdFuncPtr)(Client *, const Seperator *);
typedef struct { struct CommandRecord {
uint8 admin; uint8 admin;
std::string description; std::string description;
CmdFuncPtr function; // null means perl function CmdFuncPtr function; // null means perl function
} CommandRecord; };
extern int (*command_dispatch)(Client *, std::string, bool); extern int (*command_dispatch)(Client *, std::string, bool);
extern int command_count; // Commands Loaded Count extern int command_count; // Commands Loaded Count

View File

@ -922,7 +922,7 @@ struct DataBucketCache
enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath }; enum eStandingPetOrder { SPO_Follow, SPO_Sit, SPO_Guard, SPO_FeignDeath };
typedef enum { enum PetTypeOld {
petFamiliar, //only listens to /pet get lost petFamiliar, //only listens to /pet get lost
petAnimation, //does not listen to any commands petAnimation, //does not listen to any commands
petOther, petOther,
@ -930,4 +930,4 @@ typedef enum {
petNPCFollow, petNPCFollow,
petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands petTargetLock, //remain active as long something is on the hatelist. Don't listen to any commands
petNone = 0xFF // not a pet petNone = 0xFF // not a pet
} PetTypeOld; };

View File

@ -1108,7 +1108,7 @@ void EntityList::AESpell(
max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets); max_targets_allowed = RuleI(Spells, TargetedAOEMaxTargets);
} else if ( } else if (
IsPBAESpell(spell_id) && IsPBAESpell(spell_id) &&
IsDetrimentalSpell && is_detrimental_spell &&
!is_npc !is_npc
) { ) {
max_targets_allowed = RuleI(Spells, PointBlankAOEMaxTargets); max_targets_allowed = RuleI(Spells, PointBlankAOEMaxTargets);

View File

@ -4437,7 +4437,7 @@ void EntityList::QuestJournalledSayClose(
buf.WriteString(message); 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 // client only bothers logging if target spawn ID matches, safe to send to everyone
QueueCloseClients(sender, outapp, false, dist); QueueCloseClients(sender, outapp, false, dist);

View File

@ -17,7 +17,7 @@
*/ */
#pragma once #pragma once
typedef enum { enum QuestEventID {
EVENT_SAY = 0, EVENT_SAY = 0,
EVENT_TRADE, //being given an item or money EVENT_TRADE, //being given an item or money
EVENT_DEATH, //being killed EVENT_DEATH, //being killed
@ -169,6 +169,6 @@ typedef enum {
EVENT_SPELL_EFFECT_BOT, EVENT_SPELL_EFFECT_BOT,
EVENT_SPELL_EFFECT_BUFF_TIC_BOT, EVENT_SPELL_EFFECT_BUFF_TIC_BOT,
_LargestEventID _LargestEventID
} QuestEventID; };
extern const char *QuestEventSubroutines[_LargestEventID]; extern const char *QuestEventSubroutines[_LargestEventID];

View File

@ -447,15 +447,15 @@ void DoorManipulation::CommandHandler(Client *c, const Seperator *sep)
if (arg1 == "setinclineinc") { if (arg1 == "setinclineinc") {
std::map<float, std::string> incline_values = { std::map<float, std::string> incline_values = {
{.01, "Upright"}, {.01f, "Upright"},
{63.75, "45 Degrees",}, {63.75f, "45 Degrees",},
{130, "90 Degrees"}, {130.f, "90 Degrees"},
{192.5, "135 Degrees"}, {192.5f, "135 Degrees"},
{255, "180 Degrees"}, {255.f, "180 Degrees"},
{321.25, "225 Degrees"}, {321.25f, "225 Degrees"},
{385, "270 Degrees"}, {385.f, "270 Degrees"},
{448.75, "315 Degrees"}, {448.75f, "315 Degrees"},
{512.5, "360 Degrees"} {512.5f, "360 Degrees"}
}; };
std::vector<std::string> incline_normal_options; std::vector<std::string> incline_normal_options;

View File

@ -624,7 +624,7 @@ void Client::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank, std::str
out->guild_id = guild_id; out->guild_id = guild_id;
out->rank_ = rank; 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)); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
QueuePacket(outapp); QueuePacket(outapp);
@ -792,7 +792,7 @@ void EntityList::SendGuildMemberRankAltBanker(uint32 guild_id, uint32 rank_, std
out->guild_id = guild_id; out->guild_id = guild_id;
out->rank_ = rank_; 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)); strn0cpy(out->player_name, player_name.c_str(), sizeof(out->player_name));
c.second->QueuePacket(outapp); c.second->QueuePacket(outapp);

View File

@ -151,7 +151,7 @@ static const struct luaL_Reg bit_funcs[] = {
*/ */
#define BAD_SAR (bsar(-8, 2) != (SBits)-2) #define BAD_SAR (bsar(-8, 2) != (SBits)-2)
int luaopen_bit(lua_State *L) int luaopen_bit_embed(lua_State *L)
{ {
UBits b; UBits b;
lua_pushnumber(L, (lua_Number)1437217655L); lua_pushnumber(L, (lua_Number)1437217655L);

View File

@ -17,4 +17,6 @@
*/ */
#pragma once #pragma once
int luaopen_bit(lua_State *L); struct lua_State;
int luaopen_bit_embed(lua_State *L);

View File

@ -26,7 +26,6 @@
#include "common/guilds.h" #include "common/guilds.h"
#include "common/memory_mapped_file.h" #include "common/memory_mapped_file.h"
#include "common/misc.h" #include "common/misc.h"
#include "common/mutex.h"
#include "common/net/eqstream.h" #include "common/net/eqstream.h"
#include "common/opcodemgr.h" #include "common/opcodemgr.h"
#include "common/patches/patches.h" #include "common/patches/patches.h"
@ -216,8 +215,6 @@ int main(int argc, char **argv)
} }
} }
auto mutex = new Mutex;
LogInfo("Connecting to MySQL"); LogInfo("Connecting to MySQL");
if (!database.Connect( if (!database.Connect(
Config->DatabaseHost.c_str(), Config->DatabaseHost.c_str(),
@ -245,11 +242,13 @@ int main(int argc, char **argv)
} }
} else { } else {
content_db.SetMySQL(database); content_db.SetMySQL(database);
// when database and content_db share the same underlying mysql connection // 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 // it needs to be protected by a shared mutex otherwise we produce concurrency issues
// when database actions are occurring in different threads // when database actions are occurring in different threads
database.SetMutex(mutex); std::shared_ptr<DBcore::Mutex> sharedMutex = std::make_shared<DBcore::Mutex>();
content_db.SetMutex(mutex); database.SetMutex(sharedMutex);
content_db.SetMutex(sharedMutex);
} }
//rules: //rules:
@ -661,7 +660,6 @@ int main(int argc, char **argv)
LogInfo("Proper zone shutdown complete."); LogInfo("Proper zone shutdown complete.");
EQEmuLogSys::Instance()->CloseFileLogs(); EQEmuLogSys::Instance()->CloseFileLogs();
safe_delete(mutex);
safe_delete(QServ); safe_delete(QServ);
return 0; return 0;

View File

@ -17,7 +17,7 @@
*/ */
#include "common/compression.h" #include "common/compression.h"
#include "common/file.h" #include "common/file.h"
#include "common/memory/ksm.hpp" #include "common/memory/ksm.h"
#include "common/misc_functions.h" #include "common/misc_functions.h"
#include "zone/client.h" #include "zone/client.h"
#include "zone/map.h" #include "zone/map.h"

View File

@ -32,7 +32,7 @@
#include <deque> #include <deque>
#include <list> #include <list>
typedef struct { struct NPCProximity {
float min_x; float min_x;
float max_x; float max_x;
float min_y; float min_y;
@ -41,7 +41,7 @@ typedef struct {
float max_z; float max_z;
bool say; bool say;
bool proximity_set; bool proximity_set;
} NPCProximity; };
struct AISpells_Struct { struct AISpells_Struct {
uint32 type; // 0 = never, must be one (and only one) of the defined values uint32 type; // 0 = never, must be one (and only one) of the defined values

View File

@ -135,10 +135,11 @@ void PetitionList::AddPetition(Petition* pet) {
} }
//Return Values: 0 = Ok ; -1 = Error deleting petition. //Return Values: 0 = Ok ; -1 = Error deleting petition.
int PetitionList::DeletePetition(uint32 petnumber) { int PetitionList::DeletePetition(uint32 petnumber)
{
LinkedListIterator<Petition*> iterator(list); LinkedListIterator<Petition*> iterator(list);
iterator.Reset(); iterator.Reset();
LockMutex lock(&PList_Mutex); std::scoped_lock lock(PList_Mutex);
while(iterator.MoreElements()) { while(iterator.MoreElements()) {
if (iterator.GetData()->GetID() == petnumber) { if (iterator.GetData()->GetID() == petnumber) {
database.DeletePetitionFromDB(iterator.GetData()); database.DeletePetitionFromDB(iterator.GetData());
@ -179,18 +180,18 @@ void PetitionList::ClearPetitions() {
return; return;
} }
void PetitionList::ReadDatabase() { void PetitionList::ReadDatabase()
LockMutex lock(&PList_Mutex); {
std::scoped_lock lock(PList_Mutex);
ClearPetitions(); ClearPetitions();
database.RefreshPetitionsFromDB(); database.RefreshPetitionsFromDB();
UpdateGMQueue(); UpdateGMQueue();
return;
} }
void PetitionList::UpdatePetition(Petition* pet) { void PetitionList::UpdatePetition(Petition* pet)
LockMutex lock(&PList_Mutex); {
std::scoped_lock lock(PList_Mutex);
database.UpdatePetitionToDB(pet); database.UpdatePetitionToDB(pet);
return;
} }
void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) { void ZoneDatabase::DeletePetitionFromDB(Petition* wpet) {

View File

@ -18,12 +18,9 @@
#pragma once #pragma once
#include "common/linked_list.h" #include "common/linked_list.h"
#include "common/misc_functions.h"
#include "common/mutex.h"
#include "common/types.h" #include "common/types.h"
#include "common/zone_store.h"
#include "zone/client.h" #include <mutex>
#include "zone/zonedb.h"
class Client; class Client;
@ -118,5 +115,5 @@ public:
private: private:
LinkedList<Petition*> list; LinkedList<Petition*> list;
Mutex PList_Mutex; std::mutex PList_Mutex;
}; };

Some files were not shown because too many files have changed in this diff Show More