Skip to content

Commit 4b255ad

Browse files
committed
perf: optimize spectator retrieval and add unit tests (gtest)
Improves performance and correctness of spectator retrieval in Map and Tile by tracking creature ranges and providing efficient access methods. Refactors Thing API for safer null handling, updates Lua binding for const member functions, and adds GTest-based unit tests for spectator logic. CMake and vcpkg updated to support test builds and GTest dependency.
1 parent d39edd0 commit 4b255ad

File tree

13 files changed

+737
-209
lines changed

13 files changed

+737
-209
lines changed

CMakeLists.txt

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -104,3 +104,13 @@ endif()
104104
add_subdirectory(src/protobuf)
105105
# Src
106106
add_subdirectory(src)
107+
108+
option(OTCLIENT_BUILD_TESTS "Build unit tests" ON)
109+
110+
if(OTCLIENT_BUILD_TESTS)
111+
enable_testing()
112+
add_subdirectory(tests)
113+
log_option_enabled("Build tests")
114+
else()
115+
log_option_disabled("Build tests")
116+
endif()

src/CMakeLists.txt

Lines changed: 109 additions & 92 deletions
Original file line numberDiff line numberDiff line change
@@ -75,71 +75,12 @@ if (ANDROID OR WASM)
7575
set(FRAMEWORK_DEFINITIONS ${FRAMEWORK_DEFINITIONS} -DOPENGL_ES=2)
7676
endif()
7777

78-
# Set for use precompiled header
79-
if(TOGGLE_PRE_COMPILED_HEADER)
80-
# === PRECOMPILED HEADER ===
81-
target_precompile_headers(${PROJECT_NAME} PRIVATE framework/pch.h)
82-
message(STATUS "Use precompiled header: ON")
83-
else()
84-
message(STATUS "Use precompiled header: OFF")
85-
endif(TOGGLE_PRE_COMPILED_HEADER)
86-
87-
# === UNITY BUILD (compile time reducer) ===
88-
if(SPEED_UP_BUILD_UNITY)
89-
set_target_properties(${PROJECT_NAME} PROPERTIES UNITY_BUILD ON)
90-
log_option_enabled("Build unity for speed up compilation")
91-
endif(SPEED_UP_BUILD_UNITY)
92-
9378
set(VERSION "1.0.0")
9479

95-
# *****************************************************************************
96-
# Build flags
97-
# *****************************************************************************
98-
if (NOT MSVC)
99-
if (CMAKE_COMPILER_IS_GNUCXX)
100-
target_compile_options(${PROJECT_NAME} PRIVATE -Wno-deprecated-declarations)
101-
endif()
102-
endif()
103-
104-
if(THREADS_HAVE_PTHREAD_ARG)
105-
target_compile_options(${PROJECT_NAME} PUBLIC "-pthread")
106-
endif()
107-
108-
if(CMAKE_BUILD_TYPE STREQUAL "Release")
109-
add_definitions(-DNDEBUG)
110-
endif()
111-
11280
# *****************************************************************************
11381
# Definitions code
11482
# *****************************************************************************
11583

116-
117-
# === ASAN ===
118-
if(ASAN_ENABLED)
119-
log_option_enabled("asan")
120-
121-
if(MSVC)
122-
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
123-
target_compile_options(${PROJECT_NAME} PUBLIC /fsanitize=address)
124-
target_link_options(${PROJECT_NAME} PUBLIC /fsanitize=address)
125-
else()
126-
target_compile_options(${PROJECT_NAME} PUBLIC -fsanitize=address)
127-
target_link_options(${PROJECT_NAME} PUBLIC -fsanitize=address)
128-
endif()
129-
else()
130-
log_option_disabled("asan")
131-
endif()
132-
133-
134-
# === DEBUG LOG ===
135-
# cmake -DDEBUG_LOG=ON ..
136-
if(CMAKE_BUILD_TYPE MATCHES Debug)
137-
target_compile_definitions(${PROJECT_NAME} PRIVATE -DDEBUG_LOG=ON )
138-
log_option_enabled("DEBUG LOG")
139-
else()
140-
log_option_disabled("DEBUG LOG")
141-
endif(CMAKE_BUILD_TYPE MATCHES Debug)
142-
14384
# *****************************************************************************
14485
# Sanity Check
14586
# *****************************************************************************
@@ -208,12 +149,12 @@ if(NOT OPENSSL_FOUND)
208149
find_package(GMP REQUIRED)
209150
endif()
210151
if(ENABLE_DISCORD_RPC AND NOT ANDROID)
211-
find_package(DiscordRPC REQUIRED)
212-
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DISCORD_RPC=1)
213-
log_option_enabled("Discord Rich Presence")
152+
find_package(DiscordRPC REQUIRED)
153+
set(OTCLIENT_ENABLE_DISCORD_RPC 1)
154+
log_option_enabled("Discord Rich Presence")
214155
else()
215-
target_compile_definitions(${PROJECT_NAME} PRIVATE ENABLE_DISCORD_RPC=0)
216-
log_option_disabled("Discord Rich Presence")
156+
set(OTCLIENT_ENABLE_DISCORD_RPC 0)
157+
log_option_disabled("Discord Rich Presence")
217158
endif()
218159
if(TOGGLE_DIRECTX)
219160
find_package(DirectX REQUIRED)
@@ -359,9 +300,6 @@ set(SOURCE_FILES
359300
client/uiminimap.cpp
360301
client/uiprogressrect.cpp
361302
client/uisprite.cpp
362-
363-
main.cpp
364-
androidmain.cpp
365303
)
366304

367305
if (TOGGLE_FRAMEWORK_GRAPHICS)
@@ -438,23 +376,93 @@ if (WASM)
438376
)
439377
endif()
440378

379+
add_library(otclient_core STATIC ${SOURCE_FILES})
380+
if(NOT MSVC)
381+
target_link_options(otclient_core PUBLIC -flto=auto)
382+
endif()
383+
384+
if(TOGGLE_PRE_COMPILED_HEADER)
385+
# === PRECOMPILED HEADER ===
386+
target_precompile_headers(otclient_core PRIVATE framework/pch.h)
387+
message(STATUS "Use precompiled header: ON")
388+
else()
389+
message(STATUS "Use precompiled header: OFF")
390+
endif(TOGGLE_PRE_COMPILED_HEADER)
391+
392+
if(SPEED_UP_BUILD_UNITY)
393+
set_target_properties(otclient_core PROPERTIES UNITY_BUILD ON)
394+
log_option_enabled("Build unity for speed up compilation")
395+
endif(SPEED_UP_BUILD_UNITY)
396+
397+
if(ANDROID)
398+
target_sources(${PROJECT_NAME} PRIVATE androidmain.cpp)
399+
else()
400+
target_sources(${PROJECT_NAME} PRIVATE main.cpp)
401+
endif()
402+
403+
target_link_libraries(${PROJECT_NAME} PRIVATE otclient_core)
404+
405+
# *****************************************************************************
406+
# Build flags
407+
# *****************************************************************************
408+
if (NOT MSVC)
409+
if (CMAKE_COMPILER_IS_GNUCXX)
410+
target_compile_options(otclient_core PRIVATE -Wno-deprecated-declarations)
411+
endif()
412+
endif()
413+
414+
if(THREADS_HAVE_PTHREAD_ARG)
415+
target_compile_options(otclient_core PUBLIC "-pthread")
416+
endif()
417+
418+
if(CMAKE_BUILD_TYPE STREQUAL "Release")
419+
add_definitions(-DNDEBUG)
420+
endif()
421+
422+
# *****************************************************************************
423+
# Definitions code
424+
# *****************************************************************************
425+
426+
# === ASAN ===
427+
if(ASAN_ENABLED)
428+
log_option_enabled("asan")
429+
430+
if(MSVC)
431+
string(REGEX REPLACE "/RTC(su|[1su])" "" CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS}")
432+
target_compile_options(otclient_core PUBLIC /fsanitize=address)
433+
target_link_options(${PROJECT_NAME} PUBLIC /fsanitize=address)
434+
else()
435+
target_compile_options(otclient_core PUBLIC -fsanitize=address)
436+
target_link_options(${PROJECT_NAME} PUBLIC -fsanitize=address)
437+
endif()
438+
else()
439+
log_option_disabled("asan")
440+
endif()
441+
442+
# === DEBUG LOG ===
443+
# cmake -DDEBUG_LOG=ON ..
444+
if(CMAKE_BUILD_TYPE MATCHES Debug)
445+
target_compile_definitions(otclient_core PRIVATE -DDEBUG_LOG=ON )
446+
log_option_enabled("DEBUG LOG")
447+
else()
448+
log_option_disabled("DEBUG LOG")
449+
endif(CMAKE_BUILD_TYPE MATCHES Debug)
441450

442-
target_sources(${PROJECT_NAME} PRIVATE ${SOURCE_FILES})
443-
target_link_options(${PROJECT_NAME} PUBLIC -flto=auto)
451+
target_compile_definitions(otclient_core PRIVATE ENABLE_DISCORD_RPC=${OTCLIENT_ENABLE_DISCORD_RPC})
444452

445453
# *****************************************************************************
446454
# Includes and librarys
447455
# *****************************************************************************
448456
if(MSVC)
449457

450458
# Set variables to have Windows Vista Value so httplib will build 'inet_pton'
451-
target_compile_definitions(${PROJECT_NAME}
452-
PRIVATE
459+
target_compile_definitions(otclient_core
460+
PUBLIC
453461
NTDDI_VERSION=0x06000000
454462
_WIN32_WINNT=0x0600
455463
)
456464

457-
target_compile_options(${PROJECT_NAME} PUBLIC /MP /FS /Zf /EHsc /bigobj)
465+
target_compile_options(otclient_core PUBLIC /MP /FS /Zf /EHsc /bigobj)
458466

459467
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
460468
string(REPLACE "/Zi" "/Z7" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
@@ -474,15 +482,24 @@ if(MSVC)
474482
if(ANDROID)
475483
find_package(Vorbis CONFIG REQUIRED)
476484
endif()
477-
set_property(TARGET ${PROJECT_NAME} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
485+
foreach(msvc_target IN ITEMS otclient_core ${PROJECT_NAME})
486+
if(TARGET ${msvc_target})
487+
set_property(TARGET ${msvc_target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>")
488+
endif()
489+
endforeach()
478490
set(VCPKG_TARGET_TRIPLET "x64-windows-static" CACHE STRING "")
479491
else()
480492
log_option_disabled("STATIC_LIBRARY")
481493
set(VCPKG_TARGET_TRIPLET "x64-windows" CACHE STRING "")
494+
foreach(msvc_target IN ITEMS otclient_core ${PROJECT_NAME})
495+
if(TARGET ${msvc_target})
496+
set_property(TARGET ${msvc_target} PROPERTY MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
497+
endif()
498+
endforeach()
482499
endif()
483500

484-
target_include_directories(${PROJECT_NAME}
485-
PRIVATE
501+
target_include_directories(otclient_core
502+
PUBLIC
486503
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/>
487504
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
488505
${LUAJIT_INCLUDE_DIR}
@@ -494,8 +511,8 @@ if(MSVC)
494511
${PARALLEL_HASHMAP_INCLUDE_DIRS}
495512
${NLOHMANN_JSON_INCLUDE_DIR}
496513
)
497-
target_link_libraries(${PROJECT_NAME}
498-
PRIVATE
514+
target_link_libraries(otclient_core
515+
PUBLIC
499516
${LUAJIT_LIBRARY}
500517
${CMAKE_THREAD_LIBS_INIT}
501518
${PHYSFS_LIBRARY}
@@ -524,8 +541,8 @@ if(MSVC)
524541
fmt::fmt-header-only
525542
)
526543
elseif(ANDROID)
527-
target_include_directories(${PROJECT_NAME}
528-
PRIVATE
544+
target_include_directories(otclient_core
545+
PUBLIC
529546
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/>
530547
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
531548
${LUAJIT_INCLUDE_DIR}
@@ -539,8 +556,8 @@ elseif(ANDROID)
539556
${NLOHMANN_JSON_INCLUDE_DIR}
540557
${MINIZIP_INCLUDE_DIR}
541558
)
542-
target_link_libraries(${PROJECT_NAME}
543-
PRIVATE
559+
target_link_libraries(otclient_core
560+
PUBLIC
544561
${LUA_LIBRARY}
545562
${LUAJIT_LIBRARY}
546563
${PHYSFS_LIBRARY}
@@ -573,8 +590,8 @@ elseif(ANDROID)
573590
)
574591

575592
elseif(WASM)
576-
target_include_directories(${PROJECT_NAME}
577-
PRIVATE
593+
target_include_directories(otclient_core
594+
PUBLIC
578595
${CMAKE_SOURCE_DIR}/src
579596
${CMAKE_THREAD_LIBS_INIT}
580597
${Protobuf_INCLUDE_DIRS}
@@ -586,8 +603,8 @@ elseif(WASM)
586603
${OPENSSL_INCLUDE_DIR}
587604
${BROWSER_INCLUDE_DIR}
588605
)
589-
target_link_libraries(${PROJECT_NAME}
590-
PRIVATE
606+
target_link_libraries(otclient_core
607+
PUBLIC
591608
${LUA_LIBRARY}
592609
${PHYSFS_LIBRARY}
593610
${ZLIB_LIBRARY}
@@ -630,7 +647,7 @@ elseif(WASM)
630647
get_property(linkflags TARGET ${PROJECT_NAME} PROPERTY LINK_FLAGS)
631648

632649
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
633-
target_compile_options(${PROJECT_NAME}
650+
target_compile_options(otclient_core
634651
PRIVATE
635652
-Wall -Wextra -Wpedantic
636653
)
@@ -656,8 +673,8 @@ elseif(WASM)
656673
set(VCPKG_TARGET_TRIPLET "wasm32-emscripten" CACHE STRING "")
657674

658675
else() # Linux
659-
target_include_directories(${PROJECT_NAME}
660-
PRIVATE
676+
target_include_directories(otclient_core
677+
PUBLIC
661678
$<BUILD_INTERFACE:${PROJECT_SOURCE_DIR}/>
662679
$<INSTALL_INTERFACE:${CMAKE_INSTALL_INCLUDEDIR}>
663680
${LUAJIT_INCLUDE_DIR}
@@ -670,8 +687,8 @@ else() # Linux
670687
${NLOHMANN_JSON_INCLUDE_DIR}
671688
${OPENSSL_INCLUDE_DIR}
672689
)
673-
target_link_libraries(${PROJECT_NAME}
674-
PRIVATE
690+
target_link_libraries(otclient_core
691+
PUBLIC
675692
${LUAJIT_LIBRARY}
676693
${PHYSFS_LIBRARY}
677694
${ZLIB_LIBRARY}
@@ -710,15 +727,15 @@ else() # Linux
710727
)
711728

712729
if(CMAKE_BUILD_TYPE STREQUAL "Debug")
713-
target_compile_options(${PROJECT_NAME}
730+
target_compile_options(otclient_core
714731
PRIVATE
715732
-Wall -Wextra -Wpedantic
716733
)
717734
endif()
718735

719736
endif()
720737
if(ENABLE_DISCORD_RPC AND NOT ANDROID)
721-
target_link_libraries(${PROJECT_NAME} PRIVATE ${DISCORDRPC_LIBRARY})
738+
target_link_libraries(otclient_core PUBLIC ${DISCORDRPC_LIBRARY})
722739
endif()
723740

724741
# *****************************************************************************

src/client/creature.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -153,6 +153,8 @@ class Creature : public Thing
153153
bool isWalking() { return m_walking; }
154154

155155
bool isRemoved() { return m_removed; }
156+
bool isRemoved() const { return m_removed; }
157+
const Position& getOldPosition() const { return m_oldPosition; }
156158
bool isInvisible() { return m_outfit.isEffect() && m_outfit.getAuxId() == 13; }
157159
bool isDead() { return m_healthPercent <= 0; }
158160
bool isFullHealth() { return m_healthPercent == 100; }
@@ -211,6 +213,9 @@ minHeight,
211213
void updateWalkOffset(uint8_t totalPixelsWalked);
212214
void updateWalk();
213215

216+
void setOldPositionSilently(const Position& pos) { m_oldPosition = pos; }
217+
void setRemovedSilently(const bool removed) { m_removed = removed; }
218+
214219
ThingType* getThingType() const override;
215220
ThingType* getMountThingType() const;
216221

src/client/luafunctions.cpp

Lines changed: 8 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -598,7 +598,10 @@ void Client::registerLuaFunctions()
598598
g_lua.bindClassMemberFunction<Creature>("isWalking", &Creature::isWalking);
599599
g_lua.bindClassMemberFunction<Creature>("isInvisible", &Creature::isInvisible);
600600
g_lua.bindClassMemberFunction<Creature>("isDead", &Creature::isDead);
601-
g_lua.bindClassMemberFunction<Creature>("isRemoved", &Creature::isRemoved);
601+
g_lua.bindClassMemberFunction<Creature>(
602+
"isRemoved",
603+
static_cast<bool (Creature::*)() const>(&Creature::isRemoved)
604+
);
602605
g_lua.bindClassMemberFunction<Creature>("canBeSeen", &Creature::canBeSeen);
603606
g_lua.bindClassMemberFunction<Creature>("jump", &Creature::jump);
604607
g_lua.bindClassMemberFunction<Creature>("setMountShader", &Creature::setMountShader);
@@ -914,7 +917,10 @@ void Client::registerLuaFunctions()
914917
g_lua.bindClassMemberFunction<Tile>("isClickable", &Tile::isClickable);
915918
g_lua.bindClassMemberFunction<Tile>("isPathable", &Tile::isPathable);
916919

917-
g_lua.bindClassMemberFunction<Tile>("hasCreatures", &Tile::hasCreatures);
920+
g_lua.bindClassMemberFunction<Tile>(
921+
"hasCreatures",
922+
static_cast<bool (Tile::*)() const>(&Tile::hasCreatures)
923+
);
918924

919925
g_lua.bindClassMemberFunction<Tile>("select", &Tile::select);
920926
g_lua.bindClassMemberFunction<Tile>("unselect", &Tile::unselect);

0 commit comments

Comments
 (0)