<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FCode_Map%2FAvatarFactoryModule</id>
	<title>OpenSimulator Internals/Code Map/AvatarFactoryModule - Revision history</title>
	<link rel="self" type="application/atom+xml" href="http://osimdev.org/wiki/index.php?action=history&amp;feed=atom&amp;title=OpenSimulator_Internals%2FCode_Map%2FAvatarFactoryModule"/>
	<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/AvatarFactoryModule&amp;action=history"/>
	<updated>2026-08-04T15:27:52Z</updated>
	<subtitle>Revision history for this page on the wiki</subtitle>
	<generator>MediaWiki 1.45.3</generator>
	<entry>
		<id>http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/AvatarFactoryModule&amp;diff=91&amp;oldid=prev</id>
		<title>Jwbshaw: first</title>
		<link rel="alternate" type="text/html" href="http://osimdev.org/wiki/index.php?title=OpenSimulator_Internals/Code_Map/AvatarFactoryModule&amp;diff=91&amp;oldid=prev"/>
		<updated>2026-07-07T13:18:13Z</updated>

		<summary type="html">&lt;p&gt;first&lt;/p&gt;
&lt;p&gt;&lt;b&gt;New page&lt;/b&gt;&lt;/p&gt;&lt;div&gt;= OpenSimulator Internals/Code Map/AvatarFactoryModule =&lt;br /&gt;
&lt;br /&gt;
== Overview ==&lt;br /&gt;
&lt;br /&gt;
 OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs&lt;br /&gt;
&lt;br /&gt;
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.&lt;br /&gt;
&lt;br /&gt;
Registered as IAvatarFactoryModule. Accessed by other modules via m_scene.AvatarFactory.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Configuration ==&lt;br /&gt;
&lt;br /&gt;
 [Appearance] section in OpenSim.ini&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Key !! Default !! Purpose&lt;br /&gt;
|-&lt;br /&gt;
| DelayBeforeAppearanceSave || 5s || How long to wait after a change before saving to AvatarService&lt;br /&gt;
|-&lt;br /&gt;
| DelayBeforeAppearanceSend || 2s || How long to wait after a change before sending to other clients&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
Timer fires every 500ms (m_checkTime) to drain the send and save queues.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Event Wiring ==&lt;br /&gt;
&lt;br /&gt;
SubscribeToClientEvents() hooks per client:&lt;br /&gt;
&lt;br /&gt;
{| class=&amp;quot;wikitable&amp;quot;&lt;br /&gt;
! Event !! Handler&lt;br /&gt;
|-&lt;br /&gt;
| OnRequestWearables || Client_OnRequestWearables()&lt;br /&gt;
|-&lt;br /&gt;
| OnSetAppearance || Client_OnSetAppearance()&lt;br /&gt;
|-&lt;br /&gt;
| OnAvatarNowWearing || Client_OnAvatarNowWearing()&lt;br /&gt;
|}&lt;br /&gt;
&lt;br /&gt;
OnCachedTextureRequest is commented out.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== SetAppearance() ==&lt;br /&gt;
&lt;br /&gt;
Main entry point for appearance changes. Called from Client_OnSetAppearance() and from other modules.&lt;br /&gt;
&lt;br /&gt;
# Acquires m_setAppearanceLock (serialises concurrent updates).&lt;br /&gt;
# Calls sp.Appearance.SetVisualParams() if visualParams provided -- updates slider values, may change height.&lt;br /&gt;
# Calls sp.Appearance.SetTextureEntries() if textureEntry provided -- updates baked texture UUIDs.&lt;br /&gt;
# Calls UpdateBakedTextureCache() -- validates and stores baked textures in local asset cache and IBakedTextureModule.&lt;br /&gt;
# For NPCs: calls SendAppearance() immediately and returns.&lt;br /&gt;
# If appearance changed: calls QueueAppearanceSave().&lt;br /&gt;
# Always calls QueueAppearanceSend().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== UpdateBakedTextureCache() ==&lt;br /&gt;
&lt;br /&gt;
Called on each texture update from viewer.&lt;br /&gt;
&lt;br /&gt;
# Iterates cacheItems from viewer -- each maps a BakeType index to a CacheId and TextureID.&lt;br /&gt;
# For each entry: checks local IAssetCache for the baked texture asset.&lt;br /&gt;
# If found: updates WearableCacheItems[idx] with new TextureID and CacheId. Counts as a hit.&lt;br /&gt;
# If not found: sends SendRebakeAvatarTextures() to viewer for the missing texture. Throttled via ExpiringKey -- one rebake request per texture per 30 seconds.&lt;br /&gt;
# Clears PBR bake indices (&amp;gt;= BAKES_COUNT_PV7) that were not in the update set.&lt;br /&gt;
# If all items hit and validDirtyBakes &amp;gt; 0: stores full set to IBakedTextureModule (bake server).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== ValidateBakedTextureCache() ==&lt;br /&gt;
&lt;br /&gt;
Called from CompleteMovement() on new root agent arrival (non-HG). Returns true if cache is valid.&lt;br /&gt;
&lt;br /&gt;
# NPCs always return true.&lt;br /&gt;
# Checks each bake index: if WearableCacheItems matches face texture and asset is in local cache: hit.&lt;br /&gt;
# If local cache invalid and IBakedTextureModule available: fetches from bake server, populates local cache and WearableCacheItems.&lt;br /&gt;
# Returns true if hits &amp;gt;= BAKE_INDICES.Length (skirt index 19 is optional).&lt;br /&gt;
&lt;br /&gt;
If ValidateBakedTextureCache returns false: CompleteMovement() calls QueueAppearanceSave() to trigger a rebake cycle.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Queue / Timer Mechanism ==&lt;br /&gt;
&lt;br /&gt;
QueueAppearanceSend(agentId):&lt;br /&gt;
* Adds agentId to m_sendqueue with timestamp = now + m_sendtime.&lt;br /&gt;
* Starts m_updateTimer.&lt;br /&gt;
&lt;br /&gt;
QueueAppearanceSave(agentId):&lt;br /&gt;
* Adds agentId to m_savequeue with timestamp = now + m_savetime.&lt;br /&gt;
* Starts m_updateTimer.&lt;br /&gt;
&lt;br /&gt;
HandleAppearanceUpdateTimer() (fires every 500ms):&lt;br /&gt;
* Drains m_sendqueue: for each expired entry calls SendAppearance(agentId) -- sp.SendAppearanceToAllOtherAgents() + Animator.SendAnimPack().&lt;br /&gt;
* Drains m_savequeue: batches expired entries, runs SaveAppearance() on thread pool.&lt;br /&gt;
* Stops timer when both queues empty.&lt;br /&gt;
&lt;br /&gt;
SaveAppearance():&lt;br /&gt;
* Calls SetAppearanceAssets() -- resolves each wearable ItemID to AssetID via InventoryService.GetItem().&lt;br /&gt;
* Calls m_scene.AvatarService.SetAppearance() -- writes to ROBUST AvatarService → avatarappearance table.&lt;br /&gt;
&lt;br /&gt;
; DB writes (async, via SaveAppearance):&lt;br /&gt;
* avatarappearance -- UPDATE: full appearance for avatar UUID&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Client_OnAvatarNowWearing() ==&lt;br /&gt;
&lt;br /&gt;
Triggered when viewer sends AvatarIsWearing packet (outfit change initiated).&lt;br /&gt;
&lt;br /&gt;
# Makes a copy of current AvatarAppearance (no lock needed on copy).&lt;br /&gt;
# Updates Wearables array from the wearing list -- sets ItemID, AssetID initially UUID.Zero.&lt;br /&gt;
# Calls avatAppearance.GetAssetsFrom(sp.Appearance) -- copies known asset IDs from current appearance.&lt;br /&gt;
# Under m_setAppearanceLock: updates sp.Appearance.Wearables only (does not overwrite textures or visual params).&lt;br /&gt;
# Calls QueueAppearanceSave() -- schedules async inventory lookup and save.&lt;br /&gt;
&lt;br /&gt;
Note: Does NOT call QueueAppearanceSend(). The viewer will follow with OnSetAppearance once baking is done; that triggers the send.&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== Client_OnRequestWearables() ==&lt;br /&gt;
&lt;br /&gt;
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).&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== SaveBakedTextures() ==&lt;br /&gt;
&lt;br /&gt;
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().&lt;br /&gt;
&lt;br /&gt;
----&lt;br /&gt;
&lt;br /&gt;
== See Also ==&lt;br /&gt;
&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ScenePresence]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/AttachmentsModule]]&lt;br /&gt;
* [[OpenSimulator Internals/Code Map/ROBUST/AvatarService]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Rez In Region]]&lt;br /&gt;
* [[OpenSimulator Internals/Walkthroughs/Avatar Change Outfit]]&lt;/div&gt;</summary>
		<author><name>Jwbshaw</name></author>
	</entry>
</feed>