Better defaults when parsing ObjectUpdateCompressed
This helps our view of the cache better match the viewer's VOCache
This commit is contained in:
@@ -270,6 +270,9 @@ def normalize_object_update_compressed_data(data: bytes):
|
||||
# Only used for determining which sections are present
|
||||
del compressed["Flags"]
|
||||
|
||||
# Unlike other ObjectUpdate types, a null value in an ObjectUpdateCompressed
|
||||
# always means that there is no value, not that the value hasn't changed
|
||||
# from the client's view. Use the default value when that happens.
|
||||
ps_block = compressed.pop("PSBlockNew", None)
|
||||
if ps_block is None:
|
||||
ps_block = compressed.pop("PSBlock", None)
|
||||
@@ -278,6 +281,20 @@ def normalize_object_update_compressed_data(data: bytes):
|
||||
compressed.pop("PSBlock", None)
|
||||
if compressed["NameValue"] is None:
|
||||
compressed["NameValue"] = NameValueCollection()
|
||||
if compressed["Text"] is None:
|
||||
compressed["Text"] = b""
|
||||
compressed["TextColor"] = b""
|
||||
if compressed["MediaURL"] is None:
|
||||
compressed["MediaURL"] = b""
|
||||
if compressed["AngularVelocity"] is None:
|
||||
compressed["AngularVelocity"] = Vector3()
|
||||
if compressed["SoundFlags"] is None:
|
||||
compressed["SoundFlags"] = 0
|
||||
compressed["SoundGain"] = 0.0
|
||||
compressed["SoundRadius"] = 0.0
|
||||
compressed["Sound"] = UUID()
|
||||
if compressed["TextureEntry"] is None:
|
||||
compressed["TextureEntry"] = tmpls.TextureEntry()
|
||||
|
||||
object_data = {
|
||||
"PSBlock": ps_block.value,
|
||||
@@ -286,9 +303,9 @@ def normalize_object_update_compressed_data(data: bytes):
|
||||
"LocalID": compressed.pop("ID"),
|
||||
**compressed,
|
||||
}
|
||||
if object_data["TextureEntry"] is None:
|
||||
object_data.pop("TextureEntry")
|
||||
# Don't clobber OwnerID in case the object has a proper one.
|
||||
# Don't clobber OwnerID in case the object has a proper one from
|
||||
# a previous ObjectProperties. OwnerID isn't expected to be populated
|
||||
# on ObjectUpdates unless an attached sound is playing.
|
||||
if object_data["OwnerID"] == UUID():
|
||||
del object_data["OwnerID"]
|
||||
return object_data
|
||||
|
||||
@@ -63,18 +63,21 @@ class ProxyObjectManager(ClientObjectManager):
|
||||
cache_dir=self._region.session().cache_dir,
|
||||
)
|
||||
|
||||
def request_missed_cached_objects_soon(self):
|
||||
def request_missed_cached_objects_soon(self, report_only=False):
|
||||
if self._cache_miss_timer:
|
||||
self._cache_miss_timer.cancel()
|
||||
# Basically debounce. Will only trigger 0.2 seconds after the last time it's invoked to
|
||||
# deal with the initial flood of ObjectUpdateCached and the natural lag time between that
|
||||
# and the viewers' RequestMultipleObjects messages
|
||||
self._cache_miss_timer = asyncio.get_event_loop().call_later(
|
||||
0.2, self._request_missed_cached_objects)
|
||||
loop = asyncio.get_event_loop_policy().get_event_loop()
|
||||
self._cache_miss_timer = loop.call_later(0.2, self._request_missed_cached_objects, report_only)
|
||||
|
||||
def _request_missed_cached_objects(self):
|
||||
def _request_missed_cached_objects(self, report_only: bool):
|
||||
self._cache_miss_timer = None
|
||||
self.request_objects(self.queued_cache_misses)
|
||||
if report_only:
|
||||
print(f"Would have automatically requested {self.queued_cache_misses!r}")
|
||||
else:
|
||||
self.request_objects(self.queued_cache_misses)
|
||||
self.queued_cache_misses.clear()
|
||||
|
||||
def clear(self):
|
||||
@@ -111,8 +114,11 @@ class ProxyWorldObjectManager(ClientWorldObjectManager):
|
||||
|
||||
def _handle_object_update_cached_misses(self, region_handle: int, missing_locals: Set[int]):
|
||||
if not self._settings.ALLOW_AUTO_REQUEST_OBJECTS:
|
||||
return
|
||||
if self._settings.AUTOMATICALLY_REQUEST_MISSING_OBJECTS:
|
||||
if self._settings.USE_VIEWER_OBJECT_CACHE:
|
||||
region_mgr: Optional[ProxyObjectManager] = self._get_region_manager(region_handle)
|
||||
region_mgr.queued_cache_misses |= missing_locals
|
||||
region_mgr.request_missed_cached_objects_soon(report_only=True)
|
||||
elif self._settings.AUTOMATICALLY_REQUEST_MISSING_OBJECTS:
|
||||
# Schedule these local IDs to be requested soon if the viewer doesn't request
|
||||
# them itself. Ideally we could just mutate the CRC of the ObjectUpdateCached
|
||||
# to force a CRC cache miss in the viewer, but that appears to cause the viewer
|
||||
|
||||
@@ -418,13 +418,13 @@ class RegionObjectManagerTests(ObjectManagerTestMixin, unittest.IsolatedAsyncioT
|
||||
'AngularVelocity': Vector3(0.0, 0.0, 0.0791015625),
|
||||
'TreeSpecies': None,
|
||||
'ScratchPad': None,
|
||||
'Text': None,
|
||||
'TextColor': None,
|
||||
'MediaURL': None,
|
||||
'Sound': None,
|
||||
'SoundGain': None,
|
||||
'SoundFlags': None,
|
||||
'SoundRadius': None,
|
||||
'Text': b'',
|
||||
'TextColor': b'',
|
||||
'MediaURL': b'',
|
||||
'Sound': UUID(),
|
||||
'SoundGain': 0.0,
|
||||
'SoundFlags': 0,
|
||||
'SoundRadius': 0.0,
|
||||
'NameValue': [],
|
||||
'PathCurve': 32,
|
||||
'ProfileCurve': 0,
|
||||
|
||||
Reference in New Issue
Block a user