Files
mtgodot-poc/extension/tools/net_probe.cpp
T
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

78 lines
2.6 KiB
C++

// net_probe — connect to a Metin2 auth server, run the libsodium handshake and
// the CG_LOGIN3 exchange, print what happened. Purely diagnostic.
//
// net_probe <host> <port> <id> <pw> (defaults: 192.168.21.203 11000 admin 123456789)
#include "../src/net/auth_client.h"
#include <chrono>
#include <cstdio>
#include <string>
#include <thread>
int main(int argc, char **argv) {
std::string host = argc > 1 ? argv[1] : "192.168.21.203";
uint16_t port = argc > 2 ? static_cast<uint16_t>(std::stoi(argv[2])) : 11000;
std::string id = argc > 3 ? argv[3] : "admin";
std::string pw = argc > 4 ? argv[4] : "123456789";
std::printf("net_probe -> %s:%u id=%s\n", host.c_str(), port, id.c_str());
mtnet::AuthClient client(id, pw);
if (!client.connect(host, port)) {
std::printf("connect() failed: %s\n", client.last_error().c_str());
return 2;
}
using clock = std::chrono::steady_clock;
auto start = clock::now();
auto last_state = mtnet::NetStream::State::Offline;
bool reported_online = false, reported_cipher = false, reported_login = false;
while (std::chrono::duration_cast<std::chrono::seconds>(clock::now() - start).count() < 15) {
client.process();
if (client.state() != last_state) {
const char *s = client.state() == mtnet::NetStream::State::Connecting ? "Connecting"
: client.state() == mtnet::NetStream::State::Online ? "Online"
: "Offline";
std::printf("[state] %s\n", s);
last_state = client.state();
}
if (!reported_online && client.state() == mtnet::NetStream::State::Online) {
std::printf("[tcp] connected\n");
reported_online = true;
}
if (!reported_cipher && client.handshaked()) {
std::printf("[handshake] cipher activated (KX ok)\n");
reported_cipher = true;
}
if (!reported_login && client.sent_login()) {
std::printf("[auth] PHASE_AUTH reached, CG_LOGIN3 sent\n");
reported_login = true;
}
if (client.done()) {
break;
}
if (client.state() == mtnet::NetStream::State::Offline && reported_online) {
std::printf("[net] disconnected: %s\n", client.last_error().c_str());
break;
}
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
if (client.done() && client.success()) {
std::printf("RESULT: auth OK, login_key=0x%08X\n", client.login_key());
return 0;
}
if (client.done()) {
std::printf("RESULT: auth failed (%s)\n",
client.fail_reason().empty() ? client.last_error().c_str()
: client.fail_reason().c_str());
return 1;
}
std::printf("RESULT: timed out. last_error=%s online=%d cipher=%d login_sent=%d\n",
client.last_error().c_str(), (int)reported_online, (int)reported_cipher,
(int)reported_login);
return 3;
}