Files
mtgodot-poc/project/gamescene_test.gd
T

112 lines
4.2 KiB
GDScript
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# gamescene_test —— game_scene.gd 装配的 headless 自检(无服务器 / 无地图)。
# godot --headless --path project --script gamescene_test.gd
# 假 M2Client 驱动:断言场景装出来、子系统接线、实体镜像、主角定位。
extends SceneTree
const GameScene = preload("res://game_scene.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_dead(vid: int)
signal vitals_changed(vid: int)
signal points_changed(points: Dictionary)
signal target_info(vid: int, hp_percent: int)
signal chat(type: int, vid: int, text: String)
signal damage(vid: int, amount: int, flag: int)
signal motion(vid: int, victim_vid: int, motion: int)
signal gift_available()
signal guild_make_requested()
var ents := {}
var main := 0
func is_in_game() -> bool: return true
func get_main_vid() -> int: return main
func get_entity(vid: int) -> Dictionary: return ents.get(vid, {})
func move(_f, _a, _r, _x, _y) -> bool: return true
func attack(_m, _v) -> bool: return true
func set_target(_v) -> bool: return true
func guild_answer_make(_name: String) -> bool: return true
func spawn(vid, nm, pos, is_main := false):
ents[vid] = {"vid": vid, "name": nm, "pos": pos, "is_main": is_main,
"func": 0, "moving": false, "angle_deg": 0.0, "hp": 100, "max_hp": 100, "dead": false}
if is_main:
main = vid
entity_main_set.emit(vid)
entity_spawned.emit(ents[vid])
var _fail := 0
func _ck(c: bool, m: String) -> void:
if not c:
_fail += 1
printerr("FAIL: " + m)
func _init() -> void:
await _run()
if _fail == 0:
print("PASS: gamescene_test (assembly + wiring + entity mirror + spawn locate)")
quit(0)
else:
printerr("%d check(s) failed" % _fail)
quit(1)
func _run() -> void:
var fc := FakeClient.new()
get_root().add_child(fc)
# 主角先于场景就位(模拟重连 / 已在局内)
fc.spawn(1000, "Me", Vector3(20, 0, -30), true)
var gs: Node3D = GameScene.new()
get_root().add_child(gs)
await gs.setup(fc, "", "no_such_map") # setup 现在是协程(分帧避免阻塞漏 PONG)
await process_frame
# 1) 子系统都装出来了
_ck(gs.player != null, "player built")
_ck(gs.cam != null and gs.cam.current, "camera current")
_ck(gs.pc != null, "player_controller built")
_ck(gs.net_world != null, "net_world built")
_ck(gs.net_play != null, "net_play built")
_ck(gs.hud != null, "hud built")
_ck(gs.dragon_soul_ui == null, "Dragon Soul runtime entry disabled for target 40250")
_ck(gs.atlas_ui != null, "atlas_ui built")
_ck(gs.get_node_or_null("Entities") != null, "entity mount present")
# 2) 主角定位到出生点(load_map 失败 -> sample_height 返回 0 -> y=0
_ck(gs.player.position.distance_to(Vector3(20, 0, 30)) < 0.01, # MapCoord.to_world 翻 Z
"local player placed at spawn (world 帧), got %s" % gs.player.position)
# 3) net_world 不给主角画节点(本地 player 代表)
await process_frame
_ck(gs.net_world.node_for(1000) == null, "no net_world node for local vid")
fc.motion.emit(1000, 0, 305) # CRaceMotionData::NAME_CLAP
await process_frame
_ck(int(gs.player.get_meta("last_motion", 0)) == 305,
"local GC_MOTION reaches the player representative")
fc.gift_available.emit()
await process_frame
_ck(gs._gift_dialog != null and gs._gift_dialog.visible,
"gift server command opens a visible notification")
gs._gift_dialog.hide() # 关闭已有 modal,模拟玩家已处理上一条通知
fc.guild_make_requested.emit()
await process_frame
_ck(gs.guild_ui._create_dialog != null and gs.guild_ui._create_dialog.visible,
"guild make request reaches the in-game guild creation dialog")
gs.guild_ui._close_guild_create_dialog()
# 4) 别的实体会被镜像成挂载节点
fc.spawn(2000, "Wolf", Vector3(25, 0, -30))
await process_frame
var mob: Node3D = gs.net_world.node_for(2000)
_ck(mob != null and mob.get_parent() == gs.get_node("Entities"), "remote entity mirrored under mount")
# 5) HUD 活着,points 驱动不报错
fc.points_changed.emit({"hp": 60, "max_hp": 100, "sp": 20, "max_sp": 50,
"exp": 10, "next_exp": 100, "level": 3})
await process_frame
_ck(true, "points_changed handled without error")
gs.queue_free()