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
78 lines
2.6 KiB
C++
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;
|
|
}
|