Metin2 game client (P0–P11) + mobile asset pipeline
Networked client on the existing Godot 4.7 + libgr2 renderer:
- net: m2dev wire protocol (libsodium KX + XChaCha20), auth/select/game
phases, EntityStore world model, ~all GC/CG headers. char create/delete,
private shop / mall / cube, SHOP_GC_START_EX, guild, party (+ CG_PARTY_SET_STATE),
quests, dragon soul, refine, safebox, exchange.
- UI: in-game windows migrated 1:1 from the reference uiscript/root .py —
char status (/stat), inventory+equipment, select-item ([SELECT_ITEM] quest
token), system-option + game-option + ESC system menu, private-shop 39-grid,
party info board, shop tabs, atlas, minimap, quickbar, chat, …
- EterGrnLib polish: GR2 material blend/two-sided, LOD crossfade, motion-event
dispatch, contact shadow, ray-AABB picking, weapon grip pre-transform.
Portable asset IO (A1) — all extension/libgr2/formats/mtproto reads routed
through godot::FileAccess (res:// PCK works on iOS/Android); standalone-lib
*_path() kept for the non-Godot CTests. AssetResolver + PropertyRegistry
switched to a baked index (bake_asset_index.gd) instead of std::filesystem.
Mobile builds: build-{android,ios}.sh, export-android.sh, pack-assets.sh,
gen-debug-keystore.sh. Assets ship as a zip mounted at runtime by
project/asset_pack.gd (adb push now; HTTP download is a drop-in later).
ctest 10/10, 34 GDScript suites, macOS/iOS/Android all build.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_013EJxkHiNKS4kybHS3XKyAJ
This commit is contained in:
+129
-23
@@ -1,41 +1,147 @@
|
||||
# mtgodot GDExtension — M0' skeleton (registers Metin2Model, links libgr2).
|
||||
# mtgodot GDExtension — registers Metin2Model / Metin2AnimPlayer, links libgr2.
|
||||
# libgr2 is added at the top-level CMakeLists (vendored under ../libgr2), so here
|
||||
# we just consume the xrender::libgr2 target.
|
||||
|
||||
# --- godot-cpp (submodule @ master) ---
|
||||
# master has no per-minor branch; it ships bundled extension_api-4-*.json.
|
||||
# Pin to 4.7 to match the installed editor (4.7.1; patch-level ABI is compatible).
|
||||
# --- godot-cpp (submodule pinned at 101ae38034304346a46ea9ea84ae156d3e860496) ---
|
||||
# The parent gitlink is the source-of-truth; .gitmodules intentionally has no
|
||||
# moving branch. The selected bundle targets Godot 4.7's extension API.
|
||||
set(GODOTCPP_API_VERSION "4.7" CACHE STRING "Target Godot API version" FORCE)
|
||||
add_subdirectory(godot-cpp)
|
||||
|
||||
# --- libgr2 from the sibling xrender-poc repo ---
|
||||
# M0': plain sibling-directory reference (both repos live under .../mt/).
|
||||
# For a portable checkout, either git-submodule xrender-poc or vendor libgr2,
|
||||
# then pass -DXRENDER_POC_DIR=/path/to/xrender-poc.
|
||||
set(XRENDER_POC_DIR "${CMAKE_CURRENT_SOURCE_DIR}/../../xrender-poc"
|
||||
CACHE PATH "Path to the xrender-poc repo (provides libgr2)")
|
||||
if(NOT EXISTS "${XRENDER_POC_DIR}/libgr2/CMakeLists.txt")
|
||||
message(FATAL_ERROR
|
||||
"libgr2 not found at '${XRENDER_POC_DIR}/libgr2'. "
|
||||
"Pass -DXRENDER_POC_DIR=/path/to/xrender-poc")
|
||||
endif()
|
||||
add_subdirectory("${XRENDER_POC_DIR}/libgr2" "${CMAKE_CURRENT_BINARY_DIR}/libgr2")
|
||||
# --- vendored native deps: libsodium / libzstd / miniLZO ---
|
||||
# Built from source (pinned submodules + vendored miniLZO) so the same tree
|
||||
# compiles on the Android NDK and iOS SDK, which have no Homebrew. Exposes the
|
||||
# aliases mt3p::sodium / mt3p::zstd / mt3p::minilzo. See docs/THIRD-PARTY.md.
|
||||
add_subdirectory(third_party)
|
||||
|
||||
# --- the extension shared library ---
|
||||
add_library(mtgodot SHARED
|
||||
# --- mtnet: Metin2 net protocol core (no godot-cpp dep; libsodium only) ---
|
||||
add_library(mtnet STATIC
|
||||
src/net/secure_cipher.cpp
|
||||
src/net/net_stream.cpp
|
||||
src/net/entity_store.cpp
|
||||
src/net/mark_image.cpp
|
||||
)
|
||||
target_include_directories(mtnet PUBLIC src/net)
|
||||
target_link_libraries(mtnet PUBLIC mt3p::sodium mt3p::minilzo)
|
||||
target_compile_features(mtnet PUBLIC cxx_std_20)
|
||||
|
||||
# --- mtpack: m2dev-fork asset pack reader/writer (libsodium + zstd) ---
|
||||
add_library(mtpack STATIC
|
||||
src/pack/eterpack.cpp
|
||||
src/pack/pack_mount.cpp
|
||||
src/pack/asset_source.cpp
|
||||
)
|
||||
target_include_directories(mtpack PUBLIC src/pack)
|
||||
target_link_libraries(mtpack PUBLIC mt3p::sodium mt3p::zstd xrender::formats)
|
||||
target_compile_features(mtpack PUBLIC cxx_std_20)
|
||||
|
||||
# --- mtproto: item_proto / mob_proto reader (libsodium + LZO) ---
|
||||
add_library(mtproto STATIC src/proto/proto.cpp)
|
||||
target_include_directories(mtproto PUBLIC src/proto)
|
||||
target_link_libraries(mtproto PUBLIC mt3p::sodium mt3p::minilzo)
|
||||
target_compile_features(mtproto PUBLIC cxx_std_20)
|
||||
|
||||
# Host-only CLIs + tests: they run on the build machine, so skip them entirely
|
||||
# when cross-compiling the extension for a device.
|
||||
set(MT_HOST_BUILD FALSE)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL CMAKE_HOST_SYSTEM_NAME)
|
||||
set(MT_HOST_BUILD TRUE)
|
||||
endif()
|
||||
|
||||
if(MT_HOST_BUILD)
|
||||
add_executable(packtool tools/packtool.cpp)
|
||||
target_link_libraries(packtool PRIVATE mtpack)
|
||||
|
||||
# net_probe: connect to an auth server, run the handshake + CG_LOGIN3, report.
|
||||
add_executable(net_probe tools/net_probe.cpp)
|
||||
target_link_libraries(net_probe PRIVATE mtnet)
|
||||
|
||||
# net_e2e: full auth -> game -> char list -> select -> PHASE_GAME against a
|
||||
# real server; dumps entities / points / inventory. Live integration check.
|
||||
add_executable(net_e2e tools/net_e2e.cpp)
|
||||
target_link_libraries(net_e2e PRIVATE mtnet)
|
||||
endif()
|
||||
|
||||
if(BUILD_TESTING AND MT_HOST_BUILD)
|
||||
add_executable(net_cipher_test tests/net_cipher_test.cpp)
|
||||
target_link_libraries(net_cipher_test PRIVATE mtnet)
|
||||
add_test(NAME net.cipher_roundtrip COMMAND net_cipher_test)
|
||||
|
||||
add_executable(net_loopback_test tests/net_loopback_test.cpp)
|
||||
target_link_libraries(net_loopback_test PRIVATE mtnet)
|
||||
add_test(NAME net.loopback_flow COMMAND net_loopback_test)
|
||||
|
||||
add_executable(net_entity_test tests/net_entity_test.cpp)
|
||||
target_link_libraries(net_entity_test PRIVATE mtnet)
|
||||
add_test(NAME net.entity_store COMMAND net_entity_test)
|
||||
|
||||
add_executable(net_mark_test tests/net_mark_test.cpp)
|
||||
target_link_libraries(net_mark_test PRIVATE mtnet mt3p::minilzo)
|
||||
add_test(NAME net.guild_mark COMMAND net_mark_test)
|
||||
|
||||
add_executable(pack_roundtrip_test tests/pack_roundtrip_test.cpp)
|
||||
target_link_libraries(pack_roundtrip_test PRIVATE mtpack)
|
||||
add_test(NAME pack.roundtrip COMMAND pack_roundtrip_test)
|
||||
|
||||
add_executable(proto_test tests/proto_test.cpp)
|
||||
target_link_libraries(proto_test PRIVATE mtproto)
|
||||
add_test(NAME proto.item_mob COMMAND proto_test)
|
||||
if(DEFINED ENV{M2_ASSETS})
|
||||
set_tests_properties(proto.item_mob PROPERTIES ENVIRONMENT "M2_ASSETS=$ENV{M2_ASSETS}")
|
||||
endif()
|
||||
endif()
|
||||
|
||||
# --- the extension library ---
|
||||
# macOS/Android: SHARED (Godot dlopen()s it). iOS: STATIC — the platform forbids
|
||||
# loading dynamic libraries, so the archive is linked into the app at export time
|
||||
# (see docs/PLATFORMS.md for the remaining F1 export/sign steps).
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "iOS")
|
||||
set(MT_LIB_KIND STATIC)
|
||||
set(MT_PLAT_TAG "ios")
|
||||
elseif(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
set(MT_LIB_KIND SHARED)
|
||||
set(MT_PLAT_TAG "android")
|
||||
else()
|
||||
set(MT_LIB_KIND SHARED)
|
||||
set(MT_PLAT_TAG "macos")
|
||||
endif()
|
||||
|
||||
add_library(mtgodot ${MT_LIB_KIND}
|
||||
src/register_types.cpp
|
||||
src/metin2_model.cpp
|
||||
src/metin2_anim.cpp
|
||||
src/metin2_world.cpp
|
||||
src/terrain_splat.cpp
|
||||
src/static_object.cpp
|
||||
src/tree_placeholder.cpp
|
||||
src/environment_builder.cpp
|
||||
src/water_builder.cpp
|
||||
src/gr2_bridge.cpp
|
||||
src/m2_material.cpp
|
||||
src/dxt.cpp
|
||||
src/asset_io.cpp
|
||||
src/texture_util.cpp
|
||||
src/net/m2_client.cpp
|
||||
src/proto/proto_node.cpp
|
||||
)
|
||||
target_compile_features(mtgodot PRIVATE cxx_std_20)
|
||||
target_link_libraries(mtgodot PRIVATE godot::cpp xrender::libgr2)
|
||||
target_link_libraries(mtgodot PRIVATE godot::cpp xrender::libgr2 xrender::formats mtnet mtproto)
|
||||
|
||||
# Drop the dylib straight into the Godot project where the .gdextension expects it:
|
||||
# project/bin/libmtgodot.macos.template_debug.dylib (Debug)
|
||||
# project/bin/libmtgodot.macos.template_release.dylib (Release)
|
||||
# Godot's .gdextension expects, per platform:
|
||||
# project/bin/libmtgodot.macos.template_{debug,release}.dylib
|
||||
# project/bin/libmtgodot.ios.template_{debug,release}.a
|
||||
# project/bin/libmtgodot.android.template_{debug,release}.<arch>.so
|
||||
set(MT_CFG_TAG "$<IF:$<CONFIG:Release>,template_release,template_debug>")
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Android")
|
||||
# godot_arch_name-style suffix; OnePlus 13 = arm64.
|
||||
set(MT_ARCH_SUFFIX ".${CMAKE_ANDROID_ARCH_ABI}")
|
||||
string(REPLACE "arm64-v8a" "arm64" MT_ARCH_SUFFIX "${MT_ARCH_SUFFIX}")
|
||||
else()
|
||||
set(MT_ARCH_SUFFIX "")
|
||||
endif()
|
||||
set_target_properties(mtgodot PROPERTIES
|
||||
PREFIX "lib"
|
||||
OUTPUT_NAME "mtgodot.macos.$<IF:$<CONFIG:Release>,template_release,template_debug>"
|
||||
OUTPUT_NAME "mtgodot.${MT_PLAT_TAG}.${MT_CFG_TAG}${MT_ARCH_SUFFIX}"
|
||||
ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/project/bin"
|
||||
LIBRARY_OUTPUT_DIRECTORY "${CMAKE_SOURCE_DIR}/project/bin"
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user