///<summary> /// This method is called if a given model avatar name can not be found. If the external /// file has already been loaded once, then control returns immediately. If not, then it /// looks for a default appearance file. This file contains XML definitions of zero or more named /// avatars, each avatar can specify zero or more "outfits". Each outfit is a collection /// of items that together, define a particular ensemble for the avatar. Each avatar should /// indicate which outfit is the default, and this outfit will be automatically worn. The /// other outfits are provided to allow "real" avatars a way to easily change their outfits. /// </summary> private bool createDefaultAvatars() { // Only load once if (daload) { return false; } m_log.DebugFormat("[RADMIN] Creating default avatar entries"); daload = true; // Load processing starts here... try { string dafn = null; //m_config may be null if RemoteAdmin configuration secition is missing or disabled in OpenSim.ini if (m_config != null) { dafn = m_config.GetString("default_appearance", "default_appearance.xml"); } if (File.Exists(dafn)) { XmlDocument doc = new XmlDocument(); string name = "*unknown*"; string email = "anon@anon"; uint regX = 1000; uint regY = 1000; string passwd = UUID.Random().ToString(); // No requirement to sign-in. CachedUserInfo UI; UUID ID = UUID.Zero; AvatarAppearance mava; XmlNodeList avatars; XmlNodeList assets; XmlNode perms = null; bool include = false; bool select = false; UICallback uic; IInventoryService iserv = m_app.SceneManager.CurrentOrFirstScene.InventoryService; IAssetService aserv = m_app.SceneManager.CurrentOrFirstScene.AssetService; doc.LoadXml(File.ReadAllText(dafn)); // Load up any included assets. Duplicates will be ignored assets = doc.GetElementsByTagName("RequiredAsset"); foreach (XmlNode asset in assets) { AssetBase rass = new AssetBase(); rass.FullID = UUID.Random(); rass.Name = GetStringAttribute(asset,"name",""); rass.Description = GetStringAttribute(asset,"desc",""); rass.Type = SByte.Parse(GetStringAttribute(asset,"type","")); rass.Local = Boolean.Parse(GetStringAttribute(asset,"local","")); rass.Temporary = Boolean.Parse(GetStringAttribute(asset,"temporary","")); rass.Data = Convert.FromBase64String(asset.InnerText); aserv.Store(rass); } avatars = doc.GetElementsByTagName("Avatar"); // The document may contain multiple avatars foreach (XmlElement avatar in avatars) { m_log.DebugFormat("[RADMIN] Loading appearance for {0}, gender = {1}", GetStringAttribute(avatar,"name","?"), GetStringAttribute(avatar,"gender","?")); // Create the user identified by the avatar entry try { // Only the name value is mandatory name = GetStringAttribute(avatar,"name",name); email = GetStringAttribute(avatar,"email",email); regX = GetUnsignedAttribute(avatar,"regx",regX); regY = GetUnsignedAttribute(avatar,"regy",regY); passwd = GetStringAttribute(avatar,"password",passwd); string[] nomens = name.Split(); UI = m_app.CommunicationsManager.UserProfileCacheService.GetUserDetails(nomens[0], nomens[1]); if (null == UI) { ID = m_app.CommunicationsManager.UserAdminService.AddUser(nomens[0], nomens[1], passwd, email, regX, regY); if (ID == UUID.Zero) { m_log.ErrorFormat("[RADMIN] Avatar {0} {1} was not created", nomens[0], nomens[1]); return false; } } else { ID = UI.UserProfile.ID; } m_log.DebugFormat("[RADMIN] User {0}[{1}] created or retrieved", name, ID); include = true; } catch (Exception e) { m_log.DebugFormat("[RADMIN] Error creating user {0} : {1}", name, e.Message); include = false; } // OK, User has been created OK, now we can install the inventory. // First retrieve the current inventory (the user may already exist) // Note that althought he inventory is retrieved, the hierarchy has // not been interpreted at all. if (include) { uic = new UICallback(); // Request the inventory iserv.GetUserInventory(ID, uic.callback); // While the inventory is being fetched, setup for appearance processing if ((mava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(ID)) == null) { mava = new AvatarAppearance(); } { AvatarWearable[] wearables = mava.Wearables; for (int i=0; i<wearables.Length; i++) { wearables[i] = new AvatarWearable(); } } // Wait for the inventory to arrive uic.GetInventory(); // We can only get dresssed if an inventory is forthcoming if (uic.OK) try { m_log.DebugFormat("[RADMIN] {0} folders, {1} items in inventory", uic.folders.Count, uic.items.Count); InventoryFolderImpl cfolder = uic.root.FindFolderForType(5); // This should *never* be the case if (cfolder == null) { cfolder = new InventoryFolderImpl(); cfolder.Name = "Clothing"; cfolder.Type = 5; cfolder.Version = 1; cfolder.Owner = ID; uic.root.AddChildFolder(cfolder); // make connection iserv.AddFolder(cfolder); // store base record m_log.ErrorFormat("[RADMIN] Created clothing folder for {0}/{1}", name, ID); } // OK, now we have an inventory for the user, read in the outfits from the // default appearance XMl file. XmlNodeList outfits = avatar.GetElementsByTagName("Ensemble"); InventoryFolderImpl efolder; string oname; UUID assetid; foreach (XmlElement outfit in outfits) { m_log.DebugFormat("[RADMIN] Loading outfit {0} for {1}", GetStringAttribute(outfit,"name","?"), GetStringAttribute(avatar,"name","?")); oname = GetStringAttribute(outfit,"name",""); select = (GetStringAttribute(outfit,"default","no") == "yes"); efolder = null; // If the folder already exists, re-use it. The defaults may // change over time. Augment only. foreach (InventoryFolderImpl folder in uic.folders) { if (folder.Name == oname && folder.ParentID == cfolder.ID) { efolder = folder; break; } } // Otherwise, we must create the folder. if (efolder == null) { m_log.DebugFormat("[RADMIN] Creating outfit folder {0} for {1}", oname, name); efolder = new InventoryFolderImpl(); efolder.ID = UUID.Random(); efolder.Name = oname; efolder.Type = 5; efolder.Version = 1; efolder.Owner = ID; cfolder.AddChildFolder(efolder); // make connection iserv.AddFolder(efolder); // store base record m_log.DebugFormat("[RADMIN] Adding outfile folder {0} to folder {1}", efolder.ID, cfolder.ID); } // Now get the pieces that make up the outfit XmlNodeList items = outfit.GetElementsByTagName("Item"); foreach (XmlElement item in items) { assetid = UUID.Zero; XmlNodeList children = item.ChildNodes; foreach (XmlNode child in children) { switch (child.Name) { case "Permissions" : m_log.DebugFormat("[RADMIN] Permissions specified"); perms = child; break; case "Asset" : assetid = new UUID(child.InnerText); break; } } InventoryItemBase iitem = null; if ((iitem = efolder.FindAsset(assetid)) == null) { iitem = new InventoryItemBase(); iitem.ID = UUID.Random(); iitem.Name = GetStringAttribute(item,"name",""); iitem.Description = GetStringAttribute(item,"desc",""); iitem.InvType = GetIntegerAttribute(item,"invtype",-1); iitem.AssetType = GetIntegerAttribute(item,"assettype",-1); iitem.Flags = GetUnsignedAttribute(item,"flags",0); iitem.AssetID = assetid; // associated asset iitem.Folder = efolder.ID; // Parent folder iitem.Owner = ID; // Agent ID iitem.BasePermissions = GetUnsignedAttribute(perms,"base",0x7fffffff); iitem.NextPermissions = GetUnsignedAttribute(perms,"next",0x7fffffff); iitem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff); iitem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff); iitem.EveryOnePermissions = GetUnsignedAttribute(perms,"everyone",0x7fffffff); m_log.DebugFormat("[RADMIN] Adding item {0} to folder {1}", iitem.ID, efolder.ID); iserv.AddItem(iitem); } // Record whether or not the item is to be initially worn try { if (select && (GetStringAttribute(item, "wear", "false") == "true")) { mava.Wearables[iitem.Flags].ItemID = iitem.ID; mava.Wearables[iitem.Flags].AssetID = iitem.AssetID; } } catch {} } // foreach item in outfit m_log.DebugFormat("[RADMIN] Outfit {0} load completed", oname); } // foreach outfit m_log.DebugFormat("[RADMIN] Inventory update complete for {0}", name); m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(ID, mava); } catch (Exception e) { m_log.WarnFormat("[RADMIN] Inventory processing incomplete for user {0} : {1}", name, e.Message); } else { m_log.WarnFormat("[RADMIN] Unable to retrieve inventory for {0}[{1}]", name, ID); // continue to next avatar } } // End of include } m_log.DebugFormat("[RADMIN] Default avatar loading complete"); } else { m_log.DebugFormat("[RADMIN] No default avatar information available"); return false; } } catch (Exception e) { m_log.WarnFormat("[RADMIN] Exception whilst loading default avatars ; {0}", e.Message); return false; } return true; }
/// <summary> /// This method is called by updateAvatarAppearance once any specified model has been /// ratified, or an appropriate default value has been adopted. The intended prototype /// is known to exist, as is the target avatar. /// </summary> private void establishAppearance(UUID dest, UUID srca) { m_log.DebugFormat("[RADMIN] Initializing inventory for {0} from {1}", dest, srca); AvatarAppearance ava = m_app.CommunicationsManager.AvatarService.GetUserAppearance(srca); // If the model has no associated appearance we're done. // if (ava == null) // { // return new AvatarAppearance(); // } if (ava == null) return; UICallback sic = new UICallback(); UICallback dic = new UICallback(); IInventoryService iserv = m_app.SceneManager.CurrentOrFirstScene.InventoryService; try { Dictionary<UUID,UUID> imap = new Dictionary<UUID,UUID>(); iserv.GetUserInventory(dest, dic.callback); iserv.GetUserInventory(srca, sic.callback); dic.GetInventory(); sic.GetInventory(); if (sic.OK && dic.OK) { InventoryFolderImpl efolder; InventoryFolderImpl srcf = sic.root.FindFolderForType(5); InventoryFolderImpl dstf = dic.root.FindFolderForType(5); if (srcf == null || dstf == null) throw new Exception("Cannot locate clothing folder(s)"); foreach (InventoryFolderImpl folder in sic.folders) { if (folder.ParentID == srcf.ID) { efolder = new InventoryFolderImpl(); efolder.ID = UUID.Random(); efolder.Name = folder.Name; efolder.Type = folder.Type; efolder.Version = folder.Version; efolder.Owner = dest; dstf.AddChildFolder(efolder); iserv.AddFolder(efolder); m_log.DebugFormat("[RADMIN] Added outfile folder {0} to folder {1}", efolder.ID, srcf.ID); foreach (InventoryItemBase item in sic.items) { if (item.Folder == folder.ID) { InventoryItemBase dsti = new InventoryItemBase(); dsti.ID = UUID.Random(); dsti.Name = item.Name; dsti.Description = item.Description; dsti.InvType = item.InvType; dsti.AssetType = item.AssetType; dsti.Flags = item.Flags; dsti.AssetID = item.AssetID; dsti.Folder = efolder.ID; dsti.Owner = dest; dsti.BasePermissions = item.BasePermissions; dsti.NextPermissions = item.NextPermissions; dsti.CurrentPermissions = item.CurrentPermissions; dsti.GroupPermissions = item.GroupPermissions; dsti.EveryOnePermissions = item.EveryOnePermissions; iserv.AddItem(dsti); imap.Add(item.ID, dsti.ID); m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", dsti.ID, efolder.ID); } } } } // Update appearance tables AvatarWearable[] wearables = ava.Wearables; for (int i=0; i<wearables.Length; i++) { if (imap.ContainsKey(wearables[i].ItemID)) { AvatarWearable dw = new AvatarWearable(); dw.AssetID = wearables[i].AssetID; dw.ItemID = imap[wearables[i].ItemID]; ava.SetWearable(i, dw); } } } else { throw new Exception("Unable to load both inventories"); } m_app.CommunicationsManager.AvatarService.UpdateUserAppearance(dest, ava); } catch (Exception e) { m_log.WarnFormat("[RADMIN] Error transferring inventory for {0} : {1}", dest, e.Message); return; } return; }