装备校验链/快捷栏/公会/好友情侣/交易仓库五项差距修复(增量 129)
- 装备校验:can_equip 按 CanEquipNow→FindEquipCell→EquipItem 精确重排, 新增 find_equip_cell() 1:1 复刻(RING/UNIQUE 占用翻转、COSTUME/BELT/DS), 帝国 antiflag 降级为 tooltip 提示,LIMIT_PCBANG/REAL_TIME* 语义与倒计时文案 - 快捷栏:死亡全槽禁用+激活守卫、变身(affect 220)技能置灰、 物品槽失配置灰(服务器回收/换武器后刷新) - 公会:GUILD_AUTH_* 权限位门控踢人/公告/技能升级,/gskillup、 被宣战应答弹窗(/war·/nowar)、资金存取行(40250 服务端已禁用仍保留 1:1) - 好友/情侣:messenger 三固定组(好友/公会/情侣),lover_login/logout/ near/far/divorce 命令事件→在线/在身边状态与离婚隐藏 - 交易/仓库:ExchangeState.last_notice(ALREADY/LESS_GOLD)结束浮层提示; 仓库改密 /safebox_change_password 三段输入;关窗补 /safebox_close·/mall_close; 仓库金钱经核实 40250 无 wire 协议,UI 定界只读 - app_flow:重连时 guild_marks_ready 重复连接加 is_connected 守卫 - 相机 look_at 零向量守卫(首帧/传送落点) - 测试:equip/love/guild 断言更新,79 项中 78 绿(game_camera_test 为 HEAD 既有失败);真服冒烟 LIVE_SMOKE PASS(192.168.21.203 全链路) - docs/CLIENT-GAP.md 同步增量 129 Co-Authored-By: Claude Code <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_018kUFvQGYusuY3dkfGitmAe
This commit is contained in:
@@ -245,6 +245,9 @@ void M2Client::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_safebox_gold"), &M2Client::get_safebox_gold);
|
||||
ClassDB::bind_method(D_METHOD("get_safebox_items"), &M2Client::get_safebox_items);
|
||||
ClassDB::bind_method(D_METHOD("safebox_password", "password"), &M2Client::safebox_password);
|
||||
ClassDB::bind_method(D_METHOD("safebox_change_password", "old_password", "new_password"),
|
||||
&M2Client::safebox_change_password);
|
||||
ClassDB::bind_method(D_METHOD("safebox_close"), &M2Client::safebox_close);
|
||||
// item-mall (창고몰)
|
||||
ClassDB::bind_method(D_METHOD("is_mall_open"), &M2Client::is_mall_open);
|
||||
ClassDB::bind_method(D_METHOD("get_mall_size"), &M2Client::get_mall_size);
|
||||
@@ -252,6 +255,7 @@ void M2Client::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("mall_checkout", "mall_pos", "inv_window", "inv_cell"),
|
||||
&M2Client::mall_checkout);
|
||||
ClassDB::bind_method(D_METHOD("mall_password", "password"), &M2Client::mall_password);
|
||||
ClassDB::bind_method(D_METHOD("mall_close"), &M2Client::mall_close);
|
||||
// private (PC) shop
|
||||
ClassDB::bind_method(D_METHOD("open_private_shop", "sign", "items"),
|
||||
&M2Client::open_private_shop);
|
||||
@@ -314,6 +318,8 @@ void M2Client::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("guild_remove_member", "pid"), &M2Client::guild_remove_member);
|
||||
ClassDB::bind_method(D_METHOD("guild_offer", "amount"), &M2Client::guild_offer);
|
||||
ClassDB::bind_method(D_METHOD("guild_charge_gsp", "amount"), &M2Client::guild_charge_gsp);
|
||||
ClassDB::bind_method(D_METHOD("guild_deposit_money", "amount"), &M2Client::guild_deposit_money);
|
||||
ClassDB::bind_method(D_METHOD("guild_withdraw_money", "amount"), &M2Client::guild_withdraw_money);
|
||||
ClassDB::bind_method(D_METHOD("guild_change_grade_name", "grade", "name"),
|
||||
&M2Client::guild_change_grade_name);
|
||||
ClassDB::bind_method(D_METHOD("guild_change_grade_authority", "grade", "authority"),
|
||||
@@ -1236,6 +1242,8 @@ Dictionary M2Client::get_lover() const {
|
||||
d["valid"] = lover.valid;
|
||||
d["name"] = String::utf8(lover.name.c_str());
|
||||
d["love_point"] = (int)lover.love_point;
|
||||
d["online"] = lover.online;
|
||||
d["near"] = lover.near;
|
||||
return d;
|
||||
}
|
||||
|
||||
@@ -1373,6 +1381,9 @@ Dictionary M2Client::get_exchange() const {
|
||||
d["peer_gold"] = (int64_t)x.peer_gold;
|
||||
d["self_accept"] = x.self_accept;
|
||||
d["peer_accept"] = x.peer_accept;
|
||||
// EXCHANGE_GC_ALREADY(6)/LESS_GOLD(7) 的子头值;0 = 无。成功/取消的区分
|
||||
// 只看 CHAT_TYPE_INFO 文案(服务器两种结局都发 GC_END)。
|
||||
d["notice"] = (int)x.last_notice;
|
||||
auto slots = [](const mtnet::ExchangeSlot *arr) {
|
||||
Array a;
|
||||
for (int i = 0; i < 12; ++i) {
|
||||
@@ -1528,6 +1539,23 @@ bool M2Client::mall_password(const String &password) {
|
||||
return say(0, String("/mall_password ") + password);
|
||||
}
|
||||
|
||||
bool M2Client::safebox_change_password(const String &old_password, const String &new_password) {
|
||||
// 服务器 do_safebox_change_password 要求两个参数各 1..6 字符。
|
||||
if (old_password.is_empty() || old_password.length() > 6 ||
|
||||
new_password.is_empty() || new_password.length() > 6) {
|
||||
return false;
|
||||
}
|
||||
return say(0, String("/safebox_change_password ") + old_password + " " + new_password);
|
||||
}
|
||||
|
||||
bool M2Client::safebox_close() {
|
||||
return say(0, "/safebox_close");
|
||||
}
|
||||
|
||||
bool M2Client::mall_close() {
|
||||
return say(0, "/mall_close");
|
||||
}
|
||||
|
||||
// --- private (PC) shop ---
|
||||
|
||||
bool M2Client::open_private_shop(const godot::String &sign, const godot::Array &items) {
|
||||
@@ -1783,6 +1811,25 @@ bool M2Client::guild_offer(int amount) {
|
||||
return game && is_in_game() && mtnet::bounds::u32(amount) &&
|
||||
game->send_guild_sub_u32(mtnet::GUILD_CG_OFFER, (uint32_t)amount);
|
||||
}
|
||||
bool M2Client::guild_deposit_money(int amount) {
|
||||
// 40250 服务器禁用了存款处理(input_main.cpp GUILD_CG_DEPOSIT_MONEY 直接
|
||||
// return);原版 UI 仍发送该包,这里保持同样的线上行为。
|
||||
if (classic_sess) return is_in_game() && mtnet::bounds::u32(amount) &&
|
||||
classic_sess->send_guild_u32(mtnet::classic::GUILD_CG_DEPOSIT_MONEY,
|
||||
(uint32_t)amount);
|
||||
return game && is_in_game() && mtnet::bounds::u32(amount) &&
|
||||
game->send_guild_sub_u32(mtnet::GUILD_CG_DEPOSIT_MONEY, (uint32_t)amount);
|
||||
}
|
||||
|
||||
bool M2Client::guild_withdraw_money(int amount) {
|
||||
// 同上:40250 服务器禁用取款(且原逻辑仅会长可取,上限 500000)。
|
||||
if (classic_sess) return is_in_game() && mtnet::bounds::u32(amount) &&
|
||||
classic_sess->send_guild_u32(mtnet::classic::GUILD_CG_WITHDRAW_MONEY,
|
||||
(uint32_t)amount);
|
||||
return game && is_in_game() && mtnet::bounds::u32(amount) &&
|
||||
game->send_guild_sub_u32(mtnet::GUILD_CG_WITHDRAW_MONEY, (uint32_t)amount);
|
||||
}
|
||||
|
||||
bool M2Client::guild_charge_gsp(int amount) {
|
||||
if (!mtnet::bounds::i32(amount)) return false;
|
||||
if (classic_sess) return is_in_game() &&
|
||||
@@ -3170,6 +3217,14 @@ void M2Client::pump_classic() {
|
||||
case mtnet::ServerCommandEvent::PartyRequestDenied:
|
||||
emit_signal("party_request_denied");
|
||||
break;
|
||||
case mtnet::ServerCommandEvent::LoverLogin:
|
||||
case mtnet::ServerCommandEvent::LoverLogout:
|
||||
case mtnet::ServerCommandEvent::LoverNear:
|
||||
case mtnet::ServerCommandEvent::LoverFar:
|
||||
case mtnet::ServerCommandEvent::LoverDivorce:
|
||||
// LoverInfo 由 mutator 同步更新;lover_changed 信号在
|
||||
// take_lover_dirty() 处统一发出,这里无需单独 emit。
|
||||
break;
|
||||
case mtnet::ServerCommandEvent::SafeboxPasswordRequired:
|
||||
emit_signal("safebox_password_required");
|
||||
break;
|
||||
@@ -3680,6 +3735,14 @@ void M2Client::pump_game() {
|
||||
case mtnet::ServerCommandEvent::PartyRequestDenied:
|
||||
emit_signal("party_request_denied");
|
||||
break;
|
||||
case mtnet::ServerCommandEvent::LoverLogin:
|
||||
case mtnet::ServerCommandEvent::LoverLogout:
|
||||
case mtnet::ServerCommandEvent::LoverNear:
|
||||
case mtnet::ServerCommandEvent::LoverFar:
|
||||
case mtnet::ServerCommandEvent::LoverDivorce:
|
||||
// LoverInfo 由 mutator 同步更新;lover_changed 信号在
|
||||
// take_lover_dirty() 处统一发出,这里无需单独 emit。
|
||||
break;
|
||||
case mtnet::ServerCommandEvent::SafeboxPasswordRequired:
|
||||
emit_signal("safebox_password_required");
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user