diff --git a/CONTRIBUTORS.txt b/CONTRIBUTORS.txt index 9aadd70927..24432446c8 100644 --- a/CONTRIBUTORS.txt +++ b/CONTRIBUTORS.txt @@ -95,6 +95,7 @@ what it is today. * Mic Bowman * Michelle Argus * Michael Cortez (The Flotsam Project, http://osflotsam.org/) +* Micheil Merlin * Mike Osias (IBM) * Mike Pitman (IBM) * mikkopa/_someone - RealXtend diff --git a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs index 7ebb5de6dd..e57aaa08f7 100644 --- a/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs +++ b/OpenSim/ApplicationPlugins/RemoteController/RemoteAdminPlugin.cs @@ -998,6 +998,7 @@ namespace OpenSim.ApplicationPlugins.RemoteController string firstname = (string) requestData["user_firstname"]; string lastname = (string) requestData["user_lastname"]; string passwd = (string) requestData["user_password"]; + uint regX = Convert.ToUInt32((Int32) requestData["start_region_x"]); uint regY = Convert.ToUInt32((Int32) requestData["start_region_y"]); @@ -1005,28 +1006,25 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (requestData.Contains("user_email")) email = (string)requestData["user_email"]; - UUID scopeID = m_app.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + UUID scopeID = scene.RegionInfo.ScopeID; - UserAccount account = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, firstname, lastname); + UserAccount account = CreateUser(scopeID, firstname, lastname, passwd, email); - if (null != account) - throw new Exception(String.Format("Account {0} {1} already exists", firstname, lastname)); - - account = new UserAccount(scopeID, firstname, lastname, email); - - bool success = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.StoreUserAccount(account); - - if (!success) + if (null == account) throw new Exception(String.Format("failed to create new user {0} {1}", firstname, lastname)); - // Store the password - m_app.SceneManager.CurrentOrFirstScene.AuthenticationService.SetPassword(account.PrincipalID, passwd); + // Set home position - GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, + GridRegion home = scene.GridService.GetRegionByPosition(scopeID, (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); - if (home == null) + if (null == home) { m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", firstname, lastname); + } else { + scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, firstname, lastname); + } // Establish the avatar's initial appearance @@ -1169,9 +1167,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// start_region_y /// avatar's start region coordinates, Y /// value (changeable) - /// about_real_world + /// about_real_world (not implemented yet) /// "about" text of avatar owner (changeable) - /// about_virtual_world + /// about_virtual_world (not implemented yet) /// "about" text of avatar (changeable) /// /// @@ -1182,6 +1180,10 @@ namespace OpenSim.ApplicationPlugins.RemoteController /// true or false /// error /// error message if success is false + /// avatar_uuid + /// UUID of the updated avatar + /// account; UUID.Zero if failed. + /// /// /// @@ -1189,31 +1191,34 @@ namespace OpenSim.ApplicationPlugins.RemoteController { m_log.Info("[RADMIN]: UpdateUserAccount: new request"); m_log.Warn("[RADMIN]: This method needs update for 0.7"); + + FailIfRemoteAdminDisabled("UpdateUserAccount"); + XmlRpcResponse response = new XmlRpcResponse(); Hashtable responseData = new Hashtable(); - //lock (rslock) - //{ - // try - // { - // Hashtable requestData = (Hashtable) request.Params[0]; + lock (rslock) + { + try + { + Hashtable requestData = (Hashtable) request.Params[0]; - // // check completeness - // checkStringParameters(request, new string[] { - // "password", "user_firstname", - // "user_lastname"}); + // check completeness + checkStringParameters(request, new string[] { + "password", "user_firstname", + "user_lastname"}); - // // check password - // if (!String.IsNullOrEmpty(m_requiredPassword) && - // (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); + // check password + if (!String.IsNullOrEmpty(m_requiredPassword) && + (string) requestData["password"] != m_requiredPassword) throw new Exception("wrong password"); - // // do the job - // string firstname = (string) requestData["user_firstname"]; - // string lastname = (string) requestData["user_lastname"]; + // do the job + string firstname = (string) requestData["user_firstname"]; + string lastname = (string) requestData["user_lastname"]; - // string passwd = String.Empty; - // uint? regX = null; - // uint? regY = null; + string passwd = String.Empty; + uint? regX = null; + uint? regY = null; // uint? ulaX = null; // uint? ulaY = null; // uint? ulaZ = null; @@ -1223,11 +1228,11 @@ namespace OpenSim.ApplicationPlugins.RemoteController // string aboutFirstLive = String.Empty; // string aboutAvatar = String.Empty; - // if (requestData.ContainsKey("user_password")) passwd = (string) requestData["user_password"]; - // if (requestData.ContainsKey("start_region_x")) - // regX = Convert.ToUInt32((Int32) requestData["start_region_x"]); - // if (requestData.ContainsKey("start_region_y")) - // regY = Convert.ToUInt32((Int32) requestData["start_region_y"]); + if (requestData.ContainsKey("user_password")) passwd = (string) requestData["user_password"]; + if (requestData.ContainsKey("start_region_x")) + regX = Convert.ToUInt32((Int32) requestData["start_region_x"]); + if (requestData.ContainsKey("start_region_y")) + regY = Convert.ToUInt32((Int32) requestData["start_region_y"]); // if (requestData.ContainsKey("start_lookat_x")) // ulaX = Convert.ToUInt32((Int32) requestData["start_lookat_x"]); @@ -1247,21 +1252,18 @@ namespace OpenSim.ApplicationPlugins.RemoteController // if (requestData.ContainsKey("about_virtual_world")) // aboutAvatar = (string)requestData["about_virtual_world"]; - // UserProfileData userProfile - // = m_app.CommunicationsManager.UserService.GetUserProfile(firstname, lastname); + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, firstname, lastname); - // if (null == userProfile) - // throw new Exception(String.Format("avatar {0} {1} does not exist", firstname, lastname)); + if (null == account) + throw new Exception(String.Format("avatar {0} {1} does not exist", firstname, lastname)); - // if (!String.IsNullOrEmpty(passwd)) - // { - // m_log.DebugFormat("[RADMIN]: UpdateUserAccount: updating password for avatar {0} {1}", firstname, lastname); - // string md5PasswdHash = Util.Md5Hash(Util.Md5Hash(passwd) + ":" + String.Empty); - // userProfile.PasswordHash = md5PasswdHash; - // } - - // if (null != regX) userProfile.HomeRegionX = (uint) regX; - // if (null != regY) userProfile.HomeRegionY = (uint) regY; + if (!String.IsNullOrEmpty(passwd)) + { + m_log.DebugFormat("[RADMIN]: UpdateUserAccount: updating password for avatar {0} {1}", firstname, lastname); + ChangeUserPassword(firstname, lastname, passwd); + } // if (null != usaX) userProfile.HomeLocationX = (uint) usaX; // if (null != usaY) userProfile.HomeLocationY = (uint) usaY; @@ -1274,35 +1276,48 @@ namespace OpenSim.ApplicationPlugins.RemoteController // if (String.Empty != aboutFirstLive) userProfile.FirstLifeAboutText = aboutFirstLive; // if (String.Empty != aboutAvatar) userProfile.AboutText = aboutAvatar; - // // User has been created. Now establish gender and appearance. + // Set home position - // updateUserAppearance(responseData, requestData, userProfile.ID); + if ((null != regX) && (null != regY)) + { + GridRegion home = scene.GridService.GetRegionByPosition(scopeID, + (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); + if (null == home) { + m_log.WarnFormat("[RADMIN]: Unable to set home region for updated user account {0} {1}", firstname, lastname); + } else { + scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, firstname, lastname); + } + } - // if (!m_app.CommunicationsManager.UserService.UpdateUserProfile(userProfile)) - // throw new Exception("did not manage to update user profile"); + // User has been created. Now establish gender and appearance. - // responseData["success"] = true; + updateUserAppearance(responseData, requestData, account.PrincipalID); - // response.Value = responseData; + responseData["success"] = true; + responseData["avatar_uuid"] = account.PrincipalID.ToString(); - // m_log.InfoFormat("[RADMIN]: UpdateUserAccount: account for user {0} {1} updated, UUID {2}", - // firstname, lastname, - // userProfile.ID); - // } - // catch (Exception e) - // { - // m_log.ErrorFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.Message); - // m_log.DebugFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.ToString()); + response.Value = responseData; - // responseData["success"] = false; - // responseData["error"] = e.Message; + m_log.InfoFormat("[RADMIN]: UpdateUserAccount: account for user {0} {1} updated, UUID {2}", + firstname, lastname, + account.PrincipalID); + } + catch (Exception e) + { - // response.Value = responseData; - // } - //} + m_log.ErrorFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.Message); + m_log.DebugFormat("[RADMIN] UpdateUserAccount: failed: {0}", e.ToString()); - m_log.Info("[RADMIN]: UpdateUserAccount: request complete"); - return response; + responseData["success"] = false; + responseData["avatar_uuid"] = UUID.Zero.ToString(); + responseData["error"] = e.Message; + + response.Value = responseData; + } + m_log.Info("[RADMIN]: UpdateUserAccount: request complete"); + return response; + } } /// @@ -1316,73 +1331,74 @@ namespace OpenSim.ApplicationPlugins.RemoteController private void updateUserAppearance(Hashtable responseData, Hashtable requestData, UUID userid) { m_log.DebugFormat("[RADMIN] updateUserAppearance"); - m_log.Warn("[RADMIN]: This method needs update for 0.7"); - //string dmale = m_config.GetString("default_male", "Default Male"); - //string dfemale = m_config.GetString("default_female", "Default Female"); - //string dneut = m_config.GetString("default_female", "Default Default"); + string dmale = m_config.GetString("default_male", "Default Male"); + string dfemale = m_config.GetString("default_female", "Default Female"); + string dneut = m_config.GetString("default_female", "Default Default"); string model = String.Empty; - //// Has a gender preference been supplied? + // Has a gender preference been supplied? - //if (requestData.Contains("gender")) - //{ - // switch ((string)requestData["gender"]) - // { - // case "m" : - // model = dmale; - // break; - // case "f" : - // model = dfemale; - // break; - // case "n" : - // default : - // model = dneut; - // break; - // } - //} + if (requestData.Contains("gender")) + { + switch ((string)requestData["gender"]) + { + case "m" : + case "male" : + model = dmale; + break; + case "f" : + case "female" : + model = dfemale; + break; + case "n" : + case "neutral" : + default : + model = dneut; + break; + } + } - //// Has an explicit model been specified? + // Has an explicit model been specified? - //if (requestData.Contains("model")) - //{ - // model = (string)requestData["model"]; - //} + if (requestData.Contains("model") && (String.IsNullOrEmpty((string)requestData["gender"]))) + { + model = (string)requestData["model"]; + } - //// No appearance attributes were set + // No appearance attributes were set - //if (model == String.Empty) - //{ - // m_log.DebugFormat("[RADMIN] Appearance update not requested"); - // return; - //} + if (String.IsNullOrEmpty(model)) + { + m_log.DebugFormat("[RADMIN] Appearance update not requested"); + return; + } - //m_log.DebugFormat("[RADMIN] Setting appearance for avatar {0}, using model {1}", userid, model); + m_log.DebugFormat("[RADMIN] Setting appearance for avatar {0}, using model <{1}>", userid, model); - //string[] nomens = model.Split(); - //if (nomens.Length != 2) - //{ - // m_log.WarnFormat("[RADMIN] User appearance not set for {0}. Invalid model name : <{1}>", userid, model); - // // nomens = dmodel.Split(); - // return; - //} + string[] nomens = model.Split(); + if (nomens.Length != 2) + { + m_log.WarnFormat("[RADMIN] User appearance not set for {0}. Invalid model name : <{1}>", userid, model); + // nomens = dmodel.Split(); + return; + } - //UserProfileData mprof = m_app.CommunicationsManager.UserService.GetUserProfile(nomens[0], nomens[1]); + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount mprof = scene.UserAccountService.GetUserAccount(scopeID, nomens[0], nomens[1]); - //// Is this the first time one of the default models has been used? Create it if that is the case - //// otherwise default to male. + if (mprof == null) + { + m_log.WarnFormat("[RADMIN] Requested model ({0}) not found. Appearance unchanged", model); + return; + } - //if (mprof == null) - //{ - // m_log.WarnFormat("[RADMIN] Requested model ({0}) not found. Appearance unchanged", model); - // return; - //} + // Set current user's appearance. This bit is easy. The appearance structure is populated with + // actual asset ids, however to complete the magic we need to populate the inventory with the + // assets in question. - //// Set current user's appearance. This bit is easy. The appearance structure is populated with - //// actual asset ids, however to complete the magic we need to populate the inventory with the - //// assets in question. - - //establishAppearance(userid, mprof.ID); + establishAppearance(userid, mprof.PrincipalID); m_log.DebugFormat("[RADMIN] Finished setting appearance for avatar {0}, using model {1}", userid, model); @@ -1397,116 +1413,312 @@ namespace OpenSim.ApplicationPlugins.RemoteController private void establishAppearance(UUID dest, UUID srca) { m_log.DebugFormat("[RADMIN] Initializing inventory for {0} from {1}", dest, srca); + Scene scene = m_app.SceneManager.CurrentOrFirstScene; AvatarAppearance ava = null; - AvatarData avatar = m_app.SceneManager.CurrentOrFirstScene.AvatarService.GetAvatar(srca); + AvatarData avatar = scene.AvatarService.GetAvatar(srca); if (avatar != null) ava = avatar.ToAvatarAppearance(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; + // Simple appearance copy or copy Clothing and Bodyparts folders? + bool copyFolders = m_config.GetBoolean("copy_folders", false); + if (!copyFolders) + { + // Simple copy of wearables and appearance update + try + { + copyWearablesAndAttachments(dest, srca, ava); + + AvatarData adata = new AvatarData(ava); + scene.AvatarService.SetAvatar(dest, adata); + } + catch (Exception e) + { + m_log.WarnFormat("[RADMIN] Error transferring appearance for {0} : {1}", + dest, e.Message); + } + + return; + } + + // Copy Clothing and Bodypart folders and appearance update try { Dictionary imap = new Dictionary(); + copyInventoryFolders(dest, srca, AssetType.Clothing, imap, ava); + copyInventoryFolders(dest, srca, AssetType.Bodypart, imap, ava); - iserv.GetUserInventory(dest, dic.callback); - iserv.GetUserInventory(srca, sic.callback); + AvatarWearable[] wearables = ava.Wearables; - dic.GetInventory(); - sic.GetInventory(); - - if (sic.OK && dic.OK) + for (int i=0; i + /// + /// This method is called by establishAppearance to do a copy all inventory items + /// worn or attached to the Clothing inventory folder of the receiving avatar. + /// In parallel the avatar wearables and attachments are updated. + /// + + private void copyWearablesAndAttachments(UUID dest, UUID srca, AvatarAppearance ava) + { + IInventoryService iserv = m_app.SceneManager.CurrentOrFirstScene.InventoryService; + + // Get Clothing folder of receiver + InventoryFolderBase dstf = iserv.GetFolderForType(dest, AssetType.Clothing); + + if (dstf == null) + throw new Exception("Cannot locate folder(s)"); + + // Missing destination folder? This should *never* be the case + if (dstf.Type != (short)AssetType.Clothing) + { + dstf = new InventoryFolderBase(); + dstf.ID = UUID.Random(); + dstf.Name = "Clothing"; + dstf.Owner = dest; + dstf.Type = (short)AssetType.Clothing; + dstf.ParentID = iserv.GetRootFolder(dest).ID; + dstf.Version = 1; + iserv.AddFolder(dstf); // store base record + m_log.ErrorFormat("[RADMIN] Created folder for destination {0}", srca); + } + + // Wearables + AvatarWearable[] wearables = ava.Wearables; + AvatarWearable wearable; + + for (int i=0; i attachments = ava.GetAttachmentDictionary(); + + foreach (KeyValuePair kvp in attachments) + { + int attachpoint = kvp.Key; + UUID itemID = kvp.Value[0]; + + if (itemID != UUID.Zero) + { + // Get inventory item and copy it + InventoryItemBase item = new InventoryItemBase(itemID, srca); + item = iserv.GetItem(item); + + if (item != null) + { + InventoryItemBase dsti = new InventoryItemBase(UUID.Random(), dest); + dsti.Name = item.Name; + dsti.Description = item.Description; + dsti.InvType = item.InvType; + dsti.CreatorId = item.CreatorId; + dsti.CreatorIdAsUuid = item.CreatorIdAsUuid; + dsti.NextPermissions = item.NextPermissions; + dsti.CurrentPermissions = item.CurrentPermissions; + dsti.BasePermissions = item.BasePermissions; + dsti.EveryOnePermissions = item.EveryOnePermissions; + dsti.GroupPermissions = item.GroupPermissions; + dsti.AssetType = item.AssetType; + dsti.AssetID = item.AssetID; + dsti.GroupID = item.GroupID; + dsti.GroupOwned = item.GroupOwned; + dsti.SalePrice = item.SalePrice; + dsti.SaleType = item.SaleType; + dsti.Flags = item.Flags; + dsti.CreationDate = item.CreationDate; + dsti.Folder = dstf.ID; + + iserv.AddItem(dsti); + m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", dsti.ID, dstf.ID); + + // Attach item + ava.SetAttachment(attachpoint, dsti.ID, dsti.AssetID); + m_log.DebugFormat("[RADMIN] Attached {0}", dsti.ID); + } + else + { + m_log.WarnFormat("[RADMIN] Error transferring {0} to folder {1}", itemID, dstf.ID); + } + } + } + + + } + + /// + /// This method is called by establishAppearance to copy inventory folders to make + /// copies of Clothing and Bodyparts inventory folders and attaches worn attachments + /// + + private void copyInventoryFolders(UUID dest, UUID srca, AssetType assettype, Dictionary imap, + AvatarAppearance ava) + { + IInventoryService iserv = m_app.SceneManager.CurrentOrFirstScene.InventoryService; + + InventoryFolderBase srcf = iserv.GetFolderForType(srca, assettype); + InventoryFolderBase dstf = iserv.GetFolderForType(dest, assettype); + + if (srcf == null || dstf == null) + throw new Exception("Cannot locate folder(s)"); + + // Missing source folder? This should *never* be the case + if (srcf.Type != (short)assettype) + { + srcf = new InventoryFolderBase(); + srcf.ID = UUID.Random(); + if (assettype == AssetType.Clothing) { + srcf.Name = "Clothing"; + } else { + srcf.Name = "Body Parts"; + } + srcf.Owner = srca; + srcf.Type = (short)assettype; + srcf.ParentID = iserv.GetRootFolder(srca).ID; + srcf.Version = 1; + iserv.AddFolder(srcf); // store base record + m_log.ErrorFormat("[RADMIN] Created folder for source {0}", srca); + } + + // Missing destination folder? This should *never* be the case + if (dstf.Type != (short)assettype) + { + dstf = new InventoryFolderBase(); + dstf.ID = UUID.Random(); + dstf.Name = assettype.ToString(); + dstf.Owner = dest; + dstf.Type = (short)assettype; + dstf.ParentID = iserv.GetRootFolder(dest).ID; + dstf.Version = 1; + iserv.AddFolder(dstf); // store base record + m_log.ErrorFormat("[RADMIN] Created folder for destination {0}", srca); + } + + InventoryFolderBase efolder; + List folders = iserv.GetFolderContent(srca, srcf.ID).Folders; + + foreach (InventoryFolderBase folder in folders) + { + + efolder = new InventoryFolderBase(); + efolder.ID = UUID.Random(); + efolder.Name = folder.Name; + efolder.Owner = dest; + efolder.Type = folder.Type; + efolder.Version = folder.Version; + efolder.ParentID = dstf.ID; + iserv.AddFolder(efolder); + + m_log.DebugFormat("[RADMIN] Added folder {0} to folder {1}", efolder.ID, srcf.ID); + + List items = iserv.GetFolderContent(srca, folder.ID).Items; + + foreach (InventoryItemBase item in items) + { + InventoryItemBase dsti = new InventoryItemBase(UUID.Random(), dest); + dsti.Name = item.Name; + dsti.Description = item.Description; + dsti.InvType = item.InvType; + dsti.CreatorId = item.CreatorId; + dsti.CreatorIdAsUuid = item.CreatorIdAsUuid; + dsti.NextPermissions = item.NextPermissions; + dsti.CurrentPermissions = item.CurrentPermissions; + dsti.BasePermissions = item.BasePermissions; + dsti.EveryOnePermissions = item.EveryOnePermissions; + dsti.GroupPermissions = item.GroupPermissions; + dsti.AssetType = item.AssetType; + dsti.AssetID = item.AssetID; + dsti.GroupID = item.GroupID; + dsti.GroupOwned = item.GroupOwned; + dsti.SalePrice = item.SalePrice; + dsti.SaleType = item.SaleType; + dsti.Flags = item.Flags; + dsti.CreationDate = item.CreationDate; + dsti.Folder = efolder.ID; + + iserv.AddItem(dsti); + imap.Add(item.ID, dsti.ID); + m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", dsti.ID, efolder.ID); + + // Attach item, if original is attached + int attachpoint = ava.GetAttachpoint(item.ID); + if (attachpoint != 0) + { + ava.SetAttachment(attachpoint, dsti.ID, dsti.AssetID); + m_log.DebugFormat("[RADMIN] Attached {0}", dsti.ID); + } + } + } + } + + /// /// 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 @@ -1557,9 +1769,9 @@ namespace OpenSim.ApplicationPlugins.RemoteController bool include = false; bool select = false; - UICallback uic; - IInventoryService iserv = m_app.SceneManager.CurrentOrFirstScene.InventoryService; - IAssetService aserv = m_app.SceneManager.CurrentOrFirstScene.AssetService; + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + IInventoryService iserv = scene.InventoryService; + IAssetService aserv = scene.AssetService; doc.LoadXml(File.ReadAllText(dafn)); @@ -1596,29 +1808,31 @@ namespace OpenSim.ApplicationPlugins.RemoteController passwd = GetStringAttribute(avatar,"password",passwd); string[] nomens = name.Split(); - UUID scopeID = m_app.SceneManager.CurrentOrFirstScene.RegionInfo.ScopeID; - UserAccount account = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.GetUserAccount(scopeID, nomens[0], nomens[1]); + UUID scopeID = scene.RegionInfo.ScopeID; + UserAccount account = scene.UserAccountService.GetUserAccount(scopeID, nomens[0], nomens[1]); if (null == account) { - account = new UserAccount(scopeID, nomens[0], nomens[1], email); - bool success = m_app.SceneManager.CurrentOrFirstScene.UserAccountService.StoreUserAccount(account); - if (!success) + account = CreateUser(scopeID, nomens[0], nomens[1], passwd, email); + if (null == account) { m_log.ErrorFormat("[RADMIN] Avatar {0} {1} was not created", nomens[0], nomens[1]); return false; } - // !!! REFACTORING PROBLEM: need to set the password + } - GridRegion home = m_app.SceneManager.CurrentOrFirstScene.GridService.GetRegionByPosition(scopeID, - (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); - if (home != null) - m_app.SceneManager.CurrentOrFirstScene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); - } - else - { - ID = account.PrincipalID; + // Set home position + + GridRegion home = scene.GridService.GetRegionByPosition(scopeID, + (int)(regX * Constants.RegionSize), (int)(regY * Constants.RegionSize)); + if (null == home) { + m_log.WarnFormat("[RADMIN]: Unable to set home region for newly created user account {0} {1}", nomens[0], nomens[1]); + } else { + scene.GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + m_log.DebugFormat("[RADMIN]: Set home region {0} for updated user account {1} {2}", home.RegionID, nomens[0], nomens[1]); } + ID = account.PrincipalID; + m_log.DebugFormat("[RADMIN] User {0}[{1}] created or retrieved", name, ID); include = true; } @@ -1635,46 +1849,36 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (include) { - uic = new UICallback(); - // Request the inventory - iserv.GetUserInventory(ID, uic.callback); - - // While the inventory is being fetched, setup for appearance processing - AvatarData adata = m_app.SceneManager.CurrentOrFirstScene.AvatarService.GetAvatar(ID); + // Setup for appearance processing + AvatarData adata = scene.AvatarService.GetAvatar(ID); if (adata != null) mava = adata.ToAvatarAppearance(ID); else mava = new AvatarAppearance(); + AvatarWearable[] wearables = mava.Wearables; + for (int i=0; i folders = iserv.GetFolderContent(ID, cfolder.ID).Folders; + efolder = null; + + foreach (InventoryFolderBase folder in folders) { - if (folder.Name == oname && folder.ParentID == cfolder.ID) + if (folder.Name == oname) { efolder = folder; break; @@ -1711,14 +1918,14 @@ namespace OpenSim.ApplicationPlugins.RemoteController if (efolder == null) { m_log.DebugFormat("[RADMIN] Creating outfit folder {0} for {1}", oname, name); - efolder = new InventoryFolderImpl(); + efolder = new InventoryFolderBase(); 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 + efolder.Type = (short)AssetType.Clothing; + efolder.Version = 1; + efolder.ParentID = cfolder.ID; + iserv.AddFolder(efolder); m_log.DebugFormat("[RADMIN] Adding outfile folder {0} to folder {1}", efolder.ID, cfolder.ID); } @@ -1745,26 +1952,55 @@ namespace OpenSim.ApplicationPlugins.RemoteController InventoryItemBase iitem = null; - if ((iitem = efolder.FindAsset(assetid)) == null) + // Check if asset is in inventory already + iitem = null; + List iitems = iserv.GetFolderContent(ID, efolder.ID).Items; + + foreach (InventoryItemBase litem in iitems) { - iitem = new InventoryItemBase(); - iitem.ID = UUID.Random(); + if (litem.AssetID == assetid) + { + iitem = litem; + break; + } + } + + // Create inventory item + if (iitem == null) + { + iitem = new InventoryItemBase(UUID.Random(), ID); 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.CreatorId = GetStringAttribute(item,"creatorid",""); + iitem.CreatorIdAsUuid = (UUID)GetStringAttribute(item,"creatoruuid",""); iitem.NextPermissions = GetUnsignedAttribute(perms,"next",0x7fffffff); iitem.CurrentPermissions = GetUnsignedAttribute(perms,"current",0x7fffffff); - iitem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff); + iitem.BasePermissions = GetUnsignedAttribute(perms,"base",0x7fffffff); iitem.EveryOnePermissions = GetUnsignedAttribute(perms,"everyone",0x7fffffff); - m_log.DebugFormat("[RADMIN] Adding item {0} to folder {1}", iitem.ID, efolder.ID); + iitem.GroupPermissions = GetUnsignedAttribute(perms,"group",0x7fffffff); + iitem.AssetType = GetIntegerAttribute(item,"assettype",-1); + iitem.AssetID = assetid; // associated asset + iitem.GroupID = (UUID)GetStringAttribute(item,"groupid",""); + iitem.GroupOwned = (GetStringAttribute(item,"groupowned","false") == "true"); + iitem.SalePrice = GetIntegerAttribute(item,"saleprice",0); + iitem.SaleType = (byte)GetIntegerAttribute(item,"saletype",0); + iitem.Flags = GetUnsignedAttribute(item,"flags",0); + iitem.CreationDate = GetIntegerAttribute(item,"creationdate",Util.UnixTimeSinceEpoch()); + iitem.Folder = efolder.ID; // Parent folder + iserv.AddItem(iitem); + m_log.DebugFormat("[RADMIN] Added item {0} to folder {1}", iitem.ID, efolder.ID); } + + // Attach item, if attachpoint is specified + int attachpoint = GetIntegerAttribute(item,"attachpoint",0); + if (attachpoint != 0) + { + mava.SetAttachment(attachpoint, iitem.ID, iitem.AssetID); + m_log.DebugFormat("[RADMIN] Attached {0}", iitem.ID); + } + // Record whether or not the item is to be initially worn try { @@ -1774,25 +2010,22 @@ namespace OpenSim.ApplicationPlugins.RemoteController mava.Wearables[iitem.Flags].AssetID = iitem.AssetID; } } - catch {} + catch (Exception e) + { + m_log.WarnFormat("[RADMIN] Error wearing item {0} : {1}", iitem.ID, e.Message); + } } // 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); AvatarData adata2 = new AvatarData(mava); - m_app.SceneManager.CurrentOrFirstScene.AvatarService.SetAvatar(ID, adata2); + scene.AvatarService.SetAvatar(ID, adata2); } 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"); @@ -2660,81 +2893,115 @@ namespace OpenSim.ApplicationPlugins.RemoteController public void Dispose() { } - } - class UICallback - { - private Object uilock = new Object(); - internal InventoryFolderImpl root = null; - internal List folders; - internal List items; - internal bool OK = false; - - public void callback(ICollection p_folders, ICollection p_items) + /// + /// Create a user + /// + /// + /// + /// + /// + /// + private UserAccount CreateUser(UUID scopeID, string firstName, string lastName, string password, string email) { - lock (uilock) - { - folders = (List) p_folders; - items = (List) p_items; - OK = true; - System.Threading.Monitor.Pulse(uilock); - } - } + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + IUserAccountService m_UserAccountService = scene.UserAccountService; + IGridService m_GridService = scene.GridService; + IAuthenticationService m_AuthenticationService = scene.AuthenticationService; + IGridUserService m_GridUserService = scene.GridUserService; + IInventoryService m_InventoryService = scene.InventoryService; - public void GetInventory() - { - Dictionary fmap = new Dictionary(); - - if (OK == false) + UserAccount account = m_UserAccountService.GetUserAccount(scopeID, firstName, lastName); + if (null == account) { - lock (uilock) + account = new UserAccount(scopeID, firstName, lastName, email); + if (account.ServiceURLs == null || (account.ServiceURLs != null && account.ServiceURLs.Count == 0)) { - if (OK == false) - System.Threading.Monitor.Wait(uilock); + account.ServiceURLs = new Dictionary(); + account.ServiceURLs["HomeURI"] = string.Empty; + account.ServiceURLs["GatekeeperURI"] = string.Empty; + account.ServiceURLs["InventoryServerURI"] = string.Empty; + account.ServiceURLs["AssetServerURI"] = string.Empty; } - } - // Got the inventory OK. So now merge the content of the default appearance - // file with whatever we already have in-world. For convenience we initialize - // the inventory hierarchy. - - // Find root and build an index - - foreach (InventoryFolderImpl folder in folders) - { - if (folder.ParentID == UUID.Zero) + if (m_UserAccountService.StoreUserAccount(account)) { - if (root == null) + bool success; + if (m_AuthenticationService != null) { - root = folder; + success = m_AuthenticationService.SetPassword(account.PrincipalID, password); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); + } + + GridRegion home = null; + if (m_GridService != null) + { + List defaultRegions = m_GridService.GetDefaultRegions(UUID.Zero); + if (defaultRegions != null && defaultRegions.Count >= 1) + home = defaultRegions[0]; + + if (m_GridUserService != null && home != null) + m_GridUserService.SetHome(account.PrincipalID.ToString(), home.RegionID, new Vector3(128, 128, 0), new Vector3(0, 1, 0)); + else + m_log.WarnFormat("[RADMIN]: Unable to set home for account {0} {1}.", + firstName, lastName); } else + m_log.WarnFormat("[RADMIN]: Unable to retrieve home region for account {0} {1}.", + firstName, lastName); + + if (m_InventoryService != null) { - throw new Exception("Multiple root folders found"); + success = m_InventoryService.CreateUserInventory(account.PrincipalID); + if (!success) + m_log.WarnFormat("[RADMIN]: Unable to create inventory for account {0} {1}.", + firstName, lastName); } - } - fmap.Add(folder.ID, folder); - } - // Hard to continue if the root folder is not there - if (root == null) - { - throw new Exception("Root folder not found"); - } - - // Construct the folder hierarchy - foreach (InventoryFolderImpl folder in folders) - { - if (folder.ID != root.ID) - { - fmap[folder.ParentID].AddChildFolder(folder); + m_log.InfoFormat("[RADMIN]: Account {0} {1} created successfully", firstName, lastName); + return account; + } else { + m_log.ErrorFormat("[RADMIN]: Account creation failed for account {0} {1}", firstName, lastName); } } - - // Find a home for every pre-existing item - foreach (InventoryItemBase item in items) + else { - fmap[item.Folder].Items.Add(item.ID, item); + m_log.ErrorFormat("[RADMIN]: A user with the name {0} {1} already exists!", firstName, lastName); + } + return null; + } + + /// + /// Change password + /// + /// + /// + /// + private bool ChangeUserPassword(string firstName, string lastName, string password) + { + Scene scene = m_app.SceneManager.CurrentOrFirstScene; + IUserAccountService m_UserAccountService = scene.UserAccountService; + IAuthenticationService m_AuthenticationService = scene.AuthenticationService; + + UserAccount account = m_UserAccountService.GetUserAccount(UUID.Zero, firstName, lastName); + if (null != account) + { + bool success = false; + if (m_AuthenticationService != null) + success = m_AuthenticationService.SetPassword(account.PrincipalID, password); + if (!success) { + m_log.WarnFormat("[RADMIN]: Unable to set password for account {0} {1}.", + firstName, lastName); + return false; + } + return true; + } + else + { + m_log.ErrorFormat("[RADMIN]: No such user"); + return false; } } } diff --git a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs index d742039115..65921a2c00 100644 --- a/OpenSim/Client/MXP/ClientStack/MXPClientView.cs +++ b/OpenSim/Client/MXP/ClientStack/MXPClientView.cs @@ -1035,11 +1035,6 @@ namespace OpenSim.Client.MXP.ClientStack // Minimap function, not used. } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - // Need to translate to MXP somehow - } - public void SetChildAgentThrottle(byte[] throttle) { // Need to translate to MXP somehow @@ -1711,5 +1706,9 @@ namespace OpenSim.Client.MXP.ClientStack public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) { } + + public void StopFlying(ISceneEntity presence) + { + } } } diff --git a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs index d725943197..b808e95073 100644 --- a/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs +++ b/OpenSim/Client/Sirikata/ClientStack/SirikataClientView.cs @@ -593,11 +593,6 @@ namespace OpenSim.Client.Sirikata.ClientStack throw new System.NotImplementedException(); } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - throw new System.NotImplementedException(); - } - public void SetChildAgentThrottle(byte[] throttle) { throw new System.NotImplementedException(); @@ -1199,6 +1194,10 @@ namespace OpenSim.Client.Sirikata.ClientStack { } + public void StopFlying(ISceneEntity presence) + { + } + #endregion } } diff --git a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs index 2eec844b9d..a6c490b2bc 100644 --- a/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs +++ b/OpenSim/Client/VWoHTTP/ClientStack/VWHClientView.cs @@ -599,11 +599,6 @@ namespace OpenSim.Client.VWoHTTP.ClientStack throw new System.NotImplementedException(); } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - throw new System.NotImplementedException(); - } - public void SetChildAgentThrottle(byte[] throttle) { throw new System.NotImplementedException(); @@ -1214,5 +1209,9 @@ namespace OpenSim.Client.VWoHTTP.ClientStack public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) { } + + public void StopFlying(ISceneEntity presence) + { + } } } diff --git a/OpenSim/ConsoleClient/ConsoleClient.cs b/OpenSim/ConsoleClient/ConsoleClient.cs index 8c616e0271..f4605da0b8 100644 --- a/OpenSim/ConsoleClient/ConsoleClient.cs +++ b/OpenSim/ConsoleClient/ConsoleClient.cs @@ -29,6 +29,7 @@ using Nini.Config; using log4net; using System.Reflection; using System; +using System.IO; using System.Xml; using System.Collections.Generic; using OpenSim.Server.Base; @@ -73,9 +74,18 @@ namespace OpenSim.ConsoleClient Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/StartSession/", String.Format("USER={0}&PASS={1}", m_User, m_Pass), LoginReply); - int res = m_Server.Run(); + string pidFile = serverConfig.GetString("PIDFile", String.Empty); - Environment.Exit(res); + while (m_Server.Running) + { + System.Threading.Thread.Sleep(500); + // MainConsole.Instance.Prompt(); + } + + if (pidFile != String.Empty) + File.Delete(pidFile); + + Environment.Exit(0); return 0; } @@ -83,13 +93,14 @@ namespace OpenSim.ConsoleClient private static void SendCommand(string module, string[] cmd) { string sendCmd = ""; + string[] cmdlist = new string[cmd.Length - 1]; + + sendCmd = cmd[0]; + if (cmd.Length > 1) { - sendCmd = cmd[0]; - - Array.Copy(cmd, 1, cmd, 0, cmd.Length-1); - Array.Resize(ref cmd, cmd.Length-1); - sendCmd += "\"" + String.Join("\" \"", cmd) + "\""; + Array.Copy(cmd, 1, cmdlist, 0, cmd.Length - 1); + sendCmd += " \"" + String.Join("\" \"", cmdlist) + "\""; } Requester.MakeRequest("http://"+m_Host+":"+m_Port.ToString()+"/SessionCommand/", String.Format("ID={0}&COMMAND={1}", m_SessionID, sendCmd), CommandReply); @@ -183,16 +194,27 @@ namespace OpenSim.ConsoleClient while (lines.Count > 100) lines.RemoveAt(0); + string prompt = String.Empty; + foreach (string l in lines) { string[] parts = l.Split(new char[] {':'}, 3); if (parts.Length != 3) continue; - MainConsole.Instance.Output(parts[2].Trim(), parts[1]); + if (parts[2].StartsWith("+++") || parts[2].StartsWith("-++")) + prompt = parts[2]; + else + MainConsole.Instance.Output(parts[2].Trim(), parts[1]); } + Requester.MakeRequest(requestUrl, requestData, ReadResponses); + + if (prompt.StartsWith("+++")) + MainConsole.Instance.ReadLine(prompt.Substring(3), true, true); + else if (prompt.StartsWith("-++")) + SendCommand(String.Empty, new string[] { MainConsole.Instance.ReadLine(prompt.Substring(3), false, true) }); } public static void CommandReply(string requestUrl, string requestData, string replyData) diff --git a/OpenSim/Data/IXInventoryData.cs b/OpenSim/Data/IXInventoryData.cs index 690913670a..d85a7efb8f 100644 --- a/OpenSim/Data/IXInventoryData.cs +++ b/OpenSim/Data/IXInventoryData.cs @@ -51,7 +51,7 @@ namespace OpenSim.Data public int inventoryNextPermissions; public int inventoryCurrentPermissions; public int invType; - public UUID creatorID; + public string creatorID; public int inventoryBasePermissions; public int inventoryEveryOnePermissions; public int salePrice; diff --git a/OpenSim/Data/Migration.cs b/OpenSim/Data/Migration.cs index 4f113a2f49..c177097ebd 100644 --- a/OpenSim/Data/Migration.cs +++ b/OpenSim/Data/Migration.cs @@ -67,7 +67,6 @@ namespace OpenSim.Data /// really want is the assembly of your database class. /// /// - public class Migration { private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -173,8 +172,6 @@ namespace OpenSim.Data ExecuteScript(_conn, script); } - - public void Update() { InitMigrationsTable(); @@ -186,8 +183,8 @@ namespace OpenSim.Data return; // to prevent people from killing long migrations. - m_log.InfoFormat("[MIGRATIONS] Upgrading {0} to latest revision {1}.", _type, migrations.Keys[migrations.Count - 1]); - m_log.Info("[MIGRATIONS] NOTE: this may take a while, don't interupt this process!"); + m_log.InfoFormat("[MIGRATIONS]: Upgrading {0} to latest revision {1}.", _type, migrations.Keys[migrations.Count - 1]); + m_log.Info("[MIGRATIONS]: NOTE - this may take a while, don't interrupt this process!"); foreach (KeyValuePair kvp in migrations) { @@ -206,7 +203,7 @@ namespace OpenSim.Data } catch (Exception e) { - m_log.DebugFormat("[MIGRATIONS] Cmd was {0}", e.Message.Replace("\n", " ")); + m_log.DebugFormat("[MIGRATIONS]: Cmd was {0}", e.Message.Replace("\n", " ")); m_log.Debug("[MIGRATIONS]: An error has occurred in the migration. This may mean you could see errors trying to run OpenSim. If you see database related errors, you will need to fix the issue manually. Continuing."); ExecuteScript("ROLLBACK;"); } diff --git a/OpenSim/Data/MySQL/MySQLXInventoryData.cs b/OpenSim/Data/MySQL/MySQLXInventoryData.cs index 0fe801d696..3c73095fc3 100644 --- a/OpenSim/Data/MySQL/MySQLXInventoryData.cs +++ b/OpenSim/Data/MySQL/MySQLXInventoryData.cs @@ -64,14 +64,22 @@ namespace OpenSim.Data.MySQL public bool StoreFolder(XInventoryFolder folder) { + if (folder.folderName.Length > 64) + folder.folderName = folder.folderName.Substring(0, 64); + return m_Folders.Store(folder); } public bool StoreItem(XInventoryItem item) { + if (item.inventoryName.Length > 64) + item.inventoryName = item.inventoryName.Substring(0, 64); + if (item.inventoryDescription.Length > 128) + item.inventoryDescription = item.inventoryDescription.Substring(0, 128); + return m_Items.Store(item); } - + public bool DeleteFolders(string field, string val) { return m_Folders.Delete(field, val); diff --git a/OpenSim/Data/MySQL/Resources/AssetStore.migrations b/OpenSim/Data/MySQL/Resources/AssetStore.migrations index 9c5563038f..e0526fed9c 100644 --- a/OpenSim/Data/MySQL/Resources/AssetStore.migrations +++ b/OpenSim/Data/MySQL/Resources/AssetStore.migrations @@ -73,5 +73,5 @@ ALTER TABLE assets ADD COLUMN asset_flags INTEGER NOT NULL DEFAULT 0; :VERSION 8 -ALTER TABLE assets ADD COLUMN CreatorID varchar(36) NOT NULL DEFAULT ''; +ALTER TABLE assets ADD COLUMN CreatorID varchar(128) NOT NULL DEFAULT ''; diff --git a/OpenSim/Data/MySQL/Resources/InventoryStore.migrations b/OpenSim/Data/MySQL/Resources/InventoryStore.migrations index 8c5864e97d..3e9bad5f95 100644 --- a/OpenSim/Data/MySQL/Resources/InventoryStore.migrations +++ b/OpenSim/Data/MySQL/Resources/InventoryStore.migrations @@ -91,3 +91,11 @@ update inventoryitems set creatorID = '00000000-0000-0000-0000-000000000000' whe alter table inventoryitems modify column creatorID varchar(36) not NULL default '00000000-0000-0000-0000-000000000000'; COMMIT; + +:VERSION 5 # ------------ + +BEGIN; + +alter table inventoryitems modify column creatorID varchar(128) not NULL default '00000000-0000-0000-0000-000000000000'; + +COMMIT; diff --git a/OpenSim/Data/MySQL/Resources/RegionStore.migrations b/OpenSim/Data/MySQL/Resources/RegionStore.migrations index d8a279dc71..3f644f903f 100644 --- a/OpenSim/Data/MySQL/Resources/RegionStore.migrations +++ b/OpenSim/Data/MySQL/Resources/RegionStore.migrations @@ -717,9 +717,86 @@ ALTER TABLE regionsettings ADD COLUMN loaded_creation_datetime int unsigned NOT COMMIT; +:VERSION 32 + +BEGIN; +CREATE TABLE `regionwindlight` ( + `region_id` varchar(36) NOT NULL DEFAULT '000000-0000-0000-0000-000000000000', + `water_color_r` float(9,6) unsigned NOT NULL DEFAULT '4.000000', + `water_color_g` float(9,6) unsigned NOT NULL DEFAULT '38.000000', + `water_color_b` float(9,6) unsigned NOT NULL DEFAULT '64.000000', + `water_fog_density_exponent` float(3,1) unsigned NOT NULL DEFAULT '4.0', + `underwater_fog_modifier` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `reflection_wavelet_scale_1` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `reflection_wavelet_scale_2` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `reflection_wavelet_scale_3` float(3,1) unsigned NOT NULL DEFAULT '2.0', + `fresnel_scale` float(3,2) unsigned NOT NULL DEFAULT '0.40', + `fresnel_offset` float(3,2) unsigned NOT NULL DEFAULT '0.50', + `refract_scale_above` float(3,2) unsigned NOT NULL DEFAULT '0.03', + `refract_scale_below` float(3,2) unsigned NOT NULL DEFAULT '0.20', + `blur_multiplier` float(4,3) unsigned NOT NULL DEFAULT '0.040', + `big_wave_direction_x` float(3,2) NOT NULL DEFAULT '1.05', + `big_wave_direction_y` float(3,2) NOT NULL DEFAULT '-0.42', + `little_wave_direction_x` float(3,2) NOT NULL DEFAULT '1.11', + `little_wave_direction_y` float(3,2) NOT NULL DEFAULT '-1.16', + `normal_map_texture` varchar(36) NOT NULL DEFAULT '822ded49-9a6c-f61c-cb89-6df54f42cdf4', + `horizon_r` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `horizon_g` float(3,2) unsigned NOT NULL DEFAULT '0.25', + `horizon_b` float(3,2) unsigned NOT NULL DEFAULT '0.32', + `horizon_i` float(3,2) unsigned NOT NULL DEFAULT '0.32', + `haze_horizon` float(3,2) unsigned NOT NULL DEFAULT '0.19', + `blue_density_r` float(3,2) unsigned NOT NULL DEFAULT '0.12', + `blue_density_g` float(3,2) unsigned NOT NULL DEFAULT '0.22', + `blue_density_b` float(3,2) unsigned NOT NULL DEFAULT '0.38', + `blue_density_i` float(3,2) unsigned NOT NULL DEFAULT '0.38', + `haze_density` float(3,2) unsigned NOT NULL DEFAULT '0.70', + `density_multiplier` float(3,2) unsigned NOT NULL DEFAULT '0.18', + `distance_multiplier` float(4,1) unsigned NOT NULL DEFAULT '0.8', + `max_altitude` int(4) unsigned NOT NULL DEFAULT '1605', + `sun_moon_color_r` float(3,2) unsigned NOT NULL DEFAULT '0.24', + `sun_moon_color_g` float(3,2) unsigned NOT NULL DEFAULT '0.26', + `sun_moon_color_b` float(3,2) unsigned NOT NULL DEFAULT '0.30', + `sun_moon_color_i` float(3,2) unsigned NOT NULL DEFAULT '0.30', + `sun_moon_position` float(4,3) unsigned NOT NULL DEFAULT '0.317', + `ambient_r` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_g` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_b` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `ambient_i` float(3,2) unsigned NOT NULL DEFAULT '0.35', + `east_angle` float(3,2) unsigned NOT NULL DEFAULT '0.00', + `sun_glow_focus` float(3,2) unsigned NOT NULL DEFAULT '0.10', + `sun_glow_size` float(3,2) unsigned NOT NULL DEFAULT '1.75', + `scene_gamma` float(4,2) unsigned NOT NULL DEFAULT '1.00', + `star_brightness` float(3,2) unsigned NOT NULL DEFAULT '0.00', + `cloud_color_r` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_g` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_b` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_color_i` float(3,2) unsigned NOT NULL DEFAULT '0.41', + `cloud_x` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_y` float(3,2) unsigned NOT NULL DEFAULT '0.53', + `cloud_density` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_coverage` float(3,2) unsigned NOT NULL DEFAULT '0.27', + `cloud_scale` float(3,2) unsigned NOT NULL DEFAULT '0.42', + `cloud_detail_x` float(3,2) unsigned NOT NULL DEFAULT '1.00', + `cloud_detail_y` float(3,2) unsigned NOT NULL DEFAULT '0.53', + `cloud_detail_density` float(3,2) unsigned NOT NULL DEFAULT '0.12', + `cloud_scroll_x` float(3,2) unsigned NOT NULL DEFAULT '0.20', + `cloud_scroll_x_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', + `cloud_scroll_y` float(3,2) unsigned NOT NULL DEFAULT '0.01', + `cloud_scroll_y_lock` tinyint(1) unsigned NOT NULL DEFAULT '0', + `draw_classic_clouds` tinyint(1) unsigned NOT NULL DEFAULT '1', + PRIMARY KEY (`region_id`) +); + + :VERSION 33 #--------------------- BEGIN; ALTER TABLE regionsettings ADD map_tile_ID CHAR(36) NOT NULL DEFAULT '00000000-0000-0000-0000-000000000000'; COMMIT; +:VERSION 34 #--------------------- + +BEGIN; +ALTER TABLE `regionwindlight` CHANGE COLUMN `cloud_scroll_x` `cloud_scroll_x` FLOAT(4,2) NOT NULL DEFAULT '0.20' AFTER `cloud_detail_density`, CHANGE COLUMN `cloud_scroll_y` `cloud_scroll_y` FLOAT(4,2) NOT NULL DEFAULT '0.01' AFTER `cloud_scroll_x_lock`; +COMMIT; + diff --git a/OpenSim/Data/Null/NullAuthenticationData.cs b/OpenSim/Data/Null/NullAuthenticationData.cs index 3fb3105ec5..620deb9786 100644 --- a/OpenSim/Data/Null/NullAuthenticationData.cs +++ b/OpenSim/Data/Null/NullAuthenticationData.cs @@ -76,6 +76,5 @@ namespace OpenSim.Data.Null return false; } - } -} +} \ No newline at end of file diff --git a/OpenSim/Data/Null/NullUserAccountData.cs b/OpenSim/Data/Null/NullUserAccountData.cs index 9eb94e643c..ede23fb8fe 100644 --- a/OpenSim/Data/Null/NullUserAccountData.cs +++ b/OpenSim/Data/Null/NullUserAccountData.cs @@ -88,7 +88,7 @@ namespace OpenSim.Data.Null m_DataByUUID[data.PrincipalID] = data; m_DataByName[data.FirstName + " " + data.LastName] = data; - if (data.Data.ContainsKey("Email") && data.Data["Email"] != string.Empty) + if (data.Data.ContainsKey("Email") && data.Data["Email"] != null && data.Data["Email"] != string.Empty) m_DataByEmail[data.Data["Email"]] = data; return true; diff --git a/OpenSim/Data/Resources/OpenSim.Data.addin.xml b/OpenSim/Data/Resources/OpenSim.Data.addin.xml index 65774ffc4f..10c9c3cb28 100644 --- a/OpenSim/Data/Resources/OpenSim.Data.addin.xml +++ b/OpenSim/Data/Resources/OpenSim.Data.addin.xml @@ -3,19 +3,10 @@ - - - - - - - - - diff --git a/OpenSim/Data/SQLite/Resources/001_XInventoryStore.sql b/OpenSim/Data/SQLite/Resources/001_XInventoryStore.sql deleted file mode 100644 index 7e21996ed9..0000000000 --- a/OpenSim/Data/SQLite/Resources/001_XInventoryStore.sql +++ /dev/null @@ -1,38 +0,0 @@ -BEGIN TRANSACTION; - -CREATE TABLE inventoryfolders( - folderName varchar(255), - type integer, - version integer, - folderID varchar(255) primary key, - agentID varchar(255) not null default '00000000-0000-0000-0000-000000000000', - parentFolderID varchar(255) not null default '00000000-0000-0000-0000-000000000000'); - -CREATE TABLE inventoryitems( - assetID varchar(255), - assetType integer, - inventoryName varchar(255), - inventoryDescription varchar(255), - inventoryNextPermissions integer, - inventoryCurrentPermissions integer, - invType integer, - creatorID varchar(255), - inventoryBasePermissions integer, - inventoryEveryOnePermissions integer, - salePrice integer default 99, - saleType integer default 0, - creationDate integer default 2000, - groupID varchar(255) default '00000000-0000-0000-0000-000000000000', - groupOwned integer default 0, - flags integer default 0, - inventoryID varchar(255) primary key, - parentFolderID varchar(255) not null default '00000000-0000-0000-0000-000000000000', - avatarID varchar(255) not null default '00000000-0000-0000-0000-000000000000', - inventoryGroupPermissions integer not null default 0); - -create index inventoryfolders_agentid on inventoryfolders(agentID); -create index inventoryfolders_parentid on inventoryfolders(parentFolderID); -create index inventoryitems_parentfolderid on inventoryitems(parentFolderID); -create index inventoryitems_avatarid on inventoryitems(avatarID); - -COMMIT; diff --git a/OpenSim/Data/SQLite/Resources/002_XInventoryStore.sql b/OpenSim/Data/SQLite/Resources/002_XInventoryStore.sql deleted file mode 100644 index d38e2b77cc..0000000000 --- a/OpenSim/Data/SQLite/Resources/002_XInventoryStore.sql +++ /dev/null @@ -1,8 +0,0 @@ -ATTACH 'inventoryStore.db' AS old; - -BEGIN TRANSACTION; - -INSERT INTO inventoryfolders (folderName, type, version, folderID, agentID, parentFolderID) SELECT `name` AS folderName, `type` AS type, `version` AS version, `UUID` AS folderID, `agentID` AS agentID, `parentID` AS parentFolderID from old.inventoryfolders; -INSERT INTO inventoryitems (assetID, assetType, inventoryName, inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType, creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, salePrice, saleType, creationDate, groupID, groupOwned, flags, inventoryID, parentFolderID, avatarID, inventoryGroupPermissions) SELECT `assetID`, `assetType` AS assetType, `inventoryName` AS inventoryName, `inventoryDescription` AS inventoryDescription, `inventoryNextPermissions` AS inventoryNextPermissions, `inventoryCurrentPermissions` AS inventoryCurrentPermissions, `invType` AS invType, `creatorsID` AS creatorID, `inventoryBasePermissions` AS inventoryBasePermissions, `inventoryEveryOnePermissions` AS inventoryEveryOnePermissions, `salePrice` AS salePrice, `saleType` AS saleType, `creationDate` AS creationDate, `groupID` AS groupID, `groupOwned` AS groupOwned, `flags` AS flags, `UUID` AS inventoryID, `parentFolderID` AS parentFolderID, `avatarID` AS avatarID, `inventoryGroupPermissions` AS inventoryGroupPermissions FROM old.inventoryitems; - -COMMIT; diff --git a/OpenSim/Data/SQLite/Resources/005_AssetStore.sql b/OpenSim/Data/SQLite/Resources/005_AssetStore.sql deleted file mode 100644 index f06121abc1..0000000000 --- a/OpenSim/Data/SQLite/Resources/005_AssetStore.sql +++ /dev/null @@ -1,5 +0,0 @@ -BEGIN; - -ALTER TABLE assets ADD COLUMN asset_flags INTEGER NOT NULL DEFAULT 0; - -COMMIT; diff --git a/OpenSim/Data/SQLite/Resources/AssetStore.migrations b/OpenSim/Data/SQLite/Resources/AssetStore.migrations index bc11e13d38..f20631cc14 100644 --- a/OpenSim/Data/SQLite/Resources/AssetStore.migrations +++ b/OpenSim/Data/SQLite/Resources/AssetStore.migrations @@ -55,7 +55,7 @@ CREATE TABLE assets( Local, Temporary, asset_flags INTEGER NOT NULL DEFAULT 0, - CreatorID varchar(36) default '', + CreatorID varchar(128) default '', Data); INSERT INTO assets(UUID,Name,Description,Type,Local,Temporary,Data) @@ -64,3 +64,4 @@ DROP TABLE assets_backup; COMMIT; + diff --git a/OpenSim/Data/SQLite/Resources/RegionStore.migrations b/OpenSim/Data/SQLite/Resources/RegionStore.migrations index c47a85d026..c461bf0727 100644 --- a/OpenSim/Data/SQLite/Resources/RegionStore.migrations +++ b/OpenSim/Data/SQLite/Resources/RegionStore.migrations @@ -1,4 +1,4 @@ -:VERSION 1 +:VERSION 1 BEGIN TRANSACTION; @@ -219,59 +219,6 @@ COMMIT; BEGIN TRANSACTION; -CREATE TABLE estate_groups ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estate_managers ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estate_map ( - RegionID char(36) NOT NULL default '00000000-0000-0000-0000-000000000000', - EstateID int(11) NOT NULL -); - -CREATE TABLE estate_settings ( - EstateID INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, - EstateName varchar(64) default NULL, - AbuseEmailToEstateOwner tinyint(4) NOT NULL, - DenyAnonymous tinyint(4) NOT NULL, - ResetHomeOnTeleport tinyint(4) NOT NULL, - FixedSun tinyint(4) NOT NULL, - DenyTransacted tinyint(4) NOT NULL, - BlockDwell tinyint(4) NOT NULL, - DenyIdentified tinyint(4) NOT NULL, - AllowVoice tinyint(4) NOT NULL, - UseGlobalTime tinyint(4) NOT NULL, - PricePerMeter int(11) NOT NULL, - TaxFree tinyint(4) NOT NULL, - AllowDirectTeleport tinyint(4) NOT NULL, - RedirectGridX int(11) NOT NULL, - RedirectGridY int(11) NOT NULL, - ParentEstateID int(10) NOT NULL, - SunPosition double NOT NULL, - EstateSkipScripts tinyint(4) NOT NULL, - BillableFactor float NOT NULL, - PublicAccess tinyint(4) NOT NULL -); -insert into estate_settings (EstateID,EstateName,AbuseEmailToEstateOwner,DenyAnonymous,ResetHomeOnTeleport,FixedSun,DenyTransacted,BlockDwell,DenyIdentified,AllowVoice,UseGlobalTime,PricePerMeter,TaxFree,AllowDirectTeleport,RedirectGridX,RedirectGridY,ParentEstateID,SunPosition,PublicAccess,EstateSkipScripts,BillableFactor) values ( 99, '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', '', ''); -delete from estate_settings; -CREATE TABLE estate_users ( - EstateID int(10) NOT NULL, - uuid char(36) NOT NULL -); - -CREATE TABLE estateban ( - EstateID int(10) NOT NULL, - bannedUUID varchar(36) NOT NULL, - bannedIp varchar(16) NOT NULL, - bannedIpHostMask varchar(16) NOT NULL, - bannedNameMask varchar(64) default NULL -); - drop table regionsettings; CREATE TABLE regionsettings ( regionUUID char(36) NOT NULL, @@ -307,7 +254,7 @@ CREATE TABLE regionsettings ( fixed_sun int(11) NOT NULL, sun_position float NOT NULL, covenant char(36) default NULL, - Sandbox tinyint(4) NOT NULL, + sandbox tinyint(4) NOT NULL, PRIMARY KEY (regionUUID) ); diff --git a/OpenSim/Data/SQLite/Resources/XInventoryStore.migrations b/OpenSim/Data/SQLite/Resources/XInventoryStore.migrations new file mode 100644 index 0000000000..d5b3019c76 --- /dev/null +++ b/OpenSim/Data/SQLite/Resources/XInventoryStore.migrations @@ -0,0 +1,51 @@ +:VERSION 1 + +BEGIN TRANSACTION; + +CREATE TABLE inventoryfolders( + folderName varchar(64), + type integer, + version integer, + folderID varchar(36) primary key, + agentID varchar(36) not null default '00000000-0000-0000-0000-000000000000', + parentFolderID varchar(36) not null default '00000000-0000-0000-0000-000000000000'); + +CREATE TABLE inventoryitems( + assetID varchar(36), + assetType integer, + inventoryName varchar(64), + inventoryDescription varchar(128), + inventoryNextPermissions integer, + inventoryCurrentPermissions integer, + invType integer, + creatorID varchar(128), + inventoryBasePermissions integer, + inventoryEveryOnePermissions integer, + salePrice integer default 99, + saleType integer default 0, + creationDate integer default 2000, + groupID varchar(36) default '00000000-0000-0000-0000-000000000000', + groupOwned integer default 0, + flags integer default 0, + inventoryID varchar(36) primary key, + parentFolderID varchar(36) not null default '00000000-0000-0000-0000-000000000000', + avatarID varchar(36) not null default '00000000-0000-0000-0000-000000000000', + inventoryGroupPermissions integer not null default 0); + +create index inventoryfolders_agentid on inventoryfolders(agentID); +create index inventoryfolders_parentid on inventoryfolders(parentFolderID); +create index inventoryitems_parentfolderid on inventoryitems(parentFolderID); +create index inventoryitems_avatarid on inventoryitems(avatarID); + +COMMIT; + +:VERSION 2 + +ATTACH 'inventoryStore.db' AS old; + +BEGIN TRANSACTION; + +INSERT INTO inventoryfolders (folderName, type, version, folderID, agentID, parentFolderID) SELECT `name` AS folderName, `type` AS type, `version` AS version, `UUID` AS folderID, `agentID` AS agentID, `parentID` AS parentFolderID from old.inventoryfolders; +INSERT INTO inventoryitems (assetID, assetType, inventoryName, inventoryDescription, inventoryNextPermissions, inventoryCurrentPermissions, invType, creatorID, inventoryBasePermissions, inventoryEveryOnePermissions, salePrice, saleType, creationDate, groupID, groupOwned, flags, inventoryID, parentFolderID, avatarID, inventoryGroupPermissions) SELECT `assetID`, `assetType` AS assetType, `inventoryName` AS inventoryName, `inventoryDescription` AS inventoryDescription, `inventoryNextPermissions` AS inventoryNextPermissions, `inventoryCurrentPermissions` AS inventoryCurrentPermissions, `invType` AS invType, `creatorsID` AS creatorID, `inventoryBasePermissions` AS inventoryBasePermissions, `inventoryEveryOnePermissions` AS inventoryEveryOnePermissions, `salePrice` AS salePrice, `saleType` AS saleType, `creationDate` AS creationDate, `groupID` AS groupID, `groupOwned` AS groupOwned, `flags` AS flags, `UUID` AS inventoryID, `parentFolderID` AS parentFolderID, `avatarID` AS avatarID, `inventoryGroupPermissions` AS inventoryGroupPermissions FROM old.inventoryitems; + +COMMIT; \ No newline at end of file diff --git a/OpenSim/Data/SQLite/SQLiteEstateData.cs b/OpenSim/Data/SQLite/SQLiteEstateData.cs index 9dd4a2e69b..fcf041e41f 100644 --- a/OpenSim/Data/SQLite/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLite/SQLiteEstateData.cs @@ -328,7 +328,7 @@ namespace OpenSim.Data.SQLite public EstateSettings LoadEstateSettings(int estateID) { - string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID = :EstateID"; SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); @@ -342,7 +342,7 @@ namespace OpenSim.Data.SQLite { List result = new List(); - string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; + string sql = "select EstateID from estate_settings where estate_settings.EstateName = :EstateName"; SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); diff --git a/OpenSim/Data/SQLite/SQLiteRegionData.cs b/OpenSim/Data/SQLite/SQLiteRegionData.cs index 85703dc2ca..81d0ac4f6e 100644 --- a/OpenSim/Data/SQLite/SQLiteRegionData.cs +++ b/OpenSim/Data/SQLite/SQLiteRegionData.cs @@ -93,7 +93,7 @@ namespace OpenSim.Data.SQLite ds = new DataSet("Region"); - m_log.Info("[REGION DB]: Sqlite - connecting: " + connectionString); + m_log.Info("[SQLITE REGION DB]: Sqlite - connecting: " + connectionString); m_conn = new SqliteConnection(m_connectionString); m_conn.Open(); @@ -156,7 +156,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on prims table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on prims table"); } try @@ -165,16 +165,25 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on primshapes table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on primshapes table"); } + try + { + itemsDa.Fill(ds.Tables["primitems"]); + } + catch (Exception) + { + m_log.Info("[SQLITE REGION DB]: Caught fill error on primitems table"); + } + try { terrainDa.Fill(ds.Tables["terrain"]); } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on terrain table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on terrain table"); } try @@ -183,7 +192,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on land table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on land table"); } try @@ -192,7 +201,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on landaccesslist table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on landaccesslist table"); } try @@ -201,7 +210,7 @@ namespace OpenSim.Data.SQLite } catch (Exception) { - m_log.Info("[REGION DB]: Caught fill error on regionsettings table"); + m_log.Info("[SQLITE REGION DB]: Caught fill error on regionsettings table"); } // We have to create a data set mapping for every table, otherwise the IDataAdaptor.Update() will not populate rows with values! @@ -434,7 +443,7 @@ namespace OpenSim.Data.SQLite lock (ds) { DataRow[] primsForRegion = prims.Select(byRegion); - m_log.Info("[REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); +// m_log.Info("[SQLITE REGION DB]: Loaded " + primsForRegion.Length + " prims for region: " + regionUUID); // First, create all groups foreach (DataRow primRow in primsForRegion) @@ -456,8 +465,8 @@ namespace OpenSim.Data.SQLite } else { - m_log.Info( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + m_log.Warn( + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); prim.Shape = PrimitiveBaseShape.Default; } @@ -469,11 +478,11 @@ namespace OpenSim.Data.SQLite } catch (Exception e) { - m_log.Error("[REGION DB]: Failed create prim object in new group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); + m_log.Error("[SQLITE REGION DB]: Failed create prim object in new group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); foreach (DataColumn col in prims.Columns) { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); } } } @@ -498,7 +507,7 @@ namespace OpenSim.Data.SQLite else { m_log.Warn( - "[REGION DB]: No shape found for prim in storage, so setting default box shape"); + "[SQLITE REGION DB]: No shape found for prim in storage, so setting default box shape"); prim.Shape = PrimitiveBaseShape.Default; } @@ -508,11 +517,11 @@ namespace OpenSim.Data.SQLite } catch (Exception e) { - m_log.Error("[REGION DB]: Failed create prim object in group, exception and data follows"); - m_log.Info("[REGION DB]: " + e.ToString()); + m_log.Error("[SQLITE REGION DB]: Failed create prim object in group, exception and data follows"); + m_log.Error("[SQLITE REGION DB]: ", e); foreach (DataColumn col in prims.Columns) { - m_log.Info("[REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); + m_log.Error("[SQLITE REGION DB]: Col: " + col.ColumnName + " => " + primRow[col]); } } } @@ -525,20 +534,23 @@ namespace OpenSim.Data.SQLite /// /// the prim private void LoadItems(SceneObjectPart prim) - { - //m_log.DebugFormat("[DATASTORE]: Loading inventory for {0}, {1}", prim.Name, prim.UUID); - + { +// m_log.DebugFormat("[SQLITE REGION DB]: Loading inventory for {0} {1}", prim.Name, prim.UUID); + DataTable dbItems = ds.Tables["primitems"]; - String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); + String sql = String.Format("primID = '{0}'", prim.UUID.ToString()); DataRow[] dbItemRows = dbItems.Select(sql); IList inventory = new List(); +// m_log.DebugFormat( +// "[SQLITE REGION DB]: Found {0} items for {1} {2}", dbItemRows.Length, prim.Name, prim.UUID); + foreach (DataRow row in dbItemRows) { TaskInventoryItem item = buildItem(row); inventory.Add(item); - //m_log.DebugFormat("[DATASTORE]: Restored item {0}, {1}", item.Name, item.ItemID); +// m_log.DebugFormat("[SQLITE REGION DB]: Restored item {0} {1}", item.Name, item.ItemID); } prim.Inventory.RestoreInventoryItems(inventory); @@ -574,7 +586,7 @@ namespace OpenSim.Data.SQLite // the following is an work around for .NET. The perf // issues associated with it aren't as bad as you think. - m_log.Info("[REGION DB]: Storing terrain revision r" + revision.ToString()); + m_log.Debug("[SQLITE REGION DB]: Storing terrain revision r" + revision.ToString()); String sql = "insert into terrain(RegionUUID, Revision, Heightfield)" + " values(:RegionUUID, :Revision, :Heightfield)"; @@ -630,11 +642,11 @@ namespace OpenSim.Data.SQLite } else { - m_log.Info("[REGION DB]: No terrain found for region"); + m_log.Warn("[SQLITE REGION DB]: No terrain found for region"); return null; } - m_log.Info("[REGION DB]: Loaded terrain revision r" + rev.ToString()); + m_log.Debug("[SQLITE REGION DB]: Loaded terrain revision r" + rev.ToString()); } } return terret; @@ -1417,7 +1429,7 @@ namespace OpenSim.Data.SQLite } catch (InvalidCastException) { - m_log.ErrorFormat("[PARCEL]: unable to get parcel telehub settings for {1}", newData.Name); + m_log.ErrorFormat("[SQLITE REGION DB]: unable to get parcel telehub settings for {1}", newData.Name); newData.UserLocation = Vector3.Zero; newData.UserLookAt = Vector3.Zero; } @@ -1926,7 +1938,7 @@ namespace OpenSim.Data.SQLite /// public void StorePrimInventory(UUID primID, ICollection items) { - //m_log.InfoFormat("[REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); +// m_log.DebugFormat("[SQLITE REGION DB]: Entered StorePrimInventory with prim ID {0}", primID); DataTable dbItems = ds.Tables["primitems"]; diff --git a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs index 6064538990..ca651e1998 100644 --- a/OpenSim/Data/SQLite/SQLiteXInventoryData.cs +++ b/OpenSim/Data/SQLite/SQLiteXInventoryData.cs @@ -66,11 +66,19 @@ namespace OpenSim.Data.SQLite public bool StoreFolder(XInventoryFolder folder) { + if (folder.folderName.Length > 64) + folder.folderName = folder.folderName.Substring(0, 64); + return m_Folders.Store(folder); } public bool StoreItem(XInventoryItem item) { + if (item.inventoryName.Length > 64) + item.inventoryName = item.inventoryName.Substring(0, 64); + if (item.inventoryDescription.Length > 128) + item.inventoryDescription = item.inventoryDescription.Substring(0, 128); + return m_Items.Store(item); } diff --git a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs index e135eaa524..bf8ee147b5 100644 --- a/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs +++ b/OpenSim/Data/SQLiteLegacy/SQLiteEstateData.cs @@ -328,7 +328,7 @@ namespace OpenSim.Data.SQLiteLegacy public EstateSettings LoadEstateSettings(int estateID) { - string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID :EstateID"; + string sql = "select estate_settings."+String.Join(",estate_settings.", FieldList)+" from estate_settings where estate_settings.EstateID = :EstateID"; SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); @@ -342,7 +342,7 @@ namespace OpenSim.Data.SQLiteLegacy { List result = new List(); - string sql = "select EstateID from estate_settings where estate_settings.EstateName :EstateName"; + string sql = "select EstateID from estate_settings where estate_settings.EstateName = :EstateName"; SqliteCommand cmd = (SqliteCommand)m_connection.CreateCommand(); diff --git a/OpenSim/Data/Tests/RegionTests.cs b/OpenSim/Data/Tests/RegionTests.cs index 1f654d316b..eeffddaa1b 100644 --- a/OpenSim/Data/Tests/RegionTests.cs +++ b/OpenSim/Data/Tests/RegionTests.cs @@ -781,7 +781,7 @@ namespace OpenSim.Data.Tests // Ownership changes when you drop an object into an object // owned by someone else Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID), "Assert.That(t.OwnerID,Is.EqualTo(sog.RootPart.OwnerID))"); - Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8), "Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8))"); +// Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 16), "Assert.That(t.CurrentPermissions, Is.EqualTo(curperm | 8))"); Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID), "Assert.That(t.ParentID,Is.EqualTo(sog.RootPart.FolderID))"); Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID), "Assert.That(t.ParentPartID,Is.EqualTo(sog.RootPart.UUID))"); } diff --git a/OpenSim/Data/Tests/Resources/TestDataConnections.ini b/OpenSim/Data/Tests/Resources/TestDataConnections.ini index 5e68ab0ac1..7b55467734 100644 --- a/OpenSim/Data/Tests/Resources/TestDataConnections.ini +++ b/OpenSim/Data/Tests/Resources/TestDataConnections.ini @@ -21,4 +21,4 @@ [TestConnections] MySqlConnection="Server=localhost;Port=3306;Database=opensim-nunit;User ID=opensim-nunit;Password=opensim-nunit;" SqlConnection="Server=.\SQL2008;Database=opensim-nunit;Trusted_Connection=True;" -SqliteConnection="" \ No newline at end of file +SqliteConnection="URI=file:opensim-nunit.db,version=3" \ No newline at end of file diff --git a/OpenSim/Framework/Capabilities/Caps.cs b/OpenSim/Framework/Capabilities/Caps.cs index 62a1e17f50..da953bbef0 100644 --- a/OpenSim/Framework/Capabilities/Caps.cs +++ b/OpenSim/Framework/Capabilities/Caps.cs @@ -814,7 +814,7 @@ namespace OpenSim.Framework.Capabilities if (mm != null) { - if (!mm.UploadCovered(client)) + if (!mm.UploadCovered(client, mm.UploadCharge)) { if (client != null) client.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); diff --git a/OpenSim/Framework/ChildAgentDataUpdate.cs b/OpenSim/Framework/ChildAgentDataUpdate.cs index a1ac84c039..89ee39cecc 100644 --- a/OpenSim/Framework/ChildAgentDataUpdate.cs +++ b/OpenSim/Framework/ChildAgentDataUpdate.cs @@ -265,6 +265,46 @@ namespace OpenSim.Framework } } + public class ControllerData + { + public UUID ItemID; + public uint IgnoreControls; + public uint EventControls; + + public ControllerData(UUID item, uint ignore, uint ev) + { + ItemID = item; + IgnoreControls = ignore; + EventControls = ev; + } + + public ControllerData(OSDMap args) + { + UnpackUpdateMessage(args); + } + + public OSDMap PackUpdateMessage() + { + OSDMap controldata = new OSDMap(); + controldata["item"] = OSD.FromUUID(ItemID); + controldata["ignore"] = OSD.FromInteger(IgnoreControls); + controldata["event"] = OSD.FromInteger(EventControls); + + return controldata; + } + + + public void UnpackUpdateMessage(OSDMap args) + { + if (args["item"] != null) + ItemID = args["item"].AsUUID(); + if (args["ignore"] != null) + IgnoreControls = (uint)args["ignore"].AsInteger(); + if (args["event"] != null) + EventControls = (uint)args["event"].AsInteger(); + } + } + public class AgentData : IAgentData { private UUID m_id; @@ -313,6 +353,9 @@ namespace OpenSim.Framework public UUID[] Wearables; public AttachmentData[] Attachments; + // Scripted + public ControllerData[] Controllers; + public string CallbackURI; public virtual OSDMap Pack() @@ -403,6 +446,14 @@ namespace OpenSim.Framework args["attachments"] = attachs; } + if ((Controllers != null) && (Controllers.Length > 0)) + { + OSDArray controls = new OSDArray(Controllers.Length); + foreach (ControllerData ctl in Controllers) + controls.Add(ctl.PackUpdateMessage()); + args["controllers"] = controls; + } + if ((CallbackURI != null) && (!CallbackURI.Equals(""))) args["callback_uri"] = OSD.FromString(CallbackURI); @@ -559,6 +610,20 @@ namespace OpenSim.Framework } } + if ((args["controllers"] != null) && (args["controllers"]).Type == OSDType.Array) + { + OSDArray controls = (OSDArray)(args["controllers"]); + Controllers = new ControllerData[controls.Count]; + int i = 0; + foreach (OSD o in controls) + { + if (o.Type == OSDType.Map) + { + Controllers[i++] = new ControllerData((OSDMap)o); + } + } + } + if (args["callback_uri"] != null) CallbackURI = args["callback_uri"].AsString(); } diff --git a/OpenSim/Framework/Console/RemoteConsole.cs b/OpenSim/Framework/Console/RemoteConsole.cs index 6f8348de66..c038aaca5c 100644 --- a/OpenSim/Framework/Console/RemoteConsole.cs +++ b/OpenSim/Framework/Console/RemoteConsole.cs @@ -44,6 +44,7 @@ namespace OpenSim.Framework.Console { public int last; public long lastLineSeen; + public bool newConnection = true; } // A console that uses REST interfaces @@ -106,8 +107,15 @@ namespace OpenSim.Framework.Console public override string ReadLine(string p, bool isCommand, bool e) { + if (isCommand) + Output("+++"+p); + else + Output("-++"+p); + m_DataEvent.WaitOne(); + string cmdinput; + lock (m_InputData) { if (m_InputData.Count == 0) @@ -116,29 +124,30 @@ namespace OpenSim.Framework.Console return ""; } - string cmdinput = m_InputData[0]; + cmdinput = m_InputData[0]; m_InputData.RemoveAt(0); if (m_InputData.Count == 0) m_DataEvent.Reset(); - if (isCommand) - { - string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); - - if (cmd.Length != 0) - { - int i; - - for (i=0 ; i < cmd.Length ; i++) - { - if (cmd[i].Contains(" ")) - cmd[i] = "\"" + cmd[i] + "\""; - } - return String.Empty; - } - } - return cmdinput; } + + if (isCommand) + { + string[] cmd = Commands.Resolve(Parser.Parse(cmdinput)); + + if (cmd.Length != 0) + { + int i; + + for (i=0 ; i < cmd.Length ; i++) + { + if (cmd[i].Contains(" ")) + cmd[i] = "\"" + cmd[i] + "\""; + } + return String.Empty; + } + } + return cmdinput; } private void DoExpire() @@ -308,7 +317,7 @@ namespace OpenSim.Framework.Console return reply; } - if (post["COMMAND"] == null || post["COMMAND"].ToString() == String.Empty) + if (post["COMMAND"] == null) return reply; lock (m_InputData) @@ -416,6 +425,12 @@ namespace OpenSim.Framework.Console XmlElement rootElement = xmldoc.CreateElement("", "ConsoleSession", ""); + if (c.newConnection) + { + c.newConnection = false; + Output("+++" + DefaultPrompt); + } + lock (m_Scrollback) { long startLine = m_LineNumber - m_Scrollback.Count; diff --git a/OpenSim/Framework/IClientAPI.cs b/OpenSim/Framework/IClientAPI.cs index c1333fc285..db745481bc 100644 --- a/OpenSim/Framework/IClientAPI.cs +++ b/OpenSim/Framework/IClientAPI.cs @@ -57,7 +57,7 @@ namespace OpenSim.Framework RezMultipleAttachmentsFromInvPacket.ObjectDataBlock[] objects); public delegate void ObjectAttach( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent); public delegate void ModifyTerrain(UUID user, float height, float seconds, byte size, byte action, float north, float west, float south, float east, @@ -1017,7 +1017,6 @@ namespace OpenSim.Framework void SendCoarseLocationUpdate(List users, List CoarseLocations); - void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID); void SetChildAgentThrottle(byte[] throttle); void SendAvatarDataImmediate(ISceneEntity avatar); @@ -1308,5 +1307,7 @@ namespace OpenSim.Framework void SendChangeUserRights(UUID agentID, UUID friendID, int rights); void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId); + + void StopFlying(ISceneEntity presence); } } diff --git a/OpenSim/Framework/IMoneyModule.cs b/OpenSim/Framework/IMoneyModule.cs index 3480960aa1..3d4873df0c 100644 --- a/OpenSim/Framework/IMoneyModule.cs +++ b/OpenSim/Framework/IMoneyModule.cs @@ -35,35 +35,15 @@ namespace OpenSim.Framework bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount); - int GetBalance(IClientAPI client); - void ApplyUploadCharge(UUID agentID); - bool UploadCovered(IClientAPI client); - void ApplyGroupCreationCharge(UUID agentID); - bool GroupCreationCovered(IClientAPI client); + int GetBalance(UUID agentID); + bool UploadCovered(IClientAPI client, int amount); bool AmountCovered(IClientAPI client, int amount); void ApplyCharge(UUID agentID, int amount, string text); + void ApplyUploadCharge(UUID agentID, int amount, string text); - EconomyData GetEconomyData(); + int UploadCharge { get; } + int GroupCreationCharge { get; } event ObjectPaid OnObjectPaid; } - - public struct EconomyData - { - public int ObjectCapacity; - public int ObjectCount; - public int PriceEnergyUnit; - public int PriceGroupCreate; - public int PriceObjectClaim; - public float PriceObjectRent; - public float PriceObjectScaleFactor; - public int PriceParcelClaim; - public float PriceParcelClaimFactor; - public int PriceParcelRent; - public int PricePublicObjectDecay; - public int PricePublicObjectDelete; - public int PriceRentLight; - public int PriceUpload; - public int TeleportMinPrice; - } } diff --git a/OpenSim/Framework/RegionInfo.cs b/OpenSim/Framework/RegionInfo.cs index ad988165eb..afc4060044 100644 --- a/OpenSim/Framework/RegionInfo.cs +++ b/OpenSim/Framework/RegionInfo.cs @@ -29,14 +29,15 @@ using System; using System.Collections.Generic; using System.Net; using System.Net.Sockets; +using System.Reflection; using System.Xml; using System.IO; +using log4net; using Nini.Config; using OpenMetaverse; using OpenMetaverse.StructuredData; using OpenSim.Framework.Console; - namespace OpenSim.Framework { public class RegionLightShareData : ICloneable @@ -96,10 +97,9 @@ namespace OpenSim.Framework [Serializable] public class SimpleRegionInfo - { - // private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); - + { +// private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); + /// /// The port by which http communication occurs with the region (most noticeably, CAPS communication) /// @@ -327,8 +327,7 @@ namespace OpenSim.Framework public class RegionInfo { - // private static readonly log4net.ILog m_log - // = log4net.LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); public bool commFailTF = false; public ConfigurationMember configMember; @@ -772,9 +771,16 @@ namespace OpenSim.Framework } if (externalName == "SYSTEMIP") + { m_externalHostName = Util.GetLocalHost().ToString(); + m_log.InfoFormat( + "[REGIONINFO]: Resolving SYSTEMIP to {0} for external hostname of region {1}", + m_externalHostName, name); + } else + { m_externalHostName = externalName; + } m_regionType = config.GetString("RegionType", String.Empty); diff --git a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs index a6e00c2251..8123f2fed7 100644 --- a/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs +++ b/OpenSim/Framework/Servers/HttpServer/BaseHttpServer.cs @@ -310,7 +310,7 @@ namespace OpenSim.Framework.Servers.HttpServer } catch (Exception e) { - m_log.Error(string.Format("[BASE HTTP SERVER]: OnRequest() failed with "), e); + m_log.ErrorFormat("[BASE HTTP SERVER]: OnRequest() failed with {0}{1}", e.Message, e.StackTrace); } } diff --git a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs index 1cc19c5719..b91496be2a 100644 --- a/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs +++ b/OpenSim/Framework/Servers/HttpServer/PollServiceWorkerThread.cs @@ -73,7 +73,18 @@ namespace OpenSim.Framework.Servers.HttpServer { if (req.PollServiceArgs.HasEvents(req.RequestID, req.PollServiceArgs.Id)) { - StreamReader str = new StreamReader(req.Request.Body); + StreamReader str; + try + { + str = new StreamReader(req.Request.Body); + } + catch (System.ArgumentException) + { + // Stream was not readable means a child agent + // was closed due to logout, leaving the + // Event Queue request orphaned. + continue; + } Hashtable responsedata = req.PollServiceArgs.GetEvents(req.RequestID, req.PollServiceArgs.Id, str.ReadToEnd()); m_server.DoHTTPGruntWork(responsedata, @@ -106,4 +117,4 @@ namespace OpenSim.Framework.Servers.HttpServer m_request.Enqueue(pPollServiceHttpRequest); } } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/Servers/VersionInfo.cs b/OpenSim/Framework/Servers/VersionInfo.cs index 90b5f57929..100bf1fd52 100644 --- a/OpenSim/Framework/Servers/VersionInfo.cs +++ b/OpenSim/Framework/Servers/VersionInfo.cs @@ -29,7 +29,7 @@ namespace OpenSim { public class VersionInfo { - private const string VERSION_NUMBER = "0.7"; + private const string VERSION_NUMBER = "0.7.1"; private const Flavour VERSION_FLAVOUR = Flavour.Dev; public enum Flavour @@ -71,4 +71,4 @@ namespace OpenSim /// public readonly static int MajorInterfaceVersion = 6; } -} \ No newline at end of file +} diff --git a/OpenSim/Framework/WebUtil.cs b/OpenSim/Framework/WebUtil.cs index 94862a6372..e20866eaa3 100644 --- a/OpenSim/Framework/WebUtil.cs +++ b/OpenSim/Framework/WebUtil.cs @@ -114,7 +114,7 @@ namespace OpenSim.Framework } catch (Exception ex) { - m_log.Warn("GET from URL " + url + " failed: " + ex.Message); + m_log.Warn(httpVerb + " on URL " + url + " failed: " + ex.Message); errorMessage = ex.Message; } diff --git a/OpenSim/Region/Application/OpenSim.cs b/OpenSim/Region/Application/OpenSim.cs index a09b903bfc..501d47f6d1 100644 --- a/OpenSim/Region/Application/OpenSim.cs +++ b/OpenSim/Region/Application/OpenSim.cs @@ -192,9 +192,7 @@ namespace OpenSim // Hook up to the watchdog timer Watchdog.OnWatchdogTimeout += WatchdogTimeoutHandler; - PrintFileToConsole("startuplogo.txt"); - - m_log.InfoFormat("[NETWORK]: Using {0} as SYSTEMIP", Util.GetLocalHost().ToString()); + PrintFileToConsole("startuplogo.txt"); // For now, start at the 'root' level by default if (m_sceneManager.Scenes.Count == 1) // If there is only one region, select it diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs index 83be61ee63..f535fe805a 100644 --- a/OpenSim/Region/Application/OpenSimBase.cs +++ b/OpenSim/Region/Application/OpenSimBase.cs @@ -367,13 +367,13 @@ namespace OpenSim Environment.Exit(1); } + scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); + scene.EventManager.TriggerParcelPrimCountUpdate(); + // We need to do this after we've initialized the // scripting engines. scene.CreateScriptInstances(); - scene.loadAllLandObjectsFromStorage(regionInfo.originRegionID); - scene.EventManager.TriggerParcelPrimCountUpdate(); - m_sceneManager.Add(scene); if (m_autoCreateClientStack) diff --git a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs index 9869a99418..e9e2dca34b 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/J2KImage.cs @@ -55,7 +55,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP public IJ2KDecoder J2KDecoder; public IAssetService AssetService; public UUID AgentID; - public IHyperAssetService HyperAssets; + public IInventoryAccessModule InventoryAccessModule; public OpenJPEG.J2KLayerInfo[] Layers; public bool IsDecoded; public bool HasAsset; @@ -375,14 +375,18 @@ namespace OpenSim.Region.ClientStack.LindenUDP UUID assetID = UUID.Zero; if (asset != null) assetID = asset.FullID; - else if ((HyperAssets != null) && (sender != HyperAssets)) + else if ((InventoryAccessModule != null) && (sender != InventoryAccessModule)) { - // Try the user's inventory, but only if it's different from the regions' - string userAssets = HyperAssets.GetUserAssetServer(AgentID); - if ((userAssets != string.Empty) && (userAssets != HyperAssets.GetSimAssetServer())) + // Unfortunately we need this here, there's no other way. + // This is due to the fact that textures opened directly from the agent's inventory + // don't have any distinguishing feature. As such, in order to serve those when the + // foreign user is visiting, we need to try again after the first fail to the local + // asset service. + string assetServerURL = string.Empty; + if (InventoryAccessModule.IsForeignUser(AgentID, out assetServerURL)) { m_log.DebugFormat("[J2KIMAGE]: texture {0} not found in local asset storage. Trying user's storage.", id); - AssetService.Get(userAssets + "/" + id, HyperAssets, AssetReceived); + AssetService.Get(assetServerURL + "/" + id, InventoryAccessModule, AssetReceived); return; } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs index a516a54ca4..0aec01a021 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLClientView.cs @@ -331,6 +331,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected HashSet m_killRecord; +// protected HashSet m_attachmentsSent; + private int m_moneyBalance; private int m_animationSequenceNumber = 1; private bool m_SendLogoutPacketWhenClosing = true; @@ -355,7 +357,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP protected uint m_agentFOVCounter; protected IAssetService m_assetService; - private IHyperAssetService m_hyperAssets; private const bool m_checkPackets = true; private Timer m_propertiesPacketTimer; @@ -427,9 +428,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_entityUpdates = new PriorityQueue(m_scene.Entities.Count); m_fullUpdateDataBlocksBuilder = new List(); m_killRecord = new HashSet(); +// m_attachmentsSent = new HashSet(); m_assetService = m_scene.RequestModuleInterface(); - m_hyperAssets = m_scene.RequestModuleInterface(); m_GroupsModule = scene.RequestModuleInterface(); m_imageManager = new LLImageManager(this, m_assetService, Scene.RequestModuleInterface()); m_channelVersion = Util.StringToBytes256(scene.GetSimulatorVersion()); @@ -3411,6 +3412,9 @@ namespace OpenSim.Region.ClientStack.LindenUDP objupdate.ObjectData[0] = CreateAvatarUpdateBlock(presence); OutPacket(objupdate, ThrottleOutPacketType.Task); + + // We need to record the avatar local id since the root prim of an attachment points to this. +// m_attachmentsSent.Add(avatar.LocalId); } public void SendCoarseLocationUpdate(List users, List CoarseLocations) @@ -3420,7 +3424,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP CoarseLocationUpdatePacket loc = (CoarseLocationUpdatePacket)PacketPool.Instance.GetPacket(PacketType.CoarseLocationUpdate); loc.Header.Reliable = false; - // Each packet can only hold around 62 avatar positions and the client clears the mini-map each time + // Each packet can only hold around 60 avatar positions and the client clears the mini-map each time // a CoarseLocationUpdate packet is received. Oh well. int total = Math.Min(CoarseLocations.Count, 60); @@ -3466,7 +3470,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP double priority = m_prioritizer.GetUpdatePriority(this, entity); lock (m_entityUpdates.SyncRoot) - m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId); + m_entityUpdates.Enqueue(priority, new EntityUpdate(entity, updateFlags), entity.LocalId); } private void ProcessEntityUpdates(int maxUpdates) @@ -3542,9 +3546,42 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (!canUseImproved && !canUseCompressed) { if (update.Entity is ScenePresence) + { objectUpdateBlocks.Value.Add(CreateAvatarUpdateBlock((ScenePresence)update.Entity)); + } else - objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); + { +// if (update.Entity is SceneObjectPart && ((SceneObjectPart)update.Entity).IsAttachment) +// { +// SceneObjectPart sop = (SceneObjectPart)update.Entity; +// string text = sop.Text; +// if (text.IndexOf("\n") >= 0) +// text = text.Remove(text.IndexOf("\n")); +// +// if (m_attachmentsSent.Contains(sop.ParentID)) +// { +//// m_log.DebugFormat( +//// "[CLIENT]: Sending full info about attached prim {0} text {1}", +//// sop.LocalId, text); +// +// objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock(sop, this.m_agentId)); +// +// m_attachmentsSent.Add(sop.LocalId); +// } +// else +// { +// m_log.DebugFormat( +// "[CLIENT]: Requeueing full update of prim {0} text {1} since we haven't sent its parent {2} yet", +// sop.LocalId, text, sop.ParentID); +// +// m_entityUpdates.Enqueue(double.MaxValue, update, sop.LocalId); +// } +// } +// else +// { + objectUpdateBlocks.Value.Add(CreatePrimUpdateBlock((SceneObjectPart)update.Entity, this.m_agentId)); +// } + } } else if (!canUseImproved) { @@ -3641,30 +3678,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP #endregion Primitive Packet/Data Sending Methods - /// - /// - /// - /// - /// - /// - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - if (attachPoint > 30 && ownerID != AgentId) // Someone else's HUD - return; - - ObjectAttachPacket attach = (ObjectAttachPacket)PacketPool.Instance.GetPacket(PacketType.ObjectAttach); - // TODO: don't create new blocks if recycling an old packet - attach.AgentData.AgentID = AgentId; - attach.AgentData.SessionID = m_sessionId; - attach.AgentData.AttachmentPoint = attachPoint; - attach.ObjectData = new ObjectAttachPacket.ObjectDataBlock[1]; - attach.ObjectData[0] = new ObjectAttachPacket.ObjectDataBlock(); - attach.ObjectData[0].ObjectLocalID = localID; - attach.ObjectData[0].Rotation = rotation; - attach.Header.Zerocoded = true; - OutPacket(attach, ThrottleOutPacketType.Task); - } - void HandleQueueEmpty(ThrottleOutPacketTypeFlags categories) { if ((categories & ThrottleOutPacketTypeFlags.Task) != 0) @@ -5694,7 +5707,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP { if (att.ObjectData.Length > 0) { - handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, att.ObjectData[0].Rotation, false); + handlerObjectAttach(this, att.ObjectData[0].ObjectLocalID, att.AgentData.AttachmentPoint, false); } } } @@ -6264,8 +6277,8 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerObjectDuplicate != null) { handlerObjectDuplicate(dupe.ObjectData[i].ObjectLocalID, dupe.SharedData.Offset, - dupe.SharedData.DuplicateFlags, AgentandGroupData.AgentID, - AgentandGroupData.GroupID); + dupe.SharedData.DuplicateFlags, AgentId, + m_activeGroupID); } } @@ -6855,7 +6868,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP if (handlerObjectDuplicateOnRay != null) { handlerObjectDuplicateOnRay(dupeOnRay.ObjectData[i].ObjectLocalID, dupeOnRay.AgentData.DuplicateFlags, - dupeOnRay.AgentData.AgentID, dupeOnRay.AgentData.GroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, + AgentId, m_activeGroupID, dupeOnRay.AgentData.RayTargetID, dupeOnRay.AgentData.RayEnd, dupeOnRay.AgentData.RayStart, dupeOnRay.AgentData.BypassRaycast, dupeOnRay.AgentData.RayEndIsIntersection, dupeOnRay.AgentData.CopyCenters, dupeOnRay.AgentData.CopyRotates); } @@ -7157,59 +7170,22 @@ namespace OpenSim.Region.ClientStack.LindenUDP } else // Agent { - IInventoryService invService = m_scene.RequestModuleInterface(); - InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, AgentId); - assetRequestItem = invService.GetItem(assetRequestItem); - if (assetRequestItem == null) + IInventoryAccessModule invAccess = m_scene.RequestModuleInterface(); + if (invAccess != null) { - ILibraryService lib = m_scene.RequestModuleInterface(); - if (lib != null) - assetRequestItem = lib.LibraryRootFolder.FindItem(itemID); - if (assetRequestItem == null) - return true; - } + if (!invAccess.GetAgentInventoryItem(this, itemID, requestID)) + return false; - // At this point, we need to apply perms - // only to notecards and scripts. All - // other asset types are always available - // - if (assetRequestItem.AssetType == (int)AssetType.LSLText) - { - if (!((Scene)m_scene).Permissions.CanViewScript(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view script", false); - return true; - } - } - else if (assetRequestItem.AssetType == (int)AssetType.Notecard) - { - if (!((Scene)m_scene).Permissions.CanViewNotecard(itemID, UUID.Zero, AgentId)) - { - SendAgentAlertMessage("Insufficient permissions to view notecard", false); - return true; - } } + else + return false; - if (assetRequestItem.AssetID != requestID) - { - m_log.WarnFormat( - "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", - Name, requestID, itemID, assetRequestItem.AssetID); - return true; - } } } } - //m_assetCache.AddAssetRequest(this, transfer); - MakeAssetRequest(transfer, taskID); - /* RequestAsset = OnRequestAsset; - if (RequestAsset != null) - { - RequestAsset(this, transfer); - }*/ return true; } @@ -11420,15 +11396,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { requestID = new UUID(transferRequest.TransferInfo.Params, 80); - //m_log.Debug("[XXX] inventory asset request " + requestID); - //if (taskID == UUID.Zero) // Agent - // if (m_scene is HGScene) - // { - // m_log.Debug("[XXX] hg asset request " + requestID); - // // We may need to fetch the asset from the user's asset server into the local asset server - // HGAssetMapper mapper = ((HGScene)m_scene).AssetMapper; - // mapper.Get(requestID, AgentId); - // } } // m_log.DebugFormat("[CLIENT]: {0} requesting asset {1}", Name, requestID); @@ -11444,49 +11411,25 @@ namespace OpenSim.Region.ClientStack.LindenUDP /// protected void AssetReceived(string id, Object sender, AssetBase asset) { + if (asset == null) + return; + TransferRequestPacket transferRequest = (TransferRequestPacket)sender; UUID requestID = UUID.Zero; byte source = (byte)SourceType.Asset; - if ((transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) - || (transferRequest.TransferInfo.SourceType == 2222)) + if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) { requestID = new UUID(transferRequest.TransferInfo.Params, 0); } - else if ((transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) - || (transferRequest.TransferInfo.SourceType == 3333)) + else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) { requestID = new UUID(transferRequest.TransferInfo.Params, 80); source = (byte)SourceType.SimInventoryItem; //m_log.Debug("asset request " + requestID); } - if (null == asset) - { - if ((m_hyperAssets != null) && (transferRequest.TransferInfo.SourceType < 2000)) - { - // Try the user's inventory, but only if it's different from the regions' - string userAssets = m_hyperAssets.GetUserAssetServer(AgentId); - if ((userAssets != string.Empty) && (userAssets != m_hyperAssets.GetSimAssetServer())) - { - m_log.DebugFormat("[CLIENT]: asset {0} not found in local asset storage. Trying user's storage.", id); - if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset) - transferRequest.TransferInfo.SourceType = 2222; // marker - else if (transferRequest.TransferInfo.SourceType == (int)SourceType.SimInventoryItem) - transferRequest.TransferInfo.SourceType = 3333; // marker - - m_assetService.Get(userAssets + "/" + id, transferRequest, AssetReceived); - return; - } - } - - //m_log.DebugFormat("[ASSET CACHE]: Asset transfer request for asset which is {0} already known to be missing. Dropping", requestID); - - // FIXME: We never tell the client about assets which do not exist when requested by this transfer mechanism, which can't be right. - return; - } - // Scripts cannot be retrieved by direct request if (transferRequest.TransferInfo.SourceType == (int)SourceType.Asset && asset.Type == 10) return; @@ -11804,5 +11747,60 @@ namespace OpenSim.Region.ClientStack.LindenUDP dialog.Buttons = buttons; OutPacket(dialog, ThrottleOutPacketType.Task); } + + public void StopFlying(ISceneEntity p) + { + if (p is ScenePresence) + { + ScenePresence presence = p as ScenePresence; + // It turns out to get the agent to stop flying, you have to feed it stop flying velocities + // There's no explicit message to send the client to tell it to stop flying.. it relies on the + // velocity, collision plane and avatar height + + // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air + // when the avatar stands up + + Vector3 pos = presence.AbsolutePosition; + + if (presence.Appearance.AvatarHeight != 127.0f) + pos += new Vector3(0f, 0f, (presence.Appearance.AvatarHeight/6f)); + else + pos += new Vector3(0f, 0f, (1.56f/6f)); + + presence.AbsolutePosition = pos; + + // attach a suitable collision plane regardless of the actual situation to force the LLClient to land. + // Collision plane below the avatar's position a 6th of the avatar's height is suitable. + // Mind you, that this method doesn't get called if the avatar's velocity magnitude is greater then a + // certain amount.. because the LLClient wouldn't land in that situation anyway. + + // why are we still testing for this really old height value default??? + if (presence.Appearance.AvatarHeight != 127.0f) + presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - presence.Appearance.AvatarHeight/6f); + else + presence.CollisionPlane = new Vector4(0, 0, 0, pos.Z - (1.56f/6f)); + + + ImprovedTerseObjectUpdatePacket.ObjectDataBlock block = + CreateImprovedTerseBlock(p, false); + + const float TIME_DILATION = 1.0f; + ushort timeDilation = Utils.FloatToUInt16(TIME_DILATION, 0.0f, 1.0f); + + + ImprovedTerseObjectUpdatePacket packet = new ImprovedTerseObjectUpdatePacket(); + packet.RegionData.RegionHandle = m_scene.RegionInfo.RegionHandle; + packet.RegionData.TimeDilation = timeDilation; + packet.ObjectData = new ImprovedTerseObjectUpdatePacket.ObjectDataBlock[1]; + + packet.ObjectData[0] = block; + + OutPacket(packet, ThrottleOutPacketType.Task, true); + } + + //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, + // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); + + } } } diff --git a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs index 938cf50468..9e0db12734 100644 --- a/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs +++ b/OpenSim/Region/ClientStack/LindenUDP/LLImageManager.cs @@ -58,8 +58,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP private C5.IntervalHeap m_priorityQueue = new C5.IntervalHeap(10, new J2KImageComparer()); private object m_syncRoot = new object(); - private IHyperAssetService m_hyperAssets; - public LLClientView Client { get { return m_client; } } public AssetBase MissingImage { get { return m_missingImage; } } @@ -75,7 +73,6 @@ namespace OpenSim.Region.ClientStack.LindenUDP m_log.Error("[ClientView] - Couldn't set missing image asset, falling back to missing image packet. This is known to crash the client"); m_j2kDecodeModule = pJ2kDecodeModule; - m_hyperAssets = client.Scene.RequestModuleInterface(); } /// @@ -149,7 +146,7 @@ namespace OpenSim.Region.ClientStack.LindenUDP imgrequest.J2KDecoder = m_j2kDecodeModule; imgrequest.AssetService = m_assetCache; imgrequest.AgentID = m_client.AgentId; - imgrequest.HyperAssets = m_hyperAssets; + imgrequest.InventoryAccessModule = m_client.Scene.RequestModuleInterface(); imgrequest.DiscardLevel = newRequest.DiscardLevel; imgrequest.StartPacket = Math.Max(1, newRequest.PacketNumber); imgrequest.Priority = newRequest.Priority; diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs index d30e954a10..3d6e7f31a7 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AgentAssetsTransactions.cs @@ -182,7 +182,13 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (part.Inventory.UpdateInventoryItem(item)) { - remoteClient.SendAgentAlertMessage("Notecard saved", false); + if ((InventoryType)item.InvType == InventoryType.Notecard) + remoteClient.SendAgentAlertMessage("Notecard saved", false); + else if ((InventoryType)item.InvType == InventoryType.LSL) + remoteClient.SendAgentAlertMessage("Script saved", false); + else + remoteClient.SendAgentAlertMessage("Item saved", false); + part.GetProperties(remoteClient); } } diff --git a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs index 7e08ecf688..ae31050853 100644 --- a/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs +++ b/OpenSim/Region/CoreModules/Agent/AssetTransaction/AssetTransactionModule.cs @@ -243,7 +243,7 @@ namespace OpenSim.Region.CoreModules.Agent.AssetTransaction if (mm != null) { - if (!mm.UploadCovered(remoteClient)) + if (!mm.UploadCovered(remoteClient, mm.UploadCharge)) { remoteClient.SendAgentAlertMessage("Unable to upload asset. Insufficient funds.", false); return; diff --git a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs index f8e3d595c9..8aa87fddee 100644 --- a/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Assets/GetTextureModule.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -131,6 +131,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture != null) { + if (texture.Type != (sbyte)AssetType.Texture) + { + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + httpResponse.Send(); + return null; + } SendTexture(httpRequest, httpResponse, texture); } else @@ -147,6 +153,12 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps if (texture != null) { + if (texture.Type != (sbyte)AssetType.Texture) + { + httpResponse.StatusCode = (int)System.Net.HttpStatusCode.NotFound; + httpResponse.Send(); + return null; + } SendTexture(httpRequest, httpResponse, texture); } else @@ -178,7 +190,7 @@ namespace OpenSim.Region.CoreModules.Avatar.ObjectCaps end = Utils.Clamp(end, 1, texture.Data.Length); start = Utils.Clamp(start, 0, end - 1); - m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); + //m_log.Debug("Serving " + start + " to " + end + " of " + texture.Data.Length + " bytes for texture " + texture.ID); if (end - start < texture.Data.Length) response.StatusCode = (int)System.Net.HttpStatusCode.PartialContent; diff --git a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs index f050dcfba3..ff3036aca8 100644 --- a/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Attachments/AttachmentsModule.cs @@ -25,6 +25,7 @@ * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ +using System; using System.Collections.Generic; using System.Reflection; using log4net; @@ -68,102 +69,117 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments get { return false; } } - public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent) + // Called by client + // + public void AttachObject(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent) { m_log.Debug("[ATTACHMENTS MODULE]: Invoking AttachObject"); - - // If we can't take it, we can't attach it! - SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID); - if (part == null) - return; - if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) - return; - - // Calls attach with a Zero position - if (AttachObject(remoteClient, objectLocalID, AttachmentPt, rot, Vector3.Zero, false)) + try { - m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); - - // Save avatar attachment information - ScenePresence presence; - if (m_scene.AvatarFactory != null && m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + // If we can't take it, we can't attach it! + SceneObjectPart part = m_scene.GetSceneObjectPart(objectLocalID); + if (part == null) + return; + + if (!m_scene.Permissions.CanTakeObject(part.UUID, remoteClient.AgentId)) + return; + + // Calls attach with a Zero position + if (AttachObject(remoteClient, part.ParentGroup, AttachmentPt, false)) { - m_log.Info( - "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId - + ", AttachmentPoint: " + AttachmentPt); - - m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + m_scene.EventManager.TriggerOnAttach(objectLocalID, part.ParentGroup.GetFromItemID(), remoteClient.AgentId); + + // Save avatar attachment information + ScenePresence presence; + if (m_scene.AvatarFactory != null && m_scene.TryGetScenePresence(remoteClient.AgentId, out presence)) + { + m_log.Info( + "[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + + ", AttachmentPoint: " + AttachmentPt); + + m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); + } } } + catch (Exception e) + { + m_log.DebugFormat("[ATTACHMENTS MODULE]: exception upon Attach Object {0}", e); + } } - public bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent) + public bool AttachObject(IClientAPI remoteClient, SceneObjectGroup group, uint AttachmentPt, bool silent) { - SceneObjectGroup group = m_scene.GetGroupByPrim(objectLocalID); - if (group != null) + Vector3 attachPos = group.AbsolutePosition; + + if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) { - if (m_scene.Permissions.CanTakeObject(group.UUID, remoteClient.AgentId)) + // If the attachment point isn't the same as the one previously used + // set it's offset position = 0 so that it appears on the attachment point + // and not in a weird location somewhere unknown. + if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) { - // If the attachment point isn't the same as the one previously used - // set it's offset position = 0 so that it appears on the attachment point - // and not in a weird location somewhere unknown. - if (AttachmentPt != 0 && AttachmentPt != (uint)group.GetAttachmentPoint()) + attachPos = Vector3.Zero; + } + + // AttachmentPt 0 means the client chose to 'wear' the attachment. + if (AttachmentPt == 0) + { + // Check object for stored attachment point + AttachmentPt = (uint)group.GetAttachmentPoint(); + } + + // if we still didn't find a suitable attachment point....... + if (AttachmentPt == 0) + { + // Stick it on left hand with Zero Offset from the attachment point. + AttachmentPt = (uint)AttachmentPoint.LeftHand; + attachPos = Vector3.Zero; + } + + group.SetAttachmentPoint((byte)AttachmentPt); + group.AbsolutePosition = attachPos; + + // Remove any previous attachments + ScenePresence sp = m_scene.GetScenePresence(remoteClient.AgentId); + UUID itemID = UUID.Zero; + if (sp != null) + { + foreach(SceneObjectGroup grp in sp.Attachments) { - attachPos = Vector3.Zero; + if (grp.GetAttachmentPoint() == (byte)AttachmentPt) + { + itemID = grp.GetFromItemID(); + break; + } } + if (itemID != UUID.Zero) + DetachSingleAttachmentToInv(itemID, remoteClient); + } - // AttachmentPt 0 means the client chose to 'wear' the attachment. - if (AttachmentPt == 0) - { - // Check object for stored attachment point - AttachmentPt = (uint)group.GetAttachmentPoint(); - } - - // if we still didn't find a suitable attachment point....... - if (AttachmentPt == 0) - { - // Stick it on left hand with Zero Offset from the attachment point. - AttachmentPt = (uint)AttachmentPoint.LeftHand; - attachPos = Vector3.Zero; - } - - group.SetAttachmentPoint((byte)AttachmentPt); - group.AbsolutePosition = attachPos; - - // Saves and gets itemID - UUID itemId; - - if (group.GetFromItemID() == UUID.Zero) - { - m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemId); - } - else - { - itemId = group.GetFromItemID(); - } - - SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemId, group); - - group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); - - // In case it is later dropped again, don't let - // it get cleaned up - group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); - group.HasGroupChanged = false; + if (group.GetFromItemID() == UUID.Zero) + { + m_scene.attachObjectAssetStore(remoteClient, group, remoteClient.AgentId, out itemID); } else { - remoteClient.SendAgentAlertMessage( - "You don't have sufficient permissions to attach this object", false); - - return false; + itemID = group.GetFromItemID(); } + + SetAttachmentInventoryStatus(remoteClient, AttachmentPt, itemID, group); + + group.AttachToAgent(remoteClient.AgentId, AttachmentPt, attachPos, silent); + + // In case it is later dropped again, don't let + // it get cleaned up + group.RootPart.RemFlag(PrimFlags.TemporaryOnRez); + group.HasGroupChanged = false; } else { - m_log.DebugFormat("[ATTACHMENTS MODULE]: AttachObject found no such scene object {0}", objectLocalID); + remoteClient.SendAgentAlertMessage( + "You don't have sufficient permissions to attach this object", false); + return false; } @@ -229,8 +245,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments if (AttachmentPt != 0 && AttachmentPt != objatt.GetAttachmentPoint()) tainted = true; - AttachObject( - remoteClient, objatt.LocalId, AttachmentPt, Quaternion.Identity, objatt.AbsolutePosition, false); + AttachObject(remoteClient, objatt, AttachmentPt, false); //objatt.ScheduleGroupForFullUpdate(); if (tainted) @@ -344,7 +359,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Attachments // Save avatar attachment information if (m_scene.AvatarFactory != null) { - m_log.Debug("[ATTACHMENTS MODULE]: Saving avatar attachment. AgentID: " + remoteClient.AgentId + ", ItemID: " + itemID); + m_log.Debug("[ATTACHMENTS MODULE]: Dettaching from UserID: " + remoteClient.AgentId + ", ItemID: " + itemID); m_scene.AvatarFactory.UpdateDatabase(remoteClient.AgentId, presence.Appearance); } } diff --git a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs index 22c89370a7..7e5a8ec9f1 100644 --- a/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/AvatarFactory/AvatarFactoryModule.cs @@ -198,7 +198,7 @@ namespace OpenSim.Region.CoreModules.Avatar.AvatarFactory public void UpdateDatabase(UUID user, AvatarAppearance appearance) { - //m_log.DebugFormat("[APPEARANCE]: UpdateDatabase"); + m_log.DebugFormat("[APPEARANCE]: UpdateDatabase"); AvatarData adata = new AvatarData(appearance); m_scene.AvatarService.SetAvatar(user, adata); } diff --git a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs index b5c3176d8e..72fff948ed 100644 --- a/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Dialog/DialogModule.cs @@ -81,14 +81,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(agentID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendAgentAlertMessage(message, modal); } public void SendAlertToUser(string firstName, string lastName, string message, bool modal) { ScenePresence presence = m_scene.GetScenePresence(firstName, lastName); - if (presence != null && !presence.IsChildAgent) + if (presence != null) presence.ControllingClient.SendAgentAlertMessage(message, modal); } @@ -96,8 +96,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { m_scene.ForEachScenePresence(delegate(ScenePresence presence) { - if (!presence.IsChildAgent) - presence.ControllingClient.SendAlertMessage(message); + presence.ControllingClient.SendAlertMessage(message); }); } @@ -119,7 +118,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog } ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendDialog(objectName, objectID, ownerFirstName, ownerLastName, message, textureID, ch, buttonlabels); } @@ -128,7 +127,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog { ScenePresence sp = m_scene.GetScenePresence(avatarID); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendLoadURL(objectName, objectID, ownerID, groupOwned, message, url); } @@ -149,7 +148,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog ScenePresence sp = m_scene.GetScenePresence(avatarid); - if (sp != null && !sp.IsChildAgent) + if (sp != null) sp.ControllingClient.SendTextBoxRequest(message, chatChannel, name, ownerFirstName, ownerLastName, objectid); } @@ -205,4 +204,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Dialog return result; } } -} \ No newline at end of file +} diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs index 0c81f446f1..6f044cb8f1 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsModule.cs @@ -111,10 +111,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends protected IGridService GridService { - get - { - return m_Scenes[0].GridService; - } + get { return m_Scenes[0].GridService; } + } + + public IUserAccountService UserAccountService + { + get { return m_Scenes[0].UserAccountService; } } public IScene Scene @@ -218,41 +220,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends client.OnGrantUserRights += OnGrantUserRights; - client.OnLogout += OnLogout; - - if (m_Friends.ContainsKey(client.AgentId)) + lock (m_Friends) { - m_Friends[client.AgentId].Refcount++; - return; + if (m_Friends.ContainsKey(client.AgentId)) + { + m_Friends[client.AgentId].Refcount++; + return; + } + + UserFriendData newFriends = new UserFriendData(); + + newFriends.PrincipalID = client.AgentId; + newFriends.Friends = m_FriendsService.GetFriends(client.AgentId); + newFriends.Refcount = 1; + newFriends.RegionID = UUID.Zero; + + m_Friends.Add(client.AgentId, newFriends); } - - UserFriendData newFriends = new UserFriendData(); - - newFriends.PrincipalID = client.AgentId; - newFriends.Friends = m_FriendsService.GetFriends(client.AgentId); - newFriends.Refcount = 1; - newFriends.RegionID = UUID.Zero; - - m_Friends.Add(client.AgentId, newFriends); - //StatusChange(client.AgentId, true); } private void OnClientClosed(UUID agentID, Scene scene) { - if (m_Friends.ContainsKey(agentID)) - { - if (m_Friends[agentID].Refcount == 1) - m_Friends.Remove(agentID); - else - m_Friends[agentID].Refcount--; - } - } + ScenePresence sp = scene.GetScenePresence(agentID); + if (sp != null && !sp.IsChildAgent) + // do this for root agents closing out + StatusChange(agentID, false); - private void OnLogout(IClientAPI client) - { - StatusChange(client.AgentId, false); - m_Friends.Remove(client.AgentId); + lock (m_Friends) + if (m_Friends.ContainsKey(agentID)) + { + if (m_Friends[agentID].Refcount == 1) + m_Friends.Remove(agentID); + else + m_Friends[agentID].Refcount--; + } } private void OnMakeRootAgent(ScenePresence sp) @@ -261,11 +263,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (m_Friends.ContainsKey(agentID)) { - if (m_Friends[agentID].RegionID == UUID.Zero && m_Friends[agentID].Friends == null) - { - m_Friends[agentID].Friends = + // This is probably an overkill, but just + // to make sure we have the latest and greatest + // friends list -- always pull OnMakeRoot + m_Friends[agentID].Friends = m_FriendsService.GetFriends(agentID); - } + m_Friends[agentID].RegionID = sp.ControllingClient.Scene.RegionInfo.RegionID; } @@ -431,20 +434,29 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends /// private void StatusChange(UUID agentID, bool online) { + //m_log.DebugFormat("[FRIENDS]: StatusChange {0}", online); if (m_Friends.ContainsKey(agentID)) { + //m_log.DebugFormat("[FRIENDS]: # of friends: {0}", m_Friends[agentID].Friends.Length); List friendList = new List(); foreach (FriendInfo fi in m_Friends[agentID].Friends) { if (((fi.MyFlags & 1) != 0) && (fi.TheirFlags != -1)) friendList.Add(fi); } - foreach (FriendInfo fi in friendList) + + Util.FireAndForget(delegate { - // Notify about this user status - StatusNotify(fi, agentID, online); - } + foreach (FriendInfo fi in friendList) + { + //m_log.DebugFormat("[FRIENDS]: Notifying {0}", fi.PrincipalID); + // Notify about this user status + StatusNotify(fi, agentID, online); + } + }); } + else + m_log.WarnFormat("[FRIENDS]: {0} not found in cache", agentID); } private void StatusNotify(FriendInfo friend, UUID userID, bool online) @@ -456,21 +468,31 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends // Try local if (LocalStatusNotification(userID, friendID, online)) return; - + // The friend is not here [as root]. Let's forward. PresenceInfo[] friendSessions = PresenceService.GetAgents(new string[] { friendID.ToString() }); if (friendSessions != null && friendSessions.Length > 0) { - PresenceInfo friendSession = friendSessions[0]; + PresenceInfo friendSession = null; + foreach (PresenceInfo pinfo in friendSessions) + if (pinfo.RegionID != UUID.Zero) // let's guard against sessions-gone-bad + { + friendSession = pinfo; + break; + } + if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); + //m_log.DebugFormat("[FRIENDS]: Remote Notify to region {0}", region.RegionName); m_FriendsSimConnector.StatusNotify(region, userID, friendID, online); } } // Friend is not online. Ignore. } + else + m_log.WarnFormat("[FRIENDS]: Error parsing friend ID {0}", friend.Friend); } private void OnInstantMessage(IClientAPI client, GridInstantMessage im) @@ -481,7 +503,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends UUID principalID = new UUID(im.fromAgentID); UUID friendID = new UUID(im.toAgentID); - m_log.DebugFormat("[FRIENDS]: {0} offered friendship to {1}", principalID, friendID); + m_log.DebugFormat("[FRIENDS]: {0} ({1}) offered friendship to {2}", principalID, im.fromAgentName, friendID); // This user wants to be friends with the other user. // Let's add the relation backwards, in case the other is not online @@ -499,6 +521,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends im.imSessionID = im.fromAgentID; // Try the local sim + UserAccount account = UserAccountService.GetUserAccount(Scene.RegionInfo.ScopeID, agentID); + im.fromAgentName = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; + if (LocalFriendshipOffered(friendID, im)) return; @@ -518,12 +543,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends private void OnApproveFriendRequest(IClientAPI client, UUID agentID, UUID friendID, List callingCardFolders) { + m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); + FriendsService.StoreFriend(agentID, friendID.ToString(), 1); FriendsService.StoreFriend(friendID, agentID.ToString(), 1); // update the local cache m_Friends[agentID].Friends = FriendsService.GetFriends(agentID); - m_log.DebugFormat("[FRIENDS]: {0} accepted friendship from {1}", agentID, friendID); // // Notify the friend @@ -572,7 +598,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (friendSession != null) { GridRegion region = GridService.GetRegionByUUID(m_Scenes[0].RegionInfo.ScopeID, friendSession.RegionID); - m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + if (region != null) + m_FriendsSimConnector.FriendshipDenied(region, agentID, client.Name, friendID); + else + m_log.WarnFormat("[FRIENDS]: Could not find region {0} in locating {1}", friendSession.RegionID, friendID); } } } @@ -739,8 +768,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends bool canEditObjectsChanged = ((rights ^ userFlags) & (int)FriendRights.CanModifyObjects) != 0; if (canEditObjectsChanged) friendClient.SendChangeUserRights(userID, friendID, rights); + } + // update local cache + //m_Friends[friendID].Friends = m_FriendsService.GetFriends(friendID); + foreach (FriendInfo finfo in m_Friends[friendID].Friends) + if (finfo.Friend == userID.ToString()) + finfo.TheirFlags = rights; + return true; } @@ -753,7 +789,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends IClientAPI friendClient = LocateClientObject(friendID); if (friendClient != null) { - //m_log.DebugFormat("[FRIENDS]: Notify {0} that user {1} is {2}", friend.Friend, userID, online); + //m_log.DebugFormat("[FRIENDS]: Local Status Notify {0} that user {1} is {2}", friendID, userID, online); // the friend in this sim as root agent if (online) friendClient.SendAgentOnline(new UUID[] { userID }); diff --git a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs index 0883c5ba83..496f2abdfb 100644 --- a/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs +++ b/OpenSim/Region/CoreModules/Avatar/Friends/FriendsRequestHandler.cs @@ -35,6 +35,7 @@ using OpenSim.Framework; using OpenSim.Server.Base; using OpenSim.Framework.Servers.HttpServer; using FriendInfo = OpenSim.Services.Interfaces.FriendInfo; +using OpenSim.Services.Interfaces; using OpenMetaverse; using log4net; @@ -61,7 +62,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends sr.Close(); body = body.Trim(); - m_log.DebugFormat("[XXX]: query String: {0}", body); + //m_log.DebugFormat("[XXX]: query String: {0}", body); try { @@ -115,9 +116,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Friends if (!UUID.TryParse(request["ToID"].ToString(), out toID)) return FailureResult(); - GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, "", toID, + UserAccount account = m_FriendsModule.UserAccountService.GetUserAccount(m_FriendsModule.Scene.RegionInfo.ScopeID, fromID); + string name = (account == null) ? "Unknown" : account.FirstName + " " + account.LastName; + + GridInstantMessage im = new GridInstantMessage(m_FriendsModule.Scene, fromID, name, toID, (byte)InstantMessageDialog.FriendshipOffered, message, false, Vector3.Zero); - + + // !! HACK + im.imSessionID = im.fromAgentID; + if (m_FriendsModule.LocalFriendshipOffered(toID, im)) return SuccessResult(); diff --git a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs index 5d20e63646..83209fc86f 100644 --- a/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/InstantMessage/MessageTransferModule.cs @@ -268,6 +268,8 @@ namespace OpenSim.Region.CoreModules.Avatar.InstantMessage fromAgentName = (string)requestData["from_agent_name"]; message = (string)requestData["message"]; + if (message == null) + message = string.Empty; // Bytes don't transfer well over XMLRPC, so, we Base64 Encode them. string requestData1 = (string)requestData["dialog"]; diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs index 806aa4f155..31dfe145f5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveReadRequest.cs @@ -93,36 +93,37 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public List Execute() { - string filePath = "ERROR"; - int successfulAssetRestores = 0; - int failedAssetRestores = 0; - int successfulItemRestores = 0; - List nodesLoaded = new List(); - - //InventoryFolderImpl rootDestinationFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath); - InventoryFolderBase rootDestinationFolder - = InventoryArchiveUtils.FindFolderByPath( - m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); - - if (null == rootDestinationFolder) - { - // Possibly provide an option later on to automatically create this folder if it does not exist - m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); - - return nodesLoaded; - } - - archive = new TarArchiveReader(m_loadStream); - - // In order to load identically named folders, we need to keep track of the folders that we have already - // created - Dictionary foldersCreated = new Dictionary(); - - byte[] data; - TarArchiveReader.TarEntryType entryType; - try { + string filePath = "ERROR"; + int successfulAssetRestores = 0; + int failedAssetRestores = 0; + int successfulItemRestores = 0; + + List loadedNodes = new List(); + + List folderCandidates + = InventoryArchiveUtils.FindFolderByPath( + m_scene.InventoryService, m_userInfo.PrincipalID, m_invPath); + + if (folderCandidates.Count == 0) + { + // Possibly provide an option later on to automatically create this folder if it does not exist + m_log.ErrorFormat("[INVENTORY ARCHIVER]: Inventory path {0} does not exist", m_invPath); + + return loadedNodes; + } + + InventoryFolderBase rootDestinationFolder = folderCandidates[0]; + archive = new TarArchiveReader(m_loadStream); + + // In order to load identically named folders, we need to keep track of the folders that we have already + // resolved + Dictionary resolvedFolders = new Dictionary(); + + byte[] data; + TarArchiveReader.TarEntryType entryType; + while ((data = archive.ReadEntry(out filePath, out entryType)) != null) { if (filePath.StartsWith(ArchiveConstants.ASSETS_PATH)) @@ -139,10 +140,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } else if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH)) { + filePath = filePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); + + // Trim off the file portion if we aren't already dealing with a directory path + if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) + filePath = filePath.Remove(filePath.LastIndexOf("/") + 1); + InventoryFolderBase foundFolder = ReplicateArchivePathToUserInventory( - filePath, TarArchiveReader.TarEntryType.TYPE_DIRECTORY == entryType, - rootDestinationFolder, foldersCreated, nodesLoaded); + filePath, rootDestinationFolder, resolvedFolders, loadedNodes); if (TarArchiveReader.TarEntryType.TYPE_DIRECTORY != entryType) { @@ -155,23 +161,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // If we're loading an item directly into the given destination folder then we need to record // it separately from any loaded root folders if (rootDestinationFolder == foundFolder) - nodesLoaded.Add(item); + loadedNodes.Add(item); } } } } + + archive.Close(); + + m_log.DebugFormat( + "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", + successfulAssetRestores, failedAssetRestores); + m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); + + return loadedNodes; } finally { - archive.Close(); - } - - m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Successfully loaded {0} assets with {1} failures", - successfulAssetRestores, failedAssetRestores); - m_log.InfoFormat("[INVENTORY ARCHIVER]: Successfully loaded {0} items", successfulItemRestores); - - return nodesLoaded; + m_loadStream.Close(); + } } public void Close() @@ -183,81 +191,139 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// Replicate the inventory paths in the archive to the user's inventory as necessary. /// - /// The item archive path to replicate - /// Is the path we're dealing with a directory? + /// The item archive path to replicate /// The root folder for the inventory load - /// - /// The folders created so far. This method will add more folders if necessary + /// + /// The folders that we have resolved so far for a given archive path. + /// This method will add more folders if necessary /// - /// - /// Track the inventory nodes created. This is distinct from the folders created since for a particular folder - /// chain, only the root node needs to be recorded + /// + /// Track the inventory nodes created. /// /// The last user inventory folder created or found for the archive path public InventoryFolderBase ReplicateArchivePathToUserInventory( - string archivePath, - bool isDir, + string iarPath, InventoryFolderBase rootDestFolder, - Dictionary foldersCreated, - List nodesLoaded) + Dictionary resolvedFolders, + List loadedNodes) { - archivePath = archivePath.Substring(ArchiveConstants.INVENTORY_PATH.Length); - - // Remove the file portion if we aren't already dealing with a directory path - if (!isDir) - archivePath = archivePath.Remove(archivePath.LastIndexOf("/") + 1); - - string originalArchivePath = archivePath; + string iarPathExisting = iarPath; // m_log.DebugFormat( // "[INVENTORY ARCHIVER]: Loading folder {0} {1}", rootDestFolder.Name, rootDestFolder.ID); + + InventoryFolderBase destFolder = ResolveDestinationFolder(rootDestFolder, ref iarPathExisting, resolvedFolders); + +// m_log.DebugFormat( +// "[INVENTORY ARCHIVER]: originalArchivePath [{0}], section already loaded [{1}]", +// iarPath, iarPathExisting); + + string iarPathToCreate = iarPath.Substring(iarPathExisting.Length); + CreateFoldersForPath(destFolder, iarPathExisting, iarPathToCreate, resolvedFolders, loadedNodes); + + return destFolder; + } + + /// + /// Resolve a destination folder + /// + /// + /// We require here a root destination folder (usually the root of the user's inventory) and the archive + /// path. We also pass in a list of previously resolved folders in case we've found this one previously. + /// + /// + /// The item archive path to resolve. The portion of the path passed back is that + /// which corresponds to the resolved desintation folder. + /// + /// The root folder for the inventory load + /// + /// + /// The folders that we have resolved so far for a given archive path. + /// + /// + /// The folder in the user's inventory that matches best the archive path given. If no such folder was found + /// then the passed in root destination folder is returned. + /// + protected InventoryFolderBase ResolveDestinationFolder( + InventoryFolderBase rootDestFolder, + ref string archivePath, + Dictionary resolvedFolders) + { +// string originalArchivePath = archivePath; InventoryFolderBase destFolder = null; - // XXX: Nasty way of dealing with a path that has no directory component if (archivePath.Length > 0) { while (null == destFolder && archivePath.Length > 0) { - if (foldersCreated.ContainsKey(archivePath)) +// m_log.DebugFormat("[INVENTORY ARCHIVER]: Trying to resolve destination folder {0}", archivePath); + + if (resolvedFolders.ContainsKey(archivePath)) { // m_log.DebugFormat( // "[INVENTORY ARCHIVER]: Found previously created folder from archive path {0}", archivePath); - destFolder = foldersCreated[archivePath]; + destFolder = resolvedFolders[archivePath]; } else { - // Don't include the last slash + // Don't include the last slash so find the penultimate one int penultimateSlashIndex = archivePath.LastIndexOf("/", archivePath.Length - 2); if (penultimateSlashIndex >= 0) { + // Remove the last section of path so that we can see if we've already resolved the parent archivePath = archivePath.Remove(penultimateSlashIndex + 1); } else { - m_log.DebugFormat( - "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", - originalArchivePath); +// m_log.DebugFormat( +// "[INVENTORY ARCHIVER]: Found no previously created folder for archive path {0}", +// originalArchivePath); archivePath = string.Empty; destFolder = rootDestFolder; } } } } - else - { + + if (null == destFolder) destFolder = rootDestFolder; - } - - string archivePathSectionToCreate = originalArchivePath.Substring(archivePath.Length); - string[] rawDirsToCreate - = archivePathSectionToCreate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); + + return destFolder; + } + + /// + /// Create a set of folders for the given path. + /// + /// + /// The root folder from which the creation will take place. + /// + /// + /// the part of the iar path that already exists + /// + /// + /// The path to replicate in the user's inventory from iar + /// + /// + /// The folders that we have resolved so far for a given archive path. + /// + /// + /// Track the inventory nodes created. + /// + protected void CreateFoldersForPath( + InventoryFolderBase destFolder, + string iarPathExisting, + string iarPathToReplicate, + Dictionary resolvedFolders, + List loadedNodes) + { + string[] rawDirsToCreate = iarPathToReplicate.Split(new char[] { '/' }, StringSplitOptions.RemoveEmptyEntries); int i = 0; while (i < rawDirsToCreate.Length) { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Loading archived folder {0}", rawDirsToCreate[i]); +// m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0} from IAR", rawDirsToCreate[i]); int identicalNameIdentifierIndex = rawDirsToCreate[i].LastIndexOf( @@ -282,66 +348,19 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver newFolderId, newFolderName, m_userInfo.PrincipalID, (short)AssetType.Unknown, destFolder.ID, 1); m_scene.InventoryService.AddFolder(destFolder); - -// UUID newFolderId = UUID.Random(); -// m_scene.InventoryService.AddFolder( -// m_userInfo.CreateFolder( -// folderName, newFolderId, (ushort)AssetType.Folder, foundFolder.ID); - -// m_log.DebugFormat("[INVENTORY ARCHIVER]: Retrieving newly created folder {0}", folderName); -// foundFolder = foundFolder.GetChildFolder(newFolderId); -// m_log.DebugFormat( -// "[INVENTORY ARCHIVER]: Retrieved newly created folder {0} with ID {1}", -// foundFolder.Name, foundFolder.ID); // Record that we have now created this folder - archivePath += rawDirsToCreate[i] + "/"; - m_log.DebugFormat("[INVENTORY ARCHIVER]: Loaded archive path {0}", archivePath); - foldersCreated[archivePath] = destFolder; + iarPathExisting += rawDirsToCreate[i] + "/"; + m_log.DebugFormat("[INVENTORY ARCHIVER]: Created folder {0} from IAR", iarPathExisting); + resolvedFolders[iarPathExisting] = destFolder; if (0 == i) - nodesLoaded.Add(destFolder); + loadedNodes.Add(destFolder); i++; - } - - return destFolder; - - /* - string[] rawFolders = filePath.Split(new char[] { '/' }); - - // Find the folders that do exist along the path given - int i = 0; - bool noFolder = false; - InventoryFolderImpl foundFolder = rootDestinationFolder; - while (!noFolder && i < rawFolders.Length) - { - InventoryFolderImpl folder = foundFolder.FindFolderByPath(rawFolders[i]); - if (null != folder) - { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Found folder {0}", folder.Name); - foundFolder = folder; - i++; - } - else - { - noFolder = true; - } - } - - // Create any folders that did not previously exist - while (i < rawFolders.Length) - { - m_log.DebugFormat("[INVENTORY ARCHIVER]: Creating folder {0}", rawFolders[i]); - - UUID newFolderId = UUID.Random(); - m_userInfo.CreateFolder( - rawFolders[i++], newFolderId, (ushort)AssetType.Folder, foundFolder.ID); - foundFolder = foundFolder.GetChildFolder(newFolderId); - } - */ + } } - + /// /// Load an item from the archive /// @@ -432,4 +451,4 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver } } } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs index 47b18d85d4..84afb40b8c 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveUtils.cs @@ -55,8 +55,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// This method does not handle paths that contain multiple delimitors /// - /// FIXME: We do not yet handle situations where folders have the same name. We could handle this by some - /// XPath like expression + /// FIXME: We have no way of distinguishing folders with the same path /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. /// @@ -70,14 +69,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// The path to the required folder. /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// - /// null if the folder is not found - public static InventoryFolderBase FindFolderByPath( + /// An empty list if the folder is not found, otherwise a list of all folders that match the name + public static List FindFolderByPath( IInventoryService inventoryService, UUID userId, string path) { InventoryFolderBase rootFolder = inventoryService.GetRootFolder(userId); if (null == rootFolder) - return null; + return new List(); return FindFolderByPath(inventoryService, rootFolder, path); } @@ -88,8 +87,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// /// This method does not handle paths that contain multiple delimitors /// - /// FIXME: We do not yet handle situations where folders have the same name. We could handle this by some - /// XPath like expression + /// FIXME: We have no way of distinguishing folders with the same path. /// /// FIXME: Delimitors which occur in names themselves are not currently escapable. /// @@ -103,17 +101,25 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// The path to the required folder. /// It this is empty or consists only of the PATH_DELIMTER then this folder itself is returned. /// - /// null if the folder is not found - public static InventoryFolderBase FindFolderByPath( + /// An empty list if the folder is not found, otherwise a list of all folders that match the name + public static List FindFolderByPath( IInventoryService inventoryService, InventoryFolderBase startFolder, string path) { + List foundFolders = new List(); + if (path == string.Empty) - return startFolder; + { + foundFolders.Add(startFolder); + return foundFolders; + } path = path.Trim(); if (path == PATH_DELIMITER.ToString()) - return startFolder; + { + foundFolders.Add(startFolder); + return foundFolders; + } string[] components = SplitEscapedPath(path); components[0] = UnescapePath(components[0]); @@ -127,14 +133,13 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (folder.Name == components[0]) { if (components.Length > 1) - return FindFolderByPath(inventoryService, folder, components[1]); + foundFolders.AddRange(FindFolderByPath(inventoryService, folder, components[1])); else - return folder; + foundFolders.Add(folder); } } - // We didn't find a folder with the right name - return null; + return foundFolders; } /// @@ -201,11 +206,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (components.Length == 1) { -// m_log.DebugFormat("FOUND SINGLE COMPONENT [{0}]", components[0]); +// m_log.DebugFormat( +// "FOUND SINGLE COMPONENT [{0}]. Looking for this in [{1}] {2}", +// components[0], startFolder.Name, startFolder.ID); List items = inventoryService.GetFolderItems(startFolder.Owner, startFolder.ID); + +// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Found {0} items in FindItemByPath()", items.Count); + foreach (InventoryItemBase item in items) { +// m_log.DebugFormat("[INVENTORY ARCHIVE UTILS]: Inspecting item {0} {1}", item.Name, item.ID); + if (item.Name == components[0]) return item; } diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs index 8f3f65b0b6..25a78ff618 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiveWriteRequest.cs @@ -119,22 +119,24 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver protected void ReceivedAllAssets(ICollection assetsFoundUuids, ICollection assetsNotFoundUuids) { Exception reportedException = null; - bool succeeded = true; - + bool succeeded = true; + try { // We're almost done. Just need to write out the control file now m_archiveWriter.WriteFile(ArchiveConstants.CONTROL_FILE_PATH, Create0p1ControlFile()); m_log.InfoFormat("[ARCHIVER]: Added control file to archive."); - m_archiveWriter.Close(); } catch (Exception e) { - m_saveStream.Close(); reportedException = e; succeeded = false; } + finally + { + m_saveStream.Close(); + } m_module.TriggerInventoryArchiveSaved( m_id, succeeded, m_userInfo, m_invPath, m_saveStream, reportedException); @@ -213,69 +215,68 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// public void Execute() { - InventoryFolderBase inventoryFolder = null; - InventoryItemBase inventoryItem = null; - InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); - - bool foundStar = false; - - // Eliminate double slashes and any leading / on the path. - string[] components - = m_invPath.Split( - new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); - - int maxComponentIndex = components.Length - 1; - - // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the - // folder itself. This may get more sophisicated later on - if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) - { - foundStar = true; - maxComponentIndex--; - } - - m_invPath = String.Empty; - for (int i = 0; i <= maxComponentIndex; i++) - { - m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; - } - - // Annoyingly Split actually returns the original string if the input string consists only of delimiters - // Therefore if we still start with a / after the split, then we need the root folder - if (m_invPath.Length == 0) - { - inventoryFolder = rootFolder; - } - else - { - m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); - inventoryFolder - = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); - //inventoryFolder = m_userInfo.RootFolder.FindFolderByPath(m_invPath); - } - - // The path may point to an item instead - if (inventoryFolder == null) - { - inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); - //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); - } - - if (null == inventoryFolder && null == inventoryItem) - { - // We couldn't find the path indicated - string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); - m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", errorMessage); - m_module.TriggerInventoryArchiveSaved( - m_id, false, m_userInfo, m_invPath, m_saveStream, - new Exception(errorMessage)); - return; - } - - m_archiveWriter = new TarArchiveWriter(m_saveStream); - try { + InventoryFolderBase inventoryFolder = null; + InventoryItemBase inventoryItem = null; + InventoryFolderBase rootFolder = m_scene.InventoryService.GetRootFolder(m_userInfo.PrincipalID); + + bool foundStar = false; + + // Eliminate double slashes and any leading / on the path. + string[] components + = m_invPath.Split( + new string[] { InventoryFolderImpl.PATH_DELIMITER }, StringSplitOptions.RemoveEmptyEntries); + + int maxComponentIndex = components.Length - 1; + + // If the path terminates with a STAR then later on we want to archive all nodes in the folder but not the + // folder itself. This may get more sophisicated later on + if (maxComponentIndex >= 0 && components[maxComponentIndex] == STAR_WILDCARD) + { + foundStar = true; + maxComponentIndex--; + } + + m_invPath = String.Empty; + for (int i = 0; i <= maxComponentIndex; i++) + { + m_invPath += components[i] + InventoryFolderImpl.PATH_DELIMITER; + } + + // Annoyingly Split actually returns the original string if the input string consists only of delimiters + // Therefore if we still start with a / after the split, then we need the root folder + if (m_invPath.Length == 0) + { + inventoryFolder = rootFolder; + } + else + { + m_invPath = m_invPath.Remove(m_invPath.LastIndexOf(InventoryFolderImpl.PATH_DELIMITER)); + List candidateFolders + = InventoryArchiveUtils.FindFolderByPath(m_scene.InventoryService, rootFolder, m_invPath); + if (candidateFolders.Count > 0) + inventoryFolder = candidateFolders[0]; + } + + // The path may point to an item instead + if (inventoryFolder == null) + { + inventoryItem = InventoryArchiveUtils.FindItemByPath(m_scene.InventoryService, rootFolder, m_invPath); + //inventoryItem = m_userInfo.RootFolder.FindItemByPath(m_invPath); + } + + if (null == inventoryFolder && null == inventoryItem) + { + // We couldn't find the path indicated + string errorMessage = string.Format("Aborted save. Could not find inventory path {0}", m_invPath); + Exception e = new InventoryArchiverException(errorMessage); + m_module.TriggerInventoryArchiveSaved(m_id, false, m_userInfo, m_invPath, m_saveStream, e); + throw e; + } + + m_archiveWriter = new TarArchiveWriter(m_saveStream); + if (inventoryFolder != null) { m_log.DebugFormat( @@ -296,16 +297,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver // Don't put all this profile information into the archive right now. //SaveUsers(); + + new AssetsRequest( + new AssetsArchiver(m_archiveWriter), m_assetUuids, m_scene.AssetService, ReceivedAllAssets).Execute(); } catch (Exception) { - m_archiveWriter.Close(); + m_saveStream.Close(); throw; } - - new AssetsRequest( - new AssetsArchiver(m_archiveWriter), m_assetUuids, - m_scene.AssetService, ReceivedAllAssets).Execute(); } /// diff --git a/OpenSim/Region/Framework/Interfaces/IHyperService.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs similarity index 80% rename from OpenSim/Region/Framework/Interfaces/IHyperService.cs rename to OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs index 51ea28afc3..e07e2ca689 100644 --- a/OpenSim/Region/Framework/Interfaces/IHyperService.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverException.cs @@ -1,4 +1,4 @@ -/* +/* * Copyright (c) Contributors, http://opensimulator.org/ * See CONTRIBUTORS.TXT for a full list of copyright holders. * @@ -24,14 +24,17 @@ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. */ -using System; -using OpenMetaverse; -namespace OpenSim.Region.Framework.Interfaces +using System; + +namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver { - public interface IHyperAssetService - { - string GetUserAssetServer(UUID userID); - string GetSimAssetServer(); + /// + /// Signals an inventory archiving problem + /// + public class InventoryArchiverException : Exception + { + public InventoryArchiverException(string message) : base(message) {} + public InventoryArchiverException(string message, Exception e) : base(message, e) {} } -} +} \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs index 307db974b8..f7a2b098f5 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/InventoryArchiverModule.cs @@ -30,11 +30,11 @@ using System.Collections.Generic; using System.IO; using System.Reflection; using log4net; +using NDesk.Options; using Nini.Config; using OpenMetaverse; using OpenSim.Framework; using OpenSim.Framework.Communications; - using OpenSim.Region.Framework.Interfaces; using OpenSim.Region.Framework.Scenes; using OpenSim.Services.Interfaces; @@ -91,9 +91,12 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver scene.AddCommand( this, "load iar", - "load iar []", + "load iar []", + //"load iar [--merge] []", "Load user inventory archive (IAR).", - " is user's first name." + Environment.NewLine + //"--merge is an option which merges the loaded IAR with existing inventory folders where possible, rather than always creating new ones" + //+ " is user's first name." + Environment.NewLine + " is user's first name." + Environment.NewLine + " is user's last name." + Environment.NewLine + " is the path inside the user's inventory where the IAR should be loaded." + Environment.NewLine + " is the user's password." + Environment.NewLine @@ -133,8 +136,16 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver if (handlerInventoryArchiveSaved != null) handlerInventoryArchiveSaved(id, succeeded, userInfo, invPath, saveStream, reportedException); } + + public bool ArchiveInventory( + Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) + { + return ArchiveInventory(id, firstName, lastName, invPath, pass, saveStream, new Dictionary()); + } - public bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream) + public bool ArchiveInventory( + Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, + Dictionary options) { if (m_scenes.Count > 0) { @@ -172,7 +183,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - public bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, string savePath) + public bool ArchiveInventory( + Guid id, string firstName, string lastName, string invPath, string pass, string savePath, + Dictionary options) { if (m_scenes.Count > 0) { @@ -209,8 +222,15 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - + public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream) + { + return DearchiveInventory(firstName, lastName, invPath, pass, loadStream, new Dictionary()); + } + + public bool DearchiveInventory( + string firstName, string lastName, string invPath, string pass, Stream loadStream, + Dictionary options) { if (m_scenes.Count > 0) { @@ -252,7 +272,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver return false; } - public bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, string loadPath) + public bool DearchiveInventory( + string firstName, string lastName, string invPath, string pass, string loadPath, + Dictionary options) { if (m_scenes.Count > 0) { @@ -300,29 +322,41 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected void HandleLoadInvConsoleCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 6) - { - m_log.Error( - "[INVENTORY ARCHIVER]: usage is load iar []"); - return; - } - - m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - - string firstName = cmdparams[2]; - string lastName = cmdparams[3]; - string invPath = cmdparams[4]; - string pass = cmdparams[5]; - string loadPath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); - - m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", - loadPath, invPath, firstName, lastName); - - if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath)) + try + { + m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); + + Dictionary options = new Dictionary(); + OptionSet optionSet = new OptionSet().Add("m|merge", delegate (string v) { options["merge"] = v != null; }); + + List mainParams = optionSet.Parse(cmdparams); + + if (mainParams.Count < 6) + { + m_log.Error( + "[INVENTORY ARCHIVER]: usage is load iar []"); + return; + } + + string firstName = mainParams[2]; + string lastName = mainParams[3]; + string invPath = mainParams[4]; + string pass = mainParams[5]; + string loadPath = (mainParams.Count > 6 ? mainParams[6] : DEFAULT_INV_BACKUP_FILENAME); + m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", - loadPath, firstName, lastName); + "[INVENTORY ARCHIVER]: Loading archive {0} to inventory path {1} for {2} {3}", + loadPath, invPath, firstName, lastName); + + if (DearchiveInventory(firstName, lastName, invPath, pass, loadPath, options)) + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Loaded archive {0} for {1} {2}", + loadPath, firstName, lastName); + } + catch (InventoryArchiverException e) + { + m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); + } } /// @@ -331,30 +365,38 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected void HandleSaveInvConsoleCommand(string module, string[] cmdparams) { - if (cmdparams.Length < 6) - { - m_log.Error( - "[INVENTORY ARCHIVER]: usage is save iar []"); - return; - } - - m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); - - string firstName = cmdparams[2]; - string lastName = cmdparams[3]; - string invPath = cmdparams[4]; - string pass = cmdparams[5]; - string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); - - m_log.InfoFormat( - "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", - savePath, invPath, firstName, lastName); - Guid id = Guid.NewGuid(); - ArchiveInventory(id, firstName, lastName, invPath, pass, savePath); - + + try + { + if (cmdparams.Length < 6) + { + m_log.Error( + "[INVENTORY ARCHIVER]: usage is save iar []"); + return; + } + + m_log.Info("[INVENTORY ARCHIVER]: PLEASE NOTE THAT THIS FACILITY IS EXPERIMENTAL. BUG REPORTS WELCOME."); + + string firstName = cmdparams[2]; + string lastName = cmdparams[3]; + string invPath = cmdparams[4]; + string pass = cmdparams[5]; + string savePath = (cmdparams.Length > 6 ? cmdparams[6] : DEFAULT_INV_BACKUP_FILENAME); + + m_log.InfoFormat( + "[INVENTORY ARCHIVER]: Saving archive {0} using inventory path {1} for {2} {3}", + savePath, invPath, firstName, lastName); + + ArchiveInventory(id, firstName, lastName, invPath, pass, savePath, new Dictionary()); + } + catch (InventoryArchiverException e) + { + m_log.ErrorFormat("[INVENTORY ARCHIVER]: {0}", e.Message); + } + lock (m_pendingConsoleSaves) - m_pendingConsoleSaves.Add(id); + m_pendingConsoleSaves.Add(id); } private void SaveInvConsoleCommandCompleted( @@ -390,7 +432,9 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver /// protected UserAccount GetUserInfo(string firstName, string lastName, string pass) { - UserAccount account = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); + UserAccount account + = m_aScene.UserAccountService.GetUserAccount(m_aScene.RegionInfo.ScopeID, firstName, lastName); + if (null == account) { m_log.ErrorFormat( diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs index c81f295d8c..4531bfdfb2 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Archiver/Tests/InventoryArchiverTests.cs @@ -55,14 +55,6 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests { protected ManualResetEvent mre = new ManualResetEvent(false); - private void InventoryReceived(UUID userId) - { - lock (this) - { - Monitor.PulseAll(this); - } - } - private void SaveCompleted( Guid id, bool succeeded, UserAccount userInfo, string invPath, Stream saveStream, Exception reportedException) @@ -71,16 +63,14 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests } /// - /// Test saving a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet). + /// Test saving an inventory path to a V0.1 OpenSim Inventory Archive + /// (subject to change since there is no fixed format yet). /// - // Commenting for now! The mock inventory service needs more beef, at least for - // GetFolderForType - // REFACTORING PROBLEM. This needs to be rewritten. - //[Test] - public void TestSaveIarV0_1() + [Test] + public void TestSavePathToIarV0_1() { TestHelper.InMethod(); - log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); @@ -125,7 +115,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests item1.AssetID = asset1.FullID; item1.ID = item1Id; InventoryFolderBase objsFolder - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects"); + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; item1.Folder = objsFolder.ID; scene.AddInventoryItem(userId, item1); @@ -189,195 +179,298 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests // TODO: Test presence of more files and contents of files. } + /// + /// Test saving a single inventory item to a V0.1 OpenSim Inventory Archive + /// (subject to change since there is no fixed format yet). + /// + [Test] + public void TestSaveItemToIarV0_1() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + string userPassword = "troll"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, userPassword); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "My Little Dog Object"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); + } + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + string item1Name = "My Little Dog"; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(userId, item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; + + mre.Reset(); + archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects/" + item1Name, userPassword, archiveWriteStream); + mre.WaitOne(60000, false); + + byte[] archive = archiveWriteStream.ToArray(); + MemoryStream archiveReadStream = new MemoryStream(archive); + TarArchiveReader tar = new TarArchiveReader(archiveReadStream); + + //bool gotControlFile = false; + bool gotObject1File = false; + //bool gotObject2File = false; + string expectedObject1FileName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1); + string expectedObject1FilePath = string.Format( + "{0}{1}", + ArchiveConstants.INVENTORY_PATH, + expectedObject1FileName); + + string filePath; + TarArchiveReader.TarEntryType tarEntryType; + +// Console.WriteLine("Reading archive"); + + while (tar.ReadEntry(out filePath, out tarEntryType) != null) + { + Console.WriteLine("Got {0}", filePath); + +// if (ArchiveConstants.CONTROL_FILE_PATH == filePath) +// { +// gotControlFile = true; +// } + + if (filePath.StartsWith(ArchiveConstants.INVENTORY_PATH) && filePath.EndsWith(".xml")) + { +// string fileName = filePath.Remove(0, "Objects/".Length); +// +// if (fileName.StartsWith(part1.Name)) +// { + Assert.That(expectedObject1FilePath, Is.EqualTo(filePath)); + gotObject1File = true; +// } +// else if (fileName.StartsWith(part2.Name)) +// { +// Assert.That(fileName, Is.EqualTo(expectedObject2FileName)); +// gotObject2File = true; +// } + } + } + +// Assert.That(gotControlFile, Is.True, "No control file in archive"); + Assert.That(gotObject1File, Is.True, "No item1 file in archive"); +// Assert.That(gotObject2File, Is.True, "No object2 file in archive"); + + // TODO: Test presence of more files and contents of files. + } + /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// an account exists with the creator name. /// /// /// This test also does some deeper probing of loading into nested inventory structures - /// REFACTORING PROBLEM. This needs to be rewritten. -// [Test] -// public void TestLoadIarV0_1ExistingUsers() -// { -// TestHelper.InMethod(); + [Test] + public void TestLoadIarV0_1ExistingUsers() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); -// //log4net.Config.XmlConfigurator.Configure(); + string userFirstName = "Mr"; + string userLastName = "Tiddles"; + UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000555"); + string userItemCreatorFirstName = "Lord"; + string userItemCreatorLastName = "Lucan"; + UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); -// string userFirstName = "Mr"; -// string userLastName = "Tiddles"; -// UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000555"); -// string userItemCreatorFirstName = "Lord"; -// string userItemCreatorLastName = "Lucan"; -// UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000000666"); - -// string item1Name = "b.lsl"; -// string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1Name, UUID.Random()); + string item1Name = "b.lsl"; + string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(item1Name, UUID.Random()); -// MemoryStream archiveWriteStream = new MemoryStream(); -// TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); -// InventoryItemBase item1 = new InventoryItemBase(); -// item1.Name = item1Name; -// item1.AssetID = UUID.Random(); -// item1.GroupID = UUID.Random(); -// item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); -// //item1.CreatorId = userUuid.ToString(); -// //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; -// item1.Owner = UUID.Zero; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = item1Name; + item1.AssetID = UUID.Random(); + item1.GroupID = UUID.Random(); + item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); + //item1.CreatorId = userUuid.ToString(); + //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; + item1.Owner = UUID.Zero; -// string item1FileName -// = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); -// tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); -// tar.Close(); + string item1FileName + = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); + tar.Close(); -// MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); -// SerialiserModule serialiserModule = new SerialiserModule(); -// InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); -// // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene -// Scene scene = SceneSetupHelpers.SetupScene("inventory"); -// IUserAdminService userAdminService = scene.CommsManager.UserAdminService; + // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene + Scene scene = SceneSetupHelpers.SetupScene("inventory"); -// SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); -// userAdminService.AddUser( -// userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); -// userAdminService.AddUser( -// userItemCreatorFirstName, userItemCreatorLastName, "hampshire", -// String.Empty, 1000, 1000, userItemCreatorUuid); + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + + UserProfileTestUtils.CreateUserWithInventory( + scene, userFirstName, userLastName, userUuid, "meowfood"); + UserProfileTestUtils.CreateUserWithInventory( + scene, userItemCreatorFirstName, userItemCreatorLastName, userItemCreatorUuid, "hampshire"); -// archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); + archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); -// CachedUserInfo userInfo -// = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); - -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, item1Name); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, item1Name); -// Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); -//// We have to disable this check since loaded items that did find users via OSPA resolution are now only storing the -//// UUID, not the OSPA itself. -//// Assert.That( -//// foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), -//// "Loaded item non-uuid creator doesn't match original"); +// We have to disable this check since loaded items that did find users via OSPA resolution are now only storing the +// UUID, not the OSPA itself. // Assert.That( -// foundItem1.CreatorId, Is.EqualTo(userItemCreatorUuid.ToString()), +// foundItem1.CreatorId, Is.EqualTo(item1.CreatorId), // "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorId, Is.EqualTo(userItemCreatorUuid.ToString()), + "Loaded item non-uuid creator doesn't match original"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), + "Loaded item uuid creator doesn't match original"); + Assert.That(foundItem1.Owner, Is.EqualTo(userUuid), + "Loaded item owner doesn't match inventory reciever"); + + // Now try loading to a root child folder + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userUuid, "xA"); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", "meowfood", archiveReadStream); + + InventoryItemBase foundItem2 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, "xA/" + item1Name); + Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); + + // Now try loading to a more deeply nested folder + UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userUuid, "xB/xC"); + archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); + archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", "meowfood", archiveReadStream); + + InventoryItemBase foundItem3 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, "xB/xC/" + item1Name); + Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); + } + + [Test] + public void TestIarV0_1WithEscapedChars() + { + TestHelper.InMethod(); +// log4net.Config.XmlConfigurator.Configure(); + + string itemName = "You & you are a mean/man/"; + string humanEscapedItemName = @"You & you are a mean\/man\/"; + string userPassword = "meowfood"; + + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + + Scene scene = SceneSetupHelpers.SetupScene("Inventory"); + SceneSetupHelpers.SetupSceneModules(scene, archiverModule); + + // Create user + string userFirstName = "Jock"; + string userLastName = "Stirrup"; + UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userId, "meowfood"); + + // Create asset + SceneObjectGroup object1; + SceneObjectPart part1; + { + string partName = "part name"; + UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); + PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); + Vector3 groupPosition = new Vector3(10, 20, 30); + Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); + Vector3 offsetPosition = new Vector3(5, 10, 15); + + part1 + = new SceneObjectPart( + ownerId, shape, groupPosition, rotationOffset, offsetPosition); + part1.Name = partName; + + object1 = new SceneObjectGroup(part1); + scene.AddNewSceneObject(object1, false); + } + + UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); + AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); + scene.AssetService.Store(asset1); + + // Create item + UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = itemName; + item1.AssetID = asset1.FullID; + item1.ID = item1Id; + InventoryFolderBase objsFolder + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects")[0]; + item1.Folder = objsFolder.ID; + scene.AddInventoryItem(userId, item1); + + MemoryStream archiveWriteStream = new MemoryStream(); + archiverModule.OnInventoryArchiveSaved += SaveCompleted; + + mre.Reset(); + archiverModule.ArchiveInventory( + Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); + mre.WaitOne(60000, false); + + // LOAD ITEM + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + + archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); + + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath( + scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); + + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(userItemCreatorUuid), -// "Loaded item uuid creator doesn't match original"); -// Assert.That(foundItem1.Owner, Is.EqualTo(userUuid), -// "Loaded item owner doesn't match inventory reciever"); - -// // Now try loading to a root child folder -// UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userInfo.UserProfile.ID, "xA"); -// archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); -// archiverModule.DearchiveInventory(userFirstName, userLastName, "xA", "meowfood", archiveReadStream); - -// InventoryItemBase foundItem2 -// = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xA/" + item1Name); -// Assert.That(foundItem2, Is.Not.Null, "Didn't find loaded item 2"); - -// // Now try loading to a more deeply nested folder -// UserInventoryTestUtils.CreateInventoryFolder(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC"); -// archiveReadStream = new MemoryStream(archiveReadStream.ToArray()); -// archiverModule.DearchiveInventory(userFirstName, userLastName, "xB/xC", "meowfood", archiveReadStream); - -// InventoryItemBase foundItem3 -// = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, "xB/xC/" + item1Name); -// Assert.That(foundItem3, Is.Not.Null, "Didn't find loaded item 3"); - //} - - // REFACTORING PROBLEM. Needs rewrite. -// [Test] -// public void TestIarV0_1WithEscapedChars() -// { -// TestHelper.InMethod(); -//// log4net.Config.XmlConfigurator.Configure(); - -// string itemName = "You & you are a mean/man/"; -// string humanEscapedItemName = @"You & you are a mean\/man\/"; -// string userPassword = "meowfood"; - -// InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); - -// Scene scene = SceneSetupHelpers.SetupScene("Inventory"); -// SceneSetupHelpers.SetupSceneModules(scene, archiverModule); -// CommunicationsManager cm = scene.CommsManager; - -// // Create user -// string userFirstName = "Jock"; -// string userLastName = "Stirrup"; -// UUID userId = UUID.Parse("00000000-0000-0000-0000-000000000020"); - -// lock (this) -// { -// UserProfileTestUtils.CreateUserWithInventory( -// cm, userFirstName, userLastName, userPassword, userId, InventoryReceived); -// Monitor.Wait(this, 60000); -// } - -// // Create asset -// SceneObjectGroup object1; -// SceneObjectPart part1; -// { -// string partName = "part name"; -// UUID ownerId = UUID.Parse("00000000-0000-0000-0000-000000000040"); -// PrimitiveBaseShape shape = PrimitiveBaseShape.CreateSphere(); -// Vector3 groupPosition = new Vector3(10, 20, 30); -// Quaternion rotationOffset = new Quaternion(20, 30, 40, 50); -// Vector3 offsetPosition = new Vector3(5, 10, 15); - -// part1 -// = new SceneObjectPart( -// ownerId, shape, groupPosition, rotationOffset, offsetPosition); -// part1.Name = partName; - -// object1 = new SceneObjectGroup(part1); -// scene.AddNewSceneObject(object1, false); -// } - -// UUID asset1Id = UUID.Parse("00000000-0000-0000-0000-000000000060"); -// AssetBase asset1 = AssetHelpers.CreateAsset(asset1Id, object1); -// scene.AssetService.Store(asset1); - -// // Create item -// UUID item1Id = UUID.Parse("00000000-0000-0000-0000-000000000080"); -// InventoryItemBase item1 = new InventoryItemBase(); -// item1.Name = itemName; -// item1.AssetID = asset1.FullID; -// item1.ID = item1Id; -// InventoryFolderBase objsFolder -// = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, userId, "Objects"); -// item1.Folder = objsFolder.ID; -// scene.AddInventoryItem(userId, item1); - -// MemoryStream archiveWriteStream = new MemoryStream(); -// archiverModule.OnInventoryArchiveSaved += SaveCompleted; - -// mre.Reset(); -// archiverModule.ArchiveInventory( -// Guid.NewGuid(), userFirstName, userLastName, "Objects", userPassword, archiveWriteStream); -// mre.WaitOne(60000, false); - -// // LOAD ITEM -// MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); - -// archiverModule.DearchiveInventory(userFirstName, userLastName, "Scripts", userPassword, archiveReadStream); - -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath( -// scene.InventoryService, userId, "Scripts/Objects/" + humanEscapedItemName); - -// Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); -//// Assert.That( -//// foundItem1.CreatorId, Is.EqualTo(userUuid), -//// "Loaded item non-uuid creator doesn't match that of the loading user"); -// Assert.That( -// foundItem1.Name, Is.EqualTo(itemName), -// "Loaded item name doesn't match saved name"); -// } +// foundItem1.CreatorId, Is.EqualTo(userUuid), +// "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That( + foundItem1.Name, Is.EqualTo(itemName), + "Loaded item name doesn't match saved name"); + } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where @@ -386,76 +479,69 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// /// This may possibly one day get overtaken by the as yet incomplete temporary profiles feature /// (as tested in the a later commented out test) - /// REFACTORING PROBLEM. Needs rewrite. -// [Test] -// public void TestLoadIarV0_1AbsentUsers() -// { -// TestHelper.InMethod(); + /// This test is currently disabled + [Test] + public void TestLoadIarV0_1AbsentUsers() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); -// //log4net.Config.XmlConfigurator.Configure(); + string userFirstName = "Charlie"; + string userLastName = "Chan"; + UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000999"); + string userItemCreatorFirstName = "Bat"; + string userItemCreatorLastName = "Man"; + //UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000008888"); -// string userFirstName = "Charlie"; -// string userLastName = "Chan"; -// UUID userUuid = UUID.Parse("00000000-0000-0000-0000-000000000999"); -// string userItemCreatorFirstName = "Bat"; -// string userItemCreatorLastName = "Man"; -// //UUID userItemCreatorUuid = UUID.Parse("00000000-0000-0000-0000-000000008888"); - -// string itemName = "b.lsl"; -// string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); + string itemName = "b.lsl"; + string archiveItemName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); -// MemoryStream archiveWriteStream = new MemoryStream(); -// TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); + MemoryStream archiveWriteStream = new MemoryStream(); + TarArchiveWriter tar = new TarArchiveWriter(archiveWriteStream); -// InventoryItemBase item1 = new InventoryItemBase(); -// item1.Name = itemName; -// item1.AssetID = UUID.Random(); -// item1.GroupID = UUID.Random(); -// item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); -// //item1.CreatorId = userUuid.ToString(); -// //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; -// item1.Owner = UUID.Zero; + InventoryItemBase item1 = new InventoryItemBase(); + item1.Name = itemName; + item1.AssetID = UUID.Random(); + item1.GroupID = UUID.Random(); + item1.CreatorId = OspResolver.MakeOspa(userItemCreatorFirstName, userItemCreatorLastName); + //item1.CreatorId = userUuid.ToString(); + //item1.CreatorId = "00000000-0000-0000-0000-000000000444"; + item1.Owner = UUID.Zero; -// string item1FileName -// = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); -// tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); -// tar.Close(); + string item1FileName + = string.Format("{0}{1}", ArchiveConstants.INVENTORY_PATH, archiveItemName); + tar.WriteFile(item1FileName, UserInventoryItemSerializer.Serialize(item1)); + tar.Close(); -// MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); -// SerialiserModule serialiserModule = new SerialiserModule(); -// InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); + MemoryStream archiveReadStream = new MemoryStream(archiveWriteStream.ToArray()); + SerialiserModule serialiserModule = new SerialiserModule(); + InventoryArchiverModule archiverModule = new InventoryArchiverModule(true); -// // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene -// Scene scene = SceneSetupHelpers.SetupScene("inventory"); -// IUserAdminService userAdminService = scene.CommsManager.UserAdminService; + // Annoyingly, we have to set up a scene even though inventory loading has nothing to do with a scene + Scene scene = SceneSetupHelpers.SetupScene("inventory"); -// SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); -// userAdminService.AddUser( -// userFirstName, userLastName, "meowfood", String.Empty, 1000, 1000, userUuid); + SceneSetupHelpers.SetupSceneModules(scene, serialiserModule, archiverModule); + UserProfileTestUtils.CreateUserWithInventory(scene, userFirstName, userLastName, userUuid, "meowfood"); -// archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); + archiverModule.DearchiveInventory(userFirstName, userLastName, "/", "meowfood", archiveReadStream); -// CachedUserInfo userInfo -// = scene.CommsManager.UserProfileCacheService.GetUserDetails(userFirstName, userLastName); - -// InventoryItemBase foundItem1 -// = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userInfo.UserProfile.ID, itemName); + InventoryItemBase foundItem1 + = InventoryArchiveUtils.FindItemByPath(scene.InventoryService, userUuid, itemName); -// Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); -//// Assert.That( -//// foundItem1.CreatorId, Is.EqualTo(userUuid), -//// "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That(foundItem1, Is.Not.Null, "Didn't find loaded item 1"); // Assert.That( -// foundItem1.CreatorIdAsUuid, Is.EqualTo(userUuid), -// "Loaded item uuid creator doesn't match that of the loading user"); -// } +// foundItem1.CreatorId, Is.EqualTo(userUuid), +// "Loaded item non-uuid creator doesn't match that of the loading user"); + Assert.That( + foundItem1.CreatorIdAsUuid, Is.EqualTo(userUuid), + "Loaded item uuid creator doesn't match that of the loading user"); + } /// /// Test loading a V0.1 OpenSim Inventory Archive (subject to change since there is no fixed format yet) where /// no account exists with the creator name /// /// Disabled since temporary profiles have not yet been implemented. - /// REFACTORING PROBLEM. Needs rewrite. /// //[Test] //public void TestLoadIarV0_1TempProfiles() @@ -534,10 +620,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests /// Test replication of an archive path to the user's inventory. /// [Test] - public void TestReplicateArchivePathToUserInventory() + public void TestNewIarPath() { TestHelper.InMethod(); - //log4net.Config.XmlConfigurator.Configure(); +// log4net.Config.XmlConfigurator.Configure(); Scene scene = SceneSetupHelpers.SetupScene("inventory"); UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); @@ -545,29 +631,106 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Archiver.Tests Dictionary foldersCreated = new Dictionary(); List nodesLoaded = new List(); - string folder1Name = "a"; - string folder2Name = "b"; - string itemName = "c.lsl"; + string folder1Name = "1"; + string folder2aName = "2a"; + string folder2bName = "2b"; string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1Name, UUID.Random()); - string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); - string itemArchiveName = InventoryArchiveWriteRequest.CreateArchiveItemName(itemName, UUID.Random()); + string folder2aArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2aName, UUID.Random()); + string folder2bArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2bName, UUID.Random()); - string itemArchivePath - = string.Format( - "{0}{1}{2}{3}", - ArchiveConstants.INVENTORY_PATH, folder1ArchiveName, folder2ArchiveName, itemArchiveName); + string iarPath1 = string.Join("", new string[] { folder1ArchiveName, folder2aArchiveName }); + string iarPath2 = string.Join("", new string[] { folder1ArchiveName, folder2bArchiveName }); + { + // Test replication of path1 + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) + .ReplicateArchivePathToUserInventory( + iarPath1, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + List folder2aCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + } + + { + // Test replication of path2 + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) + .ReplicateArchivePathToUserInventory( + iarPath2, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + foldersCreated, nodesLoaded); + + List folder1Candidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1Name); + Assert.That(folder1Candidates.Count, Is.EqualTo(1)); + + InventoryFolderBase folder1 = folder1Candidates[0]; + + List folder2aCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2aName); + Assert.That(folder2aCandidates.Count, Is.EqualTo(1)); + + List folder2bCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, folder2bName); + Assert.That(folder2bCandidates.Count, Is.EqualTo(1)); + } + } + + /// + /// Test replication of a partly existing archive path to the user's inventory. This should create + /// a duplicate path without the merge option. + /// + [Test] + public void TestPartExistingIarPath() + { + TestHelper.InMethod(); + //log4net.Config.XmlConfigurator.Configure(); + + Scene scene = SceneSetupHelpers.SetupScene("inventory"); + UserAccount ua1 = UserProfileTestUtils.CreateUserWithInventory(scene); + + string folder1ExistingName = "a"; + string folder2Name = "b"; + + InventoryFolderBase folder1 + = UserInventoryTestUtils.CreateInventoryFolder( + scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + + string folder1ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder1ExistingName, UUID.Random()); + string folder2ArchiveName = InventoryArchiveWriteRequest.CreateArchiveFolderName(folder2Name, UUID.Random()); + + string itemArchivePath = string.Join("", new string[] { folder1ArchiveName, folder2ArchiveName }); + new InventoryArchiveReadRequest(scene, ua1, null, (Stream)null) .ReplicateArchivePathToUserInventory( - itemArchivePath, false, scene.InventoryService.GetRootFolder(ua1.PrincipalID), - foldersCreated, nodesLoaded); + itemArchivePath, scene.InventoryService.GetRootFolder(ua1.PrincipalID), + new Dictionary(), new List()); - InventoryFolderBase folder1 - = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, "a"); - Assert.That(folder1, Is.Not.Null, "Could not find folder a"); - InventoryFolderBase folder2 = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1, "b"); - Assert.That(folder2, Is.Not.Null, "Could not find folder b"); - } + List folder1PostCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, ua1.PrincipalID, folder1ExistingName); + Assert.That(folder1PostCandidates.Count, Is.EqualTo(2)); + + // FIXME: Temporarily, we're going to do something messy to make sure we pick up the created folder. + InventoryFolderBase folder1Post = null; + foreach (InventoryFolderBase folder in folder1PostCandidates) + { + if (folder.ID != folder1.ID) + { + folder1Post = folder; + break; + } + } +// Assert.That(folder1Post.ID, Is.EqualTo(folder1.ID)); + + List folder2PostCandidates + = InventoryArchiveUtils.FindFolderByPath(scene.InventoryService, folder1Post, "b"); + Assert.That(folder2PostCandidates.Count, Is.EqualTo(1)); + } } } \ No newline at end of file diff --git a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs index be897409e8..2f1e9dd74e 100644 --- a/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs +++ b/OpenSim/Region/CoreModules/Avatar/Inventory/Transfer/InventoryTransferModule.cs @@ -145,10 +145,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { ScenePresence presence = scene.GetScenePresence(agentId); if (presence != null) - { - if (!presence.IsChildAgent) - return scene; - } + return scene; } } return null; @@ -156,19 +153,23 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer private void OnInstantMessage(IClientAPI client, GridInstantMessage im) { - m_log.InfoFormat("OnInstantMessage {0}", im.dialog); + m_log.InfoFormat("[INVENTORY TRANSFER]: OnInstantMessage {0}", im.dialog); + Scene scene = FindClientScene(client.AgentId); if (scene == null) // Something seriously wrong here. return; - if (im.dialog == (byte) InstantMessageDialog.InventoryOffered) { //m_log.DebugFormat("Asset type {0}", ((AssetType)im.binaryBucket[0])); - - ScenePresence user = scene.GetScenePresence(new UUID(im.toAgentID)); + + if (im.binaryBucket.Length < 17) // Invalid + return; + + UUID receipientID = new UUID(im.toAgentID); + ScenePresence user = scene.GetScenePresence(receipientID); UUID copyID; // First byte is the asset type @@ -183,7 +184,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer folderID, new UUID(im.toAgentID)); InventoryFolderBase folderCopy - = scene.GiveInventoryFolder(new UUID(im.toAgentID), client.AgentId, folderID, UUID.Zero); + = scene.GiveInventoryFolder(receipientID, client.AgentId, folderID, UUID.Zero); if (folderCopy == null) { @@ -199,20 +200,22 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer im.binaryBucket[0] = (byte)AssetType.Folder; Array.Copy(copyIDBytes, 0, im.binaryBucket, 1, copyIDBytes.Length); - if (user != null && !user.IsChildAgent) + if (user != null) { user.ControllingClient.SendBulkUpdateInventory(folderCopy); } + + // HACK!! + im.imSessionID = folderID.Guid; } else { // First byte of the array is probably the item type // Next 16 bytes are the UUID - m_log.Info("OnInstantMessage - giving item"); UUID itemID = new UUID(im.binaryBucket, 1); - m_log.DebugFormat("[AGENT INVENTORY]: Inserting item {0} "+ + m_log.DebugFormat("[AGENT INVENTORY]: (giving) Inserting item {0} "+ "into agent {1}'s inventory", itemID, new UUID(im.toAgentID)); @@ -229,29 +232,32 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer copyID = itemCopy.ID; Array.Copy(copyID.GetBytes(), 0, im.binaryBucket, 1, 16); - if (user != null && !user.IsChildAgent) + if (user != null) { user.ControllingClient.SendBulkUpdateInventory(itemCopy); } + + // HACK!! + im.imSessionID = itemID.Guid; } // Send the IM to the recipient. The item is already // in their inventory, so it will not be lost if // they are offline. // - if (user != null && !user.IsChildAgent) + if (user != null) { - // And notify. Transaction ID is the item ID. We get that - // same ID back on the reply so we know what to act on - // user.ControllingClient.SendInstantMessage(im); - return; } else { if (m_TransferModule != null) - m_TransferModule.SendInstantMessage(im, delegate(bool success) {}); + m_TransferModule.SendInstantMessage(im, delegate(bool success) + { + if (!success) + client.SendAlertMessage("User not online. Inventory has been saved"); + }); } } else if (im.dialog == (byte) InstantMessageDialog.InventoryAccepted) @@ -282,10 +288,10 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer InventoryFolderBase trashFolder = invService.GetFolderForType(client.AgentId, AssetType.TrashFolder); - - UUID inventoryEntityID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip - InventoryItemBase item = new InventoryItemBase(inventoryEntityID, client.AgentId); + UUID inventoryID = new UUID(im.imSessionID); // The inventory item/folder, back from it's trip + + InventoryItemBase item = new InventoryItemBase(inventoryID, client.AgentId); item = invService.GetItem(item); InventoryFolderBase folder = null; @@ -301,7 +307,7 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer } else { - folder = new InventoryFolderBase(inventoryEntityID, client.AgentId); + folder = new InventoryFolderBase(inventoryID, client.AgentId); folder = invService.GetFolder(folder); if (folder != null & trashFolder != null) @@ -417,90 +423,18 @@ namespace OpenSim.Region.CoreModules.Avatar.Inventory.Transfer { // Check if this is ours to handle // - m_log.Info("OnFridInstantMessage"); - if (msg.dialog != (byte) InstantMessageDialog.InventoryOffered) - return; - - if (msg.binaryBucket.Length < 17) // Invalid - return; - Scene scene = FindClientScene(new UUID(msg.toAgentID)); + if (scene == null) + return; + // Find agent to deliver to // ScenePresence user = scene.GetScenePresence(new UUID(msg.toAgentID)); - if (user == null) // Shouldn't happen - { - m_log.Debug("[INVENTORY TRANSFER] Can't find recipient"); - return; - } + // Just forward to local handling + OnInstantMessage(user.ControllingClient, msg); - //CachedUserInfo userInfo = - // scene.CommsManager.UserProfileCacheService. - // GetUserDetails(user.ControllingClient.AgentId); - - //if (userInfo == null) - //{ - // m_log.Debug("[INVENTORY TRANSFER] Can't find user info of recipient"); - // return; - //} - - AssetType assetType = (AssetType)msg.binaryBucket[0]; - IInventoryService invService = scene.InventoryService; - - if (AssetType.Folder == assetType) - { - UUID folderID = new UUID(msg.binaryBucket, 1); - InventoryFolderBase folder = new InventoryFolderBase(); - - folder.ID = folderID; - folder.Owner = user.ControllingClient.AgentId; - - // Fetch from service - // - folder = invService.GetFolder(folder); - if (folder == null) - { - m_log.Debug("[INVENTORY TRANSFER] Can't find folder to give"); - return; - } - - user.ControllingClient.SendBulkUpdateInventory(folder); - - //// This unelegant, slow kludge is to reload the folders and - //// items. Since a folder give can transfer subfolders and - //// items, this is the easiest way to pull that stuff in - //// - //userInfo.DropInventory(); - //userInfo.FetchInventory(); - - // Deliver message - // - user.ControllingClient.SendInstantMessage(msg); - } - else - { - UUID itemID = new UUID(msg.binaryBucket, 1); - InventoryItemBase item = new InventoryItemBase(itemID, user.ControllingClient.AgentId); - - // Fetch from service - // - item = invService.GetItem(item); - if (item == null) - { - m_log.Debug("[INVENTORY TRANSFER] Can't find item to give"); - return; - } - - // Update item to viewer (makes it appear in proper folder) - // - user.ControllingClient.SendBulkUpdateInventory(item); - - // Deliver message - // - user.ControllingClient.SendInstantMessage(msg); - } } } } diff --git a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs index ef37f63622..ab1cfc352b 100644 --- a/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs +++ b/OpenSim/Region/CoreModules/Framework/EntityTransfer/EntityTransferModule.cs @@ -180,6 +180,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer sp.ControllingClient.SendLocalTeleport(position, lookAt, teleportFlags); sp.Teleport(position); + + foreach (SceneObjectGroup grp in sp.Attachments) + sp.Scene.EventManager.TriggerOnScriptChangedEvent(grp.LocalId, (uint)Changed.TELEPORT); } else // Another region possibly in another simulator { @@ -393,7 +396,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer agent.Position = position; SetCallbackURL(agent, sp.Scene.RegionInfo); - UpdateAgent(reg, finalDestination, agent); + if (!UpdateAgent(reg, finalDestination, agent)) + { + // Region doesn't take it + Fail(sp, finalDestination); + return; + } m_log.DebugFormat( "[ENTITY TRANSFER MODULE]: Sending new CAPS seed url {0} to client {1}", capsPath, sp.UUID); @@ -410,23 +418,15 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer teleportFlags, capsPath); } + // Let's set this to true tentatively. This does not trigger OnChildAgent + sp.IsChildAgent = true; + // TeleportFinish makes the client send CompleteMovementIntoRegion (at the destination), which // trigers a whole shebang of things there, including MakeRoot. So let's wait for confirmation // that the client contacted the destination before we send the attachments and close things here. if (!WaitForCallback(sp.UUID)) { - // Client never contacted destination. Let's restore everything back - sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); - - ResetFromTransit(sp.UUID); - - // Yikes! We should just have a ref to scene here. - //sp.Scene.InformClientOfNeighbours(sp); - EnableChildAgents(sp); - - // Finally, kill the agent we just created at the destination. - m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); - + Fail(sp, finalDestination); return; } @@ -436,7 +436,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer KillEntity(sp.Scene, sp.LocalId); + // Now let's make it officially a child agent sp.MakeChildAgent(); + // Finally, let's close this previously-known-as-root agent, when the jump is outside the view zone if (NeedsClosing(oldRegionX, newRegionX, oldRegionY, newRegionY, reg)) @@ -464,6 +466,22 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer } } + private void Fail(ScenePresence sp, GridRegion finalDestination) + { + // Client never contacted destination. Let's restore everything back + sp.ControllingClient.SendTeleportFailed("Problems connecting to destination."); + + // Fail. Reset it back + sp.IsChildAgent = false; + + ResetFromTransit(sp.UUID); + + EnableChildAgents(sp); + + // Finally, kill the agent we just created at the destination. + m_aScene.SimulationService.CloseAgent(finalDestination, sp.UUID); + + } protected virtual bool CreateAgent(ScenePresence sp, GridRegion reg, GridRegion finalDestination, AgentCircuitData agentCircuit, uint teleportFlags, out string reason) { @@ -538,6 +556,9 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer client.SendTeleportFailed("Your home region could not be found."); return; } + m_log.DebugFormat("[ENTITY TRANSFER MODULE]: User's home region is {0} {1} ({2}-{3})", + regionInfo.RegionName, regionInfo.RegionID, regionInfo.RegionLocX / Constants.RegionSize, regionInfo.RegionLocY / Constants.RegionSize); + // a little eekie that this goes back to Scene and with a forced cast, will fix that at some point... ((Scene)(client.Scene)).RequestTeleportLocation( client, regionInfo.RegionHandle, uinfo.HomePosition, uinfo.HomeLookAt, @@ -799,7 +820,12 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer cAgent.CallbackURI = "http://" + m_scene.RegionInfo.ExternalHostName + ":" + m_scene.RegionInfo.HttpPort + "/agent/" + agent.UUID.ToString() + "/" + m_scene.RegionInfo.RegionID.ToString() + "/release/"; - m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent); + if (!m_scene.SimulationService.UpdateAgent(neighbourRegion, cAgent)) + { + // region doesn't take it + ResetFromTransit(agent.UUID); + return agent; + } // Next, let's close the child agent connections that are too far away. agent.CloseChildAgents(neighbourx, neighboury); @@ -854,9 +880,6 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer CrossAttachmentsIntoNewRegion(neighbourRegion, agent, true); - // m_scene.SendKillObject(m_localId); - - agent.Scene.NotifyMyCoarseLocationChange(); // the user may change their profile information in other region, // so the userinfo in UserProfileCache is not reliable any more, delete it // REFACTORING PROBLEM. Well, not a problem, but this method is HORRIBLE! @@ -899,12 +922,40 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer /// public void EnableChildAgent(ScenePresence sp, GridRegion region) { + m_log.DebugFormat("[ENTITY TRANSFER]: Enabling child agent in new neighour {0}", region.RegionName); + + AgentCircuitData currentAgentCircuit = sp.Scene.AuthenticateHandler.GetAgentCircuitData(sp.ControllingClient.CircuitCode); AgentCircuitData agent = sp.ControllingClient.RequestClientInfo(); agent.BaseFolder = UUID.Zero; agent.InventoryFolder = UUID.Zero; agent.startpos = new Vector3(128, 128, 70); agent.child = true; agent.Appearance = sp.Appearance; + agent.CapsPath = CapsUtil.GetRandomCapsObjectPath(); + + agent.ChildrenCapSeeds = new Dictionary(sp.Scene.CapsModule.GetChildrenSeeds(sp.UUID)); + m_log.DebugFormat("[XXX] Seeds 1 {0}", agent.ChildrenCapSeeds.Count); + + if (!agent.ChildrenCapSeeds.ContainsKey(sp.Scene.RegionInfo.RegionHandle)) + agent.ChildrenCapSeeds.Add(sp.Scene.RegionInfo.RegionHandle, sp.ControllingClient.RequestClientInfo().CapsPath); + m_log.DebugFormat("[XXX] Seeds 2 {0}", agent.ChildrenCapSeeds.Count); + + sp.AddNeighbourRegion(region.RegionHandle, agent.CapsPath); + foreach (ulong h in agent.ChildrenCapSeeds.Keys) + m_log.DebugFormat("[XXX] --> {0}", h); + m_log.DebugFormat("[XXX] Adding {0}", region.RegionHandle); + agent.ChildrenCapSeeds.Add(region.RegionHandle, agent.CapsPath); + + if (sp.Scene.CapsModule != null) + { + sp.Scene.CapsModule.SetChildrenSeed(sp.UUID, agent.ChildrenCapSeeds); + } + + if (currentAgentCircuit != null) + { + agent.ServiceURLs = currentAgentCircuit.ServiceURLs; + agent.Viewer = currentAgentCircuit.Viewer; + } InformClientOfNeighbourDelegate d = InformClientOfNeighbourAsync; d.BeginInvoke(sp, agent, region, region.ExternalEndPoint, true, @@ -1112,7 +1163,7 @@ namespace OpenSim.Region.CoreModules.Framework.EntityTransfer string reason = String.Empty; - bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, 0, out reason); // m_interregionCommsOut.SendCreateChildAgent(reg.RegionHandle, a, 0, out reason); + bool regionAccepted = m_scene.SimulationService.CreateAgent(reg, a, (uint)TeleportFlags.Default, out reason); if (regionAccepted && newAgent) { diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs index 58ce550773..b13b9d8fc5 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGAssetMapper.cs @@ -95,6 +95,10 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess try { asset1.ID = url + "/" + asset.ID; + UUID temp = UUID.Zero; + // TODO: if the creator is local, stick this grid's URL in front + //if (UUID.TryParse(asset.Metadata.CreatorID, out temp)) + // asset1.Metadata.CreatorID = ??? + "/" + asset.Metadata.CreatorID; } catch { @@ -153,6 +157,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess Dictionary ids = new Dictionary(); HGUuidGatherer uuidGatherer = new HGUuidGatherer(this, m_scene.AssetService, userAssetURL); uuidGatherer.GatherAssetUuids(asset.FullID, (AssetType)asset.Type, ids); + if (ids.ContainsKey(assetID)) + ids.Remove(assetID); foreach (UUID uuid in ids.Keys) FetchAsset(userAssetURL, uuid); diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs index 2ab46aa33f..8ccc941c18 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/HGInventoryAccessModule.cs @@ -131,6 +131,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return ret; } + // DO NOT OVERRIDE THE BASE METHOD public virtual UUID DeleteToInventory(DeRezAction action, UUID folderID, SceneObjectGroup objectGroup, IClientAPI remoteClient) { @@ -138,7 +139,8 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (!assetID.Equals(UUID.Zero)) { - UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); + if (remoteClient != null) + UploadInventoryItem(remoteClient.AgentId, assetID, "", 0); } else m_log.Debug("[HGScene]: Scene.Inventory did not create asset"); @@ -191,9 +193,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess m_assMapper.Post(item.AssetID, receiver, userAssetServer); } - #endregion - - public bool IsForeignUser(UUID userID, out string assetServerURL) + public override bool IsForeignUser(UUID userID, out string assetServerURL) { assetServerURL = string.Empty; UserAccount account = null; @@ -216,5 +216,18 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return false; } + + #endregion + + protected override InventoryItemBase GetItem(UUID agentID, UUID itemID) + { + InventoryItemBase item = base.GetItem(agentID, itemID); + + string userAssetServer = string.Empty; + if (IsForeignUser(agentID, out userAssetServer)) + m_assMapper.Get(item.AssetID, agentID, userAssetServer); + + return item; + } } } diff --git a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs index 3035d889e7..1a7da61105 100644 --- a/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs +++ b/OpenSim/Region/CoreModules/Framework/InventoryAccess/InventoryAccessModule.cs @@ -286,23 +286,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { // Deleting someone else's item // - - if (remoteClient == null || objectGroup.OwnerID != remoteClient.AgentId) { - // Folder skeleton may not be loaded and we - // have to wait for the inventory to find - // the destination folder - // + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.LostAndFoundFolder); } else { - // Assume inventory skeleton was loaded during login - // and all folders can be found - // - folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); + folder = m_Scene.InventoryService.GetFolderForType(userID, AssetType.TrashFolder); } } else if (action == DeRezAction.Return) @@ -330,9 +322,20 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess } } + // Override and put into where it came from, if it came + // from anywhere in inventory + // + if (action == DeRezAction.Take || action == DeRezAction.TakeCopy) + { + if (objectGroup.RootPart.FromFolderID != UUID.Zero) + { + InventoryFolderBase f = new InventoryFolderBase(objectGroup.RootPart.FromFolderID, userID); + folder = m_Scene.InventoryService.GetFolder(f); + } + } + if (folder == null) // None of the above { - //folder = userInfo.RootFolder.FindFolder(folderID); folder = new InventoryFolderBase(folderID); if (folder == null) // Nowhere to put it @@ -378,12 +381,27 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if ((nextPerms & (uint)PermissionMask.Modify) == 0) perms &= ~(uint)PermissionMask.Modify; + // Make sure all bits but the ones we want are clear + // on take. + // This will be applied to the current perms, so + // it will do what we want. + objectGroup.RootPart.NextOwnerMask &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + objectGroup.RootPart.NextOwnerMask |= + (uint)PermissionMask.Move; + item.BasePermissions = perms & objectGroup.RootPart.NextOwnerMask; item.CurrentPermissions = item.BasePermissions; item.NextPermissions = objectGroup.RootPart.NextOwnerMask; item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask & objectGroup.RootPart.NextOwnerMask; item.GroupPermissions = objectGroup.RootPart.GroupMask & objectGroup.RootPart.NextOwnerMask; - item.CurrentPermissions |= 8; // Slam! + + // Magic number badness. Maybe this deserves an enum. + // bit 4 (16) is the "Slam" bit, it means treat as passed + // and apply next owner perms on rez + item.CurrentPermissions |= 16; // Slam! } else { @@ -393,7 +411,12 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess item.EveryOnePermissions = objectGroup.RootPart.EveryoneMask; item.GroupPermissions = objectGroup.RootPart.GroupMask; - item.CurrentPermissions |= 8; // Slam! + item.CurrentPermissions &= + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify | + (uint)PermissionMask.Move | + 7); // Preserve folded permissions } // TODO: add the new fields (Flags, Sale info, etc) @@ -494,6 +517,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess SceneObjectGroup group = SceneObjectSerializer.FromOriginalXmlFormat(itemId, xmlData); + group.RootPart.FromFolderID = item.Folder; + + // If it's rezzed in world, select it. Much easier to + // find small items. + // + if (!attachment) + group.RootPart.CreateSelected = true; + if (!m_Scene.Permissions.CanRezObject( group.Children.Count, remoteClient.AgentId, pos) && !attachment) @@ -566,7 +597,7 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess List partList = new List(group.Children.Values); group.SetGroup(remoteClient.ActiveGroupId, remoteClient); - if (rootPart.OwnerID != item.Owner) + if ((rootPart.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { //Need to kill the for sale here rootPart.ObjectSaleType = 0; @@ -574,14 +605,11 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess if (m_Scene.Permissions.PropagatePermissions()) { - if ((item.CurrentPermissions & 8) != 0) + foreach (SceneObjectPart part in partList) { - foreach (SceneObjectPart part in partList) - { - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - part.GroupMask = 0; // DO NOT propagate here - } + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; + part.GroupMask = 0; // DO NOT propagate here } group.ApplyNextOwnerPermissions(); @@ -590,19 +618,15 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess foreach (SceneObjectPart part in partList) { - if (part.OwnerID != item.Owner) + if ((part.OwnerID != item.Owner) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.Owner; part.Inventory.ChangeInventoryOwner(item.Owner); - } - else if (((item.CurrentPermissions & 8) != 0) && (!attachment)) // Slam! - { - part.EveryoneMask = item.EveryOnePermissions; - part.NextOwnerMask = item.NextPermissions; - part.GroupMask = 0; // DO NOT propagate here } + part.EveryoneMask = item.EveryOnePermissions; + part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); @@ -648,6 +672,57 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess { } + public virtual bool GetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID) + { + InventoryItemBase assetRequestItem = GetItem(remoteClient.AgentId, itemID); + if (assetRequestItem == null) + { + ILibraryService lib = m_Scene.RequestModuleInterface(); + if (lib != null) + assetRequestItem = lib.LibraryRootFolder.FindItem(itemID); + if (assetRequestItem == null) + return false; + } + + // At this point, we need to apply perms + // only to notecards and scripts. All + // other asset types are always available + // + if (assetRequestItem.AssetType == (int)AssetType.LSLText) + { + if (!m_Scene.Permissions.CanViewScript(itemID, UUID.Zero, remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to view script", false); + return false; + } + } + else if (assetRequestItem.AssetType == (int)AssetType.Notecard) + { + if (!m_Scene.Permissions.CanViewNotecard(itemID, UUID.Zero, remoteClient.AgentId)) + { + remoteClient.SendAgentAlertMessage("Insufficient permissions to view notecard", false); + return false; + } + } + + if (assetRequestItem.AssetID != requestID) + { + m_log.WarnFormat( + "[CLIENT]: {0} requested asset {1} from item {2} but this does not match item's asset {3}", + Name, requestID, itemID, assetRequestItem.AssetID); + return false; + } + + return true; + } + + + public virtual bool IsForeignUser(UUID userID, out string assetServerURL) + { + assetServerURL = string.Empty; + return false; + } + #endregion #region Misc @@ -670,6 +745,14 @@ namespace OpenSim.Region.CoreModules.Framework.InventoryAccess return asset; } + protected virtual InventoryItemBase GetItem(UUID agentID, UUID itemID) + { + IInventoryService invService = m_Scene.RequestModuleInterface(); + InventoryItemBase assetRequestItem = new InventoryItemBase(itemID, agentID); + assetRequestItem = invService.GetItem(assetRequestItem); + return assetRequestItem; + } + #endregion } } diff --git a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs index 83f004dc60..c0975eaaa0 100644 --- a/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs +++ b/OpenSim/Region/CoreModules/Scripting/EMailModules/EmailModule.cs @@ -40,7 +40,7 @@ using OpenSim.Region.Framework.Scenes; namespace OpenSim.Region.CoreModules.Scripting.EmailModules { - public class EmailModule : IEmailModule + public class EmailModule : IRegionModule, IEmailModule { // // Log diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs index ae03cdf9f6..209cf0d3c2 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Inventory/InventoryServiceInConnectorModule.cs @@ -96,7 +96,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Inventory Object[] args = new Object[] { m_Config, MainServer.Instance, "HGInventoryService" }; - ServerUtils.LoadPlugin("OpenSim.Server.Handlers.dll:HGInventoryServiceInConnector", args); + ServerUtils.LoadPlugin("OpenSim.Server.Handlers.dll:XInventoryInConnector", args); } } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs index 8a903701fa..35518d59f8 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsIn/Neighbour/NeighbourServiceInConnectorModule.cs @@ -123,17 +123,14 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsIn.Neighbour public GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) { - m_log.DebugFormat("[NEIGHBOUR IN CONNECTOR]: HelloNeighbour from {0}, to {1}. Count = {2}", - thisRegion.RegionName, regionHandle, m_Scenes.Count); foreach (Scene s in m_Scenes) { if (s.RegionInfo.RegionHandle == regionHandle) { - m_log.Debug("[NEIGHBOUR IN CONNECTOR]: Found region to SendHelloNeighbour"); + //m_log.DebugFormat("[NEIGHBOUR IN CONNECTOR]: HelloNeighbour from {0} to {1}", thisRegion.RegionName, s.RegionInfo.RegionName); return s.IncomingHelloNeighbour(thisRegion); } } - m_log.DebugFormat("[NEIGHBOUR IN CONNECTOR]: region handle {0} not found", regionHandle); return null; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs index ebd6bbdcfa..034e69272e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Asset/HGAssetBroker.cs @@ -41,7 +41,7 @@ using OpenMetaverse; namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset { public class HGAssetBroker : - ISharedRegionModule, IAssetService, IHyperAssetService + ISharedRegionModule, IAssetService { private static readonly ILog m_log = LogManager.GetLogger( @@ -150,7 +150,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Asset m_aScene = scene; scene.RegisterModuleInterface(this); - scene.RegisterModuleInterface(this); } public void RemoveRegion(Scene scene) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs index 1b00c8a9d7..b2e3f4f7f5 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/LocalGridServiceConnector.cs @@ -181,22 +181,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid public List GetNeighbours(UUID scopeID, UUID regionID) { - if (m_LocalCache.ContainsKey(regionID)) - { - List neighbours = m_LocalCache[regionID].GetNeighbours(); - if (neighbours.Count == 0) - // try the DB - neighbours = m_GridService.GetNeighbours(scopeID, regionID); - return neighbours; - } - else - { - m_log.WarnFormat("[LOCAL GRID CONNECTOR]: GetNeighbours: Requested region {0} is not on this sim", regionID); - return new List(); - } - - // Don't go to the DB - //return m_GridService.GetNeighbours(scopeID, regionID); + return m_GridService.GetNeighbours(scopeID, regionID); } public GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs index 46741a58ec..16e25e6f11 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Grid/RemoteGridServiceConnector.cs @@ -153,12 +153,9 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Grid return false; } - // Let's override GetNeighbours completely -- never go to the grid server - // Neighbours are/should be cached locally - // For retrieval from the DB, caller should call GetRegionByPosition public override List GetNeighbours(UUID scopeID, UUID regionID) { - return m_LocalGridService.GetNeighbours(scopeID, regionID); + return base.GetNeighbours(scopeID, regionID); } public override GridRegion GetRegionByUUID(UUID scopeID, UUID regionID) diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs index e09db154aa..97161fcbd1 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Inventory/HGInventoryBroker.cs @@ -202,9 +202,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory } } } - - // else put a null; it means that the methods should forward to local grid's inventory - m_InventoryURLs.Add(userID, null); } private void DropInventoryServiceURL(UUID userID) @@ -223,10 +220,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (m_InventoryURLs.ContainsKey(userID)) return m_InventoryURLs[userID]; - else - CacheInventoryServiceURL(userID); + CacheInventoryServiceURL(userID); - return m_InventoryURLs[userID]; + if (m_InventoryURLs.ContainsKey(userID)) + return m_InventoryURLs[userID]; + + return null; //it means that the methods should forward to local grid's inventory + } #endregion @@ -253,7 +253,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryFolderBase GetRootFolder(UUID userID) { - m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetRootFolder for {0}", userID); + //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetRootFolder for {0}", userID); string invURL = GetInventoryServiceURL(userID); @@ -267,7 +267,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryFolderBase GetFolderForType(UUID userID, AssetType type) { - m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetFolderForType {0} type {1}", userID, type); + //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: GetFolderForType {0} type {1}", userID, type); string invURL = GetInventoryServiceURL(userID); @@ -281,7 +281,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public InventoryCollection GetFolderContent(UUID userID, UUID folderID) { - m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderContent " + folderID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderContent " + folderID); string invURL = GetInventoryServiceURL(userID); @@ -296,7 +296,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public List GetFolderItems(UUID userID, UUID folderID) { - m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolderItems " + folderID); string invURL = GetInventoryServiceURL(userID); @@ -314,7 +314,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folder == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: AddFolder " + folder.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: AddFolder " + folder.ID); string invURL = GetInventoryServiceURL(folder.Owner); @@ -331,7 +331,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folder == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: UpdateFolder " + folder.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: UpdateFolder " + folder.ID); string invURL = GetInventoryServiceURL(folder.Owner); @@ -350,7 +350,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folderIDs.Count == 0) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: DeleteFolders for " + ownerID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: DeleteFolders for " + ownerID); string invURL = GetInventoryServiceURL(ownerID); @@ -367,7 +367,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folder == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: MoveFolder for " + folder.Owner); + //m_log.Debug("[HG INVENTORY CONNECTOR]: MoveFolder for " + folder.Owner); string invURL = GetInventoryServiceURL(folder.Owner); @@ -384,7 +384,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folder == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: PurgeFolder for " + folder.Owner); + //m_log.Debug("[HG INVENTORY CONNECTOR]: PurgeFolder for " + folder.Owner); string invURL = GetInventoryServiceURL(folder.Owner); @@ -401,7 +401,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (item == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: AddItem " + item.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: AddItem " + item.ID); string invURL = GetInventoryServiceURL(item.Owner); @@ -418,7 +418,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (item == null) return false; - m_log.Debug("[HG INVENTORY CONNECTOR]: UpdateItem " + item.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: UpdateItem " + item.ID); string invURL = GetInventoryServiceURL(item.Owner); @@ -437,7 +437,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (items.Count == 0) return true; - m_log.Debug("[HG INVENTORY CONNECTOR]: MoveItems for " + ownerID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: MoveItems for " + ownerID); string invURL = GetInventoryServiceURL(ownerID); @@ -451,15 +451,13 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public bool DeleteItems(UUID ownerID, List itemIDs) { - m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID); + //m_log.DebugFormat("[HG INVENTORY CONNECTOR]: Delete {0} items for user {1}", itemIDs.Count, ownerID); if (itemIDs == null) return false; if (itemIDs.Count == 0) return true; - m_log.Debug("[HG INVENTORY CONNECTOR]: DeleteItems for " + ownerID); - string invURL = GetInventoryServiceURL(ownerID); if (invURL == null) // not there, forward to local inventory connector to resolve @@ -474,7 +472,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory { if (item == null) return null; - m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetItem " + item.ID); string invURL = GetInventoryServiceURL(item.Owner); @@ -491,7 +489,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory if (folder == null) return null; - m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolder " + folder.ID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetFolder " + folder.ID); string invURL = GetInventoryServiceURL(folder.Owner); @@ -515,7 +513,7 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Inventory public int GetAssetPermissions(UUID userID, UUID assetID) { - m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID); + //m_log.Debug("[HG INVENTORY CONNECTOR]: GetAssetPermissions " + assetID); string invURL = GetInventoryServiceURL(userID); diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs index daba0b3bb4..f71bf4634b 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Neighbour/LocalNeighbourServiceConnector.cs @@ -121,17 +121,17 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Neighbour public GridRegion HelloNeighbour(ulong regionHandle, RegionInfo thisRegion) { - m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: HelloNeighbour from {0}, to {1}. Count = {2}", - thisRegion.RegionName, regionHandle, m_Scenes.Count); + m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: HelloNeighbour from {0}, to {1}.", + thisRegion.RegionName, regionHandle); foreach (Scene s in m_Scenes) { if (s.RegionInfo.RegionHandle == regionHandle) { - m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); + //m_log.Debug("[NEIGHBOUR CONNECTOR]: Found region to SendHelloNeighbour"); return s.IncomingHelloNeighbour(thisRegion); } } - m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: region handle {0} not found", regionHandle); + //m_log.DebugFormat("[NEIGHBOUR CONNECTOR]: region handle {0} not found", regionHandle); return null; } diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs index 9e8454f72f..3f577f2ad6 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/Simulation/RemoteSimulationConnector.cs @@ -181,7 +181,6 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.Simulation // else do the remote thing if (!m_localBackend.IsLocalRegion(destination.RegionHandle)) { - //m_regionClient.SendUserInformation(regInfo, aCircuit); return m_remoteConnector.CreateAgent(destination, aCircuit, teleportFlags, out reason); } return false; diff --git a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs index a355661f6c..e1bc243c9e 100644 --- a/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs +++ b/OpenSim/Region/CoreModules/ServiceConnectorsOut/UserAccounts/UserAccountCache.cs @@ -44,10 +44,8 @@ namespace OpenSim.Region.CoreModules.ServiceConnectorsOut.UserAccounts public UserAccountCache() { - // Warning: the size values are a bit fuzzy. What matters - // most for this cache is the count value (128 entries). m_UUIDCache = new ExpiringCache(); - m_NameCache = new ExpiringCache(); // this one is unbound + m_NameCache = new ExpiringCache(); } public void Cache(UUID userID, UserAccount account) diff --git a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs index 4d04af16e7..58698ee189 100644 --- a/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs +++ b/OpenSim/Region/CoreModules/World/Archiver/Tests/ArchiverTests.cs @@ -69,7 +69,7 @@ namespace OpenSim.Region.CoreModules.World.Archiver.Tests SerialiserModule serialiserModule = new SerialiserModule(); TerrainModule terrainModule = new TerrainModule(); - m_scene = SceneSetupHelpers.SetupScene("useraccounts"); + m_scene = SceneSetupHelpers.SetupScene(); SceneSetupHelpers.SetupSceneModules(m_scene, m_archiverModule, serialiserModule, terrainModule); } diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs index 39451421c3..2a87da28bb 100644 --- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs +++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs @@ -146,7 +146,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { // Normal Calculations - return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.objectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); + return (int)Math.Round(((float)LandData.Area / 65536.0f) * (float)m_scene.RegionInfo.ObjectCapacity * (float)m_scene.RegionInfo.RegionSettings.ObjectBonus); } } public int GetSimulatorMaxPrimCount(ILandObject thisObject) @@ -158,7 +158,7 @@ namespace OpenSim.Region.CoreModules.World.Land else { //Normal Calculations - return m_scene.objectCapacity; + return m_scene.RegionInfo.ObjectCapacity; } } #endregion diff --git a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs index b71b5f61a5..b96d95a09c 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/MapImageModule.cs @@ -70,10 +70,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap #region IMapImageGenerator Members - public byte[] WriteJpeg2000Image(string gradientmap) + public Bitmap CreateMapTile(string gradientmap) { - byte[] imageData = null; - bool drawPrimVolume = true; bool textureTerrain = false; @@ -98,32 +96,36 @@ namespace OpenSim.Region.CoreModules.World.WorldMap } terrainRenderer.Initialise(m_scene, m_config); - using (Bitmap mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize)) + Bitmap mapbmp = new Bitmap((int)Constants.RegionSize, (int)Constants.RegionSize, System.Drawing.Imaging.PixelFormat.Format24bppRgb); + //long t = System.Environment.TickCount; + //for (int i = 0; i < 10; ++i) { + terrainRenderer.TerrainToBitmap(mapbmp); + //} + //t = System.Environment.TickCount - t; + //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); + + + if (drawPrimVolume) { - //long t = System.Environment.TickCount; - //for (int i = 0; i < 10; ++i) { - terrainRenderer.TerrainToBitmap(mapbmp); - //} - //t = System.Environment.TickCount - t; - //m_log.InfoFormat("[MAPTILE] generation of 10 maptiles needed {0} ms", t); - - - if (drawPrimVolume) - { - DrawObjectVolume(m_scene, mapbmp); - } - - try - { - imageData = OpenJPEG.EncodeFromImage(mapbmp, true); - } - catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke - { - m_log.Error("Failed generating terrain map: " + e); - } + DrawObjectVolume(m_scene, mapbmp); } - return imageData; + return mapbmp; + } + + public byte[] WriteJpeg2000Image(string gradientmap) + { + try + { + using (Bitmap mapbmp = CreateMapTile(gradientmap)) + return OpenJPEG.EncodeFromImage(mapbmp, true); + } + catch (Exception e) // LEGIT: Catching problems caused by OpenJPEG p/invoke + { + m_log.Error("Failed generating terrain map: " + e); + } + + return null; } #endregion diff --git a/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs index a297cf310b..fef2ef3995 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/ShadedMapTileRenderer.cs @@ -37,6 +37,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap { public class ShadedMapTileRenderer : IMapTileTerrainRenderer { + private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95); + private static readonly ILog m_log = LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); @@ -221,8 +223,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap try { - Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); - mapbmp.SetPixel(x, yr, water); + mapbmp.SetPixel(x, yr, WATER_COLOR); } catch (ArgumentException) { diff --git a/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs b/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs index 4ecad74316..8b34f6ebdc 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/TexturedMapTileRenderer.cs @@ -136,6 +136,8 @@ namespace OpenSim.Region.CoreModules.World.WorldMap private static readonly UUID defaultTerrainTexture4 = new UUID("53a2f406-4895-1d13-d541-d2e3b86bc19c"); private static readonly Color defaultColor4 = Color.FromArgb(200, 200, 200); + private static readonly Color WATER_COLOR = Color.FromArgb(29, 71, 95); + #endregion @@ -406,8 +408,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap heightvalue = 100f - (heightvalue * 100f) / 19f; // 0 - 19 => 100 - 0 - Color water = Color.FromArgb((int)heightvalue, (int)heightvalue, 255); - mapbmp.SetPixel(x, yr, water); + mapbmp.SetPixel(x, yr, WATER_COLOR); } } } diff --git a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs index c6fb18d8f3..9d9967a22b 100644 --- a/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs +++ b/OpenSim/Region/CoreModules/World/WorldMap/WorldMapModule.cs @@ -805,7 +805,7 @@ namespace OpenSim.Region.CoreModules.World.WorldMap imgstream = new MemoryStream(); // non-async because we know we have the asset immediately. - AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.lastMapUUID.ToString()); + AssetBase mapasset = m_scene.AssetService.Get(m_scene.RegionInfo.RegionSettings.TerrainImageID.ToString()); // Decode image to System.Drawing.Image if (OpenJPEG.DecodeToImage(mapasset.Data, out managedImage, out image)) @@ -1002,41 +1002,15 @@ namespace OpenSim.Region.CoreModules.World.WorldMap public void RegenerateMaptile(byte[] data) { - // Overwrites the local Asset cache with new maptile data - // Assets are single write, this causes the asset server to ignore this update, - // but the local asset cache does not - - // this is on purpose! The net result of this is the region always has the most up to date - // map tile while protecting the (grid) asset database from bloat caused by a new asset each - // time a mapimage is generated! - UUID lastMapRegionUUID = m_scene.RegionInfo.RegionSettings.TerrainImageID; - int lastMapRefresh = 0; - int twoDays = 172800; -// int RefreshSeconds = twoDays; - - try - { - lastMapRefresh = Convert.ToInt32(m_scene.RegionInfo.lastMapRefresh); - } - catch (ArgumentException) - { - } - catch (FormatException) - { - } - catch (OverflowException) - { - } - m_log.Debug("[MAPTILE]: STORING MAPTILE IMAGE"); m_scene.RegionInfo.RegionSettings.TerrainImageID = UUID.Random(); AssetBase asset = new AssetBase( m_scene.RegionInfo.RegionSettings.TerrainImageID, - "terrainImage_" + m_scene.RegionInfo.RegionID.ToString() + "_" + lastMapRefresh.ToString(), + "terrainImage_" + m_scene.RegionInfo.RegionID.ToString(), (sbyte)AssetType.Texture, m_scene.RegionInfo.RegionID.ToString()); asset.Data = data; diff --git a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs index 6e699025b1..00f6918600 100644 --- a/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs +++ b/OpenSim/Region/DataSnapshot/ObjectSnapshot.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.DataSnapshot.Providers client.OnGrabUpdate += delegate(UUID objectID, Vector3 offset, Vector3 grapPos, IClientAPI remoteClient, List surfaceArgs) { this.Stale = true; }; client.OnObjectAttach += delegate(IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, - Quaternion rot, bool silent) { this.Stale = true; }; + bool silent) { this.Stale = true; }; client.OnObjectDuplicate += delegate(uint localID, Vector3 offset, uint dupeFlags, UUID AgentID, UUID GroupID) { this.Stale = true; }; client.OnObjectDuplicateOnRay += delegate(uint localID, uint dupeFlags, UUID AgentID, UUID GroupID, diff --git a/OpenSim/Region/DataSnapshot/SnapshotStore.cs b/OpenSim/Region/DataSnapshot/SnapshotStore.cs index 976c2c1d47..70cb2053c9 100644 --- a/OpenSim/Region/DataSnapshot/SnapshotStore.cs +++ b/OpenSim/Region/DataSnapshot/SnapshotStore.cs @@ -258,21 +258,16 @@ namespace OpenSim.Region.DataSnapshot private String GetRegionCategory(Scene scene) { - //Boolean choice between: - // "PG" - Mormontown - // "Mature" - Sodom and Gomorrah - if (scene.RegionInfo.RegionSettings.Maturity == 1) - { - return "Mature"; - } - else if (scene.RegionInfo.RegionSettings.Maturity == 0) - { + if (scene.RegionInfo.RegionSettings.Maturity == 0) return "PG"; - } - else - { - return "Unknown"; - } + + if (scene.RegionInfo.RegionSettings.Maturity == 1) + return "Mature"; + + if (scene.RegionInfo.RegionSettings.Maturity == 2) + return "Adult"; + + return "Unknown"; } private XmlNode GetGridSnapshotData(XmlDocument factory) diff --git a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs index 2681d4fcf3..f6e6163301 100644 --- a/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs +++ b/OpenSim/Region/Examples/SimpleModule/MyNpcCharacter.cs @@ -536,10 +536,6 @@ namespace OpenSim.Region.Examples.SimpleModule { } - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } @@ -1155,5 +1151,9 @@ namespace OpenSim.Region.Examples.SimpleModule public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) { } + + public void StopFlying(ISceneEntity presence) + { + } } } diff --git a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs index f8af36756c..2af25481e4 100644 --- a/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IAttachmentsModule.cs @@ -44,7 +44,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// void AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, bool silent); + IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, bool silent); /// /// Attach an object to an avatar. @@ -57,7 +57,7 @@ namespace OpenSim.Region.Framework.Interfaces /// /// true if the object was successfully attached, false otherwise bool AttachObject( - IClientAPI remoteClient, uint objectLocalID, uint AttachmentPt, Quaternion rot, Vector3 attachPos, bool silent); + IClientAPI remoteClient, SceneObjectGroup grp, uint AttachmentPt, bool silent); /// /// Rez an attachment from user inventory and change inventory status to match. diff --git a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs index 3a2c4231cf..4f1b91adee 100644 --- a/OpenSim/Region/Framework/Interfaces/IEmailModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IEmailModule.cs @@ -38,7 +38,7 @@ namespace OpenSim.Region.Framework.Interfaces public int numLeft; } - public interface IEmailModule : IRegionModule + public interface IEmailModule { void SendEmail(UUID objectID, string address, string subject, string body); Email GetNextEmail(UUID objectID, string sender, string subject); diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs index 97f4188751..05fc2add3e 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryAccessModule.cs @@ -43,5 +43,9 @@ namespace OpenSim.Region.Framework.Interfaces UUID RayTargetID, byte BypassRayCast, bool RayEndIsIntersection, bool RezSelected, bool RemoveItem, UUID fromTaskID, bool attachment); void TransferInventoryAssets(InventoryItemBase item, UUID sender, UUID receiver); + bool GetAgentInventoryItem(IClientAPI remoteClient, UUID itemID, UUID requestID); + + // Must be here because of textures in user's inventory + bool IsForeignUser(UUID userID, out string assetServerURL); } } diff --git a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs index fbadd91b20..01066e6ab1 100644 --- a/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs +++ b/OpenSim/Region/Framework/Interfaces/IInventoryArchiverModule.cs @@ -26,6 +26,7 @@ */ using System; +using System.Collections.Generic; using System.IO; using OpenSim.Services.Interfaces; @@ -59,6 +60,20 @@ namespace OpenSim.Region.Framework.Interfaces /// The stream from which the inventory archive will be loaded /// true if the first stage of the operation succeeded, false otherwise bool DearchiveInventory(string firstName, string lastName, string invPath, string pass, Stream loadStream); + + /// + /// Dearchive a user's inventory folder from the given stream + /// + /// + /// + /// The inventory path in which to place the loaded folders and items + /// The stream from which the inventory archive will be loaded + /// Dearchiving options. At the moment, the only option is ("merge", true). This merges + /// the loaded IAR with existing folders where possible. + /// true if the first stage of the operation succeeded, false otherwise + bool DearchiveInventory( + string firstName, string lastName, string invPath, string pass, Stream loadStream, + Dictionary options); /// /// Archive a user's inventory folder to the given stream @@ -70,5 +85,19 @@ namespace OpenSim.Region.Framework.Interfaces /// The stream to which the inventory archive will be saved /// true if the first stage of the operation succeeded, false otherwise bool ArchiveInventory(Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream); + + /// + /// Archive a user's inventory folder to the given stream + /// + /// ID representing this request. This will later be returned in the save event + /// + /// + /// The inventory path from which the inventory should be saved. + /// The stream to which the inventory archive will be saved + /// Archiving options. Currently, there are none. + /// true if the first stage of the operation succeeded, false otherwise + bool ArchiveInventory( + Guid id, string firstName, string lastName, string invPath, string pass, Stream saveStream, + Dictionary options); } } diff --git a/OpenSim/Region/Framework/Interfaces/ITerrain.cs b/OpenSim/Region/Framework/Interfaces/ITerrain.cs index f5662cbcf6..b42e872e6f 100644 --- a/OpenSim/Region/Framework/Interfaces/ITerrain.cs +++ b/OpenSim/Region/Framework/Interfaces/ITerrain.cs @@ -73,6 +73,7 @@ namespace OpenSim.Region.Framework.Interfaces public interface IMapImageGenerator { + System.Drawing.Bitmap CreateMapTile(string gradientmap); byte[] WriteJpeg2000Image(string gradientmap); } } diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs index ef125cd357..9db2e4135b 100644 --- a/OpenSim/Region/Framework/Scenes/EventManager.cs +++ b/OpenSim/Region/Framework/Scenes/EventManager.cs @@ -179,7 +179,7 @@ namespace OpenSim.Region.Framework.Scenes public event ScriptChangedEvent OnScriptChangedEvent; public delegate void ScriptChangedEvent(uint localID, uint change); - public delegate void ScriptControlEvent(uint localID, UUID item, UUID avatarID, uint held, uint changed); + public delegate void ScriptControlEvent(UUID item, UUID avatarID, uint held, uint changed); public event ScriptControlEvent OnScriptControlEvent; public delegate void ScriptAtTargetEvent(uint localID, uint handle, Vector3 targetpos, Vector3 atpos); @@ -1595,7 +1595,7 @@ namespace OpenSim.Region.Framework.Scenes } } - internal void TriggerControlEvent(uint p, UUID scriptUUID, UUID avatarID, uint held, uint _changed) + internal void TriggerControlEvent(UUID scriptUUID, UUID avatarID, uint held, uint _changed) { ScriptControlEvent handlerScriptControlEvent = OnScriptControlEvent; if (handlerScriptControlEvent != null) @@ -1604,7 +1604,7 @@ namespace OpenSim.Region.Framework.Scenes { try { - d(p, scriptUUID, avatarID, held, _changed); + d(scriptUUID, avatarID, held, _changed); } catch (Exception e) { diff --git a/OpenSim/Region/Framework/Scenes/Prioritizer.cs b/OpenSim/Region/Framework/Scenes/Prioritizer.cs index 1eb0c286e8..de3c360a42 100644 --- a/OpenSim/Region/Framework/Scenes/Prioritizer.cs +++ b/OpenSim/Region/Framework/Scenes/Prioritizer.cs @@ -1,4 +1,4 @@ -using System; +using System; using System.Collections.Generic; using log4net; using Nini.Config; @@ -32,6 +32,15 @@ namespace OpenSim.Region.Framework.Scenes public class Prioritizer { private static readonly ILog m_log = LogManager.GetLogger(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType); + + /// + /// This is added to the priority of all child prims, to make sure that the root prim update is sent to the + /// viewer before child prim updates. + /// The adjustment is added to child prims and subtracted from root prims, so the gap ends up + /// being double. We do it both ways so that there is a still a priority delta even if the priority is already + /// double.MinValue or double.MaxValue. + /// + private double m_childPrimAdjustmentFactor = 0.05; private Scene m_scene; @@ -42,21 +51,53 @@ namespace OpenSim.Region.Framework.Scenes public double GetUpdatePriority(IClientAPI client, ISceneEntity entity) { + double priority = 0; + + if (entity == null) + return 100000; + switch (m_scene.UpdatePrioritizationScheme) { case UpdatePrioritizationSchemes.Time: - return GetPriorityByTime(); + priority = GetPriorityByTime(); + break; case UpdatePrioritizationSchemes.Distance: - return GetPriorityByDistance(client, entity); + priority = GetPriorityByDistance(client, entity); + break; case UpdatePrioritizationSchemes.SimpleAngularDistance: - return GetPriorityByDistance(client, entity); // TODO: Reimplement SimpleAngularDistance + priority = GetPriorityByDistance(client, entity); // TODO: Reimplement SimpleAngularDistance + break; case UpdatePrioritizationSchemes.FrontBack: - return GetPriorityByFrontBack(client, entity); + priority = GetPriorityByFrontBack(client, entity); + break; case UpdatePrioritizationSchemes.BestAvatarResponsiveness: - return GetPriorityByBestAvatarResponsiveness(client, entity); + priority = GetPriorityByBestAvatarResponsiveness(client, entity); + break; default: throw new InvalidOperationException("UpdatePrioritizationScheme not defined."); + break; } + + // Adjust priority so that root prims are sent to the viewer first. This is especially important for + // attachments acting as huds, since current viewers fail to display hud child prims if their updates + // arrive before the root one. + if (entity is SceneObjectPart) + { + SceneObjectPart sop = ((SceneObjectPart)entity); + + if (sop.IsRoot) + { + if (priority >= double.MinValue + m_childPrimAdjustmentFactor) + priority -= m_childPrimAdjustmentFactor; + } + else + { + if (priority <= double.MaxValue - m_childPrimAdjustmentFactor) + priority += m_childPrimAdjustmentFactor; + } + } + + return priority; } private double GetPriorityByTime() @@ -172,7 +213,10 @@ namespace OpenSim.Region.Framework.Scenes { PhysicsActor physActor = ((SceneObjectPart)entity).ParentGroup.RootPart.PhysActor; if (physActor == null || !physActor.IsPhysical) - priority+=100; + priority += 100; + + if (((SceneObjectPart)entity).ParentGroup.RootPart.IsAttachment) + priority = 1.0; } return priority; } diff --git a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs index cc7b6485f7..6e73fe920f 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.Inventory.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.Framework.Scenes IMoneyModule money=RequestModuleInterface(); if (money != null) { - money.ApplyUploadCharge(agentID); + money.ApplyUploadCharge(agentID, money.UploadCharge, "Asset upload"); } AddInventoryItem(agentID, item); @@ -203,7 +203,7 @@ namespace OpenSim.Region.Framework.Scenes // Update item with new asset item.AssetID = asset.FullID; if (group.UpdateInventoryItem(item)) - remoteClient.SendAgentAlertMessage("Notecard saved", false); + remoteClient.SendAgentAlertMessage("Script saved", false); part.GetProperties(remoteClient); @@ -265,6 +265,10 @@ namespace OpenSim.Region.Framework.Scenes public void UpdateInventoryItemAsset(IClientAPI remoteClient, UUID transactionID, UUID itemID, InventoryItemBase itemUpd) { + // This one will let people set next perms on items in agent + // inventory. Rut-Roh. Whatever. Make this secure. Yeah. + // + // Passing something to another avatar or a an object will already InventoryItemBase item = new InventoryItemBase(itemID, remoteClient.AgentId); item = InventoryService.GetItem(item); @@ -274,11 +278,9 @@ namespace OpenSim.Region.Framework.Scenes { item.Name = itemUpd.Name; item.Description = itemUpd.Description; - item.NextPermissions = itemUpd.NextPermissions; - item.CurrentPermissions |= 8; // Slam! - item.EveryOnePermissions = itemUpd.EveryOnePermissions; - item.GroupPermissions = itemUpd.GroupPermissions; - + item.NextPermissions = itemUpd.NextPermissions & item.BasePermissions; + item.EveryOnePermissions = itemUpd.EveryOnePermissions & item.BasePermissions; + item.GroupPermissions = itemUpd.GroupPermissions & item.BasePermissions; item.GroupID = itemUpd.GroupID; item.GroupOwned = itemUpd.GroupOwned; item.CreationDate = itemUpd.CreationDate; @@ -384,28 +386,103 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.PropagatePermissions() && recipient != senderId) { - // First, make sore base is limited to the next perms - itemCopy.BasePermissions = item.BasePermissions & item.NextPermissions; - // By default, current equals base - itemCopy.CurrentPermissions = itemCopy.BasePermissions; + // Trying to do this right this time. This is evil. If + // you believe in Good, go elsewhere. Vampires and other + // evil creatores only beyond this point. You have been + // warned. - // If this is an object, replace current perms - // with folded perms + // We're going to mask a lot of things by the next perms + // Tweak the next perms to be nicer to our data + // + // In this mask, all the bits we do NOT want to mess + // with are set. These are: + // + // Transfer + // Copy + // Modufy + uint permsMask = ~ ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify); + + // Now, reduce the next perms to the mask bits + // relevant to the operation + uint nextPerms = permsMask | (item.NextPermissions & + ((uint)PermissionMask.Copy | + (uint)PermissionMask.Transfer | + (uint)PermissionMask.Modify)); + + // nextPerms now has all bits set, except for the actual + // next permission bits. + + // This checks for no mod, no copy, no trans. + // This indicates an error or messed up item. Do it like + // SL and assume trans + if (nextPerms == permsMask) + nextPerms |= (uint)PermissionMask.Transfer; + + // Inventory owner perms are the logical AND of the + // folded perms and the root prim perms, however, if + // the root prim is mod, the inventory perms will be + // mod. This happens on "take" and is of little concern + // here, save for preventing escalation + + // This hack ensures that items previously permalocked + // get unlocked when they're passed or rezzed + uint basePerms = item.BasePermissions | + (uint)PermissionMask.Move; + uint ownerPerms = item.CurrentPermissions; + + // If this is an object, root prim perms may be more + // permissive than folded perms. Use folded perms as + // a mask if (item.InvType == (int)InventoryType.Object) { - itemCopy.CurrentPermissions &= ~(uint)(PermissionMask.Copy | PermissionMask.Modify | PermissionMask.Transfer); - itemCopy.CurrentPermissions |= (item.CurrentPermissions & 7) << 13; + // Create a safe mask for the current perms + uint foldedPerms = (item.CurrentPermissions & 7) << 13; + foldedPerms |= permsMask; + + bool isRootMod = (item.CurrentPermissions & + (uint)PermissionMask.Modify) != 0 ? + true : false; + + // Mask the owner perms to the folded perms + ownerPerms &= foldedPerms; + basePerms &= foldedPerms; + + // If the root was mod, let the mask reflect that + // We also need to adjust the base here, because + // we should be able to edit in-inventory perms + // for the root prim, if it's mod. + if (isRootMod) + { + ownerPerms |= (uint)PermissionMask.Modify; + basePerms |= (uint)PermissionMask.Modify; + } } - // Ensure there is no escalation - itemCopy.CurrentPermissions &= item.NextPermissions; + // These will be applied to the root prim at next rez. + // The slam bit (bit 3) and folded permission (bits 0-2) + // are preserved due to the above mangling + ownerPerms &= nextPerms; - // Need slam bit on xfer - itemCopy.CurrentPermissions |= 8; + // Mask the base permissions. This is a conservative + // approach altering only the three main perms + basePerms &= nextPerms; + + // Assign to the actual item. Make sure the slam bit is + // set, if it wasn't set before. + itemCopy.BasePermissions = basePerms; + itemCopy.CurrentPermissions = ownerPerms | 16; // Slam itemCopy.NextPermissions = item.NextPermissions; - itemCopy.EveryOnePermissions = 0; + // This preserves "everyone can move" + itemCopy.EveryOnePermissions = item.EveryOnePermissions & + nextPerms; + + // Intentionally killing "share with group" here, as + // the recipient will not have the group this is + // set to itemCopy.GroupPermissions = 0; } else @@ -897,14 +974,15 @@ namespace OpenSim.Region.Framework.Scenes if ((part.OwnerID != destAgent) && Permissions.PropagatePermissions()) { - agentItem.BasePermissions = taskItem.BasePermissions & taskItem.NextPermissions; + agentItem.BasePermissions = taskItem.BasePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); if (taskItem.InvType == (int)InventoryType.Object) - agentItem.CurrentPermissions = agentItem.BasePermissions & ((taskItem.CurrentPermissions & 7) << 13); - agentItem.CurrentPermissions = agentItem.BasePermissions ; + agentItem.CurrentPermissions = agentItem.BasePermissions & (((taskItem.CurrentPermissions & 7) << 13) | (taskItem.CurrentPermissions & (uint)PermissionMask.Move)); + else + agentItem.CurrentPermissions = agentItem.BasePermissions & taskItem.CurrentPermissions; - agentItem.CurrentPermissions |= 8; + agentItem.CurrentPermissions |= 16; // Slam agentItem.NextPermissions = taskItem.NextPermissions; - agentItem.EveryOnePermissions = taskItem.EveryonePermissions & taskItem.NextPermissions; + agentItem.EveryOnePermissions = taskItem.EveryonePermissions & (taskItem.NextPermissions | (uint)PermissionMask.Move); agentItem.GroupPermissions = taskItem.GroupPermissions & taskItem.NextPermissions; } else @@ -1086,14 +1164,14 @@ namespace OpenSim.Region.Framework.Scenes if (Permissions.PropagatePermissions()) { destTaskItem.CurrentPermissions = srcTaskItem.CurrentPermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.GroupPermissions = srcTaskItem.GroupPermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.EveryonePermissions = srcTaskItem.EveryonePermissions & - srcTaskItem.NextPermissions; + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); destTaskItem.BasePermissions = srcTaskItem.BasePermissions & - srcTaskItem.NextPermissions; - destTaskItem.CurrentPermissions |= 8; // Slam! + (srcTaskItem.NextPermissions | (uint)PermissionMask.Move); + destTaskItem.CurrentPermissions |= 16; // Slam! } } @@ -1265,7 +1343,13 @@ namespace OpenSim.Region.Framework.Scenes } if (part.Inventory.UpdateInventoryItem(itemInfo)) { - remoteClient.SendAgentAlertMessage("Notecard saved", false); + if ((InventoryType)itemInfo.InvType == InventoryType.Notecard) + remoteClient.SendAgentAlertMessage("Notecard saved", false); + else if ((InventoryType)itemInfo.InvType == InventoryType.LSL) + remoteClient.SendAgentAlertMessage("Script saved", false); + else + remoteClient.SendAgentAlertMessage("Item saved", false); + part.GetProperties(remoteClient); } } @@ -1477,7 +1561,7 @@ namespace OpenSim.Region.Framework.Scenes srcTaskItem.NextPermissions; destTaskItem.BasePermissions = srcTaskItem.BasePermissions & srcTaskItem.NextPermissions; - destTaskItem.CurrentPermissions |= 8; // Slam! + destTaskItem.CurrentPermissions |= 16; // Slam! } } @@ -1573,18 +1657,30 @@ namespace OpenSim.Region.Framework.Scenes // for when deleting the object from it ForceSceneObjectBackup(grp); - if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) - permissionToTakeCopy = false; - if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) - permissionToTake = false; + if (remoteClient == null) + { + // Autoreturn has a null client. Nothing else does. So + // allow only returns + if (action != DeRezAction.Return) + return; - if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) - permissionToDelete = false; + permissionToTakeCopy = false; + } + else + { + if (!Permissions.CanTakeCopyObject(grp.UUID, remoteClient.AgentId)) + permissionToTakeCopy = false; + if (!Permissions.CanTakeObject(grp.UUID, remoteClient.AgentId)) + permissionToTake = false; + + if (!Permissions.CanDeleteObject(grp.UUID, remoteClient.AgentId)) + permissionToDelete = false; + } } // Handle god perms - if (Permissions.IsGod(remoteClient.AgentId)) + if ((remoteClient != null) && Permissions.IsGod(remoteClient.AgentId)) { permissionToTake = true; permissionToTakeCopy = true; @@ -1595,7 +1691,7 @@ namespace OpenSim.Region.Framework.Scenes if (action == DeRezAction.SaveToExistingUserInventoryItem) permissionToDelete = false; - // if we want to take a copy,, we also don't want to delete + // if we want to take a copy, we also don't want to delete // Note: after this point, the permissionToTakeCopy flag // becomes irrelevant. It already includes the permissionToTake // permission and after excluding no copy items here, we can @@ -1606,6 +1702,7 @@ namespace OpenSim.Region.Framework.Scenes if (!permissionToTakeCopy) return; + permissionToTake = true; // Don't delete permissionToDelete = false; } @@ -1736,7 +1833,11 @@ namespace OpenSim.Region.Framework.Scenes item.AssetType = asset.Type; item.InvType = (int)InventoryType.Object; - item.Folder = UUID.Zero; // Objects folder! + InventoryFolderBase folder = InventoryService.GetFolderForType(remoteClient.AgentId, AssetType.Object); + if (folder != null) + item.Folder = folder.ID; + else // oopsies + item.Folder = UUID.Zero; if ((remoteClient.AgentId != grp.RootPart.OwnerID) && Permissions.PropagatePermissions()) { @@ -1846,17 +1947,14 @@ namespace OpenSim.Region.Framework.Scenes group.SetGroup(sourcePart.GroupID, null); - if (rootPart.OwnerID != item.OwnerID) + if ((rootPart.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) { if (Permissions.PropagatePermissions()) { - if ((item.CurrentPermissions & 8) != 0) + foreach (SceneObjectPart part in partList) { - foreach (SceneObjectPart part in partList) - { - part.EveryoneMask = item.EveryonePermissions; - part.NextOwnerMask = item.NextPermissions; - } + part.EveryoneMask = item.EveryonePermissions; + part.NextOwnerMask = item.NextPermissions; } group.ApplyNextOwnerPermissions(); } @@ -1864,17 +1962,14 @@ namespace OpenSim.Region.Framework.Scenes foreach (SceneObjectPart part in partList) { - if (part.OwnerID != item.OwnerID) + if ((part.OwnerID != item.OwnerID) || (item.CurrentPermissions & 16) != 0) { part.LastOwnerID = part.OwnerID; part.OwnerID = item.OwnerID; part.Inventory.ChangeInventoryOwner(item.OwnerID); } - else if ((item.CurrentPermissions & 8) != 0) // Slam! - { - part.EveryoneMask = item.EveryonePermissions; - part.NextOwnerMask = item.NextPermissions; - } + part.EveryoneMask = item.EveryonePermissions; + part.NextOwnerMask = item.NextPermissions; } rootPart.TrimPermissions(); diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs index 6300665b29..b0f4ac0da8 100644 --- a/OpenSim/Region/Framework/Scenes/Scene.cs +++ b/OpenSim/Region/Framework/Scenes/Scene.cs @@ -348,6 +348,7 @@ namespace OpenSim.Region.Framework.Scenes private int m_update_backup = 200; private int m_update_terrain = 50; private int m_update_land = 1; + private int m_update_coarse_locations = 50; private int frameMS; private int physicsMS2; @@ -477,8 +478,6 @@ namespace OpenSim.Region.Framework.Scenes set { m_sceneGraph.RestorePresences = value; } } - public int objectCapacity = 45000; - #endregion #region BinaryStats @@ -686,7 +685,7 @@ namespace OpenSim.Region.Framework.Scenes StatsReporter.OnSendStatsResult += SendSimStatsPackets; StatsReporter.OnStatsIncorrect += m_sceneGraph.RecalculateStats; - StatsReporter.SetObjectCapacity(objectCapacity); + StatsReporter.SetObjectCapacity(RegionInfo.ObjectCapacity); // Old /* @@ -947,12 +946,6 @@ namespace OpenSim.Region.Framework.Scenes // Let the grid service module know, so this can be cached m_eventManager.TriggerOnRegionUp(otherRegion); - RegionInfo regInfo = new RegionInfo(xcell, ycell, otherRegion.InternalEndPoint, otherRegion.ExternalHostName); - regInfo.RegionID = otherRegion.RegionID; - regInfo.RegionName = otherRegion.RegionName; - regInfo.ScopeID = otherRegion.ScopeID; - regInfo.ExternalHostName = otherRegion.ExternalHostName; - GridRegion r = new GridRegion(regInfo); try { ForEachScenePresence(delegate(ScenePresence agent) @@ -967,7 +960,7 @@ namespace OpenSim.Region.Framework.Scenes old.Add(otherRegion.RegionHandle); agent.DropOldNeighbours(old); if (m_teleportModule != null) - m_teleportModule.EnableChildAgent(agent, r); + m_teleportModule.EnableChildAgent(agent, otherRegion); } } ); @@ -1339,6 +1332,8 @@ namespace OpenSim.Region.Framework.Scenes m_regInfo.EstateSettings.EstateOwner = account.PrincipalID; m_regInfo.EstateSettings.Save(); } + else + m_log.ErrorFormat("[SCENE]: Unable to store account. If this simulator is connected to a grid,\n you must create the estate owner account first."); } else { @@ -1417,6 +1412,18 @@ namespace OpenSim.Region.Framework.Scenes if (m_frame % m_update_presences == 0) m_sceneGraph.UpdatePresences(); + if (m_frame % m_update_coarse_locations == 0) + { + List coarseLocations; + List avatarUUIDs; + SceneGraph.GetCoarseLocations(out coarseLocations, out avatarUUIDs, 60); + // Send coarse locations to clients + ForEachScenePresence(delegate(ScenePresence presence) + { + presence.SendCoarseLocations(coarseLocations, avatarUUIDs); + }); + } + int tmpPhysicsMS2 = Util.EnvironmentTickCount(); if ((m_frame % m_update_physics == 0) && m_physics_enabled) m_sceneGraph.UpdatePreparePhysics(); @@ -1505,6 +1512,7 @@ namespace OpenSim.Region.Framework.Scenes { m_log.DebugFormat("[REGION]: Enabling logins for {0}", RegionInfo.RegionName); LoginsDisabled = false; + m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); } } } @@ -1789,6 +1797,8 @@ namespace OpenSim.Region.Framework.Scenes { RegisterCommsEvents(); + m_sceneGridService.SetScene(this); + // These two 'commands' *must be* next to each other or sim rebooting fails. //m_sceneGridService.RegisterRegion(m_interregionCommsOut, RegionInfo); @@ -1799,24 +1809,6 @@ namespace OpenSim.Region.Framework.Scenes throw new Exception(error); } - m_sceneGridService.SetScene(this); - m_sceneGridService.InformNeighborsThatRegionisUp(RequestModuleInterface(), RegionInfo); - - //Dictionary dGridSettings = m_sceneGridService.GetGridSettings(); - - //if (dGridSettings.ContainsKey("allow_forceful_banlines")) - //{ - // if (dGridSettings["allow_forceful_banlines"] != "TRUE") - // { - // m_log.Info("[GRID]: Grid is disabling forceful parcel banlists"); - // EventManager.TriggerSetAllowForcefulBan(false); - // } - // else - // { - // m_log.Info("[GRID]: Grid is allowing forceful parcel banlists"); - // EventManager.TriggerSetAllowForcefulBan(true); - // } - //} } /// @@ -2066,8 +2058,34 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.ScheduleGroupForFullUpdate(); return sceneObject; + } + + /// + /// Add an object into the scene that has come from storage + /// + /// + /// + /// + /// If true, changes to the object will be reflected in its persisted data + /// If false, the persisted data will not be changed even if the object in the scene is changed + /// + /// + /// If true, we won't persist this object until it changes + /// If false, we'll persist this object immediately + /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// + /// + /// true if the object was added, false if an object with the same uuid was already in the scene + /// + public bool AddRestoredSceneObject( + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) + { + return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, sendClientUpdates); } - + /// /// Add an object into the scene that has come from storage /// @@ -2087,7 +2105,7 @@ namespace OpenSim.Region.Framework.Scenes public bool AddRestoredSceneObject( SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) { - return m_sceneGraph.AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted); + return AddRestoredSceneObject(sceneObject, attachToBackup, alreadyPersisted, true); } /// @@ -2441,7 +2459,7 @@ namespace OpenSim.Region.Framework.Scenes /// - /// Called when objects or attachments cross the border between regions. + /// Called when objects or attachments cross the border, or teleport, between regions. /// /// /// @@ -2467,8 +2485,12 @@ namespace OpenSim.Region.Framework.Scenes newObject.RootPart.ParentGroup.CreateScriptInstances(0, false, DefaultScriptEngine, 1); + newObject.ResumeScripts(); + // Do this as late as possible so that listeners have full access to the incoming object EventManager.TriggerOnIncomingSceneObject(newObject); + + TriggerChangedTeleport(newObject); return true; } @@ -2525,7 +2547,10 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.RootPart.AddFlag(PrimFlags.TemporaryOnRez); sceneObject.RootPart.AddFlag(PrimFlags.Phantom); - AddRestoredSceneObject(sceneObject, false, false); + + // Don't sent a full update here because this will cause full updates to be sent twice for + // attachments on region crossings, resulting in viewer glitches. + AddRestoredSceneObject(sceneObject, false, false, false); // Handle attachment special case SceneObjectPart RootPrim = sceneObject.RootPart; @@ -2533,31 +2558,21 @@ namespace OpenSim.Region.Framework.Scenes // Fix up attachment Parent Local ID ScenePresence sp = GetScenePresence(sceneObject.OwnerID); - //uint parentLocalID = 0; if (sp != null) { - //parentLocalID = sp.LocalId; - - //sceneObject.RootPart.IsAttachment = true; - //sceneObject.RootPart.SetParentLocalId(parentLocalID); SceneObjectGroup grp = sceneObject; - //RootPrim.SetParentLocalId(parentLocalID); - m_log.DebugFormat( "[ATTACHMENT]: Received attachment {0}, inworld asset id {1}", grp.GetFromItemID(), grp.UUID); - - //grp.SetFromAssetID(grp.RootPart.LastOwnerID); m_log.DebugFormat( "[ATTACHMENT]: Attach to avatar {0} at position {1}", sp.UUID, grp.AbsolutePosition); - if (AttachmentsModule != null) - AttachmentsModule.AttachObject( - sp.ControllingClient, grp.LocalId, (uint)0, grp.GroupRotation, grp.AbsolutePosition, false); - RootPrim.RemFlag(PrimFlags.TemporaryOnRez); - grp.SendGroupFullUpdate(); + + if (AttachmentsModule != null) + AttachmentsModule.AttachObject(sp.ControllingClient, grp, 0, false); + } else { @@ -2585,6 +2600,27 @@ namespace OpenSim.Region.Framework.Scenes return true; } + + private void TriggerChangedTeleport(SceneObjectGroup sog) + { + ScenePresence sp = GetScenePresence(sog.OwnerID); + + if (sp != null) + { + AgentCircuitData aCircuit = m_authenticateHandler.GetAgentCircuitData(sp.UUID); + + if (aCircuit != null && (aCircuit.teleportFlags != (uint)TeleportFlags.Default)) + { + // This will get your attention + //m_log.Error("[XXX] Triggering "); + + // Trigger CHANGED_TELEPORT + sp.Scene.EventManager.TriggerOnScriptChangedEvent(sog.LocalId, (uint)Changed.TELEPORT); + } + + } + } + #endregion #region Add/Remove Avatar Methods @@ -3269,9 +3305,6 @@ namespace OpenSim.Region.Framework.Scenes catch (NullReferenceException) { } }); - ForEachScenePresence( - delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); - IAgentAssetTransactions agentTransactions = this.RequestModuleInterface(); if (agentTransactions != null) { @@ -3323,14 +3356,6 @@ namespace OpenSim.Region.Framework.Scenes } } - /// - /// Inform all other ScenePresences on this Scene that someone else has changed position on the minimap. - /// - public void NotifyMyCoarseLocationChange() - { - ForEachScenePresence(delegate(ScenePresence presence) { presence.CoarseLocationChange(); }); - } - #endregion #region Entities @@ -3403,6 +3428,8 @@ namespace OpenSim.Region.Framework.Scenes public bool NewUserConnection(AgentCircuitData agent, uint teleportFlags, out string reason) { TeleportFlags tp = (TeleportFlags)teleportFlags; + reason = String.Empty; + //Teleport flags: // // TeleportFlags.ViaGodlikeLure - Border Crossing @@ -3410,36 +3437,34 @@ namespace OpenSim.Region.Framework.Scenes // TeleportFlags.TeleportFlags.ViaLure - Teleport request sent by another user // TeleportFlags.ViaLandmark | TeleportFlags.ViaLocation | TeleportFlags.ViaLandmark | TeleportFlags.Default - Regular Teleport - - if (LoginsDisabled) - { - reason = "Logins Disabled"; - return false; - } // Don't disable this log message - it's too helpful m_log.InfoFormat( "[CONNECTION BEGIN]: Region {0} told of incoming {1} agent {2} {3} {4} (circuit code {5}, teleportflags {6})", RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, agent.AgentID, agent.circuitcode, teleportFlags); - reason = String.Empty; - if (!VerifyUserPresence(agent, out reason)) + if (LoginsDisabled) + { + reason = "Logins Disabled"; return false; + } - if (!AuthorizeUser(agent, out reason)) - return false; + ScenePresence sp = GetScenePresence(agent.AgentID); - m_log.InfoFormat( - "[CONNECTION BEGIN]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", - RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, - agent.AgentID, agent.circuitcode); - - CapsModule.NewUserConnection(agent); + if (sp != null && !sp.IsChildAgent) + { + // We have a zombie from a crashed session. + // Or the same user is trying to be root twice here, won't work. + // Kill it. + m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); + sp.ControllingClient.Close(); + sp = null; + } ILandObject land = LandChannel.GetLandObject(agent.startpos.X, agent.startpos.Y); - //On login or border crossing test land permisions - if (tp != TeleportFlags.Default) + //On login test land permisions + if (tp == TeleportFlags.ViaLogin) { if (land != null && !TestLandRestrictions(agent, land, out reason)) { @@ -3447,8 +3472,40 @@ namespace OpenSim.Region.Framework.Scenes } } - ScenePresence sp = GetScenePresence(agent.AgentID); - if (sp != null) + if (sp == null) // We don't have an [child] agent here already + { + + try + { + if (!VerifyUserPresence(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.DebugFormat("[CONNECTION BEGIN]: Exception verifying presence {0}", e.Message); + return false; + } + + try + { + if (!AuthorizeUser(agent, out reason)) + return false; + } + catch (Exception e) + { + m_log.DebugFormat("[CONNECTION BEGIN]: Exception authorizing user {0}", e.Message); + return false; + } + + m_log.InfoFormat( + "[CONNECTION BEGIN]: Region {0} authenticated and authorized incoming {1} agent {2} {3} {4} (circuit code {5})", + RegionInfo.RegionName, (agent.child ? "child" : "root"), agent.firstname, agent.lastname, + agent.AgentID, agent.circuitcode); + + CapsModule.NewUserConnection(agent); + CapsModule.AddCapsHandler(agent.AgentID); + } + else { if (sp.IsChildAgent) { @@ -3457,22 +3514,18 @@ namespace OpenSim.Region.Framework.Scenes agent.AgentID, RegionInfo.RegionName); sp.AdjustKnownSeeds(); - - return true; - } - else - { - // We have a zombie from a crashed session. Kill it. - m_log.DebugFormat("[SCENE]: Zombie scene presence detected for {0} in {1}", agent.AgentID, RegionInfo.RegionName); - sp.ControllingClient.Close(); + CapsModule.NewUserConnection(agent); } } - CapsModule.AddCapsHandler(agent.AgentID); - if (!agent.child) + // In all cases, add or update the circuit data with the new agent circuit data and teleport flags + agent.teleportFlags = teleportFlags; + m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); + + if (tp == TeleportFlags.ViaLogin) { - if (TestBorderCross(agent.startpos,Cardinals.E)) + if (TestBorderCross(agent.startpos, Cardinals.E)) { Border crossedBorder = GetCrossedBorder(agent.startpos, Cardinals.E); agent.startpos.X = crossedBorder.BorderLine.Z - 1; @@ -3537,9 +3590,6 @@ namespace OpenSim.Region.Framework.Scenes } } - agent.teleportFlags = teleportFlags; - m_authenticateHandler.AddNewCircuit(agent.circuitcode, agent); - return true; } @@ -3631,14 +3681,19 @@ namespace OpenSim.Region.Framework.Scenes } } - if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) + if (m_regInfo.EstateSettings != null) { - m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", - agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); - reason = String.Format("Denied access to region {0}: You have been banned from that region.", - RegionInfo.RegionName); - return false; + if (m_regInfo.EstateSettings.IsBanned(agent.AgentID)) + { + m_log.WarnFormat("[CONNECTION BEGIN]: Denied access to: {0} ({1} {2}) at {3} because the user is on the banlist", + agent.AgentID, agent.firstname, agent.lastname, RegionInfo.RegionName); + reason = String.Format("Denied access to region {0}: You have been banned from that region.", + RegionInfo.RegionName); + return false; + } } + else + m_log.ErrorFormat("[CONNECTION BEGIN]: Estate Settings is null!"); IGroupsModule groupsModule = RequestModuleInterface(); @@ -3650,21 +3705,31 @@ namespace OpenSim.Region.Framework.Scenes GroupMembershipData[] GroupMembership = groupsModule.GetMembershipData(agent.AgentID); - for (int i = 0; i < GroupMembership.Length; i++) - agentGroups.Add(GroupMembership[i].GroupID); + if (GroupMembership != null) + { + for (int i = 0; i < GroupMembership.Length; i++) + agentGroups.Add(GroupMembership[i].GroupID); + } + else + m_log.ErrorFormat("[CONNECTION BEGIN]: GroupMembership is null!"); } bool groupAccess = false; UUID[] estateGroups = m_regInfo.EstateSettings.EstateGroups; - foreach (UUID group in estateGroups) + if (estateGroups != null) { - if (agentGroups.Contains(group)) + foreach (UUID group in estateGroups) { - groupAccess = true; - break; + if (agentGroups.Contains(group)) + { + groupAccess = true; + break; + } } } + else + m_log.ErrorFormat("[CONNECTION BEGIN]: EstateGroups is null!"); if (!m_regInfo.EstateSettings.PublicAccess && !m_regInfo.EstateSettings.HasAccess(agent.AgentID) && @@ -3816,6 +3881,8 @@ namespace OpenSim.Region.Framework.Scenes m_log.DebugFormat( "[SCENE]: Incoming child agent update for {0} in {1}", cAgentData.AgentID, RegionInfo.RegionName); + // XPTO: if this agent is not allowed here as root, always return false + // We have to wait until the viewer contacts this region after receiving EAC. // That calls AddNewClient, which finally creates the ScenePresence ScenePresence childAgentUpdate = WaitGetScenePresence(cAgentData.AgentID); @@ -3990,7 +4057,9 @@ namespace OpenSim.Region.Framework.Scenes // bordercross if position is outside of region if (!result) + { regionHandle = m_regInfo.RegionHandle; + } else { // not in this region, undo the shift! @@ -4047,20 +4116,6 @@ namespace OpenSim.Region.Framework.Scenes #region Other Methods - public void SetObjectCapacity(int objects) - { - // Region specific config overrides global - // - if (RegionInfo.ObjectCapacity != 0) - objects = RegionInfo.ObjectCapacity; - - if (StatsReporter != null) - { - StatsReporter.SetObjectCapacity(objects); - } - objectCapacity = objects; - } - #endregion public void HandleObjectPermissionsUpdate(IClientAPI controller, UUID agentID, UUID sessionID, byte field, uint localId, uint mask, byte set) @@ -4659,7 +4714,7 @@ namespace OpenSim.Region.Framework.Scenes part.NextOwnerMask; item.GroupPermissions = part.GroupMask & part.NextOwnerMask; - item.CurrentPermissions |= 8; // Slam! + item.CurrentPermissions |= 16; // Slam! item.CreationDate = Util.UnixTimeSinceEpoch(); if (InventoryService.AddItem(item)) diff --git a/OpenSim/Region/Framework/Scenes/SceneBase.cs b/OpenSim/Region/Framework/Scenes/SceneBase.cs index ee17fbf8ed..f8591ba8ad 100644 --- a/OpenSim/Region/Framework/Scenes/SceneBase.cs +++ b/OpenSim/Region/Framework/Scenes/SceneBase.cs @@ -267,7 +267,7 @@ namespace OpenSim.Region.Framework.Scenes } catch (Exception e) { - m_log.Error("[SCENE]: SceneBase.cs: Close() - Failed with exception " + e.ToString()); + m_log.Error(string.Format("[SCENE]: SceneBase.cs: Close() - Failed with exception ", e)); } } @@ -376,7 +376,7 @@ namespace OpenSim.Region.Framework.Scenes /// public void RegisterModuleInterface(M mod) { - m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); +// m_log.DebugFormat("[SCENE BASE]: Registering interface {0}", typeof(M)); List l = null; if (!ModuleInterfaces.TryGetValue(typeof(M), out l)) diff --git a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs index bd8ccce6e1..c675322185 100644 --- a/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs +++ b/OpenSim/Region/Framework/Scenes/SceneCommunicationService.cs @@ -182,24 +182,17 @@ namespace OpenSim.Region.Framework.Scenes { //m_log.Info("[INTER]: " + debugRegionName + ": SceneCommunicationService: Sending InterRegion Notification that region is up " + region.RegionName); - for (int x = (int)region.RegionLocX - 1; x <= region.RegionLocX + 1; x++) + List neighbours = m_scene.GridService.GetNeighbours(m_scene.RegionInfo.ScopeID, m_scene.RegionInfo.RegionID); + m_log.DebugFormat("[INTERGRID]: Informing {0} neighbours that this region is up", neighbours.Count); + foreach (GridRegion n in neighbours) { - for (int y = (int)region.RegionLocY - 1; y <= region.RegionLocY + 1; y++) - { - if (!((x == region.RegionLocX) && (y == region.RegionLocY))) // skip this region - { - ulong handle = Utils.UIntsToLong((uint)x * Constants.RegionSize, (uint)y * Constants.RegionSize); - InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; - - d.BeginInvoke(neighbourService, region, handle, - InformNeighborsThatRegionisUpCompleted, - d); - } - } + InformNeighbourThatRegionUpDelegate d = InformNeighboursThatRegionIsUpAsync; + d.BeginInvoke(neighbourService, region, n.RegionHandle, + InformNeighborsThatRegionisUpCompleted, + d); } } - public delegate void SendChildAgentDataUpdateDelegate(AgentPosition cAgentData, ulong regionHandle); /// diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs index a02f614387..40332a6f93 100644 --- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs +++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs @@ -206,6 +206,43 @@ namespace OpenSim.Region.Framework.Scenes }); } + public void GetCoarseLocations(out List coarseLocations, out List avatarUUIDs, uint maxLocations) + { + coarseLocations = new List(); + avatarUUIDs = new List(); + + List presences = GetScenePresences(); + for (int i = 0; i < Math.Min(presences.Count, maxLocations); ++i) + { + ScenePresence sp = presences[i]; + // If this presence is a child agent, we don't want its coarse locations + if (sp.IsChildAgent) + return; + + if (sp.ParentID != 0) + { + // sitting avatar + SceneObjectPart sop = m_parentScene.GetSceneObjectPart(sp.ParentID); + if (sop != null) + { + coarseLocations.Add(sop.AbsolutePosition + sp.AbsolutePosition); + avatarUUIDs.Add(sp.UUID); + } + else + { + // we can't find the parent.. ! arg! + coarseLocations.Add(sp.AbsolutePosition); + avatarUUIDs.Add(sp.UUID); + } + } + else + { + coarseLocations.Add(sp.AbsolutePosition); + avatarUUIDs.Add(sp.UUID); + } + } + } + #endregion #region Entity Methods @@ -222,11 +259,15 @@ namespace OpenSim.Region.Framework.Scenes /// If true, we won't persist this object until it changes /// If false, we'll persist this object immediately /// + /// + /// If true, we send updates to the client to tell it about this object + /// If false, we leave it up to the caller to do this + /// /// /// true if the object was added, false if an object with the same uuid was already in the scene /// protected internal bool AddRestoredSceneObject( - SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted) + SceneObjectGroup sceneObject, bool attachToBackup, bool alreadyPersisted, bool sendClientUpdates) { if (!alreadyPersisted) { @@ -234,9 +275,9 @@ namespace OpenSim.Region.Framework.Scenes sceneObject.HasGroupChanged = true; } - return AddSceneObject(sceneObject, attachToBackup, true); + return AddSceneObject(sceneObject, attachToBackup, sendClientUpdates); } - + /// /// Add a newly created object to the scene. This will both update the scene, and send information about the /// new object to all clients interested in the scene. @@ -558,7 +599,7 @@ namespace OpenSim.Region.Framework.Scenes if (!Entities.Remove(agentID)) { m_log.WarnFormat( - "[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", + "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", agentID); } @@ -566,12 +607,13 @@ namespace OpenSim.Region.Framework.Scenes { Dictionary newmap = new Dictionary(m_scenePresenceMap); List newlist = new List(m_scenePresenceArray); - - // Remember the old presene reference from the dictionary - ScenePresence oldref = newmap[agentID]; + // Remove the presence reference from the dictionary - if (newmap.Remove(agentID)) + if (newmap.ContainsKey(agentID)) { + ScenePresence oldref = newmap[agentID]; + newmap.Remove(agentID); + // Find the index in the list where the old ref was stored and remove the reference newlist.RemoveAt(newlist.IndexOf(oldref)); // Swap out the dictionary and list with new references @@ -580,7 +622,7 @@ namespace OpenSim.Region.Framework.Scenes } else { - m_log.WarnFormat("[SCENE] Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); + m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); } } } @@ -1705,9 +1747,31 @@ namespace OpenSim.Region.Framework.Scenes { if (m_parentScene.Permissions.CanDuplicateObject(original.Children.Count, original.UUID, AgentID, original.AbsolutePosition)) { - SceneObjectGroup copy = original.Copy(AgentID, GroupID, true); + SceneObjectGroup copy = original.Copy(true); copy.AbsolutePosition = copy.AbsolutePosition + offset; + if (original.OwnerID != AgentID) + { + copy.SetOwnerId(AgentID); + copy.SetRootPartOwner(copy.RootPart, AgentID, GroupID); + + List partList = + new List(copy.Children.Values); + + if (m_parentScene.Permissions.PropagatePermissions()) + { + foreach (SceneObjectPart child in partList) + { + child.Inventory.ChangeInventoryOwner(AgentID); + child.TriggerScriptChangedEvent(Changed.OWNER); + child.ApplyNextOwnerPermissions(); + } + } + + copy.RootPart.ObjectSaleType = 0; + copy.RootPart.SalePrice = 10; + } + Entities.Add(copy); // Since we copy from a source group that is in selected diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs index f7e46afa6b..9a01a28b36 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.Inventory.cs @@ -172,13 +172,14 @@ namespace OpenSim.Region.Framework.Scenes taskItem.GroupPermissions = item.GroupPermissions & item.NextPermissions; taskItem.NextPermissions = item.NextPermissions; - taskItem.CurrentPermissions |= 8; + // We're adding this to a prim we don't own. Force + // owner change + taskItem.CurrentPermissions |= 16; // Slam } else { taskItem.BasePermissions = item.BasePermissions; taskItem.CurrentPermissions = item.CurrentPermissions; - taskItem.CurrentPermissions |= 8; taskItem.EveryonePermissions = item.EveryOnePermissions; taskItem.GroupPermissions = item.GroupPermissions; taskItem.NextPermissions = item.NextPermissions; @@ -281,7 +282,7 @@ namespace OpenSim.Region.Framework.Scenes PermissionMask.Move | PermissionMask.Transfer) | 7; - uint ownerMask = 0x7ffffff; + uint ownerMask = 0x7fffffff; foreach (SceneObjectPart part in m_parts.Values) { ownerMask &= part.OwnerMask; @@ -295,12 +296,16 @@ namespace OpenSim.Region.Framework.Scenes if ((ownerMask & (uint)PermissionMask.Transfer) == 0) perms &= ~(uint)PermissionMask.Transfer; - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) - perms &= ~((uint)PermissionMask.Modify >> 13); - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) - perms &= ~((uint)PermissionMask.Copy >> 13); - if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) - perms &= ~((uint)PermissionMask.Transfer >> 13); + // If root prim permissions are applied here, this would screw + // with in-inventory manipulation of the next owner perms + // in a major way. So, let's move this to the give itself. + // Yes. I know. Evil. +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Modify) == 0) +// perms &= ~((uint)PermissionMask.Modify >> 13); +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Copy) == 0) +// perms &= ~((uint)PermissionMask.Copy >> 13); +// if ((ownerMask & RootPart.NextOwnerMask & (uint)PermissionMask.Transfer) == 0) +// perms &= ~((uint)PermissionMask.Transfer >> 13); return perms; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs index 837d3a2142..1ca390a7c1 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectGroup.cs @@ -1052,6 +1052,7 @@ namespace OpenSim.Region.Framework.Scenes return; detachedpos = avatar.AbsolutePosition; + RootPart.FromItemID = UUID.Zero; AbsolutePosition = detachedpos; m_rootPart.AttachedAvatar = UUID.Zero; @@ -1471,7 +1472,7 @@ namespace OpenSim.Region.Framework.Scenes "[SCENE]: Storing {0}, {1} in {2}", Name, UUID, m_scene.RegionInfo.RegionName); - SceneObjectGroup backup_group = Copy(OwnerID, GroupID, false); + SceneObjectGroup backup_group = Copy(false); backup_group.RootPart.Velocity = RootPart.Velocity; backup_group.RootPart.Acceleration = RootPart.Acceleration; backup_group.RootPart.AngularVelocity = RootPart.AngularVelocity; @@ -1527,7 +1528,7 @@ namespace OpenSim.Region.Framework.Scenes /// Duplicates this object, including operations such as physics set up and attaching to the backup event. /// /// - public SceneObjectGroup Copy(UUID cAgentID, UUID cGroupID, bool userExposed) + public SceneObjectGroup Copy(bool userExposed) { SceneObjectGroup dupe = (SceneObjectGroup)MemberwiseClone(); dupe.m_isBackedUp = false; @@ -1550,7 +1551,9 @@ namespace OpenSim.Region.Framework.Scenes dupe.AbsolutePosition = new Vector3(AbsolutePosition.X, AbsolutePosition.Y, AbsolutePosition.Z); if (!userExposed) + { dupe.RootPart.IsAttachment = previousAttachmentStatus; + } dupe.CopyRootPart(m_rootPart, OwnerID, GroupID, userExposed); dupe.m_rootPart.LinkNum = m_rootPart.LinkNum; @@ -1575,16 +1578,6 @@ namespace OpenSim.Region.Framework.Scenes dupe.RootPart.DoPhysicsPropertyUpdate(dupe.RootPart.PhysActor.IsPhysical, true); } - // Now we've made a copy that replaces this one, we need to - // switch the owner to the person who did the copying - // Second Life copies an object and duplicates the first one in it's place - // So, we have to make a copy of this one, set it in it's place then set the owner on this one - if (userExposed) - { - SetRootPartOwner(m_rootPart, cAgentID, cGroupID); - m_rootPart.ScheduleFullUpdate(); - } - List partList; lock (m_parts) @@ -1605,12 +1598,6 @@ namespace OpenSim.Region.Framework.Scenes SceneObjectPart newPart = dupe.CopyPart(part, OwnerID, GroupID, userExposed); newPart.LinkNum = part.LinkNum; - - if (userExposed) - { - SetPartOwner(newPart, cAgentID, cGroupID); - newPart.ScheduleFullUpdate(); - } } } @@ -2012,7 +1999,8 @@ namespace OpenSim.Region.Framework.Scenes /// public void ScheduleGroupForFullUpdate() { -// m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, UUID); + if (IsAttachment) + m_log.DebugFormat("[SOG]: Scheduling full update for {0} {1}", Name, LocalId); checkAtTargets(); RootPart.ScheduleFullUpdate(); @@ -3593,7 +3581,7 @@ namespace OpenSim.Region.Framework.Scenes public virtual ISceneObject CloneForNewScene() { - SceneObjectGroup sog = Copy(this.OwnerID, this.GroupID, false); + SceneObjectGroup sog = Copy(false); sog.m_isDeleted = false; return sog; } diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs index 38b2dc2f68..13e4b564f7 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPart.cs @@ -179,6 +179,9 @@ namespace OpenSim.Region.Framework.Scenes [XmlIgnore] public UUID FromItemID; + [XmlIgnore] + public UUID FromFolderID; + [XmlIgnore] public int STATUS_ROTATE_X; @@ -1487,6 +1490,10 @@ namespace OpenSim.Region.Framework.Scenes DoPhysicsPropertyUpdate(RigidBody, true); PhysActor.SetVolumeDetect(VolumeDetectActive ? 1 : 0); } + else + { + m_log.DebugFormat("[SPEW]: physics actor is null for {0} with parent {1}", UUID, this.ParentGroup.UUID); + } } } } @@ -4133,6 +4140,10 @@ namespace OpenSim.Region.Framework.Scenes case 16: _nextOwnerMask = ApplyMask(_nextOwnerMask, set, mask) & baseMask; + // Prevent the client from creating no mod, no copy + // objects + if ((_nextOwnerMask & (uint)PermissionMask.Copy) == 0) + _nextOwnerMask |= (uint)PermissionMask.Transfer; break; } SendFullUpdateToAllClients(); diff --git a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs index 8b83b0660c..b27dc59a1c 100644 --- a/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs +++ b/OpenSim/Region/Framework/Scenes/SceneObjectPartInventory.cs @@ -31,6 +31,7 @@ using System.IO; using System.Collections.Generic; using System.Collections; using System.Reflection; +using System.Threading; using OpenMetaverse; using log4net; using OpenSim.Framework; @@ -555,7 +556,7 @@ namespace OpenSim.Region.Framework.Scenes foreach (TaskInventoryItem item in items) { m_items.Add(item.ItemID, item); - m_part.TriggerScriptChangedEvent(Changed.INVENTORY); +// m_part.TriggerScriptChangedEvent(Changed.INVENTORY); } } @@ -950,7 +951,6 @@ namespace OpenSim.Region.Framework.Scenes item.CurrentPermissions &= ~(uint)PermissionMask.Transfer; if ((item.CurrentPermissions & ((uint)PermissionMask.Modify >> 13)) == 0) item.CurrentPermissions &= ~(uint)PermissionMask.Modify; - item.CurrentPermissions |= 8; } item.CurrentPermissions &= item.NextPermissions; item.BasePermissions &= item.NextPermissions; diff --git a/OpenSim/Region/Framework/Scenes/ScenePresence.cs b/OpenSim/Region/Framework/Scenes/ScenePresence.cs index 45375b0e8c..1e8ce22f7d 100644 --- a/OpenSim/Region/Framework/Scenes/ScenePresence.cs +++ b/OpenSim/Region/Framework/Scenes/ScenePresence.cs @@ -60,12 +60,11 @@ namespace OpenSim.Region.Framework.Scenes struct ScriptControllers { public UUID itemID; - public uint objID; public ScriptControlled ignoreControls; public ScriptControlled eventControls; } - public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence); + public delegate void SendCourseLocationsMethod(UUID scene, ScenePresence presence, List coarseLocations, List avatarUUIDs); public class ScenePresence : EntityBase, ISceneEntity { @@ -173,8 +172,6 @@ namespace OpenSim.Region.Framework.Scenes public string JID = String.Empty; - // Agent moves with a PID controller causing a force to be exerted. - private bool m_newCoarseLocations = true; private float m_health = 100f; // Default AV Height @@ -1017,25 +1014,7 @@ namespace OpenSim.Region.Framework.Scenes public void StopFlying() { - // It turns out to get the agent to stop flying, you have to feed it stop flying velocities - // There's no explicit message to send the client to tell it to stop flying.. it relies on the - // velocity, collision plane and avatar height - - // Add 1/6 the avatar's height to it's position so it doesn't shoot into the air - // when the avatar stands up - - if (m_avHeight != 127.0f) - { - AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (m_avHeight / 6f)); - } - else - { - AbsolutePosition = AbsolutePosition + new Vector3(0f, 0f, (1.56f / 6f)); - } - - ControllingClient.SendPrimUpdate(this, PrimUpdateFlags.Position); - //ControllingClient.SendAvatarTerseUpdate(new SendAvatarTerseData(m_rootRegionHandle, (ushort)(m_scene.TimeDilation * ushort.MaxValue), LocalId, - // AbsolutePosition, Velocity, Vector3.Zero, m_bodyRot, new Vector4(0,0,1,AbsolutePosition.Z - 0.5f), m_uuid, null, GetUpdatePriority(ControllingClient))); + ControllingClient.StopFlying(this); } public void AddNeighbourRegion(ulong regionHandle, string cap) @@ -2296,12 +2275,6 @@ namespace OpenSim.Region.Framework.Scenes SendPrimUpdates(); - if (m_newCoarseLocations) - { - SendCoarseLocations(); - m_newCoarseLocations = false; - } - if (m_isChildAgent == false) { // PhysicsActor actor = m_physicsActor; @@ -2375,12 +2348,12 @@ namespace OpenSim.Region.Framework.Scenes m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } - public void SendCoarseLocations() + public void SendCoarseLocations(List coarseLocations, List avatarUUIDs) { SendCourseLocationsMethod d = m_sendCourseLocationsMethod; if (d != null) { - d.Invoke(m_scene.RegionInfo.originRegionID, this); + d.Invoke(m_scene.RegionInfo.originRegionID, this, coarseLocations, avatarUUIDs); } } @@ -2390,50 +2363,13 @@ namespace OpenSim.Region.Framework.Scenes m_sendCourseLocationsMethod = d; } - public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p) + public void SendCoarseLocationsDefault(UUID sceneId, ScenePresence p, List coarseLocations, List avatarUUIDs) { m_perfMonMS = Util.EnvironmentTickCount(); - - List CoarseLocations = new List(); - List AvatarUUIDs = new List(); - m_scene.ForEachScenePresence(delegate(ScenePresence sp) - { - if (sp.IsChildAgent) - return; - - if (sp.ParentID != 0) - { - // sitting avatar - SceneObjectPart sop = m_scene.GetSceneObjectPart(sp.ParentID); - if (sop != null) - { - CoarseLocations.Add(sop.AbsolutePosition + sp.m_pos); - AvatarUUIDs.Add(sp.UUID); - } - else - { - // we can't find the parent.. ! arg! - CoarseLocations.Add(sp.m_pos); - AvatarUUIDs.Add(sp.UUID); - } - } - else - { - CoarseLocations.Add(sp.m_pos); - AvatarUUIDs.Add(sp.UUID); - } - }); - - m_controllingClient.SendCoarseLocationUpdate(AvatarUUIDs, CoarseLocations); - + m_controllingClient.SendCoarseLocationUpdate(avatarUUIDs, coarseLocations); m_scene.StatsReporter.AddAgentTime(Util.EnvironmentTickCountSubtract(m_perfMonMS)); } - public void CoarseLocationChange() - { - m_newCoarseLocations = true; - } - /// /// Tell other client about this avatar (The client previously didn't know or had outdated details about this avatar) /// @@ -2668,7 +2604,6 @@ namespace OpenSim.Region.Framework.Scenes { posLastSignificantMove = AbsolutePosition; m_scene.EventManager.TriggerSignificantClientMovement(m_controllingClient); - m_scene.NotifyMyCoarseLocationChange(); } // Minimum Draw distance is 64 meters, the Radius of the draw distance sphere is 32m @@ -3121,6 +3056,18 @@ namespace OpenSim.Region.Framework.Scenes cAgent.Attachments = attachs; } + lock (scriptedcontrols) + { + ControllerData[] controls = new ControllerData[scriptedcontrols.Count]; + int i = 0; + + foreach (ScriptControllers c in scriptedcontrols.Values) + { + controls[i++] = new ControllerData(c.itemID, (uint)c.ignoreControls, (uint)c.eventControls); + } + cAgent.Controllers = controls; + } + // Animations try { @@ -3192,6 +3139,7 @@ namespace OpenSim.Region.Framework.Scenes { if (cAgent.Attachments != null) { + m_appearance.ClearAttachments(); foreach (AttachmentData att in cAgent.Attachments) { m_appearance.SetAttachment(att.AttachPoint, att.ItemID, att.AssetID); @@ -3200,6 +3148,27 @@ namespace OpenSim.Region.Framework.Scenes } catch { } + try + { + lock (scriptedcontrols) + { + if (cAgent.Controllers != null) + { + scriptedcontrols.Clear(); + + foreach (ControllerData c in cAgent.Controllers) + { + ScriptControllers sc = new ScriptControllers(); + sc.itemID = c.ItemID; + sc.ignoreControls = (ScriptControlled)c.IgnoreControls; + sc.eventControls = (ScriptControlled)c.EventControls; + + scriptedcontrols[sc.itemID] = sc; + } + } + } + } + catch { } // Animations try { @@ -3531,7 +3500,6 @@ namespace OpenSim.Region.Framework.Scenes obj.eventControls = ScriptControlled.CONTROL_ZERO; obj.itemID = Script_item_UUID; - obj.objID = Obj_localID; if (pass_on == 0 && accept == 0) { IgnoredControls |= (ScriptControlled)controls; @@ -3674,7 +3642,7 @@ namespace OpenSim.Region.Framework.Scenes if (localHeld != ScriptControlled.CONTROL_ZERO || localChange != ScriptControlled.CONTROL_ZERO) { // only send if still pressed or just changed - m_scene.EventManager.TriggerControlEvent(scriptControlData.objID, scriptUUID, UUID, (uint)localHeld, (uint)localChange); + m_scene.EventManager.TriggerControlEvent(scriptUUID, UUID, (uint)localHeld, (uint)localChange); } } } diff --git a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs index f7544ac2ee..5bdaa17f69 100644 --- a/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs +++ b/OpenSim/Region/Framework/Scenes/Serialization/SceneObjectSerializer.cs @@ -221,7 +221,16 @@ namespace OpenSim.Region.Framework.Scenes.Serialization sr = new StringReader(parts[i].OuterXml); reader = new XmlTextReader(sr); SceneObjectPart part = SceneObjectPart.FromXml(reader); + + int originalLinkNum = part.LinkNum; + sceneObject.AddPart(part); + + // SceneObjectGroup.AddPart() tries to be smart and automatically set the LinkNum. + // We override that here + if (originalLinkNum != 0) + part.LinkNum = originalLinkNum; + part.StoreUndoState(); reader.Close(); sr.Close(); diff --git a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs index 7453eae63e..ee7aa2da8d 100644 --- a/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs +++ b/OpenSim/Region/OptionalModules/Agent/InternetRelayClientView/Server/IRCClientView.cs @@ -1055,11 +1055,6 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server } - public void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - - } - public void SendAvatarDataImmediate(ISceneEntity avatar) { @@ -1680,5 +1675,9 @@ namespace OpenSim.Region.OptionalModules.Agent.InternetRelayClientView.Server public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) { } + + public void StopFlying(ISceneEntity presence) + { + } } } diff --git a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs index 56c0d985f1..3f15b69944 100644 --- a/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs +++ b/OpenSim/Region/OptionalModules/Avatar/XmlRpcGroups/GroupsModule.cs @@ -722,11 +722,11 @@ namespace OpenSim.Region.OptionalModules.Avatar.XmlRpcGroups if (money != null) { // do the transaction, that is if the agent has got sufficient funds - if (!money.GroupCreationCovered(remoteClient)) { + if (!money.AmountCovered(remoteClient, money.GroupCreationCharge)) { remoteClient.SendCreateGroupReply(UUID.Zero, false, "You have got issuficient funds to create a group."); return UUID.Zero; } - money.ApplyGroupCreationCharge(GetRequestingAgentID(remoteClient)); + money.ApplyCharge(GetRequestingAgentID(remoteClient), money.GroupCreationCharge, "Group Creation"); } UUID groupID = m_groupData.CreateGroup(GetRequestingAgentID(remoteClient), name, charter, showInList, insigniaID, membershipFee, openEnrollment, allowPublish, maturePublish, GetRequestingAgentID(remoteClient)); diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs index c277034171..ada67011b3 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/ContentManagementEntity.cs @@ -73,7 +73,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement public ContentManagementEntity(SceneObjectGroup Unchanged, bool physics) : base(Unchanged, false) { - m_UnchangedEntity = Unchanged.Copy(Unchanged.RootPart.OwnerID, Unchanged.RootPart.GroupID, false); + m_UnchangedEntity = Unchanged.Copy(false); } public ContentManagementEntity(string objectXML, Scene scene, bool physics) diff --git a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs index 1a72971b56..841ee00e59 100644 --- a/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs +++ b/OpenSim/Region/OptionalModules/ContentManagementSystem/MetaEntity.cs @@ -80,7 +80,7 @@ namespace OpenSim.Region.OptionalModules.ContentManagement /// public MetaEntity(SceneObjectGroup orig, bool physics) { - m_Entity = orig.Copy(orig.RootPart.OwnerID, orig.RootPart.GroupID, false); + m_Entity = orig.Copy(false); Initialize(physics); } diff --git a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs index b9a75cc198..653f856664 100644 --- a/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs +++ b/OpenSim/Region/OptionalModules/World/MoneyModule/SampleMoneyModule.cs @@ -108,6 +108,16 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public event ObjectPaid OnObjectPaid; + public int UploadCharge + { + get { return 0; } + } + + public int GroupCreationCharge + { + get { return 0; } + } + /// /// Startup /// @@ -128,8 +138,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule public void AddRegion(Scene scene) { // Send ObjectCapacity to Scene.. Which sends it to the SimStatsReporter. - scene.SetObjectCapacity(ObjectCapacity); - if (m_enabled) { scene.RegisterModuleInterface(this); @@ -188,17 +196,12 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // Please do not refactor these to be just one method // Existing implementations need the distinction // - public void ApplyUploadCharge(UUID agentID) - { - } - - public void ApplyGroupCreationCharge(UUID agentID) - { - } - public void ApplyCharge(UUID agentID, int amount, string text) { } + public void ApplyUploadCharge(UUID agentID, int amount, string text) + { + } public bool ObjectGiveMoney(UUID objectID, UUID fromID, UUID toID, int amount) { @@ -247,7 +250,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule if (config == "Economy" && startupConfig != null) { - ObjectCapacity = startupConfig.GetInt("ObjectCapacity", 45000); PriceEnergyUnit = startupConfig.GetInt("PriceEnergyUnit", 100); PriceObjectClaim = startupConfig.GetInt("PriceObjectClaim", 10); PricePublicObjectDecay = startupConfig.GetInt("PricePublicObjectDecay", 4); @@ -268,27 +270,6 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule } - public EconomyData GetEconomyData() - { - EconomyData edata = new EconomyData(); - edata.ObjectCapacity = ObjectCapacity; - edata.ObjectCount = ObjectCount; - edata.PriceEnergyUnit = PriceEnergyUnit; - edata.PriceGroupCreate = PriceGroupCreate; - edata.PriceObjectClaim = PriceObjectClaim; - edata.PriceObjectRent = PriceObjectRent; - edata.PriceObjectScaleFactor = PriceObjectScaleFactor; - edata.PriceParcelClaim = PriceParcelClaim; - edata.PriceParcelClaimFactor = PriceParcelClaimFactor; - edata.PriceParcelRent = PriceParcelRent; - edata.PricePublicObjectDecay = PricePublicObjectDecay; - edata.PricePublicObjectDelete = PricePublicObjectDelete; - edata.PriceRentLight = PriceRentLight; - edata.PriceUpload = PriceUpload; - edata.TeleportMinPrice = TeleportMinPrice; - return edata; - } - private void GetClientFunds(IClientAPI client) { CheckExistAndRefreshFunds(client.AgentId); @@ -717,7 +698,9 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule if (user != null) { - user.SendEconomyData(EnergyEfficiency, ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, + Scene s = LocateSceneClientIn(user.AgentId); + + user.SendEconomyData(EnergyEfficiency, s.RegionInfo.ObjectCapacity, ObjectCount, PriceEnergyUnit, PriceGroupCreate, PriceObjectClaim, PriceObjectRent, PriceObjectScaleFactor, PriceParcelClaim, PriceParcelClaimFactor, PriceParcelRent, PricePublicObjectDecay, PricePublicObjectDelete, PriceRentLight, PriceUpload, TeleportMinPrice, TeleportPriceExponent); @@ -790,7 +773,7 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule //m_log.Info("[FRIEND]: " + avatar.Name + " status:" + (!avatar.IsChildAgent).ToString()); } - public int GetBalance(IClientAPI client) + public int GetBalance(UUID agentID) { return 0; } @@ -798,16 +781,10 @@ namespace OpenSim.Region.OptionalModules.World.MoneyModule // Please do not refactor these to be just one method // Existing implementations need the distinction // - public bool UploadCovered(IClientAPI client) + public bool UploadCovered(IClientAPI client, int amount) { - return AmountCovered(client, PriceUpload); + return true; } - - public bool GroupCreationCovered(IClientAPI client) - { - return AmountCovered(client, PriceGroupCreate); - } - public bool AmountCovered(IClientAPI client, int amount) { return true; diff --git a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs index 146b3d6f32..2e0450cf76 100644 --- a/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs +++ b/OpenSim/Region/OptionalModules/World/NPC/NPCAvatar.cs @@ -627,10 +627,6 @@ namespace OpenSim.Region.OptionalModules.World.NPC { } - public virtual void AttachObject(uint localID, Quaternion rotation, byte attachPoint, UUID ownerID) - { - } - public virtual void SendDialog(string objectname, UUID objectID, string ownerFirstName, string ownerLastName, string msg, UUID textureID, int ch, string[] buttonlabels) { } @@ -1162,5 +1158,9 @@ namespace OpenSim.Region.OptionalModules.World.NPC public void SendTextBoxRequest(string message, int chatChannel, string objectname, string ownerFirstName, string ownerLastName, UUID objectId) { } + + public void StopFlying(ISceneEntity presence) + { + } } } diff --git a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs index 9beeabba0a..2342bfa141 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEDynamics.cs @@ -675,7 +675,7 @@ namespace OpenSim.Region.Physics.OdePlugin m_dir.Z = vel_now.Z; // Preserve the accumulated falling velocity d.Vector3 pos = d.BodyGetPosition(Body); - Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); +// Vector3 accel = new Vector3(-(m_dir.X - m_lastLinearVelocityVector.X / 0.1f), -(m_dir.Y - m_lastLinearVelocityVector.Y / 0.1f), m_dir.Z - m_lastLinearVelocityVector.Z / 0.1f); Vector3 posChange = new Vector3(); posChange.X = pos.X - m_lastPositionVector.X; posChange.Y = pos.Y - m_lastPositionVector.Y; diff --git a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs index 0720b5ee53..3cf45019e7 100644 --- a/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs +++ b/OpenSim/Region/Physics/OdePlugin/ODEPrim.cs @@ -1576,19 +1576,19 @@ Console.WriteLine(" JointCreateFixed"); //Console.WriteLine("Move " + m_primName); if (!d.BodyIsEnabled (Body)) d.BodyEnable (Body); // KF add 161009 // NON-'VEHICLES' are dealt with here - if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) - { - d.Vector3 avel2 = d.BodyGetAngularVel(Body); - /* - if (m_angularlock.X == 1) - avel2.X = 0; - if (m_angularlock.Y == 1) - avel2.Y = 0; - if (m_angularlock.Z == 1) - avel2.Z = 0; - d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); - */ - } +// if (d.BodyIsEnabled(Body) && !m_angularlock.ApproxEquals(Vector3.Zero, 0.003f)) +// { +// d.Vector3 avel2 = d.BodyGetAngularVel(Body); +// /* +// if (m_angularlock.X == 1) +// avel2.X = 0; +// if (m_angularlock.Y == 1) +// avel2.Y = 0; +// if (m_angularlock.Z == 1) +// avel2.Z = 0; +// d.BodySetAngularVel(Body, avel2.X, avel2.Y, avel2.Z); +// */ +// } //float PID_P = 900.0f; float m_mass = CalculateMass(); diff --git a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs index 7984bd9b00..7fd59a0ebf 100644 --- a/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs +++ b/OpenSim/Region/Physics/OdePlugin/OdePlugin.cs @@ -1771,7 +1771,19 @@ namespace OpenSim.Region.Physics.OdePlugin IMesh mesh = null; if (needsMeshing(pbs)) - mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); + { + try + { + mesh = mesher.CreateMesh(primName, pbs, size, 32f, isPhysical); + } + catch(Exception e) + { + m_log.ErrorFormat("[PHYSICS]: Exception while meshing prim {0}.", primName); + m_log.Debug(e.ToString()); + mesh = null; + return null; + } + } result = AddPrim(primName, position, size, rotation, mesh, pbs, isPhysical); diff --git a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs index 9cb349a1e9..ff0e743113 100644 --- a/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs +++ b/OpenSim/Region/RegionCombinerModule/RegionCombinerModule.cs @@ -696,7 +696,9 @@ namespace OpenSim.Region.RegionCombinerModule presence.SetSendCourseLocationMethod(SendCourseLocationUpdates); } - private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence) + // This delegate was refactored for non-combined regions. + // This combined region version will not use the pre-compiled lists of locations and ids + private void SendCourseLocationUpdates(UUID sceneId, ScenePresence presence, List coarseLocations, List avatarUUIDs) { RegionConnections connectiondata = null; lock (m_regions) diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs index 6e9a823c87..417cef4e64 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LSL_Api.cs @@ -451,12 +451,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api public LSL_Vector llVecNorm(LSL_Vector v) { m_host.AddScriptLPS(1); - double mag = LSL_Vector.Mag(v); - LSL_Vector nor = new LSL_Vector(); - nor.x = v.x / mag; - nor.y = v.y / mag; - nor.z = v.z / mag; - return nor; + return LSL_Vector.Norm(v); } public LSL_Float llVecDist(LSL_Vector a, LSL_Vector b) @@ -470,22 +465,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Now we start getting into quaternions which means sin/cos, matrices and vectors. ckrinke - // Utility function for llRot2Euler - - // normalize an angle between -PI and PI (-180 to +180 degrees) - protected double NormalizeAngle(double angle) - { - if (angle > -Math.PI && angle < Math.PI) - return angle; - - int numPis = (int)(Math.PI / angle); - double remainder = angle - Math.PI * numPis; - if (numPis % 2 == 1) - return Math.PI - angle; - return remainder; - } - - // Old implementation of llRot2Euler, now normalized + // Old implementation of llRot2Euler. Normalization not required as Atan2 function will + // only return values >= -PI (-180 degrees) and <= PI (180 degrees). public LSL_Vector llRot2Euler(LSL_Rotation r) { @@ -497,13 +478,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api double n = 2 * (r.y * r.s + r.x * r.z); double p = m * m - n * n; if (p > 0) - return new LSL_Vector(NormalizeAngle(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s))), - NormalizeAngle(Math.Atan2(n, Math.Sqrt(p))), - NormalizeAngle(Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s)))); + return new LSL_Vector(Math.Atan2(2.0 * (r.x * r.s - r.y * r.z), (-t.x - t.y + t.z + t.s)), + Math.Atan2(n, Math.Sqrt(p)), + Math.Atan2(2.0 * (r.z * r.s - r.x * r.y), (t.x - t.y - t.z + t.s))); else if (n > 0) - return new LSL_Vector(0.0, Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); + return new LSL_Vector(0.0, Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); else - return new LSL_Vector(0.0, -Math.PI * 0.5, NormalizeAngle(Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z))); + return new LSL_Vector(0.0, -Math.PI * 0.5, Math.Atan2((r.z * r.s + r.x * r.y), 0.5 - t.x - t.z)); } /* From wiki: @@ -705,22 +686,75 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { //A and B should both be normalized m_host.AddScriptLPS(1); - double dotProduct = LSL_Vector.Dot(a, b); - LSL_Vector crossProduct = LSL_Vector.Cross(a, b); - double magProduct = LSL_Vector.Mag(a) * LSL_Vector.Mag(b); - double angle = Math.Acos(dotProduct / magProduct); - LSL_Vector axis = LSL_Vector.Norm(crossProduct); - double s = Math.Sin(angle / 2); - - double x = axis.x * s; - double y = axis.y * s; - double z = axis.z * s; - double w = Math.Cos(angle / 2); - - if (Double.IsNaN(x) || Double.IsNaN(y) || Double.IsNaN(z) || Double.IsNaN(w)) - return new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); - - return new LSL_Rotation((float)x, (float)y, (float)z, (float)w); + LSL_Rotation rotBetween; + // Check for zero vectors. If either is zero, return zero rotation. Otherwise, + // continue calculation. + if (a == new LSL_Vector(0.0f, 0.0f, 0.0f) || b == new LSL_Vector(0.0f, 0.0f, 0.0f)) + { + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + a = LSL_Vector.Norm(a); + b = LSL_Vector.Norm(b); + double dotProduct = LSL_Vector.Dot(a, b); + // There are two degenerate cases possible. These are for vectors 180 or + // 0 degrees apart. These have to be detected and handled individually. + // + // Check for vectors 180 degrees apart. + // A dot product of -1 would mean the angle between vectors is 180 degrees. + if (dotProduct < -0.9999999f) + { + // First assume X axis is orthogonal to the vectors. + LSL_Vector orthoVector = new LSL_Vector(1.0f, 0.0f, 0.0f); + orthoVector = orthoVector - a * (a.x / LSL_Vector.Dot(a, a)); + // Check for near zero vector. A very small non-zero number here will create + // a rotation in an undesired direction. + if (LSL_Vector.Mag(orthoVector) > 0.0001) + { + rotBetween = new LSL_Rotation(orthoVector.x, orthoVector.y, orthoVector.z, 0.0f); + } + // If the magnitude of the vector was near zero, then assume the X axis is not + // orthogonal and use the Z axis instead. + else + { + // Set 180 z rotation. + rotBetween = new LSL_Rotation(0.0f, 0.0f, 1.0f, 0.0f); + } + } + // Check for parallel vectors. + // A dot product of 1 would mean the angle between vectors is 0 degrees. + else if (dotProduct > 0.9999999f) + { + // Set zero rotation. + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + else + { + // All special checks have been performed so get the axis of rotation. + LSL_Vector crossProduct = LSL_Vector.Cross(a, b); + // Quarternion s value is the length of the unit vector + dot product. + double qs = 1.0 + dotProduct; + rotBetween = new LSL_Rotation(crossProduct.x, crossProduct.y, crossProduct.z, qs); + // Normalize the rotation. + double mag = LSL_Rotation.Mag(rotBetween); + // We shouldn't have to worry about a divide by zero here. The qs value will be + // non-zero because we already know if we're here, then the dotProduct is not -1 so + // qs will not be zero. Also, we've already handled the input vectors being zero so the + // crossProduct vector should also not be zero. + rotBetween.x = rotBetween.x / mag; + rotBetween.y = rotBetween.y / mag; + rotBetween.z = rotBetween.z / mag; + rotBetween.s = rotBetween.s / mag; + // Check for undefined values and set zero rotation if any found. This code might not actually be required + // any longer since zero vectors are checked for at the top. + if (Double.IsNaN(rotBetween.x) || Double.IsNaN(rotBetween.y) || Double.IsNaN(rotBetween.z) || Double.IsNaN(rotBetween.s)) + { + rotBetween = new LSL_Rotation(0.0f, 0.0f, 0.0f, 1.0f); + } + } + } + return rotBetween; } public void llWhisper(int channelID, string text) @@ -2699,6 +2733,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api // objects rezzed with this method are die_at_edge by default. new_group.RootPart.SetDieAtEdge(true); + new_group.ResumeScripts(); + m_ScriptEngine.PostObjectEvent(m_host.LocalId, new EventParams( "object_rez", new Object[] { new LSL_String( @@ -2890,9 +2926,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api IAttachmentsModule attachmentsModule = m_ScriptEngine.World.AttachmentsModule; if (attachmentsModule != null) - attachmentsModule.AttachObject( - presence.ControllingClient, grp.LocalId, - (uint)attachment, Quaternion.Identity, Vector3.Zero, false); + attachmentsModule.AttachObject(presence.ControllingClient, + grp, (uint)attachment, false); } } @@ -4895,7 +4930,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case ',': if (parens == 0) { - result.Add(src.Substring(start,length).Trim()); + result.Add(new LSL_String(src.Substring(start,length).Trim())); start += length+1; length = 0; } @@ -5824,6 +5859,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api PSYS_PART_MAX_AGE = 7, PSYS_SRC_ACCEL = 8, PSYS_SRC_PATTERN = 9, + PSYS_SRC_INNERANGLE = 10, + PSYS_SRC_OUTERANGLE = 11, PSYS_SRC_TEXTURE = 12, PSYS_SRC_BURST_RATE = 13, PSYS_SRC_BURST_PART_COUNT = 15, @@ -5956,6 +5993,22 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api prules.Pattern = (Primitive.ParticleSystem.SourcePattern)tmpi; break; + // PSYS_SRC_INNERANGLE and PSYS_SRC_ANGLE_BEGIN use the same variables. The + // PSYS_SRC_OUTERANGLE and PSYS_SRC_ANGLE_END also use the same variable. The + // client tells the difference between the two by looking at the 0x02 bit in + // the PartFlags variable. + case (int)ScriptBaseClass.PSYS_SRC_INNERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.InnerAngle = (float)tempf; + prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. + break; + + case (int)ScriptBaseClass.PSYS_SRC_OUTERANGLE: + tempf = (float)rules.GetLSLFloatItem(i + 1); + prules.OuterAngle = (float)tempf; + prules.PartFlags &= 0xFFFFFFFD; // Make sure new angle format is off. + break; + case (int)ScriptBaseClass.PSYS_SRC_TEXTURE: prules.Texture = KeyOrName(rules.GetLSLStringItem(i + 1)); break; @@ -6012,11 +6065,13 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api case (int)ScriptBaseClass.PSYS_SRC_ANGLE_BEGIN: tempf = (float)rules.GetLSLFloatItem(i + 1); prules.InnerAngle = (float)tempf; + prules.PartFlags |= 0x02; // Set new angle format. break; case (int)ScriptBaseClass.PSYS_SRC_ANGLE_END: tempf = (float)rules.GetLSLFloatItem(i + 1); prules.OuterAngle = (float)tempf; + prules.PartFlags |= 0x02; // Set new angle format. break; } @@ -6518,6 +6573,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api if (cut.y - cut.x < 0.05f) { cut.x = cut.y - 0.05f; + if (cut.x < 0.0f) + { + cut.x = 0.0f; + cut.y = 0.05f; + } } shapeBlock.ProfileBegin = (ushort)(50000 * cut.x); shapeBlock.ProfileEnd = (ushort)(50000 * (1 - cut.y)); @@ -6713,9 +6773,14 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api { profilecut.y = 1f; } - if (profilecut.y - cut.x < 0.05f) + if (profilecut.y - profilecut.x < 0.05f) { - profilecut.x = cut.y - 0.05f; + profilecut.x = profilecut.y - 0.05f; + if (profilecut.x < 0.0f) + { + profilecut.x = 0.0f; + profilecut.y = 0.05f; + } } shapeBlock.ProfileBegin = (ushort)(50000 * profilecut.x); shapeBlock.ProfileEnd = (ushort)(50000 * (1 - profilecut.y)); @@ -9788,6 +9853,30 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api ScriptSleep(100); return tid.ToString(); } + + public void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + { + SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return; + + if (obj.OwnerID != m_host.OwnerID) + return; + + SetPrimParams(obj, rules); + } + + public LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules) + { + SceneObjectPart obj = World.GetSceneObjectPart(new UUID(prim)); + if (obj == null) + return new LSL_List(); + + if (obj.OwnerID != m_host.OwnerID) + return new LSL_List(); + + return GetLinkPrimitiveParams(obj, rules); + } } public class NotecardCache diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs similarity index 95% rename from OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs rename to OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs index 880ca1bb7d..fe71ed54cd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/CM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/LS_Api.cs @@ -54,13 +54,13 @@ using LSL_Vector = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Vector3; namespace OpenSim.Region.ScriptEngine.Shared.Api { [Serializable] - public class CM_Api : MarshalByRefObject, ICM_Api, IScriptApi + public class LS_Api : MarshalByRefObject, ILS_Api, IScriptApi { internal IScriptEngine m_ScriptEngine; internal SceneObjectPart m_host; internal uint m_localID; internal UUID m_itemID; - internal bool m_CMFunctionsEnabled = false; + internal bool m_LSFunctionsEnabled = false; internal IScriptModuleComms m_comms = null; public void Initialize(IScriptEngine ScriptEngine, SceneObjectPart host, uint localID, UUID itemID) @@ -70,12 +70,12 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api m_localID = localID; m_itemID = itemID; - if (m_ScriptEngine.Config.GetBoolean("AllowCareminsterFunctions", false)) - m_CMFunctionsEnabled = true; + if (m_ScriptEngine.Config.GetBoolean("AllowLightShareFunctions", false)) + m_LSFunctionsEnabled = true; m_comms = m_ScriptEngine.World.RequestModuleInterface(); if (m_comms == null) - m_CMFunctionsEnabled = false; + m_LSFunctionsEnabled = false; } public override Object InitializeLifetimeService() @@ -100,7 +100,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api //Dumps an error message on the debug console. // - internal void CMShoutError(string message) + internal void LSShoutError(string message) { if (message.Length > 1023) message = message.Substring(0, 1023); @@ -116,11 +116,11 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// Get the current Windlight scene /// /// List of windlight parameters - public LSL_List cmGetWindlightScene(LSL_List rules) + public LSL_List lsGetWindlightScene(LSL_List rules) { - if (!m_CMFunctionsEnabled) + if (!m_LSFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + LSShoutError("LightShare functions are not enabled."); return new LSL_List(); } m_host.AddScriptLPS(1); @@ -440,16 +440,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// /// success: true or false - public int cmSetWindlightScene(LSL_List rules) + public int lsSetWindlightScene(LSL_List rules) { - if (!m_CMFunctionsEnabled) + if (!m_LSFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + LSShoutError("LightShare functions are not enabled."); return 0; } if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { - CMShoutError("cmSetWindlightScene can only be used by estate managers or owners."); + LSShoutError("lsSetWindlightScene can only be used by estate managers or owners."); return 0; } int success = 0; @@ -462,7 +462,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - CMShoutError("Windlight module is disabled"); + LSShoutError("Windlight module is disabled"); return 0; } return success; @@ -472,16 +472,16 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api /// /// /// success: true or false - public int cmSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) + public int lsSetWindlightSceneTargeted(LSL_List rules, LSL_Key target) { - if (!m_CMFunctionsEnabled) + if (!m_LSFunctionsEnabled) { - CMShoutError("Careminster functions are not enabled."); + LSShoutError("LightShare functions are not enabled."); return 0; } if (!World.RegionInfo.EstateSettings.IsEstateManager(m_host.OwnerID) && World.GetScenePresence(m_host.OwnerID).GodLevel < 200) { - CMShoutError("cmSetWindlightSceneTargeted can only be used by estate managers or owners."); + LSShoutError("lsSetWindlightSceneTargeted can only be used by estate managers or owners."); return 0; } int success = 0; @@ -494,7 +494,7 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } else { - CMShoutError("Windlight module is disabled"); + LSShoutError("Windlight module is disabled"); return 0; } return success; diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs index 7ada738084..01b64eb08f 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Implementation/OSSL_Api.cs @@ -2186,5 +2186,45 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api } } } + + public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); + m_host.AddScriptLPS(1); + + return m_LSL_Api.GetLinkPrimitiveParamsEx(prim, rules); + } + + public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + CheckThreatLevel(ThreatLevel.High, "osGetPrimitiveParams"); + m_host.AddScriptLPS(1); + + m_LSL_Api.SetPrimitiveParamsEx(prim, rules); + } + + /// + /// Like osGetAgents but returns enough info for a radar + /// + /// Strided list of the UUID, position and name of each avatar in the region + public LSL_List osGetAvatarList() + { + CheckThreatLevel(ThreatLevel.None, "osGetAvatarList"); + + LSL_List result = new LSL_List(); + World.ForEachScenePresence(delegate (ScenePresence avatar) + { + if (avatar != null && avatar.UUID != m_host.OwnerID) + { + if (avatar.IsChildAgent == false) + { + result.Add(avatar.UUID); + result.Add(avatar.AbsolutePosition); + result.Add(avatar.Name); + } + } + }); + return result; + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs index 7ab04a3cbb..cba46a36c7 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILSL_Api.cs @@ -395,5 +395,8 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces LSL_Vector llWind(LSL_Vector offset); LSL_String llXorBase64Strings(string str1, string str2); LSL_String llXorBase64StringsCorrect(string str1, string str2); + + void SetPrimitiveParamsEx(LSL_Key prim, LSL_List rules); + LSL_List GetLinkPrimitiveParamsEx(LSL_Key prim, LSL_List rules); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs similarity index 92% rename from OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs rename to OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs index f13b6e50e3..9aa437b37e 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ICM_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/ILS_Api.cs @@ -38,11 +38,11 @@ using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { - public interface ICM_Api + public interface ILS_Api { // Windlight Functions - LSL_List cmGetWindlightScene(LSL_List rules); - int cmSetWindlightScene(LSL_List rules); - int cmSetWindlightSceneTargeted(LSL_List rules, key target); + LSL_List lsGetWindlightScene(LSL_List rules); + int lsSetWindlightScene(LSL_List rules); + int lsSetWindlightSceneTargeted(LSL_List rules, key target); } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs index 7a8f469746..78ee43cc08 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Interface/IOSSL_Api.cs @@ -35,6 +35,7 @@ using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces { @@ -173,5 +174,9 @@ namespace OpenSim.Region.ScriptEngine.Shared.Api.Interfaces void osSetSpeed(string UUID, float SpeedModifier); void osCauseHealing(string avatar, double healing); void osCauseDamage(string avatar, double damage); + LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules); + void osSetPrimitiveParams(LSL_Key prim, LSL_List rules); + LSL_List osGetAvatarList(); + } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs similarity index 84% rename from OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs rename to OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs index c0edaae6bc..f8dbe03ccc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/CM_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/LS_Stub.cs @@ -48,29 +48,29 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { public partial class ScriptBaseClass : MarshalByRefObject { - public ICM_Api m_CM_Functions; + public ILS_Api m_LS_Functions; - public void ApiTypeCM(IScriptApi api) + public void ApiTypeLS(IScriptApi api) { - if (!(api is ICM_Api)) + if (!(api is ILS_Api)) return; - m_CM_Functions = (ICM_Api)api; + m_LS_Functions = (ILS_Api)api; } - public LSL_List cmGetWindlightScene(LSL_List rules) + public LSL_List lsGetWindlightScene(LSL_List rules) { - return m_CM_Functions.cmGetWindlightScene(rules); + return m_LS_Functions.lsGetWindlightScene(rules); } - public int cmSetWindlightScene(LSL_List rules) + public int lsSetWindlightScene(LSL_List rules) { - return m_CM_Functions.cmSetWindlightScene(rules); + return m_LS_Functions.lsSetWindlightScene(rules); } - public int cmSetWindlightSceneTargeted(LSL_List rules, key target) + public int lsSetWindlightSceneTargeted(LSL_List rules, key target) { - return m_CM_Functions.cmSetWindlightSceneTargeted(rules, target); + return m_LS_Functions.lsSetWindlightSceneTargeted(rules, target); } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs index fd9309aefc..6cc5f518ae 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OSSL_Stub.cs @@ -41,6 +41,7 @@ using rotation = OpenSim.Region.ScriptEngine.Shared.LSL_Types.Quaternion; using key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_List = OpenSim.Region.ScriptEngine.Shared.LSL_Types.list; using LSL_String = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; +using LSL_Key = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLString; using LSL_Float = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLFloat; using LSL_Integer = OpenSim.Region.ScriptEngine.Shared.LSL_Types.LSLInteger; @@ -678,5 +679,18 @@ namespace OpenSim.Region.ScriptEngine.Shared.ScriptBase { m_OSSL_Functions.osCauseHealing(avatar, healing); } + public LSL_List osGetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + return m_OSSL_Functions.osGetPrimitiveParams(prim, rules); + } + public void osSetPrimitiveParams(LSL_Key prim, LSL_List rules) + { + m_OSSL_Functions.osSetPrimitiveParams(prim, rules); + } + + public LSL_List osGetAvatarList() + { + return m_OSSL_Functions.osGetAvatarList(); + } } } diff --git a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp index 23138efc4a..f02d2d90dc 100644 --- a/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp +++ b/OpenSim/Region/ScriptEngine/Shared/Api/Runtime/OpenSim.Region.ScriptEngine.Shared.Api.Runtime.mdp @@ -18,10 +18,10 @@ - + diff --git a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs index 1ea52c5c4e..91e03acccd 100644 --- a/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs +++ b/OpenSim/Region/ScriptEngine/Shared/LSL_Types.cs @@ -262,7 +262,12 @@ namespace OpenSim.Region.ScriptEngine.Shared public static Vector3 Norm(Vector3 vector) { double mag = Mag(vector); - return new Vector3(vector.x / mag, vector.y / mag, vector.z / mag); + if (mag > 0.0) + { + double invMag = 1.0 / mag; + return vector * invMag; + } + return new Vector3(0, 0, 0); } #endregion @@ -663,13 +668,13 @@ namespace OpenSim.Region.ScriptEngine.Shared Object[] ret; if (start < 0) - start=m_data.Length-start; + start=m_data.Length+start; if (start < 0) start=0; if (end < 0) - end=m_data.Length-end; + end=m_data.Length+end; if (end < 0) end=0; diff --git a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs index 09b79d07f2..0ac8b5c043 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/EventManager.cs @@ -356,9 +356,9 @@ namespace OpenSim.Region.ScriptEngine.XEngine // timer: not handled here // listen: not handled here - public void control(uint localID, UUID itemID, UUID agentID, uint held, uint change) + public void control(UUID itemID, UUID agentID, uint held, uint change) { - myScriptEngine.PostObjectEvent(localID, new EventParams( + myScriptEngine.PostScriptEvent(itemID, new EventParams( "control",new object[] { new LSL_Types.LSLString(agentID.ToString()), new LSL_Types.LSLInteger(held), diff --git a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs index 54074ed4fd..02993856fd 100644 --- a/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs +++ b/OpenSim/Region/ScriptEngine/XEngine/XEngine.cs @@ -122,6 +122,7 @@ namespace OpenSim.Region.ScriptEngine.XEngine private ScriptCompileQueue m_CompileQueue = new ScriptCompileQueue(); IWorkItemResult m_CurrentCompile = null; + private Dictionary m_CompileDict = new Dictionary(); public string ScriptEngineName { @@ -487,11 +488,20 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (stateSource == (int)StateSource.ScriptedRez) { + lock (m_CompileDict) + { + m_CompileDict[itemID] = 0; + } + DoOnRezScript(parms); } else { m_CompileQueue.Enqueue(parms); + lock (m_CompileDict) + { + m_CompileDict[itemID] = 0; + } if (m_CurrentCompile == null) { @@ -554,6 +564,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine bool postOnRez = (bool)p[4]; StateSource stateSource = (StateSource)p[5]; + lock(m_CompileDict) + { + if (!m_CompileDict.ContainsKey(itemID)) + return false; + m_CompileDict.Remove(itemID); + } + // Get the asset ID of the script, so we can check if we // already have it. @@ -753,8 +770,10 @@ namespace OpenSim.Region.ScriptEngine.XEngine item.Name, startParam, postOnRez, stateSource, m_MaxScriptQueue); - m_log.DebugFormat("[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}", - part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, part.ParentGroup.RootPart.AbsolutePosition.ToString()); + m_log.DebugFormat( + "[XEngine] Loaded script {0}.{1}, script UUID {2}, prim UUID {3} @ {4}.{5}", + part.ParentGroup.RootPart.Name, item.Name, assetID, part.UUID, + part.ParentGroup.RootPart.AbsolutePosition, part.ParentGroup.Scene.RegionInfo.RegionName); if (presence != null) { @@ -794,6 +813,13 @@ namespace OpenSim.Region.ScriptEngine.XEngine public void OnRemoveScript(uint localID, UUID itemID) { + // If it's not yet been compiled, make sure we don't try + lock (m_CompileDict) + { + if (m_CompileDict.ContainsKey(itemID)) + m_CompileDict.Remove(itemID); + } + lock (m_Scripts) { // Do we even have it? @@ -1255,9 +1281,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine string xml = instance.GetXMLState(); XmlDocument sdoc = new XmlDocument(); - sdoc.LoadXml(xml); - XmlNodeList rootL = sdoc.GetElementsByTagName("ScriptState"); - XmlNode rootNode = rootL[0]; + bool loadedState = true; + try + { + sdoc.LoadXml(xml); + } + catch (System.Xml.XmlException e) + { + loadedState = false; + } + + XmlNodeList rootL = null; + XmlNode rootNode = null; + if (loadedState) + { + rootL = sdoc.GetElementsByTagName("ScriptState"); + rootNode = rootL[0]; + } // Create XmlDocument doc = new XmlDocument(); @@ -1273,8 +1313,18 @@ namespace OpenSim.Region.ScriptEngine.XEngine stateData.Attributes.Append(engineName); doc.AppendChild(stateData); + XmlNode xmlstate = null; + // Add ... - XmlNode xmlstate = doc.ImportNode(rootNode, true); + if (loadedState) + { + xmlstate = doc.ImportNode(rootNode, true); + } + else + { + xmlstate = doc.CreateElement("", "ScriptState", ""); + } + stateData.AppendChild(xmlstate); string assemName = instance.GetAssemblyName(); @@ -1293,10 +1343,12 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { - FileStream tfs = File.Open(assemName + ".text", - FileMode.Open, FileAccess.Read); - tfs.Read(tdata, 0, tdata.Length); - tfs.Close(); + using (FileStream tfs = File.Open(assemName + ".text", + FileMode.Open, FileAccess.Read)) + { + tfs.Read(tdata, 0, tdata.Length); + tfs.Close(); + } assem = new System.Text.ASCIIEncoding().GetString(tdata); } @@ -1316,9 +1368,11 @@ namespace OpenSim.Region.ScriptEngine.XEngine try { - FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read); - fs.Read(data, 0, data.Length); - fs.Close(); + using (FileStream fs = File.Open(assemName, FileMode.Open, FileAccess.Read)) + { + fs.Read(data, 0, data.Length); + fs.Close(); + } assem = System.Convert.ToBase64String(data); } @@ -1334,13 +1388,15 @@ namespace OpenSim.Region.ScriptEngine.XEngine if (File.Exists(fn + ".map")) { - FileStream mfs = File.Open(fn + ".map", FileMode.Open, FileAccess.Read); - StreamReader msr = new StreamReader(mfs); - - map = msr.ReadToEnd(); - - msr.Close(); - mfs.Close(); + using (FileStream mfs = File.Open(fn + ".map", FileMode.Open, FileAccess.Read)) + { + using (StreamReader msr = new StreamReader(mfs)) + { + map = msr.ReadToEnd(); + msr.Close(); + } + mfs.Close(); + } } XmlElement assemblyData = doc.CreateElement("", "Assembly", ""); @@ -1428,30 +1484,59 @@ namespace OpenSim.Region.ScriptEngine.XEngine { Byte[] filedata = Convert.FromBase64String(base64); - FileStream fs = File.Create(path); - fs.Write(filedata, 0, filedata.Length); - fs.Close(); - - fs = File.Create(path + ".text"); - StreamWriter sw = new StreamWriter(fs); - - sw.Write(base64); - - sw.Close(); - fs.Close(); + try + { + using (FileStream fs = File.Create(path)) + { + fs.Write(filedata, 0, filedata.Length); + fs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); + } + try + { + using (FileStream fs = File.Create(path + ".text")) + { + using (StreamWriter sw = new StreamWriter(fs)) + { + sw.Write(base64); + sw.Close(); + } + fs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", path, ex.Message); + } } } string statepath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); statepath = Path.Combine(statepath, itemID.ToString() + ".state"); - FileStream sfs = File.Create(statepath); - StreamWriter ssw = new StreamWriter(sfs); - - ssw.Write(stateE.OuterXml); - - ssw.Close(); - sfs.Close(); + try + { + using (FileStream sfs = File.Create(statepath)) + { + using (StreamWriter ssw = new StreamWriter(sfs)) + { + ssw.Write(stateE.OuterXml); + ssw.Close(); + } + sfs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); + } XmlNodeList mapL = rootE.GetElementsByTagName("LineMap"); if (mapL.Count > 0) @@ -1461,13 +1546,23 @@ namespace OpenSim.Region.ScriptEngine.XEngine string mappath = Path.Combine("ScriptEngines", World.RegionInfo.RegionID.ToString()); mappath = Path.Combine(mappath, mapE.GetAttribute("Filename")); - FileStream mfs = File.Create(mappath); - StreamWriter msw = new StreamWriter(mfs); - - msw.Write(mapE.InnerText); - - msw.Close(); - mfs.Close(); + try + { + using (FileStream mfs = File.Create(mappath)) + { + using (StreamWriter msw = new StreamWriter(mfs)) + { + msw.Write(mapE.InnerText); + msw.Close(); + } + mfs.Close(); + } + } + catch (IOException ex) + { + // if there already exists a file at that location, it may be locked. + m_log.ErrorFormat("[XEngine]: File {0} already exists! {1}", statepath, ex.Message); + } } return true; diff --git a/OpenSim/Server/Base/ServicesServerBase.cs b/OpenSim/Server/Base/ServicesServerBase.cs index 63ba67310d..dee31bdf58 100644 --- a/OpenSim/Server/Base/ServicesServerBase.cs +++ b/OpenSim/Server/Base/ServicesServerBase.cs @@ -230,12 +230,23 @@ namespace OpenSim.Server.Base "shutdown", "Quit the application", HandleQuit); + // Register a command to read other commands from a file + MainConsole.Instance.Commands.AddCommand("base", false, "command-script", + "command-script