aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
authorMelanie2011-03-27 21:22:31 +0100
committerMelanie2011-03-27 21:22:31 +0100
commitf25749f0259bdfe334f77ab049ac5f892135bbc6 (patch)
tree5fd38027cbe794a1da1d87009f9975d3792f085a /OpenSim/Region
parentDon't send a windlight profile to clients if windlight is not set for (diff)
parentAdd SignpostMarv to contributors (diff)
downloadopensim-SC-f25749f0259bdfe334f77ab049ac5f892135bbc6.zip
opensim-SC-f25749f0259bdfe334f77ab049ac5f892135bbc6.tar.gz
opensim-SC-f25749f0259bdfe334f77ab049ac5f892135bbc6.tar.bz2
opensim-SC-f25749f0259bdfe334f77ab049ac5f892135bbc6.tar.xz
Merge branch 'master' of melanie@opensimulator.org:/var/git/opensim
Diffstat (limited to 'OpenSim/Region')
-rw-r--r--OpenSim/Region/Application/OpenSimBase.cs125
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs45
-rw-r--r--OpenSim/Region/CoreModules/World/Land/LandObject.cs4
-rw-r--r--OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs61
-rw-r--r--OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs131
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateDataService.cs58
-rw-r--r--OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs62
-rw-r--r--OpenSim/Region/Framework/Interfaces/ILandObject.cs5
-rw-r--r--OpenSim/Region/Framework/Scenes/EventManager.cs30
-rw-r--r--OpenSim/Region/Framework/Scenes/Scene.cs20
-rw-r--r--OpenSim/Region/Framework/Scenes/SceneGraph.cs119
11 files changed, 557 insertions, 103 deletions
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index e950613..6405811 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -793,66 +793,115 @@ namespace OpenSim
793 } 793 }
794 794
795 /// <summary> 795 /// <summary>
796 /// Load the estate information for the provided RegionInfo object. 796 /// Create an estate with an initial region.
797 /// </summary> 797 /// </summary>
798 /// <remarks>
799 /// This method doesn't allow an estate to be created with the same name as existing estates.
800 /// </remarks>
798 /// <param name="regInfo"></param> 801 /// <param name="regInfo"></param>
799 public void PopulateRegionEstateInfo(RegionInfo regInfo) 802 /// <param name="existingName">A list of estate names that already exist.</param>
803 /// <returns>true if the estate was created, false otherwise</returns>
804 public bool CreateEstate(RegionInfo regInfo, List<string> existingNames)
800 { 805 {
801 IEstateDataService estateDataService = EstateDataService; 806 // Create a new estate
807 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
808 string newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
802 809
803 if (estateDataService != null) 810 if (existingNames.Contains(newName))
804 { 811 {
805 regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, false); 812 MainConsole.Instance.OutputFormat("An estate named {0} already exists. Please try again.", newName);
813 return false;
806 } 814 }
815
816 regInfo.EstateSettings.EstateName = newName;
817
818 // FIXME: Later on, the scene constructor will reload the estate settings no matter what.
819 // Therefore, we need to do an initial save here otherwise the new estate name will be reset
820 // back to the default. The reloading of estate settings by scene could be eliminated if it
821 // knows that the passed in settings in RegionInfo are already valid. Also, it might be
822 // possible to eliminate some additional later saves made by callers of this method.
823 regInfo.EstateSettings.Save();
824
825 return true;
826 }
827
828 /// <summary>
829 /// Load the estate information for the provided RegionInfo object.
830 /// </summary>
831 /// <param name="regInfo"></param>
832 public void PopulateRegionEstateInfo(RegionInfo regInfo)
833 {
834 if (EstateDataService != null)
835 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false);
807 836
808 if (regInfo.EstateSettings.EstateID == 0) // No record at all 837 if (regInfo.EstateSettings.EstateID == 0) // No record at all
809 { 838 {
810 MainConsole.Instance.Output("Your region is not part of an estate."); 839 MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName);
840
841 List<EstateSettings> estates = EstateDataService.LoadEstateSettingsAll();
842 List<string> estateNames = new List<string>();
843 foreach (EstateSettings estate in estates)
844 estateNames.Add(estate.EstateName);
845
811 while (true) 846 while (true)
812 { 847 {
813 string response = MainConsole.Instance.CmdPrompt("Do you wish to join an existing estate?", "no", new List<string>() { "yes", "no" }); 848 if (estates.Count == 0)
814 if (response == "no") 849 {
815 { 850 MainConsole.Instance.Output("No existing estates found. You must create a new one.");
816 // Create a new estate
817 regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, true);
818
819 regInfo.EstateSettings.EstateName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
820 851
821 // FIXME: Later on, the scene constructor will reload the estate settings no matter what. 852 if (CreateEstate(regInfo, estateNames))
822 // Therefore, we need to do an initial save here otherwise the new estate name will be reset 853 break;
823 // back to the default. The reloading of estate settings by scene could be eliminated if it 854 else
824 // knows that the passed in settings in RegionInfo are already valid. Also, it might be 855 continue;
825 // possible to eliminate some additional later saves made by callers of this method.
826 regInfo.EstateSettings.Save();
827 break;
828 } 856 }
829 else 857 else
830 { 858 {
831 response = MainConsole.Instance.CmdPrompt("Estate name to join", "None"); 859 string response
832 if (response == "None") 860 = MainConsole.Instance.CmdPrompt(
833 continue; 861 string.Format(
834 862 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
835 List<int> estateIDs = estateDataService.GetEstates(response); 863 "no",
836 if (estateIDs.Count < 1) 864 new List<string>() { "yes", "no" });
865
866 if (response == "no")
837 { 867 {
838 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again"); 868 if (CreateEstate(regInfo, estateNames))
839 continue; 869 break;
870 else
871 continue;
872 }
873 else
874 {
875 response
876 = MainConsole.Instance.CmdPrompt(
877 string.Format(
878 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())),
879 "None");
880
881 if (response == "None")
882 continue;
883
884 List<int> estateIDs = EstateDataService.GetEstates(response);
885 if (estateIDs.Count < 1)
886 {
887 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
888 continue;
889 }
890
891 int estateID = estateIDs[0];
892
893 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID);
894
895 if (EstateDataService.LinkRegion(regInfo.RegionID, estateID))
896 break;
897
898 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
840 } 899 }
841
842 int estateID = estateIDs[0];
843
844 regInfo.EstateSettings = estateDataService.LoadEstateSettings(estateID);
845
846 if (estateDataService.LinkRegion(regInfo.RegionID, estateID))
847 break;
848
849 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
850 } 900 }
851 } 901 }
852 } 902 }
853 } 903 }
854 } 904 }
855
856 905
857 public class OpenSimConfigSource 906 public class OpenSimConfigSource
858 { 907 {
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index 98ba8c3..d0727d9 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
@@ -72,6 +72,7 @@ namespace OpenSim.Region.CoreModules.World.Land
72 protected Commander m_commander = new Commander("land"); 72 protected Commander m_commander = new Commander("land");
73 73
74 protected IUserManagement m_userManager; 74 protected IUserManagement m_userManager;
75 protected IPrimCountModule m_primCountModule;
75 76
76 // Minimum for parcels to work is 64m even if we don't actually use them. 77 // Minimum for parcels to work is 64m even if we don't actually use them.
77 #pragma warning disable 0429 78 #pragma warning disable 0429
@@ -147,6 +148,7 @@ namespace OpenSim.Region.CoreModules.World.Land
147 public void RegionLoaded(Scene scene) 148 public void RegionLoaded(Scene scene)
148 { 149 {
149 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 150 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
151 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
150 } 152 }
151 153
152 public void RemoveRegion(Scene scene) 154 public void RemoveRegion(Scene scene)
@@ -306,10 +308,14 @@ namespace OpenSim.Region.CoreModules.World.Land
306 /// <returns>The parcel created.</returns> 308 /// <returns>The parcel created.</returns>
307 protected ILandObject CreateDefaultParcel() 309 protected ILandObject CreateDefaultParcel()
308 { 310 {
309 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 311// m_log.DebugFormat(
312// "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
313
314 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
310 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 315 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
311 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 316 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
312 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 317 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
318
313 return AddLandObject(fullSimParcel); 319 return AddLandObject(fullSimParcel);
314 } 320 }
315 321
@@ -579,7 +585,7 @@ namespace OpenSim.Region.CoreModules.World.Land
579 } 585 }
580 else 586 else
581 { 587 {
582 m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID); 588 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid local land ID {0}", landLocalID);
583 } 589 }
584 } 590 }
585 591
@@ -590,6 +596,11 @@ namespace OpenSim.Region.CoreModules.World.Land
590 public ILandObject AddLandObject(ILandObject land) 596 public ILandObject AddLandObject(ILandObject land)
591 { 597 {
592 ILandObject new_land = land.Copy(); 598 ILandObject new_land = land.Copy();
599
600 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
601 // as a random UUID inside LandData initialization
602 if (m_primCountModule != null)
603 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID);
593 604
594 lock (m_landList) 605 lock (m_landList)
595 { 606 {
@@ -630,7 +641,7 @@ namespace OpenSim.Region.CoreModules.World.Land
630 { 641 {
631 if (m_landIDList[x, y] == local_id) 642 if (m_landIDList[x, y] == local_id)
632 { 643 {
633 m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}", 644 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Not removing land object {0}; still being used at {1}, {2}",
634 local_id, x, y); 645 local_id, x, y);
635 return; 646 return;
636 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); 647 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
@@ -851,6 +862,10 @@ namespace OpenSim.Region.CoreModules.World.Land
851 862
852 public void EventManagerOnParcelPrimCountUpdate() 863 public void EventManagerOnParcelPrimCountUpdate()
853 { 864 {
865// m_log.DebugFormat(
866// "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}",
867// m_scene.RegionInfo.RegionName);
868
854 ResetAllLandPrimCounts(); 869 ResetAllLandPrimCounts();
855 EntityBase[] entities = m_scene.Entities.GetEntities(); 870 EntityBase[] entities = m_scene.Entities.GetEntities();
856 foreach (EntityBase obj in entities) 871 foreach (EntityBase obj in entities)
@@ -1198,7 +1213,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1198 } 1213 }
1199 else 1214 else
1200 { 1215 {
1201 m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id); 1216 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid land object {0} passed for parcel object owner request", local_id);
1202 } 1217 }
1203 } 1218 }
1204 1219
@@ -1361,7 +1376,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1361 { 1376 {
1362 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1377 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1363 new_land.LandData = data.Copy(); 1378 new_land.LandData = data.Copy();
1364 new_land.SetLandBitmapFromByteArray(); 1379 new_land.SetLandBitmapFromByteArray();
1365 AddLandObject(new_land); 1380 AddLandObject(new_land);
1366 } 1381 }
1367 1382
@@ -1426,7 +1441,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1426 { 1441 {
1427 IClientAPI client; 1442 IClientAPI client;
1428 if (! m_scene.TryGetClient(agentID, out client)) { 1443 if (! m_scene.TryGetClient(agentID, out client)) {
1429 m_log.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString()); 1444 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID);
1430 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1445 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1431 } 1446 }
1432 1447
@@ -1475,7 +1490,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1475 } 1490 }
1476 else 1491 else
1477 { 1492 {
1478 m_log.WarnFormat("[LAND] unable to find parcelID {0}", parcelID); 1493 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1479 } 1494 }
1480 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1495 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1481 } 1496 }
@@ -1533,17 +1548,17 @@ namespace OpenSim.Region.CoreModules.World.Land
1533 } 1548 }
1534 catch (LLSD.LLSDParseException e) 1549 catch (LLSD.LLSDParseException e)
1535 { 1550 {
1536 m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message); 1551 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Fetch error: {0}", e.Message);
1537 m_log.ErrorFormat("[LAND] ... in request {0}", request); 1552 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: ... in request {0}", request);
1538 } 1553 }
1539 catch(InvalidCastException) 1554 catch (InvalidCastException)
1540 { 1555 {
1541 m_log.ErrorFormat("[LAND] Wrong type in request {0}", request); 1556 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Wrong type in request {0}", request);
1542 } 1557 }
1543 1558
1544 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); 1559 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
1545 response.parcel_id = parcelID; 1560 response.parcel_id = parcelID;
1546 m_log.DebugFormat("[LAND] got parcelID {0}", parcelID); 1561 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID);
1547 1562
1548 return LLSDHelpers.SerialiseLLSDReply(response); 1563 return LLSDHelpers.SerialiseLLSDReply(response);
1549 } 1564 }
@@ -1564,7 +1579,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1564 ExtendedLandData extLandData = new ExtendedLandData(); 1579 ExtendedLandData extLandData = new ExtendedLandData();
1565 Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, 1580 Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle,
1566 out extLandData.X, out extLandData.Y); 1581 out extLandData.X, out extLandData.Y);
1567 m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", 1582 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
1568 extLandData.RegionHandle, extLandData.X, extLandData.Y); 1583 extLandData.RegionHandle, extLandData.X, extLandData.Y);
1569 1584
1570 // for this region or for somewhere else? 1585 // for this region or for somewhere else?
@@ -1605,7 +1620,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1605 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 1620 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
1606 } 1621 }
1607 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. 1622 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
1608 m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...", 1623 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: got parcelinfo for parcel {0} in region {1}; sending...",
1609 data.LandData.Name, data.RegionHandle); 1624 data.LandData.Name, data.RegionHandle);
1610 // HACK for now 1625 // HACK for now
1611 RegionInfo r = new RegionInfo(); 1626 RegionInfo r = new RegionInfo();
@@ -1616,7 +1631,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1616 remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y); 1631 remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y);
1617 } 1632 }
1618 else 1633 else
1619 m_log.Debug("[LAND] got no parcelinfo; not sending"); 1634 m_log.Debug("[LAND MANAGEMENT MODULE]: got no parcelinfo; not sending");
1620 } 1635 }
1621 1636
1622 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) 1637 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime)
diff --git a/OpenSim/Region/CoreModules/World/Land/LandObject.cs b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
index 46c15ed..749bb3d 100644
--- a/OpenSim/Region/CoreModules/World/Land/LandObject.cs
+++ b/OpenSim/Region/CoreModules/World/Land/LandObject.cs
@@ -51,7 +51,7 @@ namespace OpenSim.Region.CoreModules.World.Land
51 51
52 private int m_lastSeqId = 0; 52 private int m_lastSeqId = 0;
53 53
54 protected LandData m_landData = new LandData(); 54 protected LandData m_landData = new LandData();
55 protected Scene m_scene; 55 protected Scene m_scene;
56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>(); 56 protected List<SceneObjectGroup> primsOverMe = new List<SceneObjectGroup>();
57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>(); 57 protected Dictionary<uint, UUID> m_listTransactions = new Dictionary<uint, UUID>();
@@ -79,6 +79,8 @@ namespace OpenSim.Region.CoreModules.World.Land
79 79
80 set { m_landData = value; } 80 set { m_landData = value; }
81 } 81 }
82
83 public IPrimCounts PrimCounts { get; set; }
82 84
83 public UUID RegionUUID 85 public UUID RegionUUID
84 { 86 {
diff --git a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
index 34ef67f..9fd347e 100644
--- a/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
+++ b/OpenSim/Region/CoreModules/World/Land/PrimCountModule.cs
@@ -51,8 +51,8 @@ namespace OpenSim.Region.CoreModules.World.Land
51 51
52 public class PrimCountModule : IPrimCountModule, INonSharedRegionModule 52 public class PrimCountModule : IPrimCountModule, INonSharedRegionModule
53 { 53 {
54 private static readonly ILog m_log = 54// private static readonly ILog m_log =
55 LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType); 55// LogManager.GetLogger(MethodBase.GetCurrentMethod().DeclaringType);
56 56
57 private Scene m_Scene; 57 private Scene m_Scene;
58 private Dictionary<UUID, PrimCounts> m_PrimCounts = 58 private Dictionary<UUID, PrimCounts> m_PrimCounts =
@@ -64,10 +64,16 @@ namespace OpenSim.Region.CoreModules.World.Land
64 private Dictionary<UUID, ParcelCounts> m_ParcelCounts = 64 private Dictionary<UUID, ParcelCounts> m_ParcelCounts =
65 new Dictionary<UUID, ParcelCounts>(); 65 new Dictionary<UUID, ParcelCounts>();
66 66
67 // For now, a simple simwide taint to get this up. Later parcel based 67
68 // taint to allow recounting a parcel if only ownership has changed 68 /// <value>
69 // without recounting the whole sim. 69 /// For now, a simple simwide taint to get this up. Later parcel based
70 /// taint to allow recounting a parcel if only ownership has changed
71 /// without recounting the whole sim.
72 ///
73 /// We start out tainted so that the first get call resets the various prim counts.
74 /// <value>
70 private bool m_Tainted = true; 75 private bool m_Tainted = true;
76
71 private Object m_TaintLock = new Object(); 77 private Object m_TaintLock = new Object();
72 78
73 public Type ReplaceableInterface 79 public Type ReplaceableInterface
@@ -82,9 +88,10 @@ namespace OpenSim.Region.CoreModules.World.Land
82 public void AddRegion(Scene scene) 88 public void AddRegion(Scene scene)
83 { 89 {
84 m_Scene = scene; 90 m_Scene = scene;
91
92 m_Scene.RegisterModuleInterface<IPrimCountModule>(this);
85 93
86 m_Scene.EventManager.OnParcelPrimCountAdd += 94 m_Scene.EventManager.OnObjectAddedToScene += OnParcelPrimCountAdd;
87 OnParcelPrimCountAdd;
88 m_Scene.EventManager.OnObjectBeingRemovedFromScene += 95 m_Scene.EventManager.OnObjectBeingRemovedFromScene +=
89 OnObjectBeingRemovedFromScene; 96 OnObjectBeingRemovedFromScene;
90 m_Scene.EventManager.OnParcelPrimCountTainted += 97 m_Scene.EventManager.OnParcelPrimCountTainted +=
@@ -156,6 +163,8 @@ namespace OpenSim.Region.CoreModules.World.Land
156 // NOTE: Call under Taint Lock 163 // NOTE: Call under Taint Lock
157 private void AddObject(SceneObjectGroup obj) 164 private void AddObject(SceneObjectGroup obj)
158 { 165 {
166// m_log.DebugFormat("[PRIM COUNT MODULE]: Adding object {0} to prim count", obj.Name);
167
159 if (obj.IsAttachment) 168 if (obj.IsAttachment)
160 return; 169 return;
161 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0)) 170 if (((obj.RootPart.Flags & PrimFlags.TemporaryOnRez) != 0))
@@ -164,6 +173,10 @@ namespace OpenSim.Region.CoreModules.World.Land
164 Vector3 pos = obj.AbsolutePosition; 173 Vector3 pos = obj.AbsolutePosition;
165 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y); 174 ILandObject landObject = m_Scene.LandChannel.GetLandObject(pos.X, pos.Y);
166 LandData landData = landObject.LandData; 175 LandData landData = landObject.LandData;
176
177// m_log.DebugFormat(
178// "[PRIM COUNT MODULE]: Object {0} is owned by {1} over land owned by {2}",
179// obj.Name, obj.OwnerID, landData.OwnerID);
167 180
168 ParcelCounts parcelCounts; 181 ParcelCounts parcelCounts;
169 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts)) 182 if (m_ParcelCounts.TryGetValue(landData.GlobalID, out parcelCounts))
@@ -218,8 +231,16 @@ namespace OpenSim.Region.CoreModules.World.Land
218 return primCounts; 231 return primCounts;
219 } 232 }
220 233
234
235 /// <summary>
236 /// Get the number of prims on the parcel that are owned by the parcel owner.
237 /// </summary>
238 /// <param name="parcelID"></param>
239 /// <returns></returns>
221 public int GetOwnerCount(UUID parcelID) 240 public int GetOwnerCount(UUID parcelID)
222 { 241 {
242// m_log.DebugFormat("[PRIM COUNT MODULE]: GetOwnerCount for {0}", parcelID);
243
223 lock (m_TaintLock) 244 lock (m_TaintLock)
224 { 245 {
225 if (m_Tainted) 246 if (m_Tainted)
@@ -232,6 +253,11 @@ namespace OpenSim.Region.CoreModules.World.Land
232 return 0; 253 return 0;
233 } 254 }
234 255
256 /// <summary>
257 /// Get the number of prims on the parcel that have been set to the group that owns the parcel.
258 /// </summary>
259 /// <param name="parcelID"></param>
260 /// <returns></returns>
235 public int GetGroupCount(UUID parcelID) 261 public int GetGroupCount(UUID parcelID)
236 { 262 {
237 lock (m_TaintLock) 263 lock (m_TaintLock)
@@ -246,6 +272,11 @@ namespace OpenSim.Region.CoreModules.World.Land
246 return 0; 272 return 0;
247 } 273 }
248 274
275 /// <summary>
276 /// Get the number of prims on the parcel that are not owned by the parcel owner or set to the parcel group.
277 /// </summary>
278 /// <param name="parcelID"></param>
279 /// <returns></returns>
249 public int GetOthersCount(UUID parcelID) 280 public int GetOthersCount(UUID parcelID)
250 { 281 {
251 lock (m_TaintLock) 282 lock (m_TaintLock)
@@ -260,6 +291,11 @@ namespace OpenSim.Region.CoreModules.World.Land
260 return 0; 291 return 0;
261 } 292 }
262 293
294 /// <summary>
295 /// Get the number of prims that are in the entire simulator for the owner of this parcel.
296 /// </summary>
297 /// <param name="parcelID"></param>
298 /// <returns></returns>
263 public int GetSimulatorCount(UUID parcelID) 299 public int GetSimulatorCount(UUID parcelID)
264 { 300 {
265 lock (m_TaintLock) 301 lock (m_TaintLock)
@@ -278,6 +314,12 @@ namespace OpenSim.Region.CoreModules.World.Land
278 return 0; 314 return 0;
279 } 315 }
280 316
317 /// <summary>
318 /// Get the number of prims that a particular user owns on this parcel.
319 /// </summary>
320 /// <param name="parcelID"></param>
321 /// <param name="userID"></param>
322 /// <returns></returns>
281 public int GetUserCount(UUID parcelID, UUID userID) 323 public int GetUserCount(UUID parcelID, UUID userID)
282 { 324 {
283 lock (m_TaintLock) 325 lock (m_TaintLock)
@@ -299,18 +341,21 @@ namespace OpenSim.Region.CoreModules.World.Land
299 // NOTE: This method MUST be called while holding the taint lock! 341 // NOTE: This method MUST be called while holding the taint lock!
300 private void Recount() 342 private void Recount()
301 { 343 {
344// m_log.DebugFormat("[PRIM COUNT MODULE]: Recounting prims on {0}", m_Scene.RegionInfo.RegionName);
345
302 m_OwnerMap.Clear(); 346 m_OwnerMap.Clear();
303 m_SimwideCounts.Clear(); 347 m_SimwideCounts.Clear();
304 m_ParcelCounts.Clear(); 348 m_ParcelCounts.Clear();
305 349
306 List<ILandObject> land = m_Scene.LandChannel.AllParcels(); 350 List<ILandObject> land = m_Scene.LandChannel.AllParcels();
307 351
308 foreach (ILandObject l in land) 352 foreach (ILandObject l in land)
309 { 353 {
310 LandData landData = l.LandData; 354 LandData landData = l.LandData;
311 355
312 m_OwnerMap[landData.GlobalID] = landData.OwnerID; 356 m_OwnerMap[landData.GlobalID] = landData.OwnerID;
313 m_SimwideCounts[landData.OwnerID] = 0; 357 m_SimwideCounts[landData.OwnerID] = 0;
358// m_log.DebugFormat("[PRIM COUNT MODULE]: Adding parcel count for {0}", landData.GlobalID);
314 m_ParcelCounts[landData.GlobalID] = new ParcelCounts(); 359 m_ParcelCounts[landData.GlobalID] = new ParcelCounts();
315 } 360 }
316 361
diff --git a/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
new file mode 100644
index 0000000..c9d393f
--- /dev/null
+++ b/OpenSim/Region/CoreModules/World/Land/Tests/PrimCountModuleTests.cs
@@ -0,0 +1,131 @@
1/*
2 * Copyright (c) Contributors, http://opensimulator.org/
3 * See CONTRIBUTORS.TXT for a full list of copyright holders.
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions are met:
7 * * Redistributions of source code must retain the above copyright
8 * notice, this list of conditions and the following disclaimer.
9 * * Redistributions in binary form must reproduce the above copyright
10 * notice, this list of conditions and the following disclaimer in the
11 * documentation and/or other materials provided with the distribution.
12 * * Neither the name of the OpenSimulator Project nor the
13 * names of its contributors may be used to endorse or promote products
14 * derived from this software without specific prior written permission.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE DEVELOPERS ``AS IS'' AND ANY
17 * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
18 * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
19 * DISCLAIMED. IN NO EVENT SHALL THE CONTRIBUTORS BE LIABLE FOR ANY
20 * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
21 * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
22 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
23 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
25 * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28using System;
29using System.Collections.Generic;
30using System.Reflection;
31using log4net.Config;
32using NUnit.Framework;
33using OpenMetaverse;
34using OpenMetaverse.Assets;
35using OpenSim.Framework;
36using OpenSim.Region.Framework.Interfaces;
37using OpenSim.Region.Framework.Scenes;
38using OpenSim.Tests.Common;
39using OpenSim.Tests.Common.Mock;
40using OpenSim.Tests.Common.Setup;
41
42namespace OpenSim.Region.CoreModules.World.Land.Tests
43{
44 [TestFixture]
45 public class PrimCountModuleTests
46 {
47 protected UUID m_userId = new UUID("00000000-0000-0000-0000-100000000000");
48 protected UUID m_dummyUserId = new UUID("99999999-9999-9999-9999-999999999999");
49 protected TestScene m_scene;
50 protected PrimCountModule m_pcm;
51 protected ILandObject m_lo;
52
53 [SetUp]
54 public void SetUp()
55 {
56 m_pcm = new PrimCountModule();
57 LandManagementModule lmm = new LandManagementModule();
58 m_scene = SceneSetupHelpers.SetupScene();
59 SceneSetupHelpers.SetupSceneModules(m_scene, lmm, m_pcm);
60
61 ILandObject lo = new LandObject(m_userId, false, m_scene);
62 lo.SetLandBitmap(lo.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
63 m_lo = lmm.AddLandObject(lo);
64 //scene.loadAllLandObjectsFromStorage(scene.RegionInfo.originRegionID);
65 }
66
67 /// <summary>
68 /// Test count after a parcel owner owned object is added.
69 /// </summary>
70 [Test]
71 public void TestAddOwnerObject()
72 {
73 TestHelper.InMethod();
74// log4net.Config.XmlConfigurator.Configure();
75
76 IPrimCounts pc = m_lo.PrimCounts;
77
78 Assert.That(pc.Owner, Is.EqualTo(0));
79 Assert.That(pc.Group, Is.EqualTo(0));
80 Assert.That(pc.Others, Is.EqualTo(0));
81 Assert.That(pc.Users[m_userId], Is.EqualTo(0));
82 Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0));
83 Assert.That(pc.Simulator, Is.EqualTo(0));
84
85 SceneObjectGroup sog = SceneSetupHelpers.CreateSceneObject(3, m_userId, 0x01);
86 m_scene.AddNewSceneObject(sog, false);
87
88 Assert.That(pc.Owner, Is.EqualTo(3));
89 Assert.That(pc.Group, Is.EqualTo(0));
90 Assert.That(pc.Others, Is.EqualTo(0));
91 Assert.That(pc.Users[m_userId], Is.EqualTo(3));
92 Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0));
93 Assert.That(pc.Simulator, Is.EqualTo(3));
94
95 // Add a second object and retest
96 SceneObjectGroup sog2 = SceneSetupHelpers.CreateSceneObject(2, m_userId, 0x10);
97 m_scene.AddNewSceneObject(sog2, false);
98
99 Assert.That(pc.Owner, Is.EqualTo(5));
100 Assert.That(pc.Group, Is.EqualTo(0));
101 Assert.That(pc.Others, Is.EqualTo(0));
102 Assert.That(pc.Users[m_userId], Is.EqualTo(5));
103 Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0));
104 Assert.That(pc.Simulator, Is.EqualTo(5));
105 }
106
107 /// <summary>
108 /// Test count after a parcel owner owned object is removed.
109 /// </summary>
110 [Test]
111 public void TestRemoveOwnerObject()
112 {
113 TestHelper.InMethod();
114// log4net.Config.XmlConfigurator.Configure();
115
116 IPrimCounts pc = m_lo.PrimCounts;
117
118 m_scene.AddNewSceneObject(SceneSetupHelpers.CreateSceneObject(1, m_userId, 0x1), false);
119 SceneObjectGroup sogToDelete = SceneSetupHelpers.CreateSceneObject(3, m_userId, 0x10);
120 m_scene.AddNewSceneObject(sogToDelete, false);
121 m_scene.DeleteSceneObject(sogToDelete, false);
122
123 Assert.That(pc.Owner, Is.EqualTo(1));
124 Assert.That(pc.Group, Is.EqualTo(0));
125 Assert.That(pc.Others, Is.EqualTo(0));
126 Assert.That(pc.Users[m_userId], Is.EqualTo(1));
127 Assert.That(pc.Users[m_dummyUserId], Is.EqualTo(0));
128 Assert.That(pc.Simulator, Is.EqualTo(1));
129 }
130 }
131} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
index 95c9659..38c10a6 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateDataService.cs
@@ -34,12 +34,68 @@ namespace OpenSim.Region.Framework.Interfaces
34{ 34{
35 public interface IEstateDataService 35 public interface IEstateDataService
36 { 36 {
37 /// <summary>
38 /// Load estate settings for a region.
39 /// </summary>
40 /// <param name="regionID"></param>
41 /// <param name="create">If true, then an estate is created if one is not found.</param>
42 /// <returns></returns>
37 EstateSettings LoadEstateSettings(UUID regionID, bool create); 43 EstateSettings LoadEstateSettings(UUID regionID, bool create);
44
45 /// <summary>
46 /// Load estate settings for an estate ID.
47 /// </summary>
48 /// <param name="estateID"></param>
49 /// <returns></returns>
38 EstateSettings LoadEstateSettings(int estateID); 50 EstateSettings LoadEstateSettings(int estateID);
51
52 /// <summary>
53 /// Load/Get all estate settings.
54 /// </summary>
55 /// <returns>An empty list if no estates were found.</returns>
56 List<EstateSettings> LoadEstateSettingsAll();
57
58 /// <summary>
59 /// Store estate settings.
60 /// </summary>
61 /// <remarks>
62 /// This is also called by EstateSettings.Save()</remarks>
63 /// <param name="es"></param>
39 void StoreEstateSettings(EstateSettings es); 64 void StoreEstateSettings(EstateSettings es);
65
66 /// <summary>
67 /// Get estate IDs.
68 /// </summary>
69 /// <param name="search">Name of estate to search for. This is the exact name, no parttern matching is done.</param>
70 /// <returns></returns>
40 List<int> GetEstates(string search); 71 List<int> GetEstates(string search);
72
73 /// <summary>
74 /// Get the IDs of all estates.
75 /// </summary>
76 /// <returns>An empty list if no estates were found.</returns>
77 List<int> GetEstatesAll();
78
79 /// <summary>
80 /// Link a region to an estate.
81 /// </summary>
82 /// <param name="regionID"></param>
83 /// <param name="estateID"></param>
84 /// <returns>true if the link succeeded, false otherwise</returns>
41 bool LinkRegion(UUID regionID, int estateID); 85 bool LinkRegion(UUID regionID, int estateID);
86
87 /// <summary>
88 /// Get the UUIDs of all the regions in an estate.
89 /// </summary>
90 /// <param name="estateID"></param>
91 /// <returns></returns>
42 List<UUID> GetRegions(int estateID); 92 List<UUID> GetRegions(int estateID);
93
94 /// <summary>
95 /// Delete an estate
96 /// </summary>
97 /// <param name="estateID"></param>
98 /// <returns>true if the delete succeeded, false otherwise</returns>
43 bool DeleteEstate(int estateID); 99 bool DeleteEstate(int estateID);
44 } 100 }
45} 101} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
index 87c7a05..c82661d 100644
--- a/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
+++ b/OpenSim/Region/Framework/Interfaces/IEstateDataStore.cs
@@ -33,14 +33,74 @@ namespace OpenSim.Region.Framework.Interfaces
33{ 33{
34 public interface IEstateDataStore 34 public interface IEstateDataStore
35 { 35 {
36 /// <summary>
37 /// Initialise the data store.
38 /// </summary>
39 /// <param name="connectstring"></param>
36 void Initialise(string connectstring); 40 void Initialise(string connectstring);
37 41
42 /// <summary>
43 /// Load estate settings for a region.
44 /// </summary>
45 /// <param name="regionID"></param>
46 /// <param name="create">If true, then an estate is created if one is not found.</param>
47 /// <returns></returns>
38 EstateSettings LoadEstateSettings(UUID regionID, bool create); 48 EstateSettings LoadEstateSettings(UUID regionID, bool create);
49
50 /// <summary>
51 /// Load estate settings for an estate ID.
52 /// </summary>
53 /// <param name="estateID"></param>
54 /// <returns></returns>
39 EstateSettings LoadEstateSettings(int estateID); 55 EstateSettings LoadEstateSettings(int estateID);
56
57 /// <summary>
58 /// Load/Get all estate settings.
59 /// </summary>
60 /// <returns>An empty list if no estates were found.</returns>
61 List<EstateSettings> LoadEstateSettingsAll();
62
63 /// <summary>
64 /// Store estate settings.
65 /// </summary>
66 /// <remarks>
67 /// This is also called by EstateSettings.Save()</remarks>
68 /// <param name="es"></param>
40 void StoreEstateSettings(EstateSettings es); 69 void StoreEstateSettings(EstateSettings es);
70
71 /// <summary>
72 /// Get estate IDs.
73 /// </summary>
74 /// <param name="search">Name of estate to search for. This is the exact name, no parttern matching is done.</param>
75 /// <returns></returns>
41 List<int> GetEstates(string search); 76 List<int> GetEstates(string search);
77
78 /// <summary>
79 /// Get the IDs of all estates.
80 /// </summary>
81 /// <returns>An empty list if no estates were found.</returns>
82 List<int> GetEstatesAll();
83
84 /// <summary>
85 /// Link a region to an estate.
86 /// </summary>
87 /// <param name="regionID"></param>
88 /// <param name="estateID"></param>
89 /// <returns>true if the link succeeded, false otherwise</returns>
42 bool LinkRegion(UUID regionID, int estateID); 90 bool LinkRegion(UUID regionID, int estateID);
91
92 /// <summary>
93 /// Get the UUIDs of all the regions in an estate.
94 /// </summary>
95 /// <param name="estateID"></param>
96 /// <returns></returns>
43 List<UUID> GetRegions(int estateID); 97 List<UUID> GetRegions(int estateID);
98
99 /// <summary>
100 /// Delete an estate
101 /// </summary>
102 /// <param name="estateID"></param>
103 /// <returns>true if the delete succeeded, false otherwise</returns>
44 bool DeleteEstate(int estateID); 104 bool DeleteEstate(int estateID);
45 } 105 }
46} 106} \ No newline at end of file
diff --git a/OpenSim/Region/Framework/Interfaces/ILandObject.cs b/OpenSim/Region/Framework/Interfaces/ILandObject.cs
index eeb9d3a..9c0abde 100644
--- a/OpenSim/Region/Framework/Interfaces/ILandObject.cs
+++ b/OpenSim/Region/Framework/Interfaces/ILandObject.cs
@@ -46,6 +46,11 @@ namespace OpenSim.Region.Framework.Interfaces
46 UUID RegionUUID { get; } 46 UUID RegionUUID { get; }
47 47
48 /// <summary> 48 /// <summary>
49 /// Prim counts for this land object.
50 /// </summary>
51 IPrimCounts PrimCounts { get; set; }
52
53 /// <summary>
49 /// The start point for the land object. This is the western-most point as one scans land working from 54 /// The start point for the land object. This is the western-most point as one scans land working from
50 /// north to south. 55 /// north to south.
51 /// </summary> 56 /// </summary>
diff --git a/OpenSim/Region/Framework/Scenes/EventManager.cs b/OpenSim/Region/Framework/Scenes/EventManager.cs
index c321a15..fd62535 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -242,7 +242,15 @@ namespace OpenSim.Region.Framework.Scenes
242 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 242 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
243 243
244 public event EstateToolsSunUpdate OnEstateToolsSunUpdate; 244 public event EstateToolsSunUpdate OnEstateToolsSunUpdate;
245
246 /// <summary>
247 /// Triggered when an object is added to the scene.
248 /// </summary>
249 public event Action<SceneObjectGroup> OnObjectAddedToScene;
245 250
251 /// <summary>
252 /// Triggered when an object is removed from the scene.
253 /// </summary>
246 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); 254 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
247 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; 255 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
248 256
@@ -345,6 +353,7 @@ namespace OpenSim.Region.Framework.Scenes
345 public delegate void Attach(uint localID, UUID itemID, UUID avatarID); 353 public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
346 public event Attach OnAttach; 354 public event Attach OnAttach;
347 355
356
348 /// <summary> 357 /// <summary>
349 /// Called immediately after an object is loaded from storage. 358 /// Called immediately after an object is loaded from storage.
350 /// </summary> 359 /// </summary>
@@ -800,6 +809,27 @@ namespace OpenSim.Region.Framework.Scenes
800 } 809 }
801 } 810 }
802 811
812 public void TriggerObjectAddedToScene(SceneObjectGroup obj)
813 {
814 Action<SceneObjectGroup> handler = OnObjectAddedToScene;
815 if (handler != null)
816 {
817 foreach (Action<SceneObjectGroup> d in handler.GetInvocationList())
818 {
819 try
820 {
821 d(obj);
822 }
823 catch (Exception e)
824 {
825 m_log.ErrorFormat(
826 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToScene failed - continuing. {0} {1}",
827 e.Message, e.StackTrace);
828 }
829 }
830 }
831 }
832
803 public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj) 833 public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj)
804 { 834 {
805 ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene; 835 ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index 1a6a70b..d407a6f 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1109,7 +1109,7 @@ namespace OpenSim.Region.Framework.Scenes
1109 // 1109 //
1110 while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) 1110 while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
1111 { 1111 {
1112 MainConsole.Instance.Output("The current estate has no owner set."); 1112 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", m_regInfo.EstateSettings.EstateName);
1113 List<char> excluded = new List<char>(new char[1]{' '}); 1113 List<char> excluded = new List<char>(new char[1]{' '});
1114 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded); 1114 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded);
1115 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded); 1115 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded);
@@ -1956,8 +1956,14 @@ namespace OpenSim.Region.Framework.Scenes
1956 /// If false, it is left to the caller to schedule the update 1956 /// If false, it is left to the caller to schedule the update
1957 /// </param> 1957 /// </param>
1958 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 1958 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
1959 { 1959 {
1960 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 1960 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates))
1961 {
1962 EventManager.TriggerObjectAddedToScene(sceneObject);
1963 return true;
1964 }
1965
1966 return false;
1961 } 1967 }
1962 1968
1963 /// <summary> 1969 /// <summary>
@@ -1974,7 +1980,13 @@ namespace OpenSim.Region.Framework.Scenes
1974 public bool AddNewSceneObject( 1980 public bool AddNewSceneObject(
1975 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) 1981 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
1976 { 1982 {
1977 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel); 1983 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel))
1984 {
1985 EventManager.TriggerObjectAddedToScene(sceneObject);
1986 return true;
1987 }
1988
1989 return false;
1978 } 1990 }
1979 1991
1980 /// <summary> 1992 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index 734ba22..60855b2 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -88,9 +88,21 @@ namespace OpenSim.Region.Framework.Scenes
88 protected internal object m_syncRoot = new object(); 88 protected internal object m_syncRoot = new object();
89 89
90 protected internal PhysicsScene _PhyScene; 90 protected internal PhysicsScene _PhyScene;
91 91
92 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalID = new Dictionary<uint, SceneObjectGroup>(); 92 /// <summary>
93 /// Index the SceneObjectGroup for each part by the root part's UUID.
94 /// </summary>
93 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 95 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
96
97 /// <summary>
98 /// Index the SceneObjectGroup for each part by that part's UUID.
99 /// </summary>
100 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>();
101
102 /// <summary>
103 /// Index the SceneObjectGroup for each part by that part's local ID.
104 /// </summary>
105 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
94 106
95 private Object m_updateLock = new Object(); 107 private Object m_updateLock = new Object();
96 108
@@ -133,8 +145,10 @@ namespace OpenSim.Region.Framework.Scenes
133 145
134 lock (SceneObjectGroupsByFullID) 146 lock (SceneObjectGroupsByFullID)
135 SceneObjectGroupsByFullID.Clear(); 147 SceneObjectGroupsByFullID.Clear();
136 lock (SceneObjectGroupsByLocalID) 148 lock (SceneObjectGroupsByFullPartID)
137 SceneObjectGroupsByLocalID.Clear(); 149 SceneObjectGroupsByFullPartID.Clear();
150 lock (SceneObjectGroupsByLocalPartID)
151 SceneObjectGroupsByLocalPartID.Clear();
138 152
139 Entities.Clear(); 153 Entities.Clear();
140 } 154 }
@@ -349,6 +363,10 @@ namespace OpenSim.Region.Framework.Scenes
349 363
350 if (Entities.ContainsKey(sceneObject.UUID)) 364 if (Entities.ContainsKey(sceneObject.UUID))
351 return false; 365 return false;
366
367// m_log.DebugFormat(
368// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
369// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
352 370
353 SceneObjectPart[] children = sceneObject.Parts; 371 SceneObjectPart[] children = sceneObject.Parts;
354 372
@@ -385,17 +403,20 @@ namespace OpenSim.Region.Framework.Scenes
385 OnObjectCreate(sceneObject); 403 OnObjectCreate(sceneObject);
386 404
387 lock (SceneObjectGroupsByFullID) 405 lock (SceneObjectGroupsByFullID)
388 {
389 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 406 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
407
408 lock (SceneObjectGroupsByFullPartID)
409 {
410 SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
390 foreach (SceneObjectPart part in children) 411 foreach (SceneObjectPart part in children)
391 SceneObjectGroupsByFullID[part.UUID] = sceneObject; 412 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
392 } 413 }
393 414
394 lock (SceneObjectGroupsByLocalID) 415 lock (SceneObjectGroupsByLocalPartID)
395 { 416 {
396 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; 417 SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject;
397 foreach (SceneObjectPart part in children) 418 foreach (SceneObjectPart part in children)
398 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; 419 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
399 } 420 }
400 421
401 return true; 422 return true;
@@ -426,21 +447,24 @@ namespace OpenSim.Region.Framework.Scenes
426 447
427 if (OnObjectRemove != null) 448 if (OnObjectRemove != null)
428 OnObjectRemove(Entities[uuid]); 449 OnObjectRemove(Entities[uuid]);
429 450
430 lock (SceneObjectGroupsByFullID) 451 lock (SceneObjectGroupsByFullID)
452 SceneObjectGroupsByFullID.Remove(grp.UUID);
453
454 lock (SceneObjectGroupsByFullPartID)
431 { 455 {
432 SceneObjectPart[] parts = grp.Parts; 456 SceneObjectPart[] parts = grp.Parts;
433 for (int i = 0; i < parts.Length; i++) 457 for (int i = 0; i < parts.Length; i++)
434 SceneObjectGroupsByFullID.Remove(parts[i].UUID); 458 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
435 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); 459 SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
436 } 460 }
437 461
438 lock (SceneObjectGroupsByLocalID) 462 lock (SceneObjectGroupsByLocalPartID)
439 { 463 {
440 SceneObjectPart[] parts = grp.Parts; 464 SceneObjectPart[] parts = grp.Parts;
441 for (int i = 0; i < parts.Length; i++) 465 for (int i = 0; i < parts.Length; i++)
442 SceneObjectGroupsByLocalID.Remove(parts[i].LocalId); 466 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
443 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); 467 SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
444 } 468 }
445 469
446 return Entities.Remove(uuid); 470 return Entities.Remove(uuid);
@@ -627,7 +651,7 @@ namespace OpenSim.Region.Framework.Scenes
627 if (!Entities.Remove(agentID)) 651 if (!Entities.Remove(agentID))
628 { 652 {
629 m_log.WarnFormat( 653 m_log.WarnFormat(
630 "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", 654 "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
631 agentID); 655 agentID);
632 } 656 }
633 657
@@ -650,7 +674,7 @@ namespace OpenSim.Region.Framework.Scenes
650 } 674 }
651 else 675 else
652 { 676 {
653 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 677 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
654 } 678 }
655 } 679 }
656 } 680 }
@@ -854,14 +878,14 @@ namespace OpenSim.Region.Framework.Scenes
854 878
855 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); 879 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
856 SceneObjectGroup sog; 880 SceneObjectGroup sog;
857 lock (SceneObjectGroupsByLocalID) 881 lock (SceneObjectGroupsByLocalPartID)
858 SceneObjectGroupsByLocalID.TryGetValue(localID, out sog); 882 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
859 883
860 if (sog != null) 884 if (sog != null)
861 { 885 {
862 if (sog.HasChildPrim(localID)) 886 if (sog.HasChildPrim(localID))
863 return sog; 887 return sog;
864 SceneObjectGroupsByLocalID.Remove(localID); 888 SceneObjectGroupsByLocalPartID.Remove(localID);
865 } 889 }
866 890
867 EntityBase[] entityList = GetEntities(); 891 EntityBase[] entityList = GetEntities();
@@ -873,8 +897,8 @@ namespace OpenSim.Region.Framework.Scenes
873 sog = (SceneObjectGroup)ent; 897 sog = (SceneObjectGroup)ent;
874 if (sog.HasChildPrim(localID)) 898 if (sog.HasChildPrim(localID))
875 { 899 {
876 lock (SceneObjectGroupsByLocalID) 900 lock (SceneObjectGroupsByLocalPartID)
877 SceneObjectGroupsByLocalID[localID] = sog; 901 SceneObjectGroupsByLocalPartID[localID] = sog;
878 return sog; 902 return sog;
879 } 903 }
880 } 904 }
@@ -891,16 +915,16 @@ namespace OpenSim.Region.Framework.Scenes
891 private SceneObjectGroup GetGroupByPrim(UUID fullID) 915 private SceneObjectGroup GetGroupByPrim(UUID fullID)
892 { 916 {
893 SceneObjectGroup sog; 917 SceneObjectGroup sog;
894 lock (SceneObjectGroupsByFullID) 918 lock (SceneObjectGroupsByFullPartID)
895 SceneObjectGroupsByFullID.TryGetValue(fullID, out sog); 919 SceneObjectGroupsByFullPartID.TryGetValue(fullID, out sog);
896 920
897 if (sog != null) 921 if (sog != null)
898 { 922 {
899 if (sog.ContainsPart(fullID)) 923 if (sog.ContainsPart(fullID))
900 return sog; 924 return sog;
901 925
902 lock (SceneObjectGroupsByFullID) 926 lock (SceneObjectGroupsByFullPartID)
903 SceneObjectGroupsByFullID.Remove(fullID); 927 SceneObjectGroupsByFullPartID.Remove(fullID);
904 } 928 }
905 929
906 EntityBase[] entityList = GetEntities(); 930 EntityBase[] entityList = GetEntities();
@@ -911,8 +935,8 @@ namespace OpenSim.Region.Framework.Scenes
911 sog = (SceneObjectGroup)ent; 935 sog = (SceneObjectGroup)ent;
912 if (sog.HasChildPrim(fullID)) 936 if (sog.HasChildPrim(fullID))
913 { 937 {
914 lock (SceneObjectGroupsByFullID) 938 lock (SceneObjectGroupsByFullPartID)
915 SceneObjectGroupsByFullID[fullID] = sog; 939 SceneObjectGroupsByFullPartID[fullID] = sog;
916 return sog; 940 return sog;
917 } 941 }
918 } 942 }
@@ -1064,11 +1088,12 @@ namespace OpenSim.Region.Framework.Scenes
1064 } 1088 }
1065 1089
1066 /// <summary> 1090 /// <summary>
1067 /// Performs action on all scene object groups. 1091 /// Performs action once on all scene object groups.
1068 /// </summary> 1092 /// </summary>
1069 /// <param name="action"></param> 1093 /// <param name="action"></param>
1070 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1094 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1071 { 1095 {
1096 // FIXME: Need to lock here, really.
1072 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values); 1097 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
1073 foreach (SceneObjectGroup obj in objlist) 1098 foreach (SceneObjectGroup obj in objlist)
1074 { 1099 {
@@ -1079,11 +1104,11 @@ namespace OpenSim.Region.Framework.Scenes
1079 catch (Exception e) 1104 catch (Exception e)
1080 { 1105 {
1081 // Catch it and move on. This includes situations where splist has inconsistent info 1106 // Catch it and move on. This includes situations where splist has inconsistent info
1082 m_log.WarnFormat("[SCENE]: Problem processing action in ForEachSOG: ", e.ToString()); 1107 m_log.WarnFormat(
1108 "[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}", e.Message, e.StackTrace);
1083 } 1109 }
1084 } 1110 }
1085 } 1111 }
1086
1087 1112
1088 /// <summary> 1113 /// <summary>
1089 /// Performs action on all scene presences. This can ultimately run the actions in parallel but 1114 /// Performs action on all scene presences. This can ultimately run the actions in parallel but
@@ -1103,8 +1128,8 @@ namespace OpenSim.Region.Framework.Scenes
1103 } 1128 }
1104 catch (Exception e) 1129 catch (Exception e)
1105 { 1130 {
1106 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); 1131 m_log.Info("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1107 m_log.Info("[BUG] Stack Trace: " + e.StackTrace); 1132 m_log.Info("[SCENEGRAPH]: Stack Trace: " + e.StackTrace);
1108 } 1133 }
1109 }); 1134 });
1110 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1135 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
@@ -1119,7 +1144,7 @@ namespace OpenSim.Region.Framework.Scenes
1119 } 1144 }
1120 catch (Exception e) 1145 catch (Exception e)
1121 { 1146 {
1122 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); 1147 m_log.Error("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1123 } 1148 }
1124 } 1149 }
1125 } 1150 }
@@ -1777,7 +1802,10 @@ namespace OpenSim.Region.Framework.Scenes
1777 /// <param name="rot"></param> 1802 /// <param name="rot"></param>
1778 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 1803 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1779 { 1804 {
1780 //m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID); 1805// m_log.DebugFormat(
1806// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1807// originalPrimID, offset, AgentID);
1808
1781 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 1809 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1782 if (original != null) 1810 if (original != null)
1783 { 1811 {
@@ -1808,7 +1836,28 @@ namespace OpenSim.Region.Framework.Scenes
1808 copy.RootPart.SalePrice = 10; 1836 copy.RootPart.SalePrice = 10;
1809 } 1837 }
1810 1838
1839 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1811 Entities.Add(copy); 1840 Entities.Add(copy);
1841
1842 lock (SceneObjectGroupsByFullID)
1843 SceneObjectGroupsByFullID[copy.UUID] = copy;
1844
1845 SceneObjectPart[] children = copy.Parts;
1846
1847 lock (SceneObjectGroupsByFullPartID)
1848 {
1849 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1850 foreach (SceneObjectPart part in children)
1851 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1852 }
1853
1854 lock (SceneObjectGroupsByLocalPartID)
1855 {
1856 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1857 foreach (SceneObjectPart part in children)
1858 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1859 }
1860 // PROBABLE END OF FIXME
1812 1861
1813 // Since we copy from a source group that is in selected 1862 // Since we copy from a source group that is in selected
1814 // state, but the copy is shown deselected in the viewer, 1863 // state, but the copy is shown deselected in the viewer,