cmake_minimum_required(VERSION 3.30)
project(Hoshi C CXX ASM_MASM)

set(CMAKE_CXX_STANDARD 20)

set(FETCHCONTENT_UPDATES_DISCONNECTED ON CACHE BOOL "Disable updates for FetchContent")
set(HOSHI_NDEBUG OFF CACHE BOOL "Disable Hoshi debug functionalities")

include(FetchContent)

set(BUILD_MOD ON CACHE BOOL "Build the client mod")
set(BUILD_TESTER ON CACHE BOOL "Build the tester")
set(SDKPATH "C:/Dumper-7/4.27.2-0+++UE4+Release-4.27-BLUEPROTOCOL/CppSDK" CACHE PATH "Path to the SDK")
set(VERSION "V5" CACHE STRING "Game version")
set(NTPDPATH "" CACHE FILEPATH "Path to ntpd library")

FetchContent_Declare(json URL https://github.com/nlohmann/json/releases/download/v3.11.3/json.tar.xz)
FetchContent_MakeAvailable(json)

if (BUILD_MOD)
    FetchContent_Declare(minhook GIT_REPOSITORY https://github.com/TsudaKageyu/minhook.git GIT_TAG master GIT_SHALLOW TRUE)
    FetchContent_MakeAvailable(minhook)
endif()

if (WIN32)
    add_compile_options(/GR-)  # disable rtti
    add_compile_definitions(-D_HAS_STATIC_RTTI=0)
    
    add_compile_options($<$<NOT:$<CONFIG:Debug>>:/Gy>)  # enable function-level linking
    add_link_options(/OPT:REF)  # strip unneedd functions
    add_link_options(/OPT:ICF)  # merge identical functions
    
    add_compile_options(/bigobj)
    add_compile_definitions(WIN32_LEAN_AND_MEAN NOMINMAX)
else()
    add_compile_options(-fno-rtti)
endif()

if (HOSHI_NDEBUG)
    add_compile_definitions(HOSHI_NDEBUG)
endif()

set(HOSHI_SOURCES
        main.cpp
        Util/Log.cpp
        Util/Hook.cpp
        Util/UnrealUtils.cpp
        Util/LMDebugAlloc.cpp
        Unreal/FWeakObjectPtr.cpp
        Net/ProtoDump.cpp
        Game/BugFixes.cpp
)
set(KIRANET_SOURCES
        Net/ikcp.c
        Net/KiraNet.cpp
        Net/KiraRawSocket.cpp
)
set(HOSHI_PROTO_SOURCES
        Unreal/FString.cpp
        Proto/CustomRpc.cpp
        Proto/CustomRpc_Manual.cpp
        Proto/Rpc.cpp
        Proto/RpcTypes.cpp
        Proto/CustomData_Stable.cpp
        Proto/CustomData_Version.cpp
        Proto/SdkExtension.cpp
)
set(HOSHI_DYN_SOURCES
        ${KIRANET_SOURCES}
        ${HOSHI_PROTO_SOURCES}
        DynReload.cpp
        Game/Replication.cpp
        Game/DataLoader.cpp
        Game/ApiextLoader.cpp
        Game/PlayerData.cpp
        Net/NetworkManager.cpp
        Net/NetObjectRef.cpp
        Util/Log.cpp
        Util/Hook.cpp
        Util/UnrealUtils.cpp
        Unreal/FWeakObjectPtr.cpp
        Game/MapLoader.cpp
        Game/MapLoader.h
        Game/Components/MountComponent.cpp
        Game/Components/MountComponent.h
        Game/Components/CharaCreateComponent.cpp
        Game/Components/CharaCreateComponent.h
        Game/Components/HoshiComponentManager.cpp
        Game/DebugUtil/StateMachineDumper.cpp
        Game/DebugUtil/StateMachineDumper.h
        Game/Replication_Property.cpp
        Game/Replication_Costume.cpp
        Game/HoshiPkg.cpp
        Game/HoshiPkg.h
        Util/PlatformUtils.cpp
        Util/PlatformUtils.h
        Game/Components/EquipComponent.cpp
        Game/Components/EquipComponent.h
        Game/Components/ImageUploadComponent.cpp
        Game/Components/ImageUploadComponent.h
)

include_directories(.)
include_directories(../Libraries/KiraProto.Runtime.Cpp)
include_directories(${SDKPATH})
include_directories(Version/${VERSION})
include_directories(../Hoshi.GameServer/Net/Rpc/${VERSION})
if (BUILD_MOD)
    add_library(SDK STATIC
            ${SDKPATH}/SDK/Basic.cpp
            ${SDKPATH}/SDK/CoreUObject_functions.cpp
            ${SDKPATH}/SDK/Engine_functions.cpp
            ${SDKPATH}/SDK/ActionSystem_functions.cpp
            ${SDKPATH}/SDK/SkyBlue_functions.cpp)

    add_library(Hoshi SHARED ${HOSHI_SOURCES})
    target_link_libraries(Hoshi PUBLIC minhook SDK)
    
    if (HOSHI_NDEBUG)
        target_sources(Hoshi PRIVATE ${HOSHI_DYN_SOURCES})
    else()
        add_library(HoshiDyn SHARED ${HOSHI_DYN_SOURCES})
        target_link_libraries(HoshiDyn PUBLIC minhook SDK)
        add_dependencies(Hoshi HoshiDyn)
    endif()
    
    add_library(xinput1_3 SHARED XinputLoader.cpp XinputLoader.asm XinputLoader.def)
endif()

if (BUILD_TESTER)
    add_executable(NetTesterAgent
            ${KIRANET_SOURCES}
            ${HOSHI_PROTO_SOURCES}
            Net/Test/NetTesterAgent.cpp
            Util/Log.cpp
            Util/StandaloneSupport.cpp
            Net/Test/001_MovementData.cpp
            Net/Test/Scenario.cpp
            Net/Test/TimestampSource.cpp
            Net/Test/TimestampSource.h
    )
    target_compile_definitions(NetTesterAgent PRIVATE STANDALONE)
    target_link_libraries(NetTesterAgent PRIVATE nlohmann_json::nlohmann_json)

    if (NOT NTPDPATH STREQUAL "")
        add_library(ntpd STATIC IMPORTED)
        set_target_properties(ntpd PROPERTIES IMPORTED_LOCATION ${NTPDPATH})
        target_link_libraries(NetTesterAgent PRIVATE ntpd)
        target_compile_definitions(NetTesterAgent PRIVATE WITH_NTPD)
    endif()

    if (NOT WIN32)
#        target_link_libraries(NetTesterAgent PRIVATE -static)
    endif()
endif()

add_library(HoshiServerNative SHARED
        ${KIRANET_SOURCES}
        Net/KiraServer.cpp
        Server/KiraNet.cpp
        Server/Log.cpp
)

add_executable(KiraServerTest
        ${KIRANET_SOURCES}
        Net/KiraServer.cpp
        Net/Test/KiraServerTest.cpp
        Util/Log.cpp
)
add_executable(KiraClientTest
        ${KIRANET_SOURCES}
        Net/Test/KiraClientTest.cpp
        Util/Log.cpp
)

include_directories(E:/testEnv/)