aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/OpenSim/Region
diff options
context:
space:
mode:
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.cs125
11 files changed, 559 insertions, 107 deletions
diff --git a/OpenSim/Region/Application/OpenSimBase.cs b/OpenSim/Region/Application/OpenSimBase.cs
index 9960a54..503123e 100644
--- a/OpenSim/Region/Application/OpenSimBase.cs
+++ b/OpenSim/Region/Application/OpenSimBase.cs
@@ -875,66 +875,115 @@ namespace OpenSim
875 } 875 }
876 876
877 /// <summary> 877 /// <summary>
878 /// Load the estate information for the provided RegionInfo object. 878 /// Create an estate with an initial region.
879 /// </summary> 879 /// </summary>
880 /// <remarks>
881 /// This method doesn't allow an estate to be created with the same name as existing estates.
882 /// </remarks>
880 /// <param name="regInfo"></param> 883 /// <param name="regInfo"></param>
881 public void PopulateRegionEstateInfo(RegionInfo regInfo) 884 /// <param name="existingName">A list of estate names that already exist.</param>
885 /// <returns>true if the estate was created, false otherwise</returns>
886 public bool CreateEstate(RegionInfo regInfo, List<string> existingNames)
882 { 887 {
883 IEstateDataService estateDataService = EstateDataService; 888 // Create a new estate
889 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, true);
890 string newName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
884 891
885 if (estateDataService != null) 892 if (existingNames.Contains(newName))
886 { 893 {
887 regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, false); 894 MainConsole.Instance.OutputFormat("An estate named {0} already exists. Please try again.", newName);
895 return false;
888 } 896 }
897
898 regInfo.EstateSettings.EstateName = newName;
899
900 // FIXME: Later on, the scene constructor will reload the estate settings no matter what.
901 // Therefore, we need to do an initial save here otherwise the new estate name will be reset
902 // back to the default. The reloading of estate settings by scene could be eliminated if it
903 // knows that the passed in settings in RegionInfo are already valid. Also, it might be
904 // possible to eliminate some additional later saves made by callers of this method.
905 regInfo.EstateSettings.Save();
906
907 return true;
908 }
909
910 /// <summary>
911 /// Load the estate information for the provided RegionInfo object.
912 /// </summary>
913 /// <param name="regInfo"></param>
914 public void PopulateRegionEstateInfo(RegionInfo regInfo)
915 {
916 if (EstateDataService != null)
917 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(regInfo.RegionID, false);
889 918
890 if (regInfo.EstateSettings.EstateID == 0) // No record at all 919 if (regInfo.EstateSettings.EstateID == 0) // No record at all
891 { 920 {
892 MainConsole.Instance.Output("Your region is not part of an estate."); 921 MainConsole.Instance.OutputFormat("Region {0} is not part of an estate.", regInfo.RegionName);
922
923 List<EstateSettings> estates = EstateDataService.LoadEstateSettingsAll();
924 List<string> estateNames = new List<string>();
925 foreach (EstateSettings estate in estates)
926 estateNames.Add(estate.EstateName);
927
893 while (true) 928 while (true)
894 { 929 {
895 string response = MainConsole.Instance.CmdPrompt("Do you wish to join an existing estate?", "no", new List<string>() { "yes", "no" }); 930 if (estates.Count == 0)
896 if (response == "no") 931 {
897 { 932 MainConsole.Instance.Output("No existing estates found. You must create a new one.");
898 // Create a new estate
899 regInfo.EstateSettings = estateDataService.LoadEstateSettings(regInfo.RegionID, true);
900
901 regInfo.EstateSettings.EstateName = MainConsole.Instance.CmdPrompt("New estate name", regInfo.EstateSettings.EstateName);
902 933
903 // FIXME: Later on, the scene constructor will reload the estate settings no matter what. 934 if (CreateEstate(regInfo, estateNames))
904 // Therefore, we need to do an initial save here otherwise the new estate name will be reset 935 break;
905 // back to the default. The reloading of estate settings by scene could be eliminated if it 936 else
906 // knows that the passed in settings in RegionInfo are already valid. Also, it might be 937 continue;
907 // possible to eliminate some additional later saves made by callers of this method.
908 regInfo.EstateSettings.Save();
909 break;
910 } 938 }
911 else 939 else
912 { 940 {
913 response = MainConsole.Instance.CmdPrompt("Estate name to join", "None"); 941 string response
914 if (response == "None") 942 = MainConsole.Instance.CmdPrompt(
915 continue; 943 string.Format(
916 944 "Do you wish to join region {0} to an existing estate (yes/no)?", regInfo.RegionName),
917 List<int> estateIDs = estateDataService.GetEstates(response); 945 "no",
918 if (estateIDs.Count < 1) 946 new List<string>() { "yes", "no" });
947
948 if (response == "no")
919 { 949 {
920 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again"); 950 if (CreateEstate(regInfo, estateNames))
921 continue; 951 break;
952 else
953 continue;
954 }
955 else
956 {
957 response
958 = MainConsole.Instance.CmdPrompt(
959 string.Format(
960 "Name of estate to join. Existing estate names are ({0})", string.Join(", ", estateNames.ToArray())),
961 "None");
962
963 if (response == "None")
964 continue;
965
966 List<int> estateIDs = EstateDataService.GetEstates(response);
967 if (estateIDs.Count < 1)
968 {
969 MainConsole.Instance.Output("The name you have entered matches no known estate. Please try again.");
970 continue;
971 }
972
973 int estateID = estateIDs[0];
974
975 regInfo.EstateSettings = EstateDataService.LoadEstateSettings(estateID);
976
977 if (EstateDataService.LinkRegion(regInfo.RegionID, estateID))
978 break;
979
980 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
922 } 981 }
923
924 int estateID = estateIDs[0];
925
926 regInfo.EstateSettings = estateDataService.LoadEstateSettings(estateID);
927
928 if (estateDataService.LinkRegion(regInfo.RegionID, estateID))
929 break;
930
931 MainConsole.Instance.Output("Joining the estate failed. Please try again.");
932 } 982 }
933 } 983 }
934 } 984 }
935 } 985 }
936 } 986 }
937
938 987
939 public class OpenSimConfigSource 988 public class OpenSimConfigSource
940 { 989 {
diff --git a/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs b/OpenSim/Region/CoreModules/World/Land/LandManagementModule.cs
index ad75ea5..50040ff 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
@@ -153,6 +154,7 @@ namespace OpenSim.Region.CoreModules.World.Land
153 public void RegionLoaded(Scene scene) 154 public void RegionLoaded(Scene scene)
154 { 155 {
155 m_userManager = m_scene.RequestModuleInterface<IUserManagement>(); 156 m_userManager = m_scene.RequestModuleInterface<IUserManagement>();
157 m_primCountModule = m_scene.RequestModuleInterface<IPrimCountModule>();
156 } 158 }
157 159
158 public void RemoveRegion(Scene scene) 160 public void RemoveRegion(Scene scene)
@@ -275,10 +277,14 @@ namespace OpenSim.Region.CoreModules.World.Land
275 /// <returns>The parcel created.</returns> 277 /// <returns>The parcel created.</returns>
276 protected ILandObject CreateDefaultParcel() 278 protected ILandObject CreateDefaultParcel()
277 { 279 {
278 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene); 280// m_log.DebugFormat(
281// "[LAND MANAGEMENT MODULE]: Creating default parcel for region {0}", m_scene.RegionInfo.RegionName);
282
283 ILandObject fullSimParcel = new LandObject(UUID.Zero, false, m_scene);
279 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize)); 284 fullSimParcel.SetLandBitmap(fullSimParcel.GetSquareLandBitmap(0, 0, (int)Constants.RegionSize, (int)Constants.RegionSize));
280 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner; 285 fullSimParcel.LandData.OwnerID = m_scene.RegionInfo.EstateSettings.EstateOwner;
281 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch(); 286 fullSimParcel.LandData.ClaimDate = Util.UnixTimeSinceEpoch();
287
282 return AddLandObject(fullSimParcel); 288 return AddLandObject(fullSimParcel);
283 } 289 }
284 290
@@ -496,7 +502,7 @@ namespace OpenSim.Region.CoreModules.World.Land
496 } 502 }
497 else 503 else
498 { 504 {
499 m_log.WarnFormat("[LAND]: Invalid local land ID {0}", landLocalID); 505 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid local land ID {0}", landLocalID);
500 } 506 }
501 } 507 }
502 508
@@ -507,6 +513,11 @@ namespace OpenSim.Region.CoreModules.World.Land
507 public ILandObject AddLandObject(ILandObject land) 513 public ILandObject AddLandObject(ILandObject land)
508 { 514 {
509 ILandObject new_land = land.Copy(); 515 ILandObject new_land = land.Copy();
516
517 // Only now can we add the prim counts to the land object - we rely on the global ID which is generated
518 // as a random UUID inside LandData initialization
519 if (m_primCountModule != null)
520 new_land.PrimCounts = m_primCountModule.GetPrimCounts(new_land.LandData.GlobalID);
510 521
511 lock (m_landList) 522 lock (m_landList)
512 { 523 {
@@ -547,7 +558,7 @@ namespace OpenSim.Region.CoreModules.World.Land
547 { 558 {
548 if (m_landIDList[x, y] == local_id) 559 if (m_landIDList[x, y] == local_id)
549 { 560 {
550 m_log.WarnFormat("[LAND]: Not removing land object {0}; still being used at {1}, {2}", 561 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Not removing land object {0}; still being used at {1}, {2}",
551 local_id, x, y); 562 local_id, x, y);
552 return; 563 return;
553 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y); 564 //throw new Exception("Could not remove land object. Still being used at " + x + ", " + y);
@@ -768,6 +779,10 @@ namespace OpenSim.Region.CoreModules.World.Land
768 779
769 public void EventManagerOnParcelPrimCountUpdate() 780 public void EventManagerOnParcelPrimCountUpdate()
770 { 781 {
782// m_log.DebugFormat(
783// "[LAND MANAGEMENT MODULE]: Triggered EventManagerOnParcelPrimCountUpdate() for {0}",
784// m_scene.RegionInfo.RegionName);
785
771 ResetAllLandPrimCounts(); 786 ResetAllLandPrimCounts();
772 EntityBase[] entities = m_scene.Entities.GetEntities(); 787 EntityBase[] entities = m_scene.Entities.GetEntities();
773 foreach (EntityBase obj in entities) 788 foreach (EntityBase obj in entities)
@@ -1119,7 +1134,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1119 } 1134 }
1120 else 1135 else
1121 { 1136 {
1122 m_log.WarnFormat("[PARCEL]: Invalid land object {0} passed for parcel object owner request", local_id); 1137 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Invalid land object {0} passed for parcel object owner request", local_id);
1123 } 1138 }
1124 } 1139 }
1125 1140
@@ -1295,7 +1310,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1295 1310
1296 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene); 1311 ILandObject new_land = new LandObject(data.OwnerID, data.IsGroupOwned, m_scene);
1297 new_land.LandData = data.Copy(); 1312 new_land.LandData = data.Copy();
1298 new_land.SetLandBitmapFromByteArray(); 1313 new_land.SetLandBitmapFromByteArray();
1299 AddLandObject(new_land); 1314 AddLandObject(new_land);
1300 new_land.SendLandUpdateToAvatarsOverMe(); 1315 new_land.SendLandUpdateToAvatarsOverMe();
1301 } 1316 }
@@ -1361,7 +1376,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1361 { 1376 {
1362 IClientAPI client; 1377 IClientAPI client;
1363 if (! m_scene.TryGetClient(agentID, out client)) { 1378 if (! m_scene.TryGetClient(agentID, out client)) {
1364 m_log.WarnFormat("[LAND] unable to retrieve IClientAPI for {0}", agentID.ToString()); 1379 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to retrieve IClientAPI for {0}", agentID);
1365 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1380 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1366 } 1381 }
1367 1382
@@ -1410,7 +1425,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1410 } 1425 }
1411 else 1426 else
1412 { 1427 {
1413 m_log.WarnFormat("[LAND] unable to find parcelID {0}", parcelID); 1428 m_log.WarnFormat("[LAND MANAGEMENT MODULE]: Unable to find parcelID {0}", parcelID);
1414 } 1429 }
1415 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty()); 1430 return LLSDHelpers.SerialiseLLSDReply(new LLSDEmpty());
1416 } 1431 }
@@ -1468,17 +1483,17 @@ namespace OpenSim.Region.CoreModules.World.Land
1468 } 1483 }
1469 catch (LLSD.LLSDParseException e) 1484 catch (LLSD.LLSDParseException e)
1470 { 1485 {
1471 m_log.ErrorFormat("[LAND] Fetch error: {0}", e.Message); 1486 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Fetch error: {0}", e.Message);
1472 m_log.ErrorFormat("[LAND] ... in request {0}", request); 1487 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: ... in request {0}", request);
1473 } 1488 }
1474 catch(InvalidCastException) 1489 catch (InvalidCastException)
1475 { 1490 {
1476 m_log.ErrorFormat("[LAND] Wrong type in request {0}", request); 1491 m_log.ErrorFormat("[LAND MANAGEMENT MODULE]: Wrong type in request {0}", request);
1477 } 1492 }
1478 1493
1479 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse(); 1494 LLSDRemoteParcelResponse response = new LLSDRemoteParcelResponse();
1480 response.parcel_id = parcelID; 1495 response.parcel_id = parcelID;
1481 m_log.DebugFormat("[LAND] got parcelID {0}", parcelID); 1496 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelID {0}", parcelID);
1482 1497
1483 return LLSDHelpers.SerialiseLLSDReply(response); 1498 return LLSDHelpers.SerialiseLLSDReply(response);
1484 } 1499 }
@@ -1499,7 +1514,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1499 ExtendedLandData extLandData = new ExtendedLandData(); 1514 ExtendedLandData extLandData = new ExtendedLandData();
1500 Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle, 1515 Util.ParseFakeParcelID(parcel, out extLandData.RegionHandle,
1501 out extLandData.X, out extLandData.Y); 1516 out extLandData.X, out extLandData.Y);
1502 m_log.DebugFormat("[LAND] got parcelinfo request for regionHandle {0}, x/y {1}/{2}", 1517 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: Got parcelinfo request for regionHandle {0}, x/y {1}/{2}",
1503 extLandData.RegionHandle, extLandData.X, extLandData.Y); 1518 extLandData.RegionHandle, extLandData.X, extLandData.Y);
1504 1519
1505 // for this region or for somewhere else? 1520 // for this region or for somewhere else?
@@ -1540,7 +1555,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1540 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y); 1555 info = m_scene.GridService.GetRegionByPosition(m_scene.RegionInfo.ScopeID, (int)x, (int)y);
1541 } 1556 }
1542 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark. 1557 // we need to transfer the fake parcelID, not the one in landData, so the viewer can match it to the landmark.
1543 m_log.DebugFormat("[LAND] got parcelinfo for parcel {0} in region {1}; sending...", 1558 m_log.DebugFormat("[LAND MANAGEMENT MODULE]: got parcelinfo for parcel {0} in region {1}; sending...",
1544 data.LandData.Name, data.RegionHandle); 1559 data.LandData.Name, data.RegionHandle);
1545 // HACK for now 1560 // HACK for now
1546 RegionInfo r = new RegionInfo(); 1561 RegionInfo r = new RegionInfo();
@@ -1551,7 +1566,7 @@ namespace OpenSim.Region.CoreModules.World.Land
1551 remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y); 1566 remoteClient.SendParcelInfo(r, data.LandData, parcelID, data.X, data.Y);
1552 } 1567 }
1553 else 1568 else
1554 m_log.Debug("[LAND] got no parcelinfo; not sending"); 1569 m_log.Debug("[LAND MANAGEMENT MODULE]: got no parcelinfo; not sending");
1555 } 1570 }
1556 1571
1557 public void setParcelOtherCleanTime(IClientAPI remoteClient, int localID, int otherCleanTime) 1572 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 b114db1..1e824bd 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 2d1979f..62fd2b0 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 f24c53c..4ce7a6c 100644
--- a/OpenSim/Region/Framework/Scenes/EventManager.cs
+++ b/OpenSim/Region/Framework/Scenes/EventManager.cs
@@ -246,7 +246,15 @@ namespace OpenSim.Region.Framework.Scenes
246 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID); 246 public delegate void GetScriptRunning(IClientAPI controllingClient, UUID objectID, UUID itemID);
247 247
248 public event EstateToolsSunUpdate OnEstateToolsSunUpdate; 248 public event EstateToolsSunUpdate OnEstateToolsSunUpdate;
249
250 /// <summary>
251 /// Triggered when an object is added to the scene.
252 /// </summary>
253 public event Action<SceneObjectGroup> OnObjectAddedToScene;
249 254
255 /// <summary>
256 /// Triggered when an object is removed from the scene.
257 /// </summary>
250 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj); 258 public delegate void ObjectBeingRemovedFromScene(SceneObjectGroup obj);
251 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene; 259 public event ObjectBeingRemovedFromScene OnObjectBeingRemovedFromScene;
252 260
@@ -349,6 +357,7 @@ namespace OpenSim.Region.Framework.Scenes
349 public delegate void Attach(uint localID, UUID itemID, UUID avatarID); 357 public delegate void Attach(uint localID, UUID itemID, UUID avatarID);
350 public event Attach OnAttach; 358 public event Attach OnAttach;
351 359
360
352 /// <summary> 361 /// <summary>
353 /// Called immediately after an object is loaded from storage. 362 /// Called immediately after an object is loaded from storage.
354 /// </summary> 363 /// </summary>
@@ -824,6 +833,27 @@ namespace OpenSim.Region.Framework.Scenes
824 } 833 }
825 } 834 }
826 835
836 public void TriggerObjectAddedToScene(SceneObjectGroup obj)
837 {
838 Action<SceneObjectGroup> handler = OnObjectAddedToScene;
839 if (handler != null)
840 {
841 foreach (Action<SceneObjectGroup> d in handler.GetInvocationList())
842 {
843 try
844 {
845 d(obj);
846 }
847 catch (Exception e)
848 {
849 m_log.ErrorFormat(
850 "[EVENT MANAGER]: Delegate for TriggerObjectAddedToScene failed - continuing. {0} {1}",
851 e.Message, e.StackTrace);
852 }
853 }
854 }
855 }
856
827 public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj) 857 public void TriggerObjectBeingRemovedFromScene(SceneObjectGroup obj)
828 { 858 {
829 ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene; 859 ObjectBeingRemovedFromScene handlerObjectBeingRemovedFromScene = OnObjectBeingRemovedFromScene;
diff --git a/OpenSim/Region/Framework/Scenes/Scene.cs b/OpenSim/Region/Framework/Scenes/Scene.cs
index e5c0f38..4eb5d64 100644
--- a/OpenSim/Region/Framework/Scenes/Scene.cs
+++ b/OpenSim/Region/Framework/Scenes/Scene.cs
@@ -1137,7 +1137,7 @@ namespace OpenSim.Region.Framework.Scenes
1137 // 1137 //
1138 while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null) 1138 while (m_regInfo.EstateSettings.EstateOwner == UUID.Zero && MainConsole.Instance != null)
1139 { 1139 {
1140 MainConsole.Instance.Output("The current estate has no owner set."); 1140 MainConsole.Instance.OutputFormat("Estate {0} has no owner set.", m_regInfo.EstateSettings.EstateName);
1141 List<char> excluded = new List<char>(new char[1]{' '}); 1141 List<char> excluded = new List<char>(new char[1]{' '});
1142 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded); 1142 string first = MainConsole.Instance.CmdPrompt("Estate owner first name", "Test", excluded);
1143 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded); 1143 string last = MainConsole.Instance.CmdPrompt("Estate owner last name", "User", excluded);
@@ -1998,8 +1998,14 @@ namespace OpenSim.Region.Framework.Scenes
1998 /// If false, it is left to the caller to schedule the update 1998 /// If false, it is left to the caller to schedule the update
1999 /// </param> 1999 /// </param>
2000 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates) 2000 public bool AddNewSceneObject(SceneObjectGroup sceneObject, bool attachToBackup, bool sendClientUpdates)
2001 { 2001 {
2002 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates); 2002 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, sendClientUpdates))
2003 {
2004 EventManager.TriggerObjectAddedToScene(sceneObject);
2005 return true;
2006 }
2007
2008 return false;
2003 } 2009 }
2004 2010
2005 /// <summary> 2011 /// <summary>
@@ -2016,7 +2022,13 @@ namespace OpenSim.Region.Framework.Scenes
2016 public bool AddNewSceneObject( 2022 public bool AddNewSceneObject(
2017 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel) 2023 SceneObjectGroup sceneObject, bool attachToBackup, Vector3 pos, Quaternion rot, Vector3 vel)
2018 { 2024 {
2019 return m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel); 2025 if (m_sceneGraph.AddNewSceneObject(sceneObject, attachToBackup, pos, rot, vel))
2026 {
2027 EventManager.TriggerObjectAddedToScene(sceneObject);
2028 return true;
2029 }
2030
2031 return false;
2020 } 2032 }
2021 2033
2022 /// <summary> 2034 /// <summary>
diff --git a/OpenSim/Region/Framework/Scenes/SceneGraph.cs b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
index e8cf4f4..62e7d36 100644
--- a/OpenSim/Region/Framework/Scenes/SceneGraph.cs
+++ b/OpenSim/Region/Framework/Scenes/SceneGraph.cs
@@ -97,9 +97,21 @@ namespace OpenSim.Region.Framework.Scenes
97 protected internal object m_syncRoot = new object(); 97 protected internal object m_syncRoot = new object();
98 98
99 protected internal PhysicsScene _PhyScene; 99 protected internal PhysicsScene _PhyScene;
100 100
101 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalID = new Dictionary<uint, SceneObjectGroup>(); 101 /// <summary>
102 /// Index the SceneObjectGroup for each part by the root part's UUID.
103 /// </summary>
102 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>(); 104 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullID = new Dictionary<UUID, SceneObjectGroup>();
105
106 /// <summary>
107 /// Index the SceneObjectGroup for each part by that part's UUID.
108 /// </summary>
109 protected internal Dictionary<UUID, SceneObjectGroup> SceneObjectGroupsByFullPartID = new Dictionary<UUID, SceneObjectGroup>();
110
111 /// <summary>
112 /// Index the SceneObjectGroup for each part by that part's local ID.
113 /// </summary>
114 protected internal Dictionary<uint, SceneObjectGroup> SceneObjectGroupsByLocalPartID = new Dictionary<uint, SceneObjectGroup>();
103 115
104 private Object m_updateLock = new Object(); 116 private Object m_updateLock = new Object();
105 117
@@ -147,8 +159,10 @@ namespace OpenSim.Region.Framework.Scenes
147 159
148 lock (SceneObjectGroupsByFullID) 160 lock (SceneObjectGroupsByFullID)
149 SceneObjectGroupsByFullID.Clear(); 161 SceneObjectGroupsByFullID.Clear();
150 lock (SceneObjectGroupsByLocalID) 162 lock (SceneObjectGroupsByFullPartID)
151 SceneObjectGroupsByLocalID.Clear(); 163 SceneObjectGroupsByFullPartID.Clear();
164 lock (SceneObjectGroupsByLocalPartID)
165 SceneObjectGroupsByLocalPartID.Clear();
152 166
153 Entities.Clear(); 167 Entities.Clear();
154 } 168 }
@@ -390,6 +404,10 @@ namespace OpenSim.Region.Framework.Scenes
390 404
391 if (Entities.ContainsKey(sceneObject.UUID)) 405 if (Entities.ContainsKey(sceneObject.UUID))
392 return false; 406 return false;
407
408// m_log.DebugFormat(
409// "[SCENEGRAPH]: Adding scene object {0} {1}, with {2} parts on {3}",
410// sceneObject.Name, sceneObject.UUID, sceneObject.Parts.Length, m_parentScene.RegionInfo.RegionName);
393 411
394 SceneObjectPart[] children = sceneObject.Parts; 412 SceneObjectPart[] children = sceneObject.Parts;
395 413
@@ -426,17 +444,20 @@ namespace OpenSim.Region.Framework.Scenes
426 OnObjectCreate(sceneObject); 444 OnObjectCreate(sceneObject);
427 445
428 lock (SceneObjectGroupsByFullID) 446 lock (SceneObjectGroupsByFullID)
429 {
430 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject; 447 SceneObjectGroupsByFullID[sceneObject.UUID] = sceneObject;
448
449 lock (SceneObjectGroupsByFullPartID)
450 {
451 SceneObjectGroupsByFullPartID[sceneObject.UUID] = sceneObject;
431 foreach (SceneObjectPart part in children) 452 foreach (SceneObjectPart part in children)
432 SceneObjectGroupsByFullID[part.UUID] = sceneObject; 453 SceneObjectGroupsByFullPartID[part.UUID] = sceneObject;
433 } 454 }
434 455
435 lock (SceneObjectGroupsByLocalID) 456 lock (SceneObjectGroupsByLocalPartID)
436 { 457 {
437 SceneObjectGroupsByLocalID[sceneObject.LocalId] = sceneObject; 458 SceneObjectGroupsByLocalPartID[sceneObject.LocalId] = sceneObject;
438 foreach (SceneObjectPart part in children) 459 foreach (SceneObjectPart part in children)
439 SceneObjectGroupsByLocalID[part.LocalId] = sceneObject; 460 SceneObjectGroupsByLocalPartID[part.LocalId] = sceneObject;
440 } 461 }
441 462
442 return true; 463 return true;
@@ -467,21 +488,24 @@ namespace OpenSim.Region.Framework.Scenes
467 488
468 if (OnObjectRemove != null) 489 if (OnObjectRemove != null)
469 OnObjectRemove(Entities[uuid]); 490 OnObjectRemove(Entities[uuid]);
470 491
471 lock (SceneObjectGroupsByFullID) 492 lock (SceneObjectGroupsByFullID)
493 SceneObjectGroupsByFullID.Remove(grp.UUID);
494
495 lock (SceneObjectGroupsByFullPartID)
472 { 496 {
473 SceneObjectPart[] parts = grp.Parts; 497 SceneObjectPart[] parts = grp.Parts;
474 for (int i = 0; i < parts.Length; i++) 498 for (int i = 0; i < parts.Length; i++)
475 SceneObjectGroupsByFullID.Remove(parts[i].UUID); 499 SceneObjectGroupsByFullPartID.Remove(parts[i].UUID);
476 SceneObjectGroupsByFullID.Remove(grp.RootPart.UUID); 500 SceneObjectGroupsByFullPartID.Remove(grp.RootPart.UUID);
477 } 501 }
478 502
479 lock (SceneObjectGroupsByLocalID) 503 lock (SceneObjectGroupsByLocalPartID)
480 { 504 {
481 SceneObjectPart[] parts = grp.Parts; 505 SceneObjectPart[] parts = grp.Parts;
482 for (int i = 0; i < parts.Length; i++) 506 for (int i = 0; i < parts.Length; i++)
483 SceneObjectGroupsByLocalID.Remove(parts[i].LocalId); 507 SceneObjectGroupsByLocalPartID.Remove(parts[i].LocalId);
484 SceneObjectGroupsByLocalID.Remove(grp.RootPart.LocalId); 508 SceneObjectGroupsByLocalPartID.Remove(grp.RootPart.LocalId);
485 } 509 }
486 510
487 return Entities.Remove(uuid); 511 return Entities.Remove(uuid);
@@ -697,7 +721,7 @@ namespace OpenSim.Region.Framework.Scenes
697 if (!Entities.Remove(agentID)) 721 if (!Entities.Remove(agentID))
698 { 722 {
699 m_log.WarnFormat( 723 m_log.WarnFormat(
700 "[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list", 724 "[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene Entities list",
701 agentID); 725 agentID);
702 } 726 }
703 727
@@ -721,7 +745,7 @@ namespace OpenSim.Region.Framework.Scenes
721 } 745 }
722 else 746 else
723 { 747 {
724 m_log.WarnFormat("[SCENE]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID); 748 m_log.WarnFormat("[SCENEGRAPH]: Tried to remove non-existent scene presence with agent ID {0} from scene ScenePresences list", agentID);
725 } 749 }
726 } 750 }
727 finally 751 finally
@@ -934,14 +958,14 @@ namespace OpenSim.Region.Framework.Scenes
934 958
935 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID); 959 //m_log.DebugFormat("Entered GetGroupByPrim with localID {0}", localID);
936 SceneObjectGroup sog; 960 SceneObjectGroup sog;
937 lock (SceneObjectGroupsByLocalID) 961 lock (SceneObjectGroupsByLocalPartID)
938 SceneObjectGroupsByLocalID.TryGetValue(localID, out sog); 962 SceneObjectGroupsByLocalPartID.TryGetValue(localID, out sog);
939 963
940 if (sog != null) 964 if (sog != null)
941 { 965 {
942 if (sog.HasChildPrim(localID)) 966 if (sog.HasChildPrim(localID))
943 return sog; 967 return sog;
944 SceneObjectGroupsByLocalID.Remove(localID); 968 SceneObjectGroupsByLocalPartID.Remove(localID);
945 } 969 }
946 970
947 EntityBase[] entityList = GetEntities(); 971 EntityBase[] entityList = GetEntities();
@@ -953,8 +977,8 @@ namespace OpenSim.Region.Framework.Scenes
953 sog = (SceneObjectGroup)ent; 977 sog = (SceneObjectGroup)ent;
954 if (sog.HasChildPrim(localID)) 978 if (sog.HasChildPrim(localID))
955 { 979 {
956 lock (SceneObjectGroupsByLocalID) 980 lock (SceneObjectGroupsByLocalPartID)
957 SceneObjectGroupsByLocalID[localID] = sog; 981 SceneObjectGroupsByLocalPartID[localID] = sog;
958 return sog; 982 return sog;
959 } 983 }
960 } 984 }
@@ -971,16 +995,16 @@ namespace OpenSim.Region.Framework.Scenes
971 private SceneObjectGroup GetGroupByPrim(UUID fullID) 995 private SceneObjectGroup GetGroupByPrim(UUID fullID)
972 { 996 {
973 SceneObjectGroup sog; 997 SceneObjectGroup sog;
974 lock (SceneObjectGroupsByFullID) 998 lock (SceneObjectGroupsByFullPartID)
975 SceneObjectGroupsByFullID.TryGetValue(fullID, out sog); 999 SceneObjectGroupsByFullPartID.TryGetValue(fullID, out sog);
976 1000
977 if (sog != null) 1001 if (sog != null)
978 { 1002 {
979 if (sog.ContainsPart(fullID)) 1003 if (sog.ContainsPart(fullID))
980 return sog; 1004 return sog;
981 1005
982 lock (SceneObjectGroupsByFullID) 1006 lock (SceneObjectGroupsByFullPartID)
983 SceneObjectGroupsByFullID.Remove(fullID); 1007 SceneObjectGroupsByFullPartID.Remove(fullID);
984 } 1008 }
985 1009
986 EntityBase[] entityList = GetEntities(); 1010 EntityBase[] entityList = GetEntities();
@@ -991,8 +1015,8 @@ namespace OpenSim.Region.Framework.Scenes
991 sog = (SceneObjectGroup)ent; 1015 sog = (SceneObjectGroup)ent;
992 if (sog.HasChildPrim(fullID)) 1016 if (sog.HasChildPrim(fullID))
993 { 1017 {
994 lock (SceneObjectGroupsByFullID) 1018 lock (SceneObjectGroupsByFullPartID)
995 SceneObjectGroupsByFullID[fullID] = sog; 1019 SceneObjectGroupsByFullPartID[fullID] = sog;
996 return sog; 1020 return sog;
997 } 1021 }
998 } 1022 }
@@ -1144,16 +1168,15 @@ namespace OpenSim.Region.Framework.Scenes
1144 } 1168 }
1145 1169
1146 /// <summary> 1170 /// <summary>
1147 /// Performs action on all scene object groups. 1171 /// Performs action once on all scene object groups.
1148 /// </summary> 1172 /// </summary>
1149 /// <param name="action"></param> 1173 /// <param name="action"></param>
1150 protected internal void ForEachSOG(Action<SceneObjectGroup> action) 1174 protected internal void ForEachSOG(Action<SceneObjectGroup> action)
1151 { 1175 {
1152 EntityBase[] objlist = Entities.GetAllByType<SceneObjectGroup>(); 1176 // FIXME: Need to lock here, really.
1153 foreach (EntityBase ent in objlist) 1177 List<SceneObjectGroup> objlist = new List<SceneObjectGroup>(SceneObjectGroupsByFullID.Values);
1178 foreach (SceneObjectGroup obj in objlist)
1154 { 1179 {
1155 SceneObjectGroup obj = (SceneObjectGroup)ent;
1156
1157 try 1180 try
1158 { 1181 {
1159 action(obj); 1182 action(obj);
@@ -1161,11 +1184,11 @@ namespace OpenSim.Region.Framework.Scenes
1161 catch (Exception e) 1184 catch (Exception e)
1162 { 1185 {
1163 // Catch it and move on. This includes situations where splist has inconsistent info 1186 // Catch it and move on. This includes situations where splist has inconsistent info
1164 m_log.WarnFormat("[SCENE]: Problem processing action in ForEachSOG: ", e.ToString()); 1187 m_log.WarnFormat(
1188 "[SCENEGRAPH]: Problem processing action in ForEachSOG: {0} {1}", e.Message, e.StackTrace);
1165 } 1189 }
1166 } 1190 }
1167 } 1191 }
1168
1169 1192
1170 /// <summary> 1193 /// <summary>
1171 /// Performs action on all scene presences. This can ultimately run the actions in parallel but 1194 /// Performs action on all scene presences. This can ultimately run the actions in parallel but
@@ -1185,8 +1208,8 @@ namespace OpenSim.Region.Framework.Scenes
1185 } 1208 }
1186 catch (Exception e) 1209 catch (Exception e)
1187 { 1210 {
1188 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); 1211 m_log.Info("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1189 m_log.Info("[BUG] Stack Trace: " + e.StackTrace); 1212 m_log.Info("[SCENEGRAPH]: Stack Trace: " + e.StackTrace);
1190 } 1213 }
1191 }); 1214 });
1192 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction); 1215 Parallel.ForEach<ScenePresence>(GetScenePresences(), protectedAction);
@@ -1201,7 +1224,7 @@ namespace OpenSim.Region.Framework.Scenes
1201 } 1224 }
1202 catch (Exception e) 1225 catch (Exception e)
1203 { 1226 {
1204 m_log.Info("[BUG] in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString()); 1227 m_log.Error("[SCENEGRAPH]: Error in " + m_parentScene.RegionInfo.RegionName + ": " + e.ToString());
1205 } 1228 }
1206 } 1229 }
1207 } 1230 }
@@ -1884,7 +1907,10 @@ namespace OpenSim.Region.Framework.Scenes
1884 /// <param name="rot"></param> 1907 /// <param name="rot"></param>
1885 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot) 1908 public SceneObjectGroup DuplicateObject(uint originalPrimID, Vector3 offset, uint flags, UUID AgentID, UUID GroupID, Quaternion rot)
1886 { 1909 {
1887 //m_log.DebugFormat("[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}", originalPrim, offset, AgentID); 1910// m_log.DebugFormat(
1911// "[SCENE]: Duplication of object {0} at offset {1} requested by agent {2}",
1912// originalPrimID, offset, AgentID);
1913
1888 SceneObjectGroup original = GetGroupByPrim(originalPrimID); 1914 SceneObjectGroup original = GetGroupByPrim(originalPrimID);
1889 if (original != null) 1915 if (original != null)
1890 { 1916 {
@@ -1912,7 +1938,28 @@ namespace OpenSim.Region.Framework.Scenes
1912 } 1938 }
1913 } 1939 }
1914 1940
1941 // FIXME: This section needs to be refactored so that it just calls AddSceneObject()
1915 Entities.Add(copy); 1942 Entities.Add(copy);
1943
1944 lock (SceneObjectGroupsByFullID)
1945 SceneObjectGroupsByFullID[copy.UUID] = copy;
1946
1947 SceneObjectPart[] children = copy.Parts;
1948
1949 lock (SceneObjectGroupsByFullPartID)
1950 {
1951 SceneObjectGroupsByFullPartID[copy.UUID] = copy;
1952 foreach (SceneObjectPart part in children)
1953 SceneObjectGroupsByFullPartID[part.UUID] = copy;
1954 }
1955
1956 lock (SceneObjectGroupsByLocalPartID)
1957 {
1958 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1959 foreach (SceneObjectPart part in children)
1960 SceneObjectGroupsByLocalPartID[copy.LocalId] = copy;
1961 }
1962 // PROBABLE END OF FIXME
1916 1963
1917 // Since we copy from a source group that is in selected 1964 // Since we copy from a source group that is in selected
1918 // state, but the copy is shown deselected in the viewer, 1965 // state, but the copy is shown deselected in the viewer,