add LEAP client connection addon hook

This commit is contained in:
Salad Dais
2022-10-17 21:28:11 +00:00
parent b0dca80b87
commit 25a397bcc5
4 changed files with 40 additions and 8 deletions

View File

@@ -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.addon_utils import send_chat, BaseAddon, show_message
from hippolyzer.lib.proxy.commands import handle_command from hippolyzer.lib.proxy.commands import handle_command
from hippolyzer.lib.proxy.region import ProxiedRegion 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` # 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): 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() @handle_command()
async def show_ui_inspector(self, session: Session, _region: ProxiedRegion): async def show_ui_inspector(self, session: Session, _region: ProxiedRegion):
"""Spawn a GUI for inspecting the UI state""" """Spawn a GUI for inspecting the UI state"""

View File

@@ -1,7 +1,6 @@
from __future__ import annotations from __future__ import annotations
from typing import * from typing import *
import abc import abc
import copy import copy
import dataclasses import dataclasses
@@ -9,6 +8,8 @@ import multiprocessing
import pickle import pickle
import warnings import warnings
import outleap
from hippolyzer.lib.base.datatypes import UUID, Vector3 from hippolyzer.lib.base.datatypes import UUID, Vector3
from hippolyzer.lib.base.message.message import Block, Message from hippolyzer.lib.base.message.message import Block, Message
from hippolyzer.lib.base.objects import Object from hippolyzer.lib.base.objects import Object
@@ -194,6 +195,9 @@ class BaseAddon(metaclass=MetaBaseAddon):
session: Optional[Session], region: Optional[ProxiedRegion]): session: Optional[Session], region: Optional[ProxiedRegion]):
pass pass
async def handle_leap_client_added(self, session_manager: SessionManager, leap_client: outleap.LEAPClient):
pass
_T = TypeVar("_T") _T = TypeVar("_T")
_U = TypeVar("_U", "Session", "SessionManager") _U = TypeVar("_U", "Session", "SessionManager")

View File

@@ -15,6 +15,8 @@ import time
from types import ModuleType from types import ModuleType
from typing import * from typing import *
import outleap
from hippolyzer.lib.base.datatypes import UUID from hippolyzer.lib.base.datatypes import UUID
from hippolyzer.lib.base.helpers import get_mtime from hippolyzer.lib.base.helpers import get_mtime
from hippolyzer.lib.base.message.message import Message 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) cls.SCHEDULER.kill_matching_tasks(lifetime_mask=TaskLifeScope.ADDON, creator=addon)
@classmethod @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(): for module in cls.FRESH_ADDON_MODULES.values():
if not module: if not module:
continue 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: if ret:
return ret return ret
@@ -378,15 +380,15 @@ class AddonManager:
return commands return commands
@classmethod @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): 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: if ret:
return 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 @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: if cls._SUBPROCESS:
return return
@@ -396,6 +398,20 @@ class AddonManager:
if not hook_func: if not hook_func:
return return
try: 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) return hook_func(*args, **kwargs)
except: except:
logging.exception("Exploded in %r's %s hook" % (addon, hook_name)) logging.exception("Exploded in %r's %s hook" % (addon, hook_name))
@@ -577,3 +593,7 @@ class AddonManager:
with addon_ctx.push(session, region): with addon_ctx.push(session, region):
return cls._call_all_addon_hooks("handle_proxied_packet", session_manager, return cls._call_all_addon_hooks("handle_proxied_packet", session_manager,
packet, session, region) 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)

View File

@@ -235,6 +235,7 @@ class SessionManager:
async def leap_client_connected(self, leap_client: LEAPClient): async def leap_client_connected(self, leap_client: LEAPClient):
self.pending_leap_clients.append(leap_client) self.pending_leap_clients.append(leap_client)
AddonManager.handle_leap_client_added(self, leap_client)
@dataclasses.dataclass @dataclasses.dataclass