108 lines
3.4 KiB
GDScript
108 lines
3.4 KiB
GDScript
extends SceneTree
|
|
|
|
const PythonUISurface = preload("res://python_ui_surface.gd")
|
|
const Python3DSurface = preload("res://python_3d_surface.gd")
|
|
|
|
var ui: Control
|
|
var world: Node3D
|
|
|
|
func _initialize() -> void:
|
|
call_deferred("run")
|
|
|
|
func _py(source: String) -> bool:
|
|
return Metin2PythonHost.run_line(source) == ""
|
|
|
|
func _pump_until(seconds: float, condition: Callable) -> bool:
|
|
var deadline := Time.get_ticks_msec() + int(seconds * 1000.0)
|
|
while Time.get_ticks_msec() < deadline:
|
|
if condition.call():
|
|
return true
|
|
await process_frame
|
|
return condition.call()
|
|
|
|
func run() -> void:
|
|
root.size = Vector2i(1024, 768)
|
|
world = Python3DSurface.new()
|
|
world.name = "Python3DSurface"
|
|
ui = PythonUISurface.new()
|
|
ui.name = "PythonUISurface"
|
|
root.add_child(ui)
|
|
root.add_child(world)
|
|
|
|
var err: String = ui.run_app()
|
|
if err != "":
|
|
print("ERROR: run_app: ", err)
|
|
quit(1)
|
|
return
|
|
|
|
await _pump_until(15, func(): return _py(
|
|
"import __main__, os, networkModule, introLogin, introSelect, game, player, background, chr, chrmgr\n"
|
|
+ "__main__._stream = [o for o in __import__('gc').get_objects() if isinstance(o, networkModule.MainStream)][0]"
|
|
))
|
|
|
|
await _pump_until(20, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, introLogin.LoginWindow)"
|
|
))
|
|
|
|
var host = OS.get_environment("MT_LIVE_HOST")
|
|
var login = OS.get_environment("MT_LIVE_LOGIN")
|
|
var pwd = OS.get_environment("MT_LIVE_PASSWORD")
|
|
var auth_port = int(OS.get_environment("MT_LIVE_AUTH_PORT"))
|
|
var game_port = int(OS.get_environment("MT_LIVE_GAME_PORT"))
|
|
|
|
_py("_stream.SetConnectInfo('%s', %d, '%s', %d)\n" % [host, game_port, host, auth_port]
|
|
+ "_stream.curPhaseWindow.Connect('%s', '%s')" % [login, pwd])
|
|
|
|
await _pump_until(30, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, introSelect.SelectCharacterWindow)"
|
|
))
|
|
|
|
_py("_stream.curPhaseWindow.SelectSlot(0)\n_stream.curPhaseWindow.StartGame()")
|
|
|
|
await _pump_until(60, func(): return _py(
|
|
"assert isinstance(_stream.curPhaseWindow, game.GameWindow) and _stream.curPhaseWindow.IsShow()"
|
|
))
|
|
|
|
await _pump_until(10, func(): return world.draw_count > 0)
|
|
for i in 30:
|
|
await process_frame
|
|
|
|
var draws: Array = Metin2PythonHost.render3d_draws()
|
|
print("Game 3D draws count: ", draws.size())
|
|
|
|
# Find actual actors
|
|
var actor_draws: Array = []
|
|
for draw in draws:
|
|
var tex = draw.get("texture0", "").to_lower()
|
|
var is_actor = false
|
|
for k in ["pc/", "pc2/", "monster/", "npc/", "warrior", "assassin", "sura", "shaman", "dog", "wolf"]:
|
|
if k in tex:
|
|
is_actor = true
|
|
break
|
|
if is_actor:
|
|
actor_draws.append(draw)
|
|
|
|
print("Actual actor draws count: ", actor_draws.size())
|
|
|
|
var actor_low := {}
|
|
for draw in actor_draws:
|
|
var draw_xform: Transform3D = world.d3d_transform(draw["world"])
|
|
var key := str(draw["world"])
|
|
for vertex in draw["positions"]:
|
|
var p: Vector3 = draw_xform * vertex
|
|
if not actor_low.has(key) or p.z < actor_low[key].z:
|
|
actor_low[key] = p
|
|
|
|
print("Distinct actors count: ", actor_low.size())
|
|
if world.terrain:
|
|
var worst_actor_gap_cm := 0.0
|
|
for key in actor_low:
|
|
var low: Vector3 = actor_low[key]
|
|
var ground := float(world.terrain.call("sample_height", low.x / 100.0, -low.y / 100.0)) * 100.0
|
|
var gap = absf(low.z - ground)
|
|
print("Actor at (%f, %f): foot_z=%f, ground_z=%f, gap=%f cm" % [low.x, low.y, low.z, ground, gap])
|
|
worst_actor_gap_cm = maxf(worst_actor_gap_cm, gap)
|
|
print("WORST ACTUAL ACTOR GAP: ", worst_actor_gap_cm, " cm")
|
|
|
|
quit(0)
|