完善客户端功能并同步差距文档

This commit is contained in:
shenlei
2026-09-03 18:40:01 +09:00
parent f93a172296
commit 13ccb8d02d
135 changed files with 21881 additions and 1259 deletions
+150
View File
@@ -0,0 +1,150 @@
# complex_item_drop_test —— 仓库 / 商城 / 交易 / NPC 商店的物品态回归。
# 验证增量 54 的全局 MouseController 可以把物品送到各窗口的明确目标槽,
# 而不是只验证背包和快捷栏。
extends SceneTree
const MouseController = preload("res://ui/mouse_controller.gd")
const CursorManager = preload("res://ui/cursor_manager.gd")
const SafeboxUI = preload("res://ui/safebox_ui.gd")
const MallUI = preload("res://ui/mall_ui.gd")
const ShopUI = preload("res://ui/shop_ui.gd")
const ExchangeUI = preload("res://ui/exchange_ui.gd")
class FakeClient extends Node:
signal safebox_changed()
signal mall_opened(size: int)
signal mall_changed()
signal shop_opened(vid: int)
signal shop_closed()
signal shop_error(kind: String)
signal exchange_changed()
var calls: Array = []
var safe_open := true
var safe_size := 1
var safe_items: Array = []
var mall_open := true
var mall_size := 1
var mall_items: Array = []
var shop_open := true
var exchange := {"active": true, "self_items": [], "peer_items": []}
func is_safebox_open() -> bool: return safe_open
func get_safebox_size() -> int: return safe_size
func get_safebox_gold() -> int: return 0
func get_safebox_items() -> Array: return safe_items
func safebox_checkin(dst, window, cell) -> bool:
calls.append(["safe_checkin", dst, window, cell]); return true
func safebox_move(src, dst, count) -> bool:
calls.append(["safe_move", src, dst, count]); return true
func safebox_checkout(src, window, cell) -> bool:
calls.append(["safe_checkout", src, window, cell]); return true
func is_mall_open() -> bool: return mall_open
func get_mall_size() -> int: return mall_size
func get_mall_items() -> Array: return mall_items
func mall_checkout(src, window, cell) -> bool:
calls.append(["mall_checkout", src, window, cell]); return true
func is_shop_open() -> bool: return shop_open
func get_shop_items() -> Array: return []
func get_shop() -> Dictionary: return {"tabs": [{"name": "", "items": []}]}
func shop_sell(cell, count) -> bool:
calls.append(["shop_sell", cell, count]); return true
func get_exchange() -> Dictionary: return exchange
func exchange_add_item(window, cell, slot) -> bool:
calls.append(["exchange_add_item", window, cell, slot]); return true
var _fail := 0
func _ck(condition: bool, message: String) -> void:
if not condition:
_fail += 1
printerr("FAIL: " + message)
func _has_call(client: FakeClient, name: String, predicate: Callable) -> bool:
for call in client.calls:
if call[0] == name and predicate.call(call):
return true
return false
func _init() -> void:
var host := Control.new()
get_root().add_child(host)
var cursor := CursorManager.new()
get_root().add_child(cursor)
var mouse := MouseController.new()
get_root().add_child(mouse)
mouse.setup(host, cursor)
var client := FakeClient.new()
get_root().add_child(client)
var safe := SafeboxUI.new()
safe.item_mouse = mouse
get_root().add_child(safe)
safe.setup(client, host)
client.safe_items = [{"cell": 2, "vnum": 19, "count": 3}]
safe.refresh()
_ck(mouse._targets.size() >= 45, "safebox registers all 45 visible drop slots")
_ck(safe._drop_to_slot({"window": 1, "cell": 7, "vnum": 19, "count": 1}, 4),
"inventory item drops into empty safebox slot")
_ck(_has_call(client, "safe_checkin", func(c): return c[1] == 4 and c[2] == 1 and c[3] == 7),
"safebox drop uses explicit destination slot")
var safe_item := safe._cells[2] as Button
var safe_event := InputEventMouseButton.new()
safe_event.button_index = MOUSE_BUTTON_LEFT
safe_event.pressed = true
safe._on_grid_input(2, safe_event)
_ck(mouse.is_attached() and int(mouse.attached().get("window", -1)) == 3,
"safebox item enters global item state")
mouse.cancel()
var mall := MallUI.new()
mall.item_mouse = mouse
get_root().add_child(mall)
mall.setup(client, host)
client.mall_items = [{"cell": 5, "vnum": 27, "count": 2}]
mall.refresh()
var mall_name := mall._list.get_child(0).get_child(0) as Label
var mall_event := InputEventMouseButton.new()
mall_event.button_index = MOUSE_BUTTON_LEFT
mall_event.pressed = true
mall_name.gui_input.emit(mall_event)
_ck(mouse.is_attached() and int(mouse.attached().get("window", -1)) == 4
and int(mouse.attached().get("cell", -1)) == 5,
"mall item enters global item state")
mouse.cancel()
var exchange := ExchangeUI.new()
exchange.item_mouse = mouse
get_root().add_child(exchange)
exchange.setup(client, host)
_ck(exchange._drop_to_slot({"window": 1, "cell": 8, "vnum": 29, "count": 1}, 6),
"inventory item drops into empty exchange slot")
_ck(_has_call(client, "exchange_add_item", func(c): return c[1] == 1 and c[2] == 8 and c[3] == 6),
"exchange drop uses explicit display slot")
var shop := ShopUI.new()
shop.item_mouse = mouse
get_root().add_child(shop)
shop.setup(client, host)
shop.open()
_ck(shop._mode == 1 and not shop._sell_drop_target.visible,
"shop opens in buy mode with sell target hidden")
_ck(not shop._drop_to_sell({"window": 1, "cell": 9, "vnum": 31, "count": 4}),
"buy mode rejects item drop to sell target")
shop._set_mode(2)
_ck(shop._mode == 2 and shop._sell_drop_target.visible,
"sell mode shows sell target")
_ck(shop._drop_to_sell({"window": 1, "cell": 9, "vnum": 31, "count": 4}),
"inventory item drops into shop sell target")
_ck(_has_call(client, "shop_sell", func(c): return c[1] == 9 and c[2] == 1),
"shop drop uses selected sell quantity")
if _fail == 0:
print("PASS: complex_item_drop_test (safebox + mall + exchange + shop)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)