From 25a397bcc521e0c4dc3624ab8272c085eedd33c1 Mon Sep 17 00:00:00 2001 From: Salad Dais Date: Mon, 17 Oct 2022 21:28:11 +0000 Subject: [PATCH] add LEAP client connection addon hook --- addon_examples/leap_example.py | 9 +++++++- hippolyzer/lib/proxy/addon_utils.py | 6 +++++- hippolyzer/lib/proxy/addons.py | 32 +++++++++++++++++++++++------ hippolyzer/lib/proxy/sessions.py | 1 + 4 files changed, 40 insertions(+), 8 deletions(-) diff --git a/addon_examples/leap_example.py b/addon_examples/leap_example.py index b95ed12..b87fbe3 100644 --- a/addon_examples/leap_example.py +++ b/addon_examples/leap_example.py @@ -11,7 +11,7 @@ from outleap.scripts.inspector import LEAPInspectorGUI from hippolyzer.lib.proxy.addon_utils import send_chat, BaseAddon, show_message from hippolyzer.lib.proxy.commands import handle_command from hippolyzer.lib.proxy.region import ProxiedRegion -from hippolyzer.lib.proxy.sessions import Session +from hippolyzer.lib.proxy.sessions import Session, SessionManager # Path found using `outleap-inspector` @@ -19,6 +19,13 @@ FPS_PATH = outleap.UIPath("/main_view/menu_stack/status_bar_container/status/tim class LEAPExampleAddon(BaseAddon): + async def handle_leap_client_added(self, session_manager: SessionManager, leap_client: outleap.LEAPClient): + # You can do things as soon as the LEAP client connects, like if you want to automate + # login or whatever. + viewer_control_api = outleap.LLViewerControlAPI(leap_client) + # Ask for a config value and print it in the viewer logs + print(await viewer_control_api.get("Global", "StatsPilotFile")) + @handle_command() async def show_ui_inspector(self, session: Session, _region: ProxiedRegion): """Spawn a GUI for inspecting the UI state""" diff --git a/hippolyzer/lib/proxy/addon_utils.py b/hippolyzer/lib/proxy/addon_utils.py index 899f745..97dc39c 100644 --- a/hippolyzer/lib/proxy/addon_utils.py +++ b/hippolyzer/lib/proxy/addon_utils.py @@ -1,7 +1,6 @@ from __future__ import annotations from typing import * - import abc import copy import dataclasses @@ -9,6 +8,8 @@ import multiprocessing import pickle import warnings +import outleap + from hippolyzer.lib.base.datatypes import UUID, Vector3 from hippolyzer.lib.base.message.message import Block, Message from hippolyzer.lib.base.objects import Object @@ -194,6 +195,9 @@ class BaseAddon(metaclass=MetaBaseAddon): session: Optional[Session], region: Optional[ProxiedRegion]): pass + async def handle_leap_client_added(self, session_manager: SessionManager, leap_client: outleap.LEAPClient): + pass + _T = TypeVar("_T") _U = TypeVar("_U", "Session", "SessionManager") diff --git a/hippolyzer/lib/proxy/addons.py b/hippolyzer/lib/proxy/addons.py index 23ae5b9..4281f13 100644 --- a/hippolyzer/lib/proxy/addons.py +++ b/hippolyzer/lib/proxy/addons.py @@ -15,6 +15,8 @@ import time from types import ModuleType from typing import * +import outleap + from hippolyzer.lib.base.datatypes import UUID from hippolyzer.lib.base.helpers import get_mtime from hippolyzer.lib.base.message.message import Message @@ -343,11 +345,11 @@ class AddonManager: cls.SCHEDULER.kill_matching_tasks(lifetime_mask=TaskLifeScope.ADDON, creator=addon) @classmethod - def _call_all_addon_hooks(cls, hook_name, *args, **kwargs): + def _call_all_addon_hooks(cls, hook_name, *args, call_async=False, **kwargs): for module in cls.FRESH_ADDON_MODULES.values(): if not module: continue - ret = cls._call_module_hooks(module, hook_name, *args, **kwargs) + ret = cls._call_module_hooks(module, hook_name, *args, call_async=call_async, **kwargs) if ret: return ret @@ -378,15 +380,15 @@ class AddonManager: return commands @classmethod - def _call_module_hooks(cls, module, hook_name, *args, **kwargs): + def _call_module_hooks(cls, module, hook_name, *args, call_async=False, **kwargs): for addon in cls._get_module_addons(module): - ret = cls._try_call_hook(addon, hook_name, *args, **kwargs) + ret = cls._try_call_hook(addon, hook_name, *args, call_async=call_async, **kwargs) if ret: return ret - return cls._try_call_hook(module, hook_name, *args, **kwargs) + return cls._try_call_hook(module, hook_name, *args, call_async=call_async, **kwargs) @classmethod - def _try_call_hook(cls, addon, hook_name, *args, **kwargs): + def _try_call_hook(cls, addon, hook_name, *args, call_async=False, **kwargs): if cls._SUBPROCESS: return @@ -396,6 +398,20 @@ class AddonManager: if not hook_func: return try: + if call_async: + old_hook_func = hook_func + + # Wrapper so we can invoke an async hook synchronously. + def _wrapper(*w_args, **w_kwargs): + cls.SCHEDULER.schedule_task( + old_hook_func(*w_args, **w_kwargs), + scope=TaskLifeScope.ADDON, + creator=addon, + ) + # Fall through to any other handlers as well, + # async handlers don't chain. + return None + hook_func = _wrapper return hook_func(*args, **kwargs) except: logging.exception("Exploded in %r's %s hook" % (addon, hook_name)) @@ -577,3 +593,7 @@ class AddonManager: with addon_ctx.push(session, region): return cls._call_all_addon_hooks("handle_proxied_packet", session_manager, packet, session, region) + + @classmethod + def handle_leap_client_added(cls, session_manager: SessionManager, leap_client: outleap.LEAPClient): + return cls._call_all_addon_hooks("handle_leap_client_added", session_manager, leap_client, call_async=True) diff --git a/hippolyzer/lib/proxy/sessions.py b/hippolyzer/lib/proxy/sessions.py index 9b49379..918ac1b 100644 --- a/hippolyzer/lib/proxy/sessions.py +++ b/hippolyzer/lib/proxy/sessions.py @@ -235,6 +235,7 @@ class SessionManager: async def leap_client_connected(self, leap_client: LEAPClient): self.pending_leap_clients.append(leap_client) + AddonManager.handle_leap_client_added(self, leap_client) @dataclasses.dataclass