Jump to content

OpenSimulator Internals/Code Map/AvatarFactoryModule

From Open Simulator Technical Help
Revision as of 13:18, 7 July 2026 by Jwbshaw (talk | contribs) (first)
(diff) ← Older revision | Latest revision (diff) | Newer revision → (diff)

OpenSimulator Internals/Code Map/AvatarFactoryModule

[edit]

Overview

[edit]
OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs

INonSharedRegionModule. Manages avatar appearance: receives baked texture updates from the viewer, validates the baked texture cache on login, queues appearance saves to AvatarService, and sends appearance to other clients. One instance per region.

Registered as IAvatarFactoryModule. Accessed by other modules via m_scene.AvatarFactory.


Configuration

[edit]
[Appearance] section in OpenSim.ini
Key Default Purpose
DelayBeforeAppearanceSave 5s How long to wait after a change before saving to AvatarService
DelayBeforeAppearanceSend 2s How long to wait after a change before sending to other clients

Timer fires every 500ms (m_checkTime) to drain the send and save queues.


Event Wiring

[edit]

SubscribeToClientEvents() hooks per client:

Event Handler
OnRequestWearables Client_OnRequestWearables()
OnSetAppearance Client_OnSetAppearance()
OnAvatarNowWearing Client_OnAvatarNowWearing()

OnCachedTextureRequest is commented out.


SetAppearance()

[edit]

Main entry point for appearance changes. Called from Client_OnSetAppearance() and from other modules.

  1. Acquires m_setAppearanceLock (serialises concurrent updates).
  2. Calls sp.Appearance.SetVisualParams() if visualParams provided -- updates slider values, may change height.
  3. Calls sp.Appearance.SetTextureEntries() if textureEntry provided -- updates baked texture UUIDs.
  4. Calls UpdateBakedTextureCache() -- validates and stores baked textures in local asset cache and IBakedTextureModule.
  5. For NPCs: calls SendAppearance() immediately and returns.
  6. If appearance changed: calls QueueAppearanceSave().
  7. Always calls QueueAppearanceSend().

UpdateBakedTextureCache()

[edit]

Called on each texture update from viewer.

  1. Iterates cacheItems from viewer -- each maps a BakeType index to a CacheId and TextureID.
  2. For each entry: checks local IAssetCache for the baked texture asset.
  3. If found: updates WearableCacheItems[idx] with new TextureID and CacheId. Counts as a hit.
  4. If not found: sends SendRebakeAvatarTextures() to viewer for the missing texture. Throttled via ExpiringKey -- one rebake request per texture per 30 seconds.
  5. Clears PBR bake indices (>= BAKES_COUNT_PV7) that were not in the update set.
  6. If all items hit and validDirtyBakes > 0: stores full set to IBakedTextureModule (bake server).

ValidateBakedTextureCache()

[edit]

Called from CompleteMovement() on new root agent arrival (non-HG). Returns true if cache is valid.

  1. NPCs always return true.
  2. Checks each bake index: if WearableCacheItems matches face texture and asset is in local cache: hit.
  3. If local cache invalid and IBakedTextureModule available: fetches from bake server, populates local cache and WearableCacheItems.
  4. Returns true if hits >= BAKE_INDICES.Length (skirt index 19 is optional).

If ValidateBakedTextureCache returns false: CompleteMovement() calls QueueAppearanceSave() to trigger a rebake cycle.


Queue / Timer Mechanism

[edit]

QueueAppearanceSend(agentId):

  • Adds agentId to m_sendqueue with timestamp = now + m_sendtime.
  • Starts m_updateTimer.

QueueAppearanceSave(agentId):

  • Adds agentId to m_savequeue with timestamp = now + m_savetime.
  • Starts m_updateTimer.

HandleAppearanceUpdateTimer() (fires every 500ms):

  • Drains m_sendqueue: for each expired entry calls SendAppearance(agentId) -- sp.SendAppearanceToAllOtherAgents() + Animator.SendAnimPack().
  • Drains m_savequeue: batches expired entries, runs SaveAppearance() on thread pool.
  • Stops timer when both queues empty.

SaveAppearance():

  • Calls SetAppearanceAssets() -- resolves each wearable ItemID to AssetID via InventoryService.GetItem().
  • Calls m_scene.AvatarService.SetAppearance() -- writes to ROBUST AvatarService → avatarappearance table.
DB writes (async, via SaveAppearance)
  • avatarappearance -- UPDATE: full appearance for avatar UUID

Client_OnAvatarNowWearing()

[edit]

Triggered when viewer sends AvatarIsWearing packet (outfit change initiated).

  1. Makes a copy of current AvatarAppearance (no lock needed on copy).
  2. Updates Wearables array from the wearing list -- sets ItemID, AssetID initially UUID.Zero.
  3. Calls avatAppearance.GetAssetsFrom(sp.Appearance) -- copies known asset IDs from current appearance.
  4. Under m_setAppearanceLock: updates sp.Appearance.Wearables only (does not overwrite textures or visual params).
  5. Calls QueueAppearanceSave() -- schedules async inventory lookup and save.

Note: Does NOT call QueueAppearanceSend(). The viewer will follow with OnSetAppearance once baking is done; that triggers the send.


Client_OnRequestWearables()

[edit]

Viewer requests wearable list (e.g. on login or reconnect). Fires async with a 4-second sleep before sending. Calls client.SendWearables(sp.Appearance.Wearables, sp.Appearance.Serial).


SaveBakedTextures()

[edit]

Saves baked textures from local asset cache to permanent AssetService storage. Used for NPCs. Marks assets as non-local, non-temporary, stores via m_scene.AssetService.Store().


See Also

[edit]