fix: 装备属性面板避让逻辑 + 多项功能更新

- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧
- inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域
- 包含其他累积的功能开发和测试文件
This commit is contained in:
shen
2026-09-21 16:38:59 -07:00
parent 1522a8a1a1
commit c93894313a
5498 changed files with 4558004 additions and 1442 deletions
+36 -10
View File
@@ -25,13 +25,22 @@ var _deadline := 0.0
var _sent := false
var _classic := false
var _classic_rx := PackedByteArray()
var _status_body_rx := PackedByteArray()
func query(host: String, port: int, callback: Callable = Callable(), timeout_s := 3.0) -> void:
# ServerStateChecker owns one probe stream. Cancel the previous transport
# before replacing it so a repeated request cannot leave an old socket alive
# behind the new callback.
if _peer != null:
_peer.disconnect_from_host()
_peer = null
set_process(false)
_cb = callback
_peer = StreamPeerTCP.new()
_sent = false
_classic = OS.get_environment("MT_PROTOCOL") == "classic"
_classic_rx = PackedByteArray()
_status_body_rx = PackedByteArray()
_deadline = _now() + timeout_s
if _peer.connect_to_host(host, port) != OK:
_finish({})
@@ -132,24 +141,41 @@ func _try_parse() -> void:
_peer.get_data(rest)
func _read_body() -> void:
# 已消费 4 字节头;接着 int32 count + count × {i16 port, u8 status}
if _peer.get_available_bytes() < 4:
# 已消费 4 字节头;接着 int32 count + count × {i16 port, u8 status}
# StreamPeerTCP 可能把 body 分成多个到达批次,必须保留已收到的
# 字节,不能像旧实现一样在第一条不完整 record 时提前 finish。
var avail := _peer.get_available_bytes()
if avail > 0:
var chunk: Array = _peer.get_data(avail)
if chunk[0] != OK:
_finish({})
return
_status_body_rx.append_array(chunk[1])
if _status_body_rx.size() < 4:
return
var count: int = _status_body_rx.decode_s32(0)
if count < 0 or count > 4096:
_finish({})
return
var total := 4 + count * 3
if _status_body_rx.size() < total:
return
var cnt_r: Array = _peer.get_data(4)
var count: int = (cnt_r[1] as PackedByteArray).decode_s32(0)
var out := {}
for i in count:
if _peer.get_available_bytes() < 3:
break
var rec: PackedByteArray = _peer.get_data(3)[1]
out[rec.decode_s16(0)] = rec.decode_u8(2)
var off := 4 + i * 3
out[_status_body_rx.decode_s16(off)] = _status_body_rx.decode_u8(off + 2)
_finish(out)
func _finish(m: Dictionary) -> void:
# Capture the callback before emitting `done`: a listener may immediately
# start the next probe. Calling the mutable `_cb` afterwards would deliver
# the old result to the new request (a stale re-entrant callback).
var callback := _cb
_cb = Callable()
set_process(false)
if _peer:
_peer.disconnect_from_host()
_peer = null
done.emit(m)
if _cb.is_valid():
_cb.call(m)
if callback.is_valid():
callback.call(m)