Jump to content

OpenSimulator Internals/Code Map/ROBUST/AvatarService

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

OpenSimulator Internals/Code Map/ROBUST/AvatarService

[edit]

Overview

[edit]

AvatarService stores and retrieves avatar appearance data. It is a thin layer over a key-value database table -- all appearance state is stored as named string pairs keyed by PrincipalID.

Source files:

OpenSim/Services/AvatarService/AvatarService.cs
OpenSim/Services/AvatarService/AvatarServiceBase.cs

Constructor and Config Loading

[edit]
AvatarServiceBase(IConfigSource config)

Config is read in two layers; [AvatarService] overrides [DatabaseService]:

Section Key Default Notes
[DatabaseService] StorageProvider (none) DLL name -- fallback
[DatabaseService] ConnectionString (none) DB connection string -- fallback
[AvatarService] StorageProvider (inherited) Overrides [DatabaseService]
[AvatarService] ConnectionString (inherited) Overrides [DatabaseService]
[AvatarService] Realm Avatars Table name

Throws if StorageProvider is empty or if the plugin cannot be loaded.

The loaded plugin is stored as m_Database (IAvatarData).


Data Model

[edit]

Avatar data is stored as a flat key-value table. Each row has:

  • PrincipalID -- avatar UUID
  • Name -- attribute name (e.g. "AvatarType", "AvatarHeight", attachment slot names)
  • Value -- string value

AvatarType is stored as a separate named row, not in the Data dictionary. Value 1 = SL-style avatar.

Attachment slots are stored with names prefixed by underscore ("_").

AvatarData.ToAvatarAppearance() and AvatarData(AvatarAppearance) handle conversion between the flat key-value representation and the structured AvatarAppearance object. Those conversions are in OpenSim/Framework/, not in this service.


GetAvatar

[edit]
public AvatarData GetAvatar(UUID principalID)
  1. Queries m_Database.Get("PrincipalID", principalID.ToString()) -- returns all rows for this avatar
  2. If no rows found: returns AvatarData with AvatarType = 1 (SL avatar), empty Data dictionary
  3. Iterates rows:
    • Row with Name == "AvatarType" sets ret.AvatarType
    • All other rows go into ret.Data[Name] = Value
  4. Returns populated AvatarData

GetAppearance() calls GetAvatar() then calls avatar.ToAvatarAppearance() on the result.


SetAvatar

[edit]
public bool SetAvatar(UUID principalID, AvatarData avatar)

Write is delete-then-reinsert -- no partial update:

  1. Deletes all existing rows for principalID
  2. Stores the AvatarType row first
  3. Iterates avatar.Data:
    • Special case: AvatarHeight -- validates as float in range [0, 10]
      • Attempts locale-insensitive parse (replaces comma with period)
      • If unparseable or out of range: silently substitutes 1.771488f
      • Comment in source notes this was a hack added 2011-07-30 to cope with bad values injected by buggy simulators on OSGrid. Comment suggests removal after six months -- it is still present.
    • All other keys stored as-is
    • On any Store() failure: deletes all rows for principalID and returns false
  4. Returns true if all rows stored successfully

SetAppearance() constructs AvatarData from an AvatarAppearance object, then calls SetAvatar().


ResetAvatar

[edit]
public bool ResetAvatar(UUID principalID)

Deletes all rows for principalID. Returns the result of m_Database.Delete().


SetItems

[edit]
public bool SetItems(UUID principalID, string[] names, string[] values)

Stores a parallel array of name/value pairs for principalID. Returns false if arrays are different lengths. Stores each pair individually; stops and returns false on first Store() failure. Does not delete existing rows first -- this is a partial update, unlike SetAvatar().


RemoveItems

[edit]
public bool RemoveItems(UUID principalID, string[] names)

Deletes individual named rows for principalID. Iterates names and calls m_Database.Delete(principalID, name) for each. Always returns true regardless of individual delete results.


Notes

[edit]
  • The AvatarHeight sanitization hack (justified 2011-07-30) is still present and active. The original comment estimated it could be removed after six months.
  • SetAvatar() and SetItems() have different write semantics: SetAvatar() is a full replace (delete-all, reinsert); SetItems() is upsert (no prior delete).
  • RemoveItems() always returns true -- individual delete failures are silently ignored.
  • There are no console commands registered by this service.

See Also

[edit]