Files
shenandClaude Sonnet 5 47baf6c0c6 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
2026-08-31 20:02:12 +09:00

67 lines
3.0 KiB
C++
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
// Metin2 -> Godot 坐标 / 单位统一转换(纯数学,无 godot 依赖)。
// BACKLOG I5 · SHINSOO §6。extension 侧的 mtgodot::coord 薄封装应直接调用这里,
// 不得另写公式。
//
// Metin2:厘米,Z-up(左手) Godot:米,Y-up(右手)
// Godot.x = Metin2.x * 0.01
// Godot.y = Metin2.z * 0.01
// Godot.z = -Metin2.y * 0.01
// 等价于 make_conv 的 rotate(-90°,X) + scale(0.01)。
#pragma once
#include <cstdint>
#include <string>
namespace fmt::m2coord {
struct Vec3 { double x = 0, y = 0, z = 0; };
constexpr double CM_TO_M = 0.01;
constexpr int CELLSCALE = 200; // PRTerrainLib TerrainType.h
constexpr int TERRAIN_SIZE = 128;
constexpr int CHUNK_CM = CELLSCALE * TERRAIN_SIZE; // 25600 —— 一个区块的边长(cm)
// 位置:厘米 Z-up -> 米 Y-up。
inline Vec3 position_to_godot(double x_cm, double y_cm, double z_cm) {
return { x_cm * CM_TO_M, z_cm * CM_TO_M, -y_cm * CM_TO_M };
}
inline Vec3 position_to_godot(const Vec3& v) { return position_to_godot(v.x, v.y, v.z); }
// 方向:只做轴转换,不缩放、不平移。
inline Vec3 direction_to_godot(double x, double y, double z) {
return { x, z, -y };
}
// 区块目录编号:tile_id = tile_x*1000 + tile_y,目录名 = 6 位十进制。
inline uint32_t tile_id(int tile_x, int tile_y) {
return uint32_t(tile_x) * 1000u + uint32_t(tile_y);
}
std::string tile_dir(int tile_x, int tile_y); // "000000" / "001003"
bool parse_tile_dir(const std::string& name, int& tile_x, int& tile_y);
// 区块原点(该区块 (0,0) 格在地图内的厘米坐标,未做轴转换)。
inline Vec3 chunk_origin_cm(int tile_x, int tile_y) {
return { double(tile_x) * CHUNK_CM, double(tile_y) * CHUNK_CM, 0.0 };
}
// height.raw 采样值 -> 厘米高度:raw * HeightScale。
inline double height_raw_to_cm(uint16_t raw, double height_scale) {
return double(raw) * height_scale;
}
struct Mat3 { double m[9]; }; // row-major: m[r*3+c]
// AreaData 的 yaw#pitch#roll(度)-> **Metin2 Z-up 空间**的旋转(行主序 3×3)。
// 忠实移植原客户端 `CGraphicObjectInstance::SetRotation` 的
// `D3DXMatrixRotationYawPitchRoll(yaw, pitch, roll)`(列向量约定下 = Ry(yaw)·Rx(pitch)·Rz(roll))。
// 注意 Metin2 世界是 Z-upyaw 绕 Y、pitch 绕 X、**roll 绕 Z = 竖直轴 = 朝向**。
// areadata 单值旋转 → roll`Area.cpp:820`)。这一版**未**做 Z-up→Y-up 轴转换,
// 直接塞进 Godot Basis 会把「朝向」错当成绕 Godot Z 的翻滚 —— 放置物体请用 object_basis_godot()。
Mat3 ypr_basis(double yaw_deg, double pitch_deg, double roll_deg);
// 同上,但已把旋转共轭到 **Godot Y-up 空间**R_godot = C · R_m2 · C⁻¹,C = rotate(-90°,X))。
// 可直接作为 Godot Basis 使用:物体的 Godot 变换 = Transform3D(object_basis_godot(...), g) * make_conv()。
// roll(朝向)→ 绕 Godot +Y 的 heading,不再翻滚。行主序 3×3。
Mat3 object_basis_godot(double yaw_deg, double pitch_deg, double roll_deg);
} // namespace fmt::m2coord