- item_tooltip_view.gd: 新增 avoid_rect 属性,tooltip 与装备窗口重叠时自动推到左侧 - inventory_ui.gd: 悬停装备时传入窗口矩形作为避让区域 - 包含其他累积的功能开发和测试文件
88 lines
2.6 KiB
GDScript
88 lines
2.6 KiB
GDScript
# net_world_reset_test —— 40250 Loading/Destroy 边界的 NetWorld 清理回归。
|
|
# 覆盖旧模型升级队列、聊天尾标、target/hover 和节点在 world reset 后不能回灌。
|
|
extends SceneTree
|
|
|
|
const NetWorld = preload("res://net_world.gd")
|
|
|
|
class FakeClient extends Node:
|
|
signal entity_spawned(entity: Dictionary)
|
|
signal entity_despawned(vid: int)
|
|
signal entity_moved(vid: int)
|
|
signal entity_main_set(vid: int)
|
|
signal entity_info(vid: int, entity: Dictionary)
|
|
signal chat(type: int, vid: int, text: String)
|
|
signal vitals_changed(vid: int)
|
|
signal entity_dead(vid: int)
|
|
signal damage(vid: int, amount: int, flag: int)
|
|
var entities := {}
|
|
|
|
func get_entity(vid: int) -> Dictionary:
|
|
return entities.get(vid, {})
|
|
|
|
func get_entities() -> Array:
|
|
return entities.values()
|
|
|
|
func get_pvp_relations() -> Array:
|
|
return []
|
|
|
|
func get_duel() -> Dictionary:
|
|
return {}
|
|
|
|
func add(vid: int, is_main := false) -> Dictionary:
|
|
var d := {"vid": vid, "name": "e%d" % vid, "is_main": is_main,
|
|
"pos": Vector3.ZERO, "pos_cm": Vector3.ZERO, "func": 0,
|
|
"moving": false, "angle_deg": 0.0, "hp": 100, "max_hp": 100,
|
|
"dead": false, "race": 101, "affect_flags": 0,
|
|
"parts": [0, 0, 0, 0]}
|
|
entities[vid] = d
|
|
return d
|
|
|
|
var _fail := 0
|
|
|
|
func _ck(ok: bool, message: String) -> void:
|
|
if not ok:
|
|
_fail += 1
|
|
printerr("FAIL: " + message)
|
|
|
|
func _init() -> void:
|
|
await _run()
|
|
if _fail == 0:
|
|
print("PASS: net_world_reset_test (Loading cleanup generation)")
|
|
quit(0)
|
|
else:
|
|
printerr("%d check(s) failed" % _fail)
|
|
quit(1)
|
|
|
|
func _run() -> void:
|
|
var mount := Node3D.new()
|
|
var client := FakeClient.new()
|
|
var world: Node = NetWorld.new()
|
|
get_root().add_child(mount)
|
|
get_root().add_child(client)
|
|
get_root().add_child(world)
|
|
world.setup(client, mount)
|
|
world.set_model_factory(func(_d: Dictionary) -> Node3D: return Node3D.new())
|
|
client.add(1, true)
|
|
client.add(2, false)
|
|
client.entity_main_set.emit(1)
|
|
world.catch_up()
|
|
_ck(world._upgrade_queue.has(2), "visible remote model upgrade is queued before reset")
|
|
|
|
# Seed the same transient presentation state that 40250 removes with the
|
|
# actor manager during Loading.
|
|
world._chat_tails[2] = {"text": "old", "name_flag": false}
|
|
world.set_target_vid(2)
|
|
world.set_hover_vid(2)
|
|
|
|
world.clear_for_map_change()
|
|
_ck(world._by_vid.is_empty(), "reset removes all live actor nodes")
|
|
_ck(world._upgrade_queue.is_empty(), "reset cancels stale model upgrade queue")
|
|
_ck(world._chat_tails.is_empty(), "reset removes stale chat tails")
|
|
_ck(world._target_vid == 0 and world._hover_vid == 0,
|
|
"reset clears target and hover actor references")
|
|
|
|
world.free()
|
|
client.free()
|
|
mount.free()
|
|
await process_frame
|