OpenSimulator Internals/Code Map/ROBUST/AvatarService
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)
- Queries m_Database.Get("PrincipalID", principalID.ToString()) -- returns all rows for this avatar
- If no rows found: returns AvatarData with AvatarType = 1 (SL avatar), empty Data dictionary
- Iterates rows:
- Row with Name == "AvatarType" sets ret.AvatarType
- All other rows go into ret.Data[Name] = Value
- 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:
- Deletes all existing rows for principalID
- Stores the AvatarType row first
- 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
- Special case: AvatarHeight -- validates as float in range [0, 10]
- 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.