add LEAP client connection addon hook
This commit is contained in:
@@ -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"""
|
||||||
|
|||||||
@@ -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")
|
||||||
|
|||||||
@@ -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)
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
Reference in New Issue
Block a user