From 4ebc19a2617fe6858a35bc112aead4514dee5e2c Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 19:03:54 +0300 Subject: [PATCH 1/9] refactor some code to prevent possible crashes and bugs --- src/game/char.cpp | 4 +-- src/game/char.h | 2 +- src/game/char_battle.cpp | 2 +- src/game/cmd_gm.cpp | 68 +++++++++++++++++++++------------------ src/game/desc.cpp | 7 ++++ src/game/guild.cpp | 4 +-- src/game/item_manager.cpp | 63 +++++++++++++++++++++--------------- 7 files changed, 86 insertions(+), 64 deletions(-) diff --git a/src/game/char.cpp b/src/game/char.cpp index 4d73434..1b3dbfa 100644 --- a/src/game/char.cpp +++ b/src/game/char.cpp @@ -6010,13 +6010,13 @@ void CHARACTER::EffectPacket(int enumEffectType) PacketAround(&p, sizeof(TPacketGCSpecialEffect)); } -void CHARACTER::SpecificEffectPacket(const char filename[MAX_EFFECT_FILE_NAME]) +void CHARACTER::SpecificEffectPacket(const std::string& stEffectName) { TPacketGCSpecificEffect p; p.header = HEADER_GC_SPECIFIC_EFFECT; p.vid = GetVID(); - memcpy (p.effect_file, filename, MAX_EFFECT_FILE_NAME); + strlcpy(p.effect_file, stEffectName.c_str(), sizeof(p.effect_file)); PacketAround(&p, sizeof(TPacketGCSpecificEffect)); } diff --git a/src/game/char.h b/src/game/char.h index 8d52d56..6779b3a 100644 --- a/src/game/char.h +++ b/src/game/char.h @@ -1091,7 +1091,7 @@ class CHARACTER : public CEntity, public CFSM, public CHorseRider // void PotionPacket(int iPotionType); void EffectPacket(int enumEffectType); - void SpecificEffectPacket(const char filename[128]); + void SpecificEffectPacket(const std::string& stEffectName); // ADD_MONSTER_REFINE bool DoRefine(LPITEM item, bool bMoneyOnly = false); diff --git a/src/game/char_battle.cpp b/src/game/char_battle.cpp index 3817eac..d962cff 100644 --- a/src/game/char_battle.cpp +++ b/src/game/char_battle.cpp @@ -3195,7 +3195,7 @@ LPCHARACTER CHARACTER::GetNearestVictim(LPCHARACTER pkChr) LPCHARACTER pAttacker = CHARACTER_MANAGER::instance().Find(c_VID); - if (!pAttacker) + if (!pAttacker || pAttacker->IsDead()) continue; if (pAttacker->IsAffectFlag(AFF_EUNHYUNG) || diff --git a/src/game/cmd_gm.cpp b/src/game/cmd_gm.cpp index 28c13e6..1efb680 100644 --- a/src/game/cmd_gm.cpp +++ b/src/game/cmd_gm.cpp @@ -4082,28 +4082,28 @@ ACMD (do_item_full_set) { item = ITEM_MANAGER::instance().CreateItem(11699); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(13049); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(15189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(12529 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(14109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(17209 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(16209 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); } break; @@ -4111,28 +4111,28 @@ ACMD (do_item_full_set) { item = ITEM_MANAGER::instance().CreateItem(11299); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(13049); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(15189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(3159 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(12249 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(14109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(17109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(16109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); } break; @@ -4140,28 +4140,28 @@ ACMD (do_item_full_set) { item = ITEM_MANAGER::instance().CreateItem(11899); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(13049); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(15189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(7159 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(12669 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(14109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(17209 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(16209 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); } break; @@ -4169,31 +4169,35 @@ ACMD (do_item_full_set) { item = ITEM_MANAGER::instance().CreateItem(11499); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(13049); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(15189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(1139 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(12389 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(14109 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(17189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); item = ITEM_MANAGER::instance().CreateItem(16189 ); - if (!item || !item->EquipTo(ch, item->FindEquipCell(ch))) + if (item && !item->EquipTo(ch, item->FindEquipCell(ch))) M2_DESTROY_ITEM(item); } break; + + default: + ch->ChatPacket(CHAT_TYPE_INFO, "Full set is not available for your job"); + break; } } diff --git a/src/game/desc.cpp b/src/game/desc.cpp index 9c281b4..0016c57 100644 --- a/src/game/desc.cpp +++ b/src/game/desc.cpp @@ -428,6 +428,13 @@ void DESC::Packet(const void * c_pvData, int iSize) if (m_iPhase == PHASE_CLOSE) // 끊는 상태면 보내지 않는다. return; + if (!m_lpOutputBuffer) + { + sys_err("DESC::Packet: Trying to send packet but output buffer is NULL! (DESC: %p)", this); + SetPhase(PHASE_CLOSE); + return; + } + if (m_stRelayName.length() != 0) { // Relay 패킷은 암호화하지 않는다. diff --git a/src/game/guild.cpp b/src/game/guild.cpp index 1e1a771..9e7ce59 100644 --- a/src/game/guild.cpp +++ b/src/game/guild.cpp @@ -2013,13 +2013,13 @@ void CGuild::Invite( LPCHARACTER pchInviter, LPCHARACTER pchInvitee ) TPacketGCGuild p; p.header = HEADER_GC_GUILD; - p.size = sizeof(p) + sizeof(DWORD) + GUILD_NAME_MAX_LEN + 1; + p.size = sizeof(p) + sizeof(DWORD) + GUILD_NAME_MAX_LEN; p.subheader = GUILD_SUBHEADER_GC_GUILD_INVITE; TEMP_BUFFER buf; buf.write( &p, sizeof(p) ); buf.write( &gid, sizeof(DWORD) ); - buf.write( GetName(), GUILD_NAME_MAX_LEN + 1 ); + buf.write( GetName(), GUILD_NAME_MAX_LEN ); pchInvitee->GetDesc()->Packet( buf.read_peek(), buf.size() ); } diff --git a/src/game/item_manager.cpp b/src/game/item_manager.cpp index 489ece7..585c13f 100644 --- a/src/game/item_manager.cpp +++ b/src/game/item_manager.cpp @@ -469,21 +469,31 @@ void ITEM_MANAGER::SaveSingleItem(LPITEM item) void ITEM_MANAGER::Update() { - std::unordered_set::iterator it = m_set_pkItemForDelayedSave.begin(); - std::unordered_set::iterator this_it; - - while (it != m_set_pkItemForDelayedSave.end()) + for (auto it = m_set_pkItemForDelayedSave.begin(); it != m_set_pkItemForDelayedSave.end();) { - this_it = it++; - LPITEM item = *this_it; - - // SLOW_QUERY 플래그가 있는 것은 종료시에만 저장한다. - if (item->GetOwner() && IS_SET(item->GetFlag(), ITEM_FLAG_SLOW_QUERY)) + LPITEM item = *it; + if (!item) + { + sys_err("nullptr item, erasing from delayed save."); + it = m_set_pkItemForDelayedSave.erase(it); continue; + } + + if (!FindByVID(item->GetVID())) + { + sys_err("Invalid item(%u), erasing from delayed save.", item->GetVID()); + it = m_set_pkItemForDelayedSave.erase(it); + continue; + } + + if (item->GetOwner() && IS_SET(item->GetFlag(), ITEM_FLAG_SLOW_QUERY)) + { + ++it; // just skip don't erase + continue; + } SaveSingleItem(item); - - m_set_pkItemForDelayedSave.erase(this_it); + it = m_set_pkItemForDelayedSave.erase(it); } } @@ -619,28 +629,29 @@ TItemTable * ITEM_MANAGER::GetTable(DWORD vnum) int ITEM_MANAGER::RealNumber(DWORD vnum) { - int bot, top, mid; + if (m_vec_prototype.empty()) + return -1; - bot = 0; - top = m_vec_prototype.size(); + int left = 0; + int right = m_vec_prototype.size() - 1; - TItemTable * pTable = &m_vec_prototype[0]; - - while (1) + while (left <= right) { - mid = (bot + top) >> 1; + int mid = (left + right) / 2; - if ((pTable + mid)->dwVnum == vnum) - return (mid); + if (mid < 0 || mid >= static_cast(m_vec_prototype.size())) + return -1; - if (bot >= top) - return (-1); + if (m_vec_prototype[mid].dwVnum == vnum) + return mid; - if ((pTable + mid)->dwVnum > vnum) - top = mid - 1; - else - bot = mid + 1; + if (m_vec_prototype[mid].dwVnum > vnum) + right = mid - 1; + else + left = mid + 1; } + + return -1; } bool ITEM_MANAGER::GetVnum(const char * c_pszName, DWORD & r_dwVnum) From 2ba77cdc467805d541410903b32cddf30ab7e2e9 Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 19:24:11 +0300 Subject: [PATCH 2/9] enabled detailed packet logs for easier debugging --- src/game/desc.cpp | 14 +++++++++++++- src/game/desc.h | 1 + src/game/input.cpp | 33 +++++++++++++++++++++++++++++---- 3 files changed, 43 insertions(+), 5 deletions(-) diff --git a/src/game/desc.cpp b/src/game/desc.cpp index 0016c57..0501245 100644 --- a/src/game/desc.cpp +++ b/src/game/desc.cpp @@ -230,7 +230,7 @@ bool DESC::Setup(LPFDWATCH _fdw, socket_t _fd, const struct sockaddr_in & c_rSoc // m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2); //else //NOTE: 이걸 나라별로 다르게 잡아야할 이유가 있나? - m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 2); + m_lpOutputBuffer = buffer_new(DEFAULT_PACKET_BUFFER_SIZE * 3); // Default: 2 m_iMinInputBufferLen = MAX_INPUT_LEN >> 1; m_lpInputBuffer = buffer_new(MAX_INPUT_LEN); @@ -418,6 +418,12 @@ void DESC::BufferedPacket(const void * c_pvData, int iSize) if (!m_lpBufferedOutputBuffer) m_lpBufferedOutputBuffer = buffer_new(MAX(1024, iSize)); +#ifdef _DEBUG + const std::string stName = GetCharacter() ? GetCharacter()->GetName() : GetHostName(); + const auto kHeader = *(static_cast(c_pvData)); + sys_log(0, "[B] SENT HEADER : %u(0x%X) to %s (size %d) ", kHeader, kHeader, stName.c_str(), iSize); +#endif + buffer_write(m_lpBufferedOutputBuffer, c_pvData, iSize); } @@ -435,6 +441,12 @@ void DESC::Packet(const void * c_pvData, int iSize) return; } +#ifdef _DEBUG + const std::string stName = GetCharacter() ? GetCharacter()->GetName() : GetHostName(); + const auto kHeader = *(static_cast(c_pvData)); + sys_log(0, "[N] SENT HEADER : %u(0x%X) to %s (size %d) ", kHeader, kHeader, stName.c_str(), iSize); +#endif + if (m_stRelayName.length() != 0) { // Relay 패킷은 암호화하지 않는다. diff --git a/src/game/desc.h b/src/game/desc.h index 4001f2a..e0f5135 100644 --- a/src/game/desc.h +++ b/src/game/desc.h @@ -111,6 +111,7 @@ class DESC LPCHARACTER GetCharacter() { return m_lpCharacter; } bool IsPhase(int phase) const { return m_iPhase == phase ? true : false; } + int32_t GetPhase() const { return m_iPhase; } const struct sockaddr_in & GetAddr() { return m_SockAddr; } diff --git a/src/game/input.cpp b/src/game/input.cpp index 4bd7633..584acd0 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -81,14 +81,33 @@ bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes, iPacketLen = 1; else if (!m_pPacketInfo->Get(bHeader, &iPacketLen, &c_pszName)) { - sys_err("UNKNOWN HEADER: %d, LAST HEADER: %d(%d), REMAIN BYTES: %d, fd: %d", - bHeader, bLastHeader, iLastPacketLen, m_iBufferLeft, lpDesc->GetSocket()); - //printdata((BYTE *) c_pvOrig, m_iBufferLeft); + LPCHARACTER ch = lpDesc->GetCharacter(); + + char szLogBuffer[1024]; + snprintf(szLogBuffer, sizeof(szLogBuffer), + "UNKNOWN HEADER: %u(0x%X) LAST HEADER: %u(0x%X)[%u], REMAIN BYTES: %d, CHAR: %s, PHASE: %d, fd: %d host: %s", + bHeader, bHeader, bLastHeader, bLastHeader, iLastPacketLen, m_iBufferLeft, + ch ? ch->GetName() : "", + lpDesc->GetPhase(), lpDesc->GetSocket(), lpDesc->GetHostName() + ); + + if (lpDesc->GetPhase() < PHASE_SELECT) // early phase + sys_log(0, szLogBuffer); + else + sys_err(szLogBuffer); + +#if defined(_DEBUG) && defined(_WIN32) + printdata((uint8_t*)c_pvOrig, m_iBufferLeft); +#endif lpDesc->SetPhase(PHASE_CLOSE); return true; } - sys_log(0, "PACKET %d (%s)", bHeader, c_pszName); +#ifdef _DEBUG + const auto ch = lpDesc->GetCharacter(); + const std::string stName = ch ? ch->GetName() : lpDesc->GetHostName(); + sys_log(0, "RECEIVED HEADER : %u(0x%X) to %s (size %d) ", bHeader, bHeader, stName.c_str(), iBytes); +#endif if (m_iBufferLeft < iPacketLen) return true; @@ -103,7 +122,13 @@ bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes, int iExtraPacketSize = Analyze(lpDesc, bHeader, c_pData); if (iExtraPacketSize < 0) + { + sys_err("Failed to analyze header(%u) size: %d phase: %d host %s from %s (%u) in: %u", + bHeader, iPacketLen, lpDesc->GetPhase(), lpDesc->GetHostName(), + ch ? ch->GetName() : "NO_CHAR", ch ? ch->GetPlayerID() : 0, ch ? ch->GetMapIndex() : 0 + ); return true; + } iPacketLen += iExtraPacketSize; lpDesc->Log("%s %d", c_pszName, iPacketLen); From dcc66752082462fb2000f4df5e8bfd83ebc0ac6e Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:11:49 +0300 Subject: [PATCH 3/9] disable build libpoly entrypoint --- src/libpoly/main.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/libpoly/main.cpp b/src/libpoly/main.cpp index 04f6763..b799978 100644 --- a/src/libpoly/main.cpp +++ b/src/libpoly/main.cpp @@ -2,11 +2,15 @@ #include #endif +// #define LIBPOLY_STANDALONE +#ifdef LIBPOLY_STANDALONE + #include "Poly.h" #include #include #include +#include using namespace std; @@ -45,3 +49,4 @@ int main(int argc, char ** argv) return 0; } +#endif From fd1df0b328f449d4f391ef2b18ac714864c3b24f Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:25:54 +0300 Subject: [PATCH 4/9] add git derived version info --- CMakeLists.txt | 28 ++++++++++++++++++++++++++++ src/db/CMakeLists.txt | 2 ++ src/db/version.cpp | 6 +++++- src/game/CMakeLists.txt | 2 ++ src/game/version.cpp | 6 +++++- 5 files changed, 42 insertions(+), 2 deletions(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index a4e7dd6..a5135bd 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,34 @@ set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin) +# Derive a version string from git for the db target +find_package(Git QUIET) +if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_SOURCE_DIR} describe --always --dirty --tags + OUTPUT_VARIABLE GIT_DESCRIBE_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) +endif() + +if(NOT GIT_DESCRIBE_VERSION) + if(GIT_FOUND) + execute_process( + COMMAND ${GIT_EXECUTABLE} -C ${CMAKE_SOURCE_DIR} rev-parse --short HEAD + OUTPUT_VARIABLE GIT_DESCRIBE_VERSION + OUTPUT_STRIP_TRAILING_WHITESPACE + ERROR_QUIET + ) + else() + set(GIT_DESCRIBE_VERSION "unknown") + endif() +endif() + +if(NOT GIT_DESCRIBE_VERSION) + set(GIT_DESCRIBE_VERSION "unknown") +endif() + add_definitions(-DNOMINMAX) add_definitions(-DWIN32_LEAN_AND_MEAN) diff --git a/src/db/CMakeLists.txt b/src/db/CMakeLists.txt index cd7ee16..ac37748 100644 --- a/src/db/CMakeLists.txt +++ b/src/db/CMakeLists.txt @@ -2,6 +2,8 @@ add_executable(db ${DB_SOURCES}) +target_compile_definitions(db PRIVATE GIT_DESCRIBE="${GIT_DESCRIBE_VERSION}") + target_link_libraries(db common libgame diff --git a/src/db/version.cpp b/src/db/version.cpp index 9b5eab3..dc6bcff 100644 --- a/src/db/version.cpp +++ b/src/db/version.cpp @@ -1,6 +1,10 @@ #include #include +#ifndef GIT_DESCRIBE +#define GIT_DESCRIBE "unknown" +#endif + void WriteVersion() { #ifndef OS_WINDOWS @@ -8,7 +12,7 @@ void WriteVersion() if (NULL != fp) { - fprintf(fp, "db revision: %s\n", __P4_VERSION__); + fprintf(fp, "db revision: %s\n", GIT_DESCRIBE); //fprintf(fp, "%s@%s:%s\n", __USER__, __HOSTNAME__, __PWD__); fclose(fp); } diff --git a/src/game/CMakeLists.txt b/src/game/CMakeLists.txt index 53fac79..00ec51c 100644 --- a/src/game/CMakeLists.txt +++ b/src/game/CMakeLists.txt @@ -2,6 +2,8 @@ add_executable(game ${GAME_SOURCES}) +target_compile_definitions(game PRIVATE GIT_DESCRIBE="${GIT_DESCRIBE_VERSION}") + target_link_libraries(game common libgame diff --git a/src/game/version.cpp b/src/game/version.cpp index eb26bee..ebbcd09 100644 --- a/src/game/version.cpp +++ b/src/game/version.cpp @@ -1,5 +1,9 @@ #include +#ifndef GIT_DESCRIBE_VERSION +#define GIT_DESCRIBE_VERSION "unknown" +#endif + void WriteVersion() { #ifndef OS_WINDOWS @@ -7,7 +11,7 @@ void WriteVersion() if (fp) { - fprintf(fp, "game revision: 40250"); + fprintf(fp, "game revision: %s\n", GIT_DESCRIBE_VERSION); //fprintf(fp, "game revision: %s\n", __SVN_VERSION__); //fprintf(fp, "%s@%s:%s\n", __USER__, __HOSTNAME__, __PWD__); fclose(fp); From b2f39b365f49601996076e04461a2a6f369b787d Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:28:05 +0300 Subject: [PATCH 5/9] remove FreeBSD specific MD5 includes To solve: unknown type name 'MD5_CTX' --- src/game/auth_brazil.cpp | 4 ---- src/game/cmd_general.cpp | 4 ---- 2 files changed, 8 deletions(-) diff --git a/src/game/auth_brazil.cpp b/src/game/auth_brazil.cpp index 8586054..f2b5228 100644 --- a/src/game/auth_brazil.cpp +++ b/src/game/auth_brazil.cpp @@ -13,11 +13,7 @@ #endif #include #include -#ifdef OS_FREEBSD -#include -#else #include "libthecore/xmd5.h" -#endif #include "auth_brazil.h" diff --git a/src/game/cmd_general.cpp b/src/game/cmd_general.cpp index 7b90465..fbb9c8f 100644 --- a/src/game/cmd_general.cpp +++ b/src/game/cmd_general.cpp @@ -1,9 +1,5 @@ #include "stdafx.h" -#ifdef OS_FREEBSD -#include -#else #include "libthecore/xmd5.h" -#endif #include "utils.h" #include "config.h" From bccf27ed6ade1589d62e8fed2aae90bc3e1a8d75 Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:30:12 +0300 Subject: [PATCH 6/9] refactor arena iteration in AddArena To solve: /home/test/m2dev-server-src/src/game/arena.cpp:83:75: error: comparison between pointer and integer ('CArena *' and 'bool') 83 | if ((CArena*)(*iter)->CheckArea(startA_X, startA_Y, startB_X, startB_Y) == false) --- src/game/arena.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/src/game/arena.cpp b/src/game/arena.cpp index 8ae4ce0..b335657 100644 --- a/src/game/arena.cpp +++ b/src/game/arena.cpp @@ -76,11 +76,9 @@ bool CArenaManager::AddArena(DWORD mapIdx, WORD startA_X, WORD startA_Y, WORD st bool CArenaMap::AddArena(DWORD mapIdx, WORD startA_X, WORD startA_Y, WORD startB_X, WORD startB_Y) { - itertype(m_listArena) iter = m_listArena.begin(); - - for (; iter != m_listArena.end(); iter++) + for (const auto& arena : m_listArena) { - if ((CArena*)(*iter)->CheckArea(startA_X, startA_Y, startB_X, startB_Y) == false) + if (arena->CheckArea(startA_X, startA_Y, startB_X, startB_Y) == false) { sys_log(0, "CArenaMap::AddArena - Same Start Position set. stA(%d, %d) stB(%d, %d)", startA_X, startA_Y, startB_X, startB_Y); return false; From b17033d587dc61598b1ee8d67b18c17c41415b9f Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:40:04 +0300 Subject: [PATCH 7/9] remove OS_FREEBSD preventation from xmd5 --- src/libthecore/xmd5.cpp | 4 ---- src/libthecore/xmd5.h | 5 +---- 2 files changed, 1 insertion(+), 8 deletions(-) diff --git a/src/libthecore/xmd5.cpp b/src/libthecore/xmd5.cpp index 3608929..b3bec1d 100644 --- a/src/libthecore/xmd5.cpp +++ b/src/libthecore/xmd5.cpp @@ -1,7 +1,5 @@ #include "stdafx.h" -#ifndef OS_FREEBSD - /* * luau (Lib Update/Auto-Update): Simple Update Library * Copyright (C) 2003 David Eklund @@ -341,5 +339,3 @@ void MD5Transform(uint32_t buf[4], uint32_t const in[16]) buf[2] += c; buf[3] += d; } - -#endif // #ifndef OS_FREEBSD \ No newline at end of file diff --git a/src/libthecore/xmd5.h b/src/libthecore/xmd5.h index dca5327..b1c31b7 100644 --- a/src/libthecore/xmd5.h +++ b/src/libthecore/xmd5.h @@ -1,5 +1,4 @@ -#ifndef OS_FREEBSD - +#pragma once /* * luau (Lib Update/Auto-Update): Simple Update Library * Copyright (C) 2003 David Eklund @@ -65,5 +64,3 @@ char* MD5End(MD5_CTX *, char *); char* lutil_md5_file(const char *filename, char *buf); char* lutil_md5_data(const unsigned char *data, unsigned int len, char *buf); - -#endif // #ifndef OS_FREEBSD From ccbaa03dbaf70bc5155476e9a654bef689b7f9f5 Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 20:41:35 +0300 Subject: [PATCH 8/9] add missing ch data --- src/game/input.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/game/input.cpp b/src/game/input.cpp index 584acd0..9773e30 100644 --- a/src/game/input.cpp +++ b/src/game/input.cpp @@ -123,6 +123,7 @@ bool CInputProcessor::Process(LPDESC lpDesc, const void * c_pvOrig, int iBytes, if (iExtraPacketSize < 0) { + LPCHARACTER ch = lpDesc->GetCharacter(); sys_err("Failed to analyze header(%u) size: %d phase: %d host %s from %s (%u) in: %u", bHeader, iPacketLen, lpDesc->GetPhase(), lpDesc->GetHostName(), ch ? ch->GetName() : "NO_CHAR", ch ? ch->GetPlayerID() : 0, ch ? ch->GetMapIndex() : 0 From a878786e5811a85a91d4aa42086ada58a405bf6b Mon Sep 17 00:00:00 2001 From: mq1n Date: Tue, 2 Sep 2025 21:02:06 +0300 Subject: [PATCH 9/9] add Github actions workflow for FreeBSD build --- .github/workflows/main.yml | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+) create mode 100644 .github/workflows/main.yml diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml new file mode 100644 index 0000000..5267492 --- /dev/null +++ b/.github/workflows/main.yml @@ -0,0 +1,35 @@ +name: build + +on: + push: + branches: + - main + +jobs: + bsd: + runs-on: ubuntu-latest + name: Main build job + steps: + - uses: actions/checkout@v4 + - name: FreeBSD job + id: test + uses: vmactions/freebsd-vm@v1 + with: + usesh: true + sync: sshfs + prepare: | + pkg install -y git cmake gmake + run: | + mkdir build + cd build + cmake .. + gmake all -j6 + - name: Collect outputs + run: | + mkdir _output + cp build/bin/* _output + - name: Upload + uses: actions/upload-artifact@v4 + with: + name: output_bsd + path: _output \ No newline at end of file