Compare commits
3 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6f87ec8725 | ||
|
|
fb885d8eec | ||
|
|
78281ed12b |
2
.github/workflows/bundle_windows.yml
vendored
2
.github/workflows/bundle_windows.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
||||
run: |
|
||||
python -m pip install --upgrade pip
|
||||
pip install -r requirements.txt
|
||||
pip install -e .
|
||||
pip install -e .[gui]
|
||||
pip install cx_freeze
|
||||
|
||||
- name: Bundle with cx_Freeze
|
||||
|
||||
2
.github/workflows/pytest.yml
vendored
2
.github/workflows/pytest.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
||||
pip install -r requirements.txt
|
||||
pip install -r requirements-test.txt
|
||||
sudo apt-get install libopenjp2-7
|
||||
pip install -e .
|
||||
pip install -e .[gui]
|
||||
- name: Run Flake8
|
||||
run: |
|
||||
flake8 .
|
||||
|
||||
@@ -35,7 +35,9 @@ with low-level SL details. See the [Local Animation addon example](https://githu
|
||||
* Activate the virtualenv by running the appropriate activation script
|
||||
* * Under Linux this would be something like `source <virtualenv_dir>/bin/activate`
|
||||
* * Under Windows it's `<virtualenv_dir>\Scripts\activate.bat`
|
||||
* Run `pip install hippolyzer`, or run `pip install -e .` in a cloned repo to install an editable version
|
||||
* Run `pip install hippolyzer[gui]` for a full install, or run `pip install -e .[gui]` in a cloned repo to install an editable version
|
||||
* * If you only want the core library without proxy or GUI support, use `pip install hippolyzer` or `pip install -e .`
|
||||
* * If you only want proxy/CLI support without the GUI, use `pip install hippolyzer[proxy]` or `pip install -e .[proxy]`
|
||||
|
||||
### Binary Windows Builds
|
||||
|
||||
|
||||
94
addon_examples/appearance_delay_tracker.py
Normal file
94
addon_examples/appearance_delay_tracker.py
Normal file
@@ -0,0 +1,94 @@
|
||||
"""
|
||||
Try and diagnose very slow avatar appearance loads when the avatars first come on the scene
|
||||
|
||||
I guess use LEAP or something to detect when things _actually_ declouded.
|
||||
"""
|
||||
from typing import *
|
||||
|
||||
import dataclasses
|
||||
import datetime as dt
|
||||
|
||||
from hippolyzer.lib.base.datatypes import UUID
|
||||
from hippolyzer.lib.base.message.message import Message
|
||||
from hippolyzer.lib.base.objects import Object
|
||||
from hippolyzer.lib.base.templates import PCode
|
||||
from hippolyzer.lib.proxy.addon_utils import BaseAddon, GlobalProperty
|
||||
from hippolyzer.lib.proxy.http_flow import HippoHTTPFlow
|
||||
from hippolyzer.lib.proxy.region import ProxiedRegion
|
||||
from hippolyzer.lib.proxy.sessions import Session, SessionManager
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AvatarBakeRequest:
|
||||
requested: dt.datetime
|
||||
received: Optional[dt.datetime] = None
|
||||
|
||||
|
||||
@dataclasses.dataclass
|
||||
class AvatarAppearanceRecord:
|
||||
object_received: dt.datetime
|
||||
"""When we learned about the agent as an object"""
|
||||
appearance_received: Optional[dt.datetime] = None
|
||||
"""When AvatarAppearance was first received"""
|
||||
bake_requests: Dict[str, AvatarBakeRequest] = dataclasses.field(default_factory=dict)
|
||||
"""Layer name -> request / response details"""
|
||||
|
||||
|
||||
class AppearanceDelayTrackerAddon(BaseAddon):
|
||||
# Should be able to access this in the REPL
|
||||
# Normally we'd use a session property, but we may not have a proper session context for some requests
|
||||
av_appearance_data: Dict[UUID, AvatarAppearanceRecord] = GlobalProperty(dict)
|
||||
|
||||
def handle_object_updated(self, session: Session, region: ProxiedRegion,
|
||||
obj: Object, updated_props: Set[str], msg: Optional[Message]):
|
||||
if obj.PCode == PCode.AVATAR and obj.FullID not in self.av_appearance_data:
|
||||
self.av_appearance_data[obj.FullID] = AvatarAppearanceRecord(object_received=dt.datetime.now())
|
||||
|
||||
def handle_lludp_message(self, session: Session, region: ProxiedRegion, message: Message):
|
||||
if message.name != "AvatarAppearance":
|
||||
return
|
||||
agent_id = message["Sender"]["ID"]
|
||||
appearance_data = self.av_appearance_data.get(agent_id)
|
||||
if not appearance_data:
|
||||
print(f"Got appearance for {agent_id} without knowing about object?")
|
||||
return
|
||||
|
||||
if appearance_data.appearance_received:
|
||||
return
|
||||
appearance_data.appearance_received = dt.datetime.now()
|
||||
|
||||
def handle_http_request(self, session_manager: SessionManager, flow: HippoHTTPFlow):
|
||||
if not flow.cap_data:
|
||||
return
|
||||
if flow.cap_data.cap_name != "AppearanceService":
|
||||
return
|
||||
|
||||
agent_id = UUID(flow.request.url.split('/')[-3])
|
||||
slot_name = flow.request.url.split('/')[-2]
|
||||
appearance_data = self.av_appearance_data.get(agent_id)
|
||||
if not appearance_data:
|
||||
print(f"Got AppearanceService req for {agent_id} without knowing about object?")
|
||||
return
|
||||
if slot_name in appearance_data.bake_requests:
|
||||
# We already requested this slot before
|
||||
return
|
||||
appearance_data.bake_requests[slot_name] = AvatarBakeRequest(requested=dt.datetime.now())
|
||||
|
||||
def handle_http_response(self, session_manager: SessionManager, flow: HippoHTTPFlow):
|
||||
if not flow.cap_data:
|
||||
return
|
||||
if flow.cap_data.cap_name != "AppearanceService":
|
||||
return
|
||||
|
||||
agent_id = UUID(flow.request.url.split('/')[-3])
|
||||
slot_name = flow.request.url.split('/')[-2]
|
||||
appearance_data = self.av_appearance_data.get(agent_id)
|
||||
if not appearance_data:
|
||||
return
|
||||
slot_details = appearance_data.bake_requests.get(slot_name)
|
||||
if not slot_details:
|
||||
return
|
||||
slot_details.received = dt.datetime.now()
|
||||
|
||||
|
||||
addons = [AppearanceDelayTrackerAddon()]
|
||||
@@ -719,7 +719,9 @@ class MessageBuilderWindow(QtWidgets.QMainWindow):
|
||||
transport = None
|
||||
off_circuit = self.checkOffCircuit.isChecked()
|
||||
if off_circuit:
|
||||
transport = SocketUDPTransport(socket.socket(socket.AF_INET, socket.SOCK_DGRAM))
|
||||
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
sock.bind(("0.0.0.0", 0))
|
||||
transport = SocketUDPTransport(sock)
|
||||
region.circuit.send(msg, transport=transport)
|
||||
if off_circuit:
|
||||
transport.close()
|
||||
|
||||
@@ -26,24 +26,31 @@ classifiers = [
|
||||
]
|
||||
dependencies = [
|
||||
"aiohttp<4.0.0",
|
||||
"arpeggio",
|
||||
"defusedxml",
|
||||
"gltflib",
|
||||
"Glymur<0.9.7",
|
||||
"idna<3,>=2.5",
|
||||
"lazy-object-proxy",
|
||||
"llsd<1.1.0",
|
||||
"mitmproxy>=11.0.0,<12",
|
||||
"numpy<2.0",
|
||||
"outleap<1.0",
|
||||
"ptpython<4.0",
|
||||
"pycollada",
|
||||
"pyside6-essentials",
|
||||
"qasync",
|
||||
"recordclass>=0.23.1,<0.24",
|
||||
"transformations",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
proxy = [
|
||||
"arpeggio",
|
||||
"mitmproxy>=11.0.0,<12",
|
||||
"outleap<1.0",
|
||||
"ptpython<4.0",
|
||||
"Werkzeug<4.0",
|
||||
]
|
||||
gui = [
|
||||
"hippolyzer[proxy]",
|
||||
"pyside6-essentials",
|
||||
"qasync",
|
||||
]
|
||||
|
||||
[tool.setuptools.packages.find]
|
||||
where = ["."]
|
||||
|
||||
Reference in New Issue
Block a user