cmake_minimum_required(VERSION 3.24)
project(DingoSDK LANGUAGES CXX C)
if(WIN32)
    if(NOT MSVC OR NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
        message(FATAL_ERROR "DingoSDK on Windows requires MSVC and the x64 platform.")
    endif()
else()
    if(NOT CMAKE_SIZEOF_VOID_P EQUAL 8)
        message(FATAL_ERROR "DingoSDK on Linux requires a 64-bit platform.")
    endif()
    message(STATUS "Linux build: dedicated server only (launcher/runtime stay Windows-only).")
endif()

include(cmake/ProjectOptions.cmake)
include(cmake/Dependencies.cmake)
include(cmake/CustomScriptData.cmake)
include(cmake/Core.cmake)
if(WIN32)
    include(cmake/Features.cmake)
    include(cmake/UI.cmake)
    include(cmake/Runtime.cmake)
endif()
include(cmake/Apps.cmake)
if(WIN32)
    include(cmake/Backtrace.cmake)
endif()

option(DINGOSDK_BUILD_TESTS "Build logging regression tests" OFF)
option(DINGOSDK_BUILD_PARK_EDITOR_TESTS "Build park editor regression tests" OFF)
option(DINGOSDK_BUILD_TRAINER_TESTS "Build the trainer's tools and regression tests" OFF)
if(DINGOSDK_BUILD_PARK_EDITOR_TESTS)
    enable_testing()
    add_executable(dingosdk_park_randomization_tests Engine/Game/World/Test/park_randomization_tests.cpp)
    add_test(NAME park_randomization COMMAND dingosdk_park_randomization_tests)
endif()
if(DINGOSDK_BUILD_PARK_EDITOR_TESTS AND WIN32)
    enable_testing()
    add_executable(dingosdk_park_editor_tests Extension/Objects/ParkEditor/Test/park_editor_tests.cpp)
    target_link_libraries(dingosdk_park_editor_tests PRIVATE dingosdk_local_profile)
    add_test(NAME park_editor COMMAND dingosdk_park_editor_tests "${CMAKE_CURRENT_BINARY_DIR}/editor-fixtures")
    add_executable(dingosdk_park_editor_ui_tests Extension/UI/Overlay/Test/park_editor_tests.cpp
        Extension/UI/Overlay/park_editor.cpp Extension/UI/Overlay/park_editor_actions.cpp
        Extension/UI/Overlay/park_editor_panels.cpp Extension/UI/Overlay/park_editor_viewport.cpp Extension/UI/Overlay/park_previews.cpp)
    target_link_libraries(dingosdk_park_editor_ui_tests PRIVATE dingosdk_imgui dingosdk_json dingosdk_game_archives dingosdk_content_cache dingosdk_logging)
    add_test(NAME park_editor_ui COMMAND dingosdk_park_editor_ui_tests "${CMAKE_CURRENT_BINARY_DIR}/editor-preview" "${DINGOSDK_TEST_GAME_ROOT}")
    add_executable(dingosdk_park_editor_transaction_tests Extension/Objects/ParkEditor/Test/park_editor_transaction_tests.cpp)
    target_link_libraries(dingosdk_park_editor_transaction_tests PRIVATE dingosdk_local_profile dingosdk_logging)
    add_test(NAME park_editor_transactions COMMAND dingosdk_park_editor_transaction_tests)
    add_executable(dingosdk_profile_migration_tests Extension/Profile/Test/profile_migration_tests.cpp)
    target_link_libraries(dingosdk_profile_migration_tests PRIVATE dingosdk_local_profile)
    add_test(NAME profile_migration COMMAND dingosdk_profile_migration_tests)
    add_executable(dingosdk_profile_change_tests Extension/Profile/Test/profile_change_tests.cpp)
    target_link_libraries(dingosdk_profile_change_tests PRIVATE dingosdk_local_profile)
    add_test(NAME profile_changes COMMAND dingosdk_profile_change_tests)
    add_executable(dingosdk_music_favorites_tests Extension/Music/Test/local_music_favorites_tests.cpp)
    target_link_libraries(dingosdk_music_favorites_tests PRIVATE dingosdk_local_profile)
    add_test(NAME music_favorites COMMAND dingosdk_music_favorites_tests)
    add_executable(dingosdk_object_categories_tests Extension/Objects/Test/object_categories_tests.cpp)
    target_link_libraries(dingosdk_object_categories_tests PRIVATE dingosdk_local_profile)
    add_test(NAME object_categories COMMAND dingosdk_object_categories_tests)
endif()
option(DINGOSDK_BUILD_MULTIPLAYER_TESTS "Build multiplayer protocol regression tests" OFF)
if(DINGOSDK_BUILD_MULTIPLAYER_TESTS)
    enable_testing()
    if(WIN32)
        add_executable(dingosdk_voice_tests Extension/Multiplayer/Test/voice_chat_tests.cpp Extension/Multiplayer/Net/protocol.cpp
            Extension/Multiplayer/Net/delta_codec.cpp Extension/Multiplayer/Net/wire_codec.cpp)
        target_link_libraries(dingosdk_voice_tests PRIVATE dingosdk_lz4 dingosdk_zstd)
        add_test(NAME multiplayer_voice COMMAND dingosdk_voice_tests)
    endif()
    add_executable(dingosdk_party_tests Extension/Multiplayer/Test/party_tests.cpp Extension/Multiplayer/Session/party_book.cpp)
    target_include_directories(dingosdk_party_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME multiplayer_parties COMMAND dingosdk_party_tests)
    add_executable(dingosdk_server_activity_tests Server/Test/server_activity_tests.cpp Server/server_activity.cpp
        Extension/Throwdowns/throwdown_wire.cpp)
    target_include_directories(dingosdk_server_activity_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME server_activity COMMAND dingosdk_server_activity_tests)
    add_executable(dingosdk_server_text_tests Server/Test/server_text_tests.cpp)
    target_include_directories(dingosdk_server_text_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME server_text COMMAND dingosdk_server_text_tests)
    add_executable(dingosdk_speed_check_tests Server/Test/speed_check_tests.cpp)
    target_include_directories(dingosdk_speed_check_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME server_speed_check COMMAND dingosdk_speed_check_tests)
    add_executable(dingosdk_server_config_tests Server/Test/server_config_tests.cpp Server/server_config.cpp
        Extension/Multiplayer/Net/protocol.cpp)
    target_include_directories(dingosdk_server_config_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    if(WIN32)
        target_link_libraries(dingosdk_server_config_tests PRIVATE dingosdk_launcher_support dingosdk_world_layer_scan dingosdk_json
            dingosdk_lz4 dingosdk_zstd dingosdk_logging)
    else()
        target_link_libraries(dingosdk_server_config_tests PRIVATE dingosdk_launcher_support dingosdk_world_layer_scan dingosdk_json
            dingosdk_lz4 dingosdk_zstd)
    endif()
    add_test(NAME server_config COMMAND dingosdk_server_config_tests)
    add_executable(dingosdk_server_release_tests Server/Test/server_release_tests.cpp Server/server_release.cpp)
    target_include_directories(dingosdk_server_release_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_server_release_tests PRIVATE dingosdk_json)
    add_test(NAME server_release COMMAND dingosdk_server_release_tests)
    add_executable(dingosdk_global_bans_tests Server/Test/global_bans_tests.cpp Server/global_bans.cpp
        Extension/Multiplayer/developer_identity.cpp Extension/Multiplayer/word_lists.cpp)
    target_include_directories(dingosdk_global_bans_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_global_bans_tests PRIVATE dingosdk_json dingosdk_word_filter $<$<BOOL:${WIN32}>:dingosdk_https>)
    add_test(NAME server_global_bans COMMAND dingosdk_global_bans_tests)
    add_executable(dingosdk_word_filter_tests Engine/Core/Text/Test/word_filter_tests.cpp)
    target_link_libraries(dingosdk_word_filter_tests PRIVATE dingosdk_word_filter)
    add_test(NAME word_filter COMMAND dingosdk_word_filter_tests)
    add_executable(dingosdk_multiplayer_bandwidth_tests
        Extension/Multiplayer/Test/bandwidth_tests.cpp Extension/Multiplayer/Net/protocol.cpp Extension/Multiplayer/Remote/playback_buffers.cpp
        Extension/Multiplayer/Net/wire_codec.cpp Extension/Multiplayer/Net/delta_codec.cpp)
    target_link_libraries(dingosdk_multiplayer_bandwidth_tests PRIVATE dingosdk_lz4 dingosdk_zstd)
    add_test(NAME multiplayer_bandwidth COMMAND dingosdk_multiplayer_bandwidth_tests)
    # With a pose-dump recording as its argument it prints what each encoding costs on real play.
    add_executable(dingosdk_pose_codec_tests
        Extension/Multiplayer/Test/pose_codec_tests.cpp Extension/Multiplayer/Net/protocol.cpp Extension/Multiplayer/Remote/playback_buffers.cpp
        Extension/Multiplayer/Net/wire_codec.cpp Extension/Multiplayer/Net/delta_codec.cpp)
    target_link_libraries(dingosdk_pose_codec_tests PRIVATE dingosdk_lz4 dingosdk_zstd)
    add_test(NAME multiplayer_pose_codec COMMAND dingosdk_pose_codec_tests)
    add_executable(dingosdk_multiplayer_lane_tests Extension/Multiplayer/Test/steam_lanes_tests.cpp)
    target_include_directories(dingosdk_multiplayer_lane_tests SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/External/steam_networking")
    add_test(NAME multiplayer_lanes COMMAND dingosdk_multiplayer_lane_tests)
    add_executable(dingosdk_multiplayer_prediction_tests
        Extension/Multiplayer/Test/prediction_tests.cpp Extension/Multiplayer/Net/protocol.cpp Extension/Multiplayer/Remote/playback_buffers.cpp)
    add_test(NAME multiplayer_prediction COMMAND dingosdk_multiplayer_prediction_tests)
endif()
if(DINGOSDK_BUILD_MULTIPLAYER_TESTS AND WIN32)
    add_executable(dingosdk_velocity_boost_tests Engine/Game/Skater/Test/velocity_boost_tests.cpp)
    add_test(NAME velocity_boost COMMAND dingosdk_velocity_boost_tests)
    if(EXISTS "${PROJECT_SOURCE_DIR}/tests/first_person_spring_tests.cpp")
        add_executable(dingosdk_first_person_spring_tests tests/first_person_spring_tests.cpp)
        target_include_directories(dingosdk_first_person_spring_tests PRIVATE "${PROJECT_SOURCE_DIR}")
        add_test(NAME first_person_spring COMMAND dingosdk_first_person_spring_tests)
    endif()
    add_executable(dingosdk_first_person_stabilize_tests Engine/Game/Skater/Test/first_person_stabilize_tests.cpp)
    target_include_directories(dingosdk_first_person_stabilize_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME first_person_stabilize COMMAND dingosdk_first_person_stabilize_tests)
    add_executable(dingosdk_playstation_report_tests Engine/Game/Input/Test/playstation_report_tests.cpp)
    target_include_directories(dingosdk_playstation_report_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME playstation_report COMMAND dingosdk_playstation_report_tests)
    add_executable(dingosdk_physics_tuning_tests Extension/Skater/Test/physics_tuning_tests.cpp
        Extension/Skater/physics_tuning_model.cpp)
    target_include_directories(dingosdk_physics_tuning_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_physics_tuning_tests PRIVATE dingosdk_game_archives)
    add_test(NAME physics_tuning COMMAND dingosdk_physics_tuning_tests "${DINGOSDK_TEST_GAME_ROOT}")
    add_executable(dingosdk_camera_observer_tests Extension/Skater/Test/camera_observer_tests.cpp)
    add_test(NAME camera_observer_recovery COMMAND dingosdk_camera_observer_tests)
    add_executable(dingosdk_linear_transform_tests Engine/Game/Abi/Test/linear_transform_tests.cpp)
    target_include_directories(dingosdk_linear_transform_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME linear_transform COMMAND dingosdk_linear_transform_tests)
    add_executable(dingosdk_draw_packet_tests Engine/Game/Rendering/Test/draw_packet_tests.cpp)
    target_include_directories(dingosdk_draw_packet_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME draw_packet COMMAND dingosdk_draw_packet_tests)
    add_executable(dingosdk_skinned_mesh_tests Engine/Resource/Test/skinned_mesh_tests.cpp)
    target_include_directories(dingosdk_skinned_mesh_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_skinned_mesh_tests PRIVATE dingosdk_frostbite)
    add_test(NAME skinned_mesh COMMAND dingosdk_skinned_mesh_tests)
    add_executable(dingosdk_game_textures_tests Engine/Vfs/Test/game_textures_tests.cpp)
    target_include_directories(dingosdk_game_textures_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_game_textures_tests PRIVATE dingosdk_game_archives)
    add_test(NAME game_textures COMMAND dingosdk_game_textures_tests "${DINGOSDK_TEST_GAME_ROOT}")
    add_executable(dingosdk_native_menu_view_tests Extension/UI/NativeMenu/Test/native_menu_view_tests.cpp)
    add_executable(dingosdk_loading_screen_tests Extension/World/Test/loading_screen_tests.cpp)
    target_include_directories(dingosdk_loading_screen_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME loading_screen_selection COMMAND dingosdk_loading_screen_tests)
    add_test(NAME native_menu_browser COMMAND dingosdk_native_menu_view_tests)
    add_executable(dingosdk_native_tools_view_tests Extension/UI/NativeMenu/Test/native_tools_view_tests.cpp)
    target_include_directories(dingosdk_native_tools_view_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME native_menu_tools COMMAND dingosdk_native_tools_view_tests)
    add_executable(dingosdk_native_menu_lifetime_tests Extension/UI/NativeMenu/Test/native_menu_lifetime_tests.cpp)
    add_test(NAME native_menu_lifetime COMMAND dingosdk_native_menu_lifetime_tests)
    add_executable(dingosdk_native_callback_tests Engine/Game/Abi/Test/native_callback_queue_tests.cpp)
    target_include_directories(dingosdk_native_callback_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME native_callback_lifetime COMMAND dingosdk_native_callback_tests)
    add_executable(dingosdk_steam_friend_join_tests Extension/Multiplayer/Test/steam_friend_join_tests.cpp)
    add_test(NAME steam_friend_join COMMAND dingosdk_steam_friend_join_tests)
    add_executable(dingosdk_multiplayer_tests
        Extension/Multiplayer/Test/protocol_tests.cpp Extension/Multiplayer/Net/protocol.cpp Extension/Multiplayer/Remote/playback_buffers.cpp
        Extension/Multiplayer/Net/wire_codec.cpp Extension/Multiplayer/Steam/steam_server_browser.cpp Server/steam_server.cpp
        Extension/Throwdowns/throwdown_wire.cpp Extension/Multiplayer/developer_identity.cpp)
    target_link_libraries(dingosdk_multiplayer_tests PRIVATE dingosdk_lz4 dingosdk_zstd dingosdk_logging dingosdk_word_filter dingosdk_json)
    add_test(NAME multiplayer_protocol COMMAND dingosdk_multiplayer_tests)
    add_executable(dingosdk_throwdown_relay_tests Extension/Throwdowns/Test/throwdown_relay_tests.cpp
        Extension/Throwdowns/throwdown_relay.cpp Extension/Throwdowns/throwdown_wire.cpp)
    target_include_directories(dingosdk_throwdown_relay_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_throwdown_relay_tests PRIVATE dingosdk_logging)
    add_test(NAME throwdown_relay COMMAND dingosdk_throwdown_relay_tests)
    add_executable(dingosdk_multiplayer_native_tests
        Extension/Multiplayer/Test/native_layout_tests.cpp Extension/Multiplayer/Net/protocol.cpp)
    add_test(NAME multiplayer_native_layout COMMAND dingosdk_multiplayer_native_tests)
    add_executable(dingosdk_multiplayer_lobby_tests
        Extension/Multiplayer/Test/lobby_tests.cpp Extension/Multiplayer/Steam/steam_lobbies.cpp
        Extension/Multiplayer/Net/protocol.cpp)
    target_link_libraries(dingosdk_multiplayer_lobby_tests PRIVATE dingosdk_word_filter)
    add_test(NAME multiplayer_lobbies COMMAND dingosdk_multiplayer_lobby_tests)
    add_executable(dingosdk_multiplayer_mesh_tests
        Extension/Multiplayer/Test/mesh_tests.cpp Extension/Multiplayer/Net/protocol.cpp Extension/Multiplayer/Remote/playback_buffers.cpp
        Extension/Multiplayer/Net/wire_codec.cpp Extension/Multiplayer/Net/delta_codec.cpp
        Extension/Multiplayer/Session/password.cpp Extension/Multiplayer/Session/party_book.cpp
        Extension/Multiplayer/Steam/steam_lobbies.cpp Extension/Multiplayer/Steam/steam_server_browser.cpp
        Extension/Multiplayer/word_lists.cpp)
    target_link_libraries(dingosdk_multiplayer_mesh_tests PRIVATE dingosdk_logging dingosdk_launcher_support dingosdk_lz4 dingosdk_zstd bcrypt
        dingosdk_word_filter dingosdk_json)
    add_test(NAME multiplayer_mesh COMMAND dingosdk_multiplayer_mesh_tests)
    add_executable(dingosdk_developer_identity_tests
        Extension/Multiplayer/Test/developer_identity_tests.cpp Extension/Multiplayer/developer_identity.cpp
        Extension/Multiplayer/developer_identity_fetch.cpp Extension/Multiplayer/word_lists.cpp)
    target_link_libraries(dingosdk_developer_identity_tests PRIVATE dingosdk_json dingosdk_https dingosdk_logging dingosdk_word_filter winhttp)
    add_test(NAME developer_identity COMMAND dingosdk_developer_identity_tests)
    add_executable(dingosdk_settings_lock_tests Engine/Game/Settings/Test/multiplayer_settings_lock_tests.cpp)
    target_include_directories(dingosdk_settings_lock_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME multiplayer_settings_lock COMMAND dingosdk_settings_lock_tests)
    add_executable(dingosdk_simulation_time_tests Engine/Game/Settings/Test/simulation_time_tests.cpp)
    target_include_directories(dingosdk_simulation_time_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME simulation_time COMMAND dingosdk_simulation_time_tests)
    add_executable(dingosdk_held_input_tests Extension/UI/Overlay/Test/held_input_tests.cpp)
    add_test(NAME overlay_held_input COMMAND dingosdk_held_input_tests)
    add_executable(dingosdk_ea_service_block_tests Extension/Boot/Test/ea_service_block_tests.cpp)
    target_include_directories(dingosdk_ea_service_block_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME ea_service_block COMMAND dingosdk_ea_service_block_tests)
    add_executable(dingosdk_discord_presence_tests Extension/Boot/Test/discord_presence_tests.cpp Extension/Boot/discord_presence.cpp)
    target_include_directories(dingosdk_discord_presence_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_discord_presence_tests PRIVATE dingosdk_json dingosdk_logging)
    add_test(NAME discord_presence COMMAND dingosdk_discord_presence_tests)
    # The dedicated server's host under a full server of simulated players, over a transport
    # that is not Steam's: what its passes cost, and a hash of what it sent (not run by ctest).
    add_executable(dingosdk_server_load_tests Server/Test/server_load_tests.cpp Server/server_host.cpp Server/server_party.cpp
        Extension/Multiplayer/Session/party_book.cpp Server/server_config.cpp
        Server/server_update.cpp Server/server_release.cpp Launcher/updater.cpp
        Server/global_bans.cpp Extension/Multiplayer/developer_identity.cpp Extension/Multiplayer/word_lists.cpp
        Extension/Multiplayer/Net/protocol.cpp
        Extension/Multiplayer/Net/delta_codec.cpp Extension/Multiplayer/Net/wire_codec.cpp
        Extension/Multiplayer/Remote/playback_buffers.cpp Extension/Multiplayer/Session/password.cpp
        Server/server_activity.cpp Server/server_votes.cpp Server/server_commands.cpp Extension/Throwdowns/throwdown_wire.cpp)
    target_include_directories(dingosdk_server_load_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_include_directories(dingosdk_server_load_tests SYSTEM PRIVATE "${PROJECT_SOURCE_DIR}/External/steam_networking")
    target_link_libraries(dingosdk_server_load_tests PRIVATE dingosdk_launcher_support dingosdk_world_layer_scan dingosdk_json
        dingosdk_lz4 dingosdk_zstd dingosdk_logging dingosdk_miniz dingosdk_word_filter dingosdk_https winhttp bcrypt winmm)
endif()
# The route and logging tests live in the local, untracked tests/ folder.
option(DINGOSDK_BUILD_ROUTE_TESTS "Build native route cycle regression tests" OFF)
if(DINGOSDK_BUILD_ROUTE_TESTS AND EXISTS "${PROJECT_SOURCE_DIR}/tests/route_cycle_tests.cpp")
    enable_testing()
    add_executable(dingosdk_route_cycle_tests tests/route_cycle_tests.cpp)
    target_include_directories(dingosdk_route_cycle_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME route_cycle_guard COMMAND dingosdk_route_cycle_tests)
    add_executable(dingosdk_route_endpoint_tests tests/route_endpoint_tests.cpp)
    target_link_libraries(dingosdk_route_endpoint_tests PRIVATE dingosdk_hooks)
    add_test(NAME route_endpoint_guard COMMAND dingosdk_route_endpoint_tests)
endif()
if(DINGOSDK_BUILD_TESTS AND EXISTS "${PROJECT_SOURCE_DIR}/tests/logging_tests.cpp")
    enable_testing()
    add_executable(dingosdk_logging_tests tests/logging_tests.cpp)
    target_link_libraries(dingosdk_logging_tests PRIVATE dingosdk_logging)
    add_test(NAME logging_regressions COMMAND dingosdk_logging_tests)
endif()

# Header-only game contracts belong to the runtime's subsystem tree.
if(WIN32)
    file(GLOB_RECURSE game_headers CONFIGURE_DEPENDS "${PROJECT_SOURCE_DIR}/Engine/Game/*.h")
    target_sources(dingosdk_runtime PRIVATE ${game_headers})
endif()
if(DINGOSDK_BUILD_TRAINER_TESTS)
    enable_testing()
    add_executable(dingosdk_trainer_tuning_dump Extension/Trainer/Test/tuning_dump.cpp Extension/Skater/physics_tuning_model.cpp)
    target_include_directories(dingosdk_trainer_tuning_dump PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_trainer_tuning_dump PRIVATE dingosdk_game_archives)
    # Fails when the game's data stops naming a tuning value (the trainer's table comes from those names).
    add_test(NAME trainer_tuning_names COMMAND dingosdk_trainer_tuning_dump "${DINGOSDK_TEST_GAME_ROOT}")
    # What a session's host shares beyond its tuning: the encoding, and what a guest refuses.
    add_executable(dingosdk_trainer_session_tests Extension/Trainer/Test/session_extras_tests.cpp Extension/Trainer/trainer_session.cpp)
    target_include_directories(dingosdk_trainer_session_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME trainer_session_extras COMMAND dingosdk_trainer_session_tests)
    # Ground-safe arrivals: the downward ray, the landing watch, and the remembered map waypoint.
    add_executable(dingosdk_trainer_landing_tests Extension/Trainer/Test/landing_tests.cpp)
    target_include_directories(dingosdk_trainer_landing_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME trainer_landing COMMAND dingosdk_trainer_landing_tests)
    add_executable(dingosdk_trainer_asset_list Extension/Trainer/Test/asset_list.cpp)
    target_include_directories(dingosdk_trainer_asset_list PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_trainer_asset_list PRIVATE dingosdk_game_archives)
endif()
option(DINGOSDK_BUILD_ROAD_RASH_TESTS "Build Road Rash regression tests" OFF)
if(DINGOSDK_BUILD_ROAD_RASH_TESTS)
    enable_testing()
    # The side of a fall, the marks a count of bails leaves, the items' names and where a decal goes.
    add_executable(dingosdk_road_rash_tests Extension/RoadRash/Test/road_rash_tests.cpp)
    target_include_directories(dingosdk_road_rash_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME road_rash COMMAND dingosdk_road_rash_tests)
endif()
option(DINGOSDK_BUILD_HALL_OF_MEAT_TESTS "Build Hall of Meat regression tests" OFF)
if(DINGOSDK_BUILD_HALL_OF_MEAT_TESTS)
    enable_testing()
    # The bail: its phases, what each hit did, the Meat it scores and the card that shows it.
    add_executable(dingosdk_hall_of_meat_tests Extension/HallOfMeat/Test/hall_of_meat_tests.cpp
        Extension/HallOfMeat/hall_of_meat_model.cpp Extension/HallOfMeat/hall_of_meat_card.cpp)
    target_include_directories(dingosdk_hall_of_meat_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    add_test(NAME hall_of_meat COMMAND dingosdk_hall_of_meat_tests)
    # skate.'s own skeleton mesh, read from the game's data and posed (with a Skate folder).
    add_executable(dingosdk_hall_of_meat_skeleton_tests Extension/HallOfMeat/Test/hall_of_meat_skeleton_tests.cpp
        Extension/HallOfMeat/hall_of_meat_skeleton.cpp)
    target_include_directories(dingosdk_hall_of_meat_skeleton_tests PRIVATE "${PROJECT_SOURCE_DIR}")
    target_link_libraries(dingosdk_hall_of_meat_skeleton_tests PRIVATE dingosdk_game_archives dingosdk_logging)
    add_test(NAME hall_of_meat_skeleton COMMAND dingosdk_hall_of_meat_skeleton_tests "${DINGOSDK_TEST_GAME_ROOT}")
endif()
get_property(project_targets DIRECTORY PROPERTY BUILDSYSTEM_TARGETS)
foreach(target IN LISTS project_targets)
    if(NOT target MATCHES "^(dingosdk_imgui|dingosdk_detours|dingosdk_sqlite|dingosdk_lz4|dingosdk_zstd|dingosdk_miniz)$")
        dingosdk_configure_target(${target})
    endif()
endforeach()
